mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-01-04 04:04:19 +00:00
[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>
This commit is contained in:
parent
f5e54d6e53
commit
f71d20e961
@ -177,6 +177,16 @@ Who: Jean Delvare <khali@linux-fr.org>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: Unused EXPORT_SYMBOL/EXPORT_SYMBOL_GPL exports
|
||||
(temporary transition config option provided until then)
|
||||
The transition config option will also be removed at the same time.
|
||||
When: before 2.6.19
|
||||
Why: Unused symbols are both increasing the size of the kernel binary
|
||||
and are often a sign of "wrong API"
|
||||
Who: Arjan van de Ven <arjan@linux.intel.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: remove EXPORT_SYMBOL(tasklist_lock)
|
||||
When: August 2006
|
||||
Files: kernel/fork.c
|
||||
|
@ -58,6 +58,20 @@
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_gpl) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: Normal unused symbols */ \
|
||||
__ksymtab_unused : AT(ADDR(__ksymtab_unused) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab_unused) = .; \
|
||||
*(__ksymtab_unused) \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_unused) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-only unused symbols */ \
|
||||
__ksymtab_unused_gpl : AT(ADDR(__ksymtab_unused_gpl) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab_unused_gpl) = .; \
|
||||
*(__ksymtab_unused_gpl) \
|
||||
VMLINUX_SYMBOL(__stop___ksymtab_unused_gpl) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-future-only symbols */ \
|
||||
__ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___ksymtab_gpl_future) = .; \
|
||||
@ -79,6 +93,20 @@
|
||||
VMLINUX_SYMBOL(__stop___kcrctab_gpl) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: Normal unused symbols */ \
|
||||
__kcrctab_unused : AT(ADDR(__kcrctab_unused) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___kcrctab_unused) = .; \
|
||||
*(__kcrctab_unused) \
|
||||
VMLINUX_SYMBOL(__stop___kcrctab_unused) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-only unused symbols */ \
|
||||
__kcrctab_unused_gpl : AT(ADDR(__kcrctab_unused_gpl) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___kcrctab_unused_gpl) = .; \
|
||||
*(__kcrctab_unused_gpl) \
|
||||
VMLINUX_SYMBOL(__stop___kcrctab_unused_gpl) = .; \
|
||||
} \
|
||||
\
|
||||
/* Kernel symbol table: GPL-future-only symbols */ \
|
||||
__kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - LOAD_OFFSET) { \
|
||||
VMLINUX_SYMBOL(__start___kcrctab_gpl_future) = .; \
|
||||
|
@ -203,6 +203,15 @@ void *__symbol_get_gpl(const char *symbol);
|
||||
#define EXPORT_SYMBOL_GPL_FUTURE(sym) \
|
||||
__EXPORT_SYMBOL(sym, "_gpl_future")
|
||||
|
||||
|
||||
#ifdef CONFIG_UNUSED_SYMBOLS
|
||||
#define EXPORT_UNUSED_SYMBOL(sym) __EXPORT_SYMBOL(sym, "_unused")
|
||||
#define EXPORT_UNUSED_SYMBOL_GPL(sym) __EXPORT_SYMBOL(sym, "_unused_gpl")
|
||||
#else
|
||||
#define EXPORT_UNUSED_SYMBOL(sym)
|
||||
#define EXPORT_UNUSED_SYMBOL_GPL(sym)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
struct module_ref
|
||||
@ -261,6 +270,15 @@ struct module
|
||||
unsigned int num_gpl_syms;
|
||||
const unsigned long *gpl_crcs;
|
||||
|
||||
/* unused exported symbols. */
|
||||
const struct kernel_symbol *unused_syms;
|
||||
unsigned int num_unused_syms;
|
||||
const unsigned long *unused_crcs;
|
||||
/* GPL-only, unused exported symbols. */
|
||||
const struct kernel_symbol *unused_gpl_syms;
|
||||
unsigned int num_unused_gpl_syms;
|
||||
const unsigned long *unused_gpl_crcs;
|
||||
|
||||
/* symbols that will be GPL-only in the near future. */
|
||||
const struct kernel_symbol *gpl_future_syms;
|
||||
unsigned int num_gpl_future_syms;
|
||||
@ -456,6 +474,8 @@ void module_remove_driver(struct device_driver *);
|
||||
#define EXPORT_SYMBOL(sym)
|
||||
#define EXPORT_SYMBOL_GPL(sym)
|
||||
#define EXPORT_SYMBOL_GPL_FUTURE(sym)
|
||||
#define EXPORT_UNUSED_SYMBOL(sym)
|
||||
#define EXPORT_UNUSED_SYMBOL_GPL(sym)
|
||||
|
||||
/* Given an address, look for it in the exception tables. */
|
||||
static inline const struct exception_table_entry *
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Rewritten by Rusty Russell, on the backs of many others...
|
||||
/*
|
||||
Copyright (C) 2002 Richard Henderson
|
||||
Copyright (C) 2001 Rusty Russell, 2002 Rusty Russell IBM.
|
||||
|
||||
@ -122,9 +122,17 @@ extern const struct kernel_symbol __start___ksymtab_gpl[];
|
||||
extern const struct kernel_symbol __stop___ksymtab_gpl[];
|
||||
extern const struct kernel_symbol __start___ksymtab_gpl_future[];
|
||||
extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
|
||||
extern const struct kernel_symbol __start___ksymtab_unused[];
|
||||
extern const struct kernel_symbol __stop___ksymtab_unused[];
|
||||
extern const struct kernel_symbol __start___ksymtab_unused_gpl[];
|
||||
extern const struct kernel_symbol __stop___ksymtab_unused_gpl[];
|
||||
extern const struct kernel_symbol __start___ksymtab_gpl_future[];
|
||||
extern const struct kernel_symbol __stop___ksymtab_gpl_future[];
|
||||
extern const unsigned long __start___kcrctab[];
|
||||
extern const unsigned long __start___kcrctab_gpl[];
|
||||
extern const unsigned long __start___kcrctab_gpl_future[];
|
||||
extern const unsigned long __start___kcrctab_unused[];
|
||||
extern const unsigned long __start___kcrctab_unused_gpl[];
|
||||
|
||||
#ifndef CONFIG_MODVERSIONS
|
||||
#define symversion(base, idx) NULL
|
||||
@ -144,6 +152,17 @@ static const struct kernel_symbol *lookup_symbol(const char *name,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void printk_unused_warning(const char *name)
|
||||
{
|
||||
printk(KERN_WARNING "Symbol %s is marked as UNUSED, "
|
||||
"however this module is using it.\n", name);
|
||||
printk(KERN_WARNING "This symbol will go away in the future.\n");
|
||||
printk(KERN_WARNING "Please evalute if this is the right api to use, "
|
||||
"and if it really is, submit a report the linux kernel "
|
||||
"mailinglist together with submitting your code for "
|
||||
"inclusion.\n");
|
||||
}
|
||||
|
||||
/* Find a symbol, return value, crc and module which owns it */
|
||||
static unsigned long __find_symbol(const char *name,
|
||||
struct module **owner,
|
||||
@ -186,6 +205,25 @@ static unsigned long __find_symbol(const char *name,
|
||||
return ks->value;
|
||||
}
|
||||
|
||||
ks = lookup_symbol(name, __start___ksymtab_unused,
|
||||
__stop___ksymtab_unused);
|
||||
if (ks) {
|
||||
printk_unused_warning(name);
|
||||
*crc = symversion(__start___kcrctab_unused,
|
||||
(ks - __start___ksymtab_unused));
|
||||
return ks->value;
|
||||
}
|
||||
|
||||
if (gplok)
|
||||
ks = lookup_symbol(name, __start___ksymtab_unused_gpl,
|
||||
__stop___ksymtab_unused_gpl);
|
||||
if (ks) {
|
||||
printk_unused_warning(name);
|
||||
*crc = symversion(__start___kcrctab_unused_gpl,
|
||||
(ks - __start___ksymtab_unused_gpl));
|
||||
return ks->value;
|
||||
}
|
||||
|
||||
/* Now try modules. */
|
||||
list_for_each_entry(mod, &modules, list) {
|
||||
*owner = mod;
|
||||
@ -204,6 +242,23 @@ static unsigned long __find_symbol(const char *name,
|
||||
return ks->value;
|
||||
}
|
||||
}
|
||||
ks = lookup_symbol(name, mod->unused_syms, mod->unused_syms + mod->num_unused_syms);
|
||||
if (ks) {
|
||||
printk_unused_warning(name);
|
||||
*crc = symversion(mod->unused_crcs, (ks - mod->unused_syms));
|
||||
return ks->value;
|
||||
}
|
||||
|
||||
if (gplok) {
|
||||
ks = lookup_symbol(name, mod->unused_gpl_syms,
|
||||
mod->unused_gpl_syms + mod->num_unused_gpl_syms);
|
||||
if (ks) {
|
||||
printk_unused_warning(name);
|
||||
*crc = symversion(mod->unused_gpl_crcs,
|
||||
(ks - mod->unused_gpl_syms));
|
||||
return ks->value;
|
||||
}
|
||||
}
|
||||
ks = lookup_symbol(name, mod->gpl_future_syms,
|
||||
(mod->gpl_future_syms +
|
||||
mod->num_gpl_future_syms));
|
||||
@ -1407,6 +1462,8 @@ static struct module *load_module(void __user *umod,
|
||||
exportindex, modindex, obsparmindex, infoindex, gplindex,
|
||||
crcindex, gplcrcindex, versindex, pcpuindex, gplfutureindex,
|
||||
gplfuturecrcindex, unwindex = 0;
|
||||
unsigned int unusedindex, unusedcrcindex, unusedgplindex,
|
||||
unusedgplcrcindex;
|
||||
struct module *mod;
|
||||
long err = 0;
|
||||
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
|
||||
@ -1487,9 +1544,13 @@ static struct module *load_module(void __user *umod,
|
||||
exportindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab");
|
||||
gplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl");
|
||||
gplfutureindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_gpl_future");
|
||||
unusedindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused");
|
||||
unusedgplindex = find_sec(hdr, sechdrs, secstrings, "__ksymtab_unused_gpl");
|
||||
crcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab");
|
||||
gplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl");
|
||||
gplfuturecrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_gpl_future");
|
||||
unusedcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused");
|
||||
unusedgplcrcindex = find_sec(hdr, sechdrs, secstrings, "__kcrctab_unused_gpl");
|
||||
setupindex = find_sec(hdr, sechdrs, secstrings, "__param");
|
||||
exindex = find_sec(hdr, sechdrs, secstrings, "__ex_table");
|
||||
obsparmindex = find_sec(hdr, sechdrs, secstrings, "__obsparm");
|
||||
@ -1638,14 +1699,27 @@ static struct module *load_module(void __user *umod,
|
||||
mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;
|
||||
mod->num_gpl_future_syms = sechdrs[gplfutureindex].sh_size /
|
||||
sizeof(*mod->gpl_future_syms);
|
||||
mod->num_unused_syms = sechdrs[unusedindex].sh_size /
|
||||
sizeof(*mod->unused_syms);
|
||||
mod->num_unused_gpl_syms = sechdrs[unusedgplindex].sh_size /
|
||||
sizeof(*mod->unused_gpl_syms);
|
||||
mod->gpl_future_syms = (void *)sechdrs[gplfutureindex].sh_addr;
|
||||
if (gplfuturecrcindex)
|
||||
mod->gpl_future_crcs = (void *)sechdrs[gplfuturecrcindex].sh_addr;
|
||||
|
||||
mod->unused_syms = (void *)sechdrs[unusedindex].sh_addr;
|
||||
if (unusedcrcindex)
|
||||
mod->unused_crcs = (void *)sechdrs[unusedcrcindex].sh_addr;
|
||||
mod->unused_gpl_syms = (void *)sechdrs[unusedgplindex].sh_addr;
|
||||
if (unusedgplcrcindex)
|
||||
mod->unused_crcs = (void *)sechdrs[unusedgplcrcindex].sh_addr;
|
||||
|
||||
#ifdef CONFIG_MODVERSIONS
|
||||
if ((mod->num_syms && !crcindex) ||
|
||||
(mod->num_gpl_syms && !gplcrcindex) ||
|
||||
(mod->num_gpl_future_syms && !gplfuturecrcindex)) {
|
||||
(mod->num_gpl_future_syms && !gplfuturecrcindex) ||
|
||||
(mod->num_unused_syms && !unusedcrcindex) ||
|
||||
(mod->num_unused_gpl_syms && !unusedgplcrcindex)) {
|
||||
printk(KERN_WARNING "%s: No versions for exported symbols."
|
||||
" Tainting kernel.\n", mod->name);
|
||||
add_taint(TAINT_FORCED_MODULE);
|
||||
|
@ -23,6 +23,22 @@ config MAGIC_SYSRQ
|
||||
keys are documented in <file:Documentation/sysrq.txt>. Don't say Y
|
||||
unless you really know what this hack does.
|
||||
|
||||
config UNUSED_SYMBOLS
|
||||
bool "Enable unused/obsolete exported symbols"
|
||||
default y if X86
|
||||
help
|
||||
Unused but exported symbols make the kernel needlessly bigger. For
|
||||
that reason most of these unused exports will soon be removed. This
|
||||
option is provided temporarily to provide a transition period in case
|
||||
some external kernel module needs one of these symbols anyway. If you
|
||||
encounter such a case in your module, consider if you are actually
|
||||
using the right API. (rationale: since nobody in the kernel is using
|
||||
this in a module, there is a pretty good chance it's actually the
|
||||
wrong interface to use). If you really need the symbol, please send a
|
||||
mail to the linux kernel mailing list mentioning the symbol and why
|
||||
you really need it, and what the merge plan to the mainline kernel for
|
||||
your module is.
|
||||
|
||||
config DEBUG_KERNEL
|
||||
bool "Kernel debugging"
|
||||
help
|
||||
|
Loading…
Reference in New Issue
Block a user