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 /kernel/module.c | |
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>
Diffstat (limited to 'kernel/module.c')
-rw-r--r-- | kernel/module.c | 78 |
1 files changed, 76 insertions, 2 deletions
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); |