diff options
author | Arjan van de Ven <arjan@linux.intel.com> | 2006-06-28 07:26:45 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-06-28 17:59:04 -0400 |
commit | f71d20e961474dde77e6558396efb93d6ac80a4b (patch) | |
tree | 669610f79521fd173c28fc47bef39ecd4cdf52ab | |
parent | f5e54d6e53a20cef45af7499e86164f0e0d16bb2 (diff) |
[PATCH] Add EXPORT_UNUSED_SYMBOL and EXPORT_UNUSED_SYMBOL_GPL
Temporarily add EXPORT_UNUSED_SYMBOL and EXPORT_UNUSED_SYMBOL_GPL. These
will be used as a transition measure for symbols that aren't used in the
kernel and are on the way out. When a module uses such a symbol, a warning
is printk'd at modprobe time.
The main reason for removing unused exports is size: eacho export takes
roughly between 100 and 150 bytes of kernel space in the binary. This
patch gives users the option to immediately get this size gain via a config
option.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | Documentation/feature-removal-schedule.txt | 10 | ||||
-rw-r--r-- | include/asm-generic/vmlinux.lds.h | 28 | ||||
-rw-r--r-- | include/linux/module.h | 20 | ||||
-rw-r--r-- | kernel/module.c | 78 | ||||
-rw-r--r-- | lib/Kconfig.debug | 16 |
5 files changed, 150 insertions, 2 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 027285d0c26c..033ac91da07a 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -177,6 +177,16 @@ Who: Jean Delvare <khali@linux-fr.org> | |||
177 | 177 | ||
178 | --------------------------- | 178 | --------------------------- |
179 | 179 | ||
180 | What: Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports | ||
181 | (temporary transition config option provided until then) | ||
182 | The transition config option will also be removed at the same time. | ||
183 | When: before 2.6.19 | ||
184 | Why: Unused symbols are both increasing the size of the kernel binary | ||
185 | and are often a sign of "wrong API" | ||
186 | Who: Arjan van de Ven <arjan@linux.intel.com> | ||
187 | |||
188 | --------------------------- | ||
189 | |||
180 | What: remove EXPORT_SYMBOL(tasklist_lock) | 190 | What: remove EXPORT_SYMBOL(tasklist_lock) |
181 | When: August 2006 | 191 | When: August 2006 |
182 | Files: kernel/fork.c | 192 | Files: kernel/fork.c |
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 9d11550b4818..db5a3732f106 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h | |||
@@ -58,6 +58,20 @@ | |||
58 | VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \ | 58 | VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \ |
59 | } \ | 59 | } \ |
60 | \ | 60 | \ |
61 | /* Kernel symbol table: Normal unused symbols */ \ | ||
62 | __ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \ | ||
63 | VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \ | ||
64 | *(__ksymtab_unused) \ | ||
65 | VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \ | ||
66 | } \ | ||
67 | \ | ||
68 | /* Kernel symbol table: GPL-only unused symbols */ \ | ||
69 | __ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \ | ||
70 | VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \ | ||
71 | *(__ksymtab_unused_gpl) \ | ||
72 | VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \ | ||
73 | } \ | ||
74 | \ | ||
61 | /* Kernel symbol table: GPL-future-only symbols */ \ | 75 | /* Kernel symbol table: GPL-future-only symbols */ \ |
62 | __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \ | 76 | __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \ |
63 | VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \ | 77 | VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \ |
@@ -79,6 +93,20 @@ | |||
79 | VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \ | 93 | VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \ |
80 | } \ | 94 | } \ |
81 | \ | 95 | \ |
96 | /* Kernel symbol table: Normal unused symbols */ \ | ||
97 | __kcrctab_unused : AT(ADDR(__kcrctab_unused) - LOAD_OFFSET) { \ | ||
98 | VMLINUX_SYMBOL(__start___kcrctab_unused) = .; \ | ||
99 | *(__kcrctab_unused) \ | ||
100 | VMLINUX_SYMBOL(__stop___kcrctab_unused) = .; \ | ||
101 | } \ | ||
102 | \ | ||
103 | /* Kernel symbol table: GPL-only unused symbols */ \ | ||
104 | __kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \ | ||
105 | VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .; \ | ||
106 | *(__kcrctab_unused_gpl) \ | ||
107 | VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .; \ | ||
108 | } \ | ||
109 | \ | ||
82 | /* Kernel symbol table: GPL-future-only symbols */ \ | 110 | /* Kernel symbol table: GPL-future-only symbols */ \ |
83 | __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \ | 111 | __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \ |
84 | VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \ | 112 | VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \ |
diff --git a/include/linux/module.h b/include/linux/module.h index 9ebbb74b7b72..9e9dc7c24d95 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -203,6 +203,15 @@ void *__symbol_get_gpl(const char *symbol); | |||
203 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) \ | 203 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) \ |
204 | __EXPORT_SYMBOL(sym, "_gpl_future") | 204 | __EXPORT_SYMBOL(sym, "_gpl_future") |
205 | 205 | ||
206 | |||
207 | #ifdef CONFIG_UNUSED_SYMBOLS | ||
208 | #define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused") | ||
209 | #define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl") | ||
210 | #else | ||
211 | #define EXPORT_UNUSED_SYMBOL(sym) | ||
212 | #define EXPORT_UNUSED_SYMBOL_GPL(sym) | ||
213 | #endif | ||
214 | |||
206 | #endif | 215 | #endif |
207 | 216 | ||
208 | struct module_ref | 217 | struct module_ref |
@@ -261,6 +270,15 @@ struct module | |||
261 | unsigned int num_gpl_syms; | 270 | unsigned int num_gpl_syms; |
262 | const unsigned long *gpl_crcs; | 271 | const unsigned long *gpl_crcs; |
263 | 272 | ||
273 | /* unused exported symbols. */ | ||
274 | const struct kernel_symbol *unused_syms; | ||
275 | unsigned int num_unused_syms; | ||
276 | const unsigned long *unused_crcs; | ||
277 | /* GPL-only, unused exported symbols. */ | ||
278 | const struct kernel_symbol *unused_gpl_syms; | ||
279 | unsigned int num_unused_gpl_syms; | ||
280 | const unsigned long *unused_gpl_crcs; | ||
281 | |||
264 | /* symbols that will be GPL-only in the near future. */ | 282 | /* symbols that will be GPL-only in the near future. */ |
265 | const struct kernel_symbol *gpl_future_syms; | 283 | const struct kernel_symbol *gpl_future_syms; |
266 | unsigned int num_gpl_future_syms; | 284 | unsigned int num_gpl_future_syms; |
@@ -456,6 +474,8 @@ void module_remove_driver(struct device_driver *); | |||
456 | #define EXPORT_SYMBOL(sym) | 474 | #define EXPORT_SYMBOL(sym) |
457 | #define EXPORT_SYMBOL_GPL(sym) | 475 | #define EXPORT_SYMBOL_GPL(sym) |
458 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) | 476 | #define EXPORT_SYMBOL_GPL_FUTURE(sym) |
477 | #define EXPORT_UNUSED_SYMBOL(sym) | ||
478 | #define EXPORT_UNUSED_SYMBOL_GPL(sym) | ||
459 | 479 | ||
460 | /* Given an address, look for it in the exception tables. */ | 480 | /* Given an address, look for it in the exception tables. */ |
461 | static inline const struct exception_table_entry * | 481 | static inline const struct exception_table_entry * |
diff --git a/kernel/module.c b/kernel/module.c index 10e5b872adf6..03b738172a8c 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Rewritten by Rusty Russell, on the backs of many others... | 1 | /* |
2 | Copyright (C) 2002 Richard Henderson | 2 | Copyright (C) 2002 Richard Henderson |
3 | Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM. | 3 | Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM. |
4 | 4 | ||
@@ -122,9 +122,17 @@ extern const struct kernel_symbol __start___ksymtab_gpl[]; | |||
122 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; | 122 | extern const struct kernel_symbol __stop___ksymtab_gpl[]; |
123 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; | 123 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; |
124 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; | 124 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; |
125 | extern const struct kernel_symbol __start___ksymtab_unused[]; | ||
126 | extern const struct kernel_symbol __stop___ksymtab_unused[]; | ||
127 | extern const struct kernel_symbol __start___ksymtab_unused_gpl[]; | ||
128 | extern const struct kernel_symbol __stop___ksymtab_unused_gpl[]; | ||
129 | extern const struct kernel_symbol __start___ksymtab_gpl_future[]; | ||
130 | extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; | ||
125 | extern const unsigned long __start___kcrctab[]; | 131 | extern const unsigned long __start___kcrctab[]; |
126 | extern const unsigned long __start___kcrctab_gpl[]; | 132 | extern const unsigned long __start___kcrctab_gpl[]; |
127 | extern const unsigned long __start___kcrctab_gpl_future[]; | 133 | extern const unsigned long __start___kcrctab_gpl_future[]; |
134 | extern const unsigned long __start___kcrctab_unused[]; | ||
135 | extern const unsigned long __start___kcrctab_unused_gpl[]; | ||
128 | 136 | ||
129 | #ifndef CONFIG_MODVERSIONS | 137 | #ifndef CONFIG_MODVERSIONS |
130 | #define symversion(base, idx) NULL | 138 | #define symversion(base, idx) NULL |
@@ -144,6 +152,17 @@ static const struct kernel_symbol *lookup_symbol(const char *name, | |||
144 | return NULL; | 152 | return NULL; |
145 | } | 153 | } |
146 | 154 | ||
155 | static void printk_unused_warning(const char *name) | ||
156 | { | ||
157 | printk(KERN_WARNING "Symbol %s is marked as UNUSED, " | ||
158 | "however this module is using it.\n", name); | ||
159 | printk(KERN_WARNING "This symbol will go away in the future.\n"); | ||
160 | printk(KERN_WARNING "Please evalute if this is the right api to use, " | ||
161 | "and if it really is, submit a report the linux kernel " | ||
162 | "mailinglist together with submitting your code for " | ||
163 | "inclusion.\n"); | ||
164 | } | ||
165 | |||
147 | /* Find a symbol, return value, crc and module which owns it */ | 166 | /* Find a symbol, return value, crc and module which owns it */ |
148 | static unsigned long __find_symbol(const char *name, | 167 | static unsigned long __find_symbol(const char *name, |
149 | struct module **owner, | 168 | struct module **owner, |
@@ -186,6 +205,25 @@ static unsigned long __find_symbol(const char *name, | |||
186 | return ks->value; | 205 | return ks->value; |
187 | } | 206 | } |
188 | 207 | ||
208 | ks = lookup_symbol(name, __start___ksymtab_unused, | ||
209 | __stop___ksymtab_unused); | ||
210 | if (ks) { | ||
211 | printk_unused_warning(name); | ||
212 | *crc = symversion(__start___kcrctab_unused, | ||
213 | (ks - __start___ksymtab_unused)); | ||
214 | return ks->value; | ||
215 | } | ||
216 | |||
217 | if (gplok) | ||
218 | ks = lookup_symbol(name, __start___ksymtab_unused_gpl, | ||
219 | __stop___ksymtab_unused_gpl); | ||
220 | if (ks) { | ||
221 | printk_unused_warning(name); | ||
222 | *crc = symversion(__start___kcrctab_unused_gpl, | ||
223 | (ks - __start___ksymtab_unused_gpl)); | ||
224 | return ks->value; | ||
225 | } | ||
226 | |||
189 | /* Now try modules. */ | 227 | /* Now try modules. */ |
190 | list_for_each_entry(mod, &modules, list) { | 228 | list_for_each_entry(mod, &modules, list) { |
191 | *owner = mod; | 229 | *owner = mod; |
@@ -204,6 +242,23 @@ static unsigned long __find_symbol(const char *name, | |||
204 | return ks->value; | 242 | return ks->value; |
205 | } | 243 | } |
206 | } | 244 | } |
245 | ks = lookup_symbol(name, mod->unused_syms, mod->unused_syms + mod->num_unused_syms); | ||
246 | if (ks) { | ||
247 | printk_unused_warning(name); | ||
248 | *crc = symversion(mod->unused_crcs, (ks - mod->unused_syms)); | ||
249 | return ks->value; | ||
250 | } | ||
251 | |||
252 | if (gplok) { | ||
253 | ks = lookup_symbol(name, mod->unused_gpl_syms, | ||
254 | mod->unused_gpl_syms + mod->num_unused_gpl_syms); | ||
255 | if (ks) { | ||
256 | printk_unused_warning(name); | ||
257 | *crc = symversion(mod->unused_gpl_crcs, | ||
258 | (ks - mod->unused_gpl_syms)); | ||
259 | return ks->value; | ||
260 | } | ||
261 | } | ||
207 | ks = lookup_symbol(name, mod->gpl_future_syms, | 262 | ks = lookup_symbol(name, mod->gpl_future_syms, |
208 | (mod->gpl_future_syms + | 263 | (mod->gpl_future_syms + |
209 | mod->num_gpl_future_syms)); | 264 | mod->num_gpl_future_syms)); |
@@ -1407,6 +1462,8 @@ static struct module *load_module(void __user *umod, | |||
1407 | exportindex, modindex, obsparmindex, infoindex, gplindex, | 1462 | exportindex, modindex, obsparmindex, infoindex, gplindex, |
1408 | crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex, | 1463 | crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex, |
1409 | gplfuturecrcindex, unwindex = 0; | 1464 | gplfuturecrcindex, unwindex = 0; |
1465 | unsigned int unusedindex, unusedcrcindex, unusedgplindex, | ||
1466 | unusedgplcrcindex; | ||
1410 | struct module *mod; | 1467 | struct module *mod; |
1411 | long err = 0; | 1468 | long err = 0; |
1412 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ | 1469 | void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */ |
@@ -1487,9 +1544,13 @@ static struct module *load_module(void __user *umod, | |||
1487 | exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab"); | 1544 | exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab"); |
1488 | gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl"); | 1545 | gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl"); |
1489 | gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future"); | 1546 | gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future"); |
1547 | unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused"); | ||
1548 | unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl"); | ||
1490 | crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab"); | 1549 | crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab"); |
1491 | gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl"); | 1550 | gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl"); |
1492 | gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future"); | 1551 | gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future"); |
1552 | unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused"); | ||
1553 | unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl"); | ||
1493 | setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); | 1554 | setupindex = find_sec(hdr, sechdrs, secstrings, "__param"); |
1494 | exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); | 1555 | exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table"); |
1495 | obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); | 1556 | obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm"); |
@@ -1638,14 +1699,27 @@ static struct module *load_module(void __user *umod, | |||
1638 | mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; | 1699 | mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr; |
1639 | mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / | 1700 | mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size / |
1640 | sizeof(*mod->gpl_future_syms); | 1701 | sizeof(*mod->gpl_future_syms); |
1702 | mod->num_unused_syms = sechdrs[unusedindex].sh_size / | ||
1703 | sizeof(*mod->unused_syms); | ||
1704 | mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size / | ||
1705 | sizeof(*mod->unused_gpl_syms); | ||
1641 | mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr; | 1706 | mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr; |
1642 | if (gplfuturecrcindex) | 1707 | if (gplfuturecrcindex) |
1643 | mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; | 1708 | mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr; |
1644 | 1709 | ||
1710 | mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr; | ||
1711 | if (unusedcrcindex) | ||
1712 | mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr; | ||
1713 | mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr; | ||
1714 | if (unusedgplcrcindex) | ||
1715 | mod->unused_crcs = (void *)sechdrs[unusedgplcrcindex].sh_addr; | ||
1716 | |||
1645 | #ifdef CONFIG_MODVERSIONS | 1717 | #ifdef CONFIG_MODVERSIONS |
1646 | if ((mod->num_syms && !crcindex) || | 1718 | if ((mod->num_syms && !crcindex) || |
1647 | (mod->num_gpl_syms && !gplcrcindex) || | 1719 | (mod->num_gpl_syms && !gplcrcindex) || |
1648 | (mod->num_gpl_future_syms && !gplfuturecrcindex)) { | 1720 | (mod->num_gpl_future_syms && !gplfuturecrcindex) || |
1721 | (mod->num_unused_syms && !unusedcrcindex) || | ||
1722 | (mod->num_unused_gpl_syms && !unusedgplcrcindex)) { | ||
1649 | printk(KERN_WARNING "%s: No versions for exported symbols." | 1723 | printk(KERN_WARNING "%s: No versions for exported symbols." |
1650 | " Tainting kernel.\n", mod->name); | 1724 | " Tainting kernel.\n", mod->name); |
1651 | add_taint(TAINT_FORCED_MODULE); | 1725 | add_taint(TAINT_FORCED_MODULE); |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 5330911ebd30..e4fcbd12cf6e 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
@@ -23,6 +23,22 @@ config MAGIC_SYSRQ | |||
23 | keys are documented in <file:Documentation/sysrq.txt>. Don't say Y | 23 | keys are documented in <file:Documentation/sysrq.txt>. Don't say Y |
24 | unless you really know what this hack does. | 24 | unless you really know what this hack does. |
25 | 25 | ||
26 | config UNUSED_SYMBOLS | ||
27 | bool "Enable unused/obsolete exported symbols" | ||
28 | default y if X86 | ||
29 | help | ||
30 | Unused but exported symbols make the kernel needlessly bigger. For | ||
31 | that reason most of these unused exports will soon be removed. This | ||
32 | option is provided temporarily to provide a transition period in case | ||
33 | some external kernel module needs one of these symbols anyway. If you | ||
34 | encounter such a case in your module, consider if you are actually | ||
35 | using the right API. (rationale: since nobody in the kernel is using | ||
36 | this in a module, there is a pretty good chance it's actually the | ||
37 | wrong interface to use). If you really need the symbol, please send a | ||
38 | mail to the linux kernel mailing list mentioning the symbol and why | ||
39 | you really need it, and what the merge plan to the mainline kernel for | ||
40 | your module is. | ||
41 | |||
26 | config DEBUG_KERNEL | 42 | config DEBUG_KERNEL |
27 | bool "Kernel debugging" | 43 | bool "Kernel debugging" |
28 | help | 44 | help |