aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/module.c
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2006-06-28 07:26:45 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-06-28 17:59:04 -0400
commitf71d20e961474dde77e6558396efb93d6ac80a4b (patch)
tree669610f79521fd173c28fc47bef39ecd4cdf52ab /kernel/module.c
parentf5e54d6e53a20cef45af7499e86164f0e0d16bb2 (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.c78
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[];
122extern const struct kernel_symbol __stop___ksymtab_gpl[]; 122extern const struct kernel_symbol __stop___ksymtab_gpl[];
123extern const struct kernel_symbol __start___ksymtab_gpl_future[]; 123extern const struct kernel_symbol __start___ksymtab_gpl_future[];
124extern const struct kernel_symbol __stop___ksymtab_gpl_future[]; 124extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
125extern const struct kernel_symbol __start___ksymtab_unused[];
126extern const struct kernel_symbol __stop___ksymtab_unused[];
127extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
128extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
129extern const struct kernel_symbol __start___ksymtab_gpl_future[];
130extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
125extern const unsigned long __start___kcrctab[]; 131extern const unsigned long __start___kcrctab[];
126extern const unsigned long __start___kcrctab_gpl[]; 132extern const unsigned long __start___kcrctab_gpl[];
127extern const unsigned long __start___kcrctab_gpl_future[]; 133extern const unsigned long __start___kcrctab_gpl_future[];
134extern const unsigned long __start___kcrctab_unused[];
135extern 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
155static 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 */
148static unsigned long __find_symbol(const char *name, 167static 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);