Commit 265300c6 authored by Rusty Russell's avatar Rusty Russell Committed by Linus Torvalds

[PATCH] Symbol list removal

This removes the symbol list, and the concept of kernel symbol groups,
in favour of just iterating through the modules.  Now all iteration is
within kernel/module.c, this is a fairly trivial cleanup.
parent 72ea6af5
...@@ -111,22 +111,6 @@ extern const struct gtype##_id __mod_##gtype##_table \ ...@@ -111,22 +111,6 @@ extern const struct gtype##_id __mod_##gtype##_table \
#define MODULE_DEVICE_TABLE(type,name) \ #define MODULE_DEVICE_TABLE(type,name) \
MODULE_GENERIC_TABLE(type##_device,name) MODULE_GENERIC_TABLE(type##_device,name)
struct kernel_symbol_group
{
/* Links us into the global symbol list */
struct list_head list;
/* Module which owns it (if any) */
struct module *owner;
/* Are we internal use only? */
int gplonly;
unsigned int num_syms;
const struct kernel_symbol *syms;
const unsigned long *crcs;
};
/* Given an address, look for it in the exception tables */ /* Given an address, look for it in the exception tables */
const struct exception_table_entry *search_exception_tables(unsigned long add); const struct exception_table_entry *search_exception_tables(unsigned long add);
...@@ -204,10 +188,14 @@ struct module ...@@ -204,10 +188,14 @@ struct module
char name[MODULE_NAME_LEN]; char name[MODULE_NAME_LEN];
/* Exported symbols */ /* Exported symbols */
struct kernel_symbol_group symbols; const struct kernel_symbol *syms;
unsigned int num_ksyms;
const unsigned long *crcs;
/* GPL-only exported symbols. */ /* GPL-only exported symbols. */
struct kernel_symbol_group gpl_symbols; const struct kernel_symbol *gpl_syms;
unsigned int num_gpl_syms;
const unsigned long *gpl_crcs;
/* Exception tables */ /* Exception tables */
struct exception_table extable; struct exception_table extable;
...@@ -401,8 +389,6 @@ extern struct module __this_module; ...@@ -401,8 +389,6 @@ extern struct module __this_module;
struct module __this_module struct module __this_module
__attribute__((section(".gnu.linkonce.this_module"))) = { __attribute__((section(".gnu.linkonce.this_module"))) = {
.name = __stringify(KBUILD_MODNAME), .name = __stringify(KBUILD_MODNAME),
.symbols = { .owner = &__this_module },
.gpl_symbols = { .owner = &__this_module, .gplonly = 1 },
.init = init_module, .init = init_module,
#ifdef CONFIG_MODULE_UNLOAD #ifdef CONFIG_MODULE_UNLOAD
.exit = cleanup_module, .exit = cleanup_module,
...@@ -454,14 +440,6 @@ static inline void __deprecated MOD_DEC_USE_COUNT(struct module *module) ...@@ -454,14 +440,6 @@ static inline void __deprecated MOD_DEC_USE_COUNT(struct module *module)
#define __MODULE_STRING(x) __stringify(x) #define __MODULE_STRING(x) __stringify(x)
/*
* The exception and symbol tables, and the lock
* to protect them.
*/
extern spinlock_t modlist_lock;
extern struct list_head extables;
extern struct list_head symbols;
/* Use symbol_get and symbol_put instead. You'll thank me. */ /* Use symbol_get and symbol_put instead. You'll thank me. */
#define HAVE_INTER_MODULE #define HAVE_INTER_MODULE
extern void inter_module_register(const char *, struct module *, const void *); extern void inter_module_register(const char *, struct module *, const void *);
......
...@@ -58,7 +58,6 @@ static spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED; ...@@ -58,7 +58,6 @@ static spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;
/* List of modules, protected by module_mutex AND modlist_lock */ /* List of modules, protected by module_mutex AND modlist_lock */
static DECLARE_MUTEX(module_mutex); static DECLARE_MUTEX(module_mutex);
static LIST_HEAD(modules); static LIST_HEAD(modules);
static LIST_HEAD(symbols);
static LIST_HEAD(extables); static LIST_HEAD(extables);
/* We require a truly strong try_module_get() */ /* We require a truly strong try_module_get() */
...@@ -92,25 +91,60 @@ static unsigned int find_sec(Elf_Ehdr *hdr, ...@@ -92,25 +91,60 @@ static unsigned int find_sec(Elf_Ehdr *hdr,
return 0; return 0;
} }
/* Find a symbol, return value and the symbol group */ /* Provided by the linker */
extern const struct kernel_symbol __start___ksymtab[];
extern const struct kernel_symbol __stop___ksymtab[];
extern const struct kernel_symbol __start___ksymtab_gpl[];
extern const struct kernel_symbol __stop___ksymtab_gpl[];
extern const unsigned long __start___kcrctab[];
extern const unsigned long __start___kcrctab_gpl[];
#ifndef CONFIG_MODVERSIONS
#define symversion(base, idx) NULL
#else
#define symversion(base, idx) ((base) ? ((base) + (idx)) : NULL)
#endif
/* Find a symbol, return value, crc and module which owns it */
static unsigned long __find_symbol(const char *name, static unsigned long __find_symbol(const char *name,
struct kernel_symbol_group **group, struct module **owner,
unsigned int *symidx, const unsigned long **crc,
int gplok) int gplok)
{ {
struct kernel_symbol_group *ks; struct module *mod;
list_for_each_entry(ks, &symbols, list) {
unsigned int i; unsigned int i;
if (ks->gplonly && !gplok) /* Core kernel first. */
continue; *owner = NULL;
for (i = 0; i < ks->num_syms; i++) { for (i = 0; __start___ksymtab+i < __stop___ksymtab; i++) {
if (strcmp(ks->syms[i].name, name) == 0) { if (strcmp(__start___ksymtab[i].name, name) == 0) {
*group = ks; *crc = symversion(__start___kcrctab, i);
if (symidx) return __start___ksymtab[i].value;
*symidx = i; }
return ks->syms[i].value; }
if (gplok) {
for (i = 0; __start___ksymtab_gpl+i<__stop___ksymtab_gpl; i++)
if (strcmp(__start___ksymtab_gpl[i].name, name) == 0) {
*crc = symversion(__start___kcrctab_gpl, i);
return __start___ksymtab_gpl[i].value;
}
}
/* Now try modules. */
list_for_each_entry(mod, &modules, list) {
*owner = mod;
for (i = 0; i < mod->num_ksyms; i++)
if (strcmp(mod->syms[i].name, name) == 0) {
*crc = symversion(mod->crcs, i);
return mod->syms[i].value;
}
if (gplok) {
for (i = 0; i < mod->num_gpl_syms; i++) {
if (strcmp(mod->gpl_syms[i].name, name) == 0) {
*crc = symversion(mod->crcs, i);
return mod->gpl_syms[i].value;
}
} }
} }
} }
...@@ -539,13 +573,14 @@ static void print_unload_info(struct seq_file *m, struct module *mod) ...@@ -539,13 +573,14 @@ static void print_unload_info(struct seq_file *m, struct module *mod)
void __symbol_put(const char *symbol) void __symbol_put(const char *symbol)
{ {
struct kernel_symbol_group *ksg; struct module *owner;
unsigned long flags; unsigned long flags;
const unsigned long *crc;
spin_lock_irqsave(&modlist_lock, flags); spin_lock_irqsave(&modlist_lock, flags);
if (!__find_symbol(symbol, &ksg, NULL, 1)) if (!__find_symbol(symbol, &owner, &crc, 1))
BUG(); BUG();
module_put(ksg->owner); module_put(owner);
spin_unlock_irqrestore(&modlist_lock, flags); spin_unlock_irqrestore(&modlist_lock, flags);
} }
EXPORT_SYMBOL(__symbol_put); EXPORT_SYMBOL(__symbol_put);
...@@ -743,19 +778,15 @@ static int check_version(Elf_Shdr *sechdrs, ...@@ -743,19 +778,15 @@ static int check_version(Elf_Shdr *sechdrs,
unsigned int versindex, unsigned int versindex,
const char *symname, const char *symname,
struct module *mod, struct module *mod,
struct kernel_symbol_group *ksg, const unsigned long *crc)
unsigned int symidx)
{ {
unsigned long crc;
unsigned int i, num_versions; unsigned int i, num_versions;
struct modversion_info *versions; struct modversion_info *versions;
/* Exporting module didn't supply crcs? OK, we're already tainted. */ /* Exporting module didn't supply crcs? OK, we're already tainted. */
if (!ksg->crcs) if (!crc)
return 1; return 1;
crc = ksg->crcs[symidx];
versions = (void *) sechdrs[versindex].sh_addr; versions = (void *) sechdrs[versindex].sh_addr;
num_versions = sechdrs[versindex].sh_size num_versions = sechdrs[versindex].sh_size
/ sizeof(struct modversion_info); / sizeof(struct modversion_info);
...@@ -764,12 +795,12 @@ static int check_version(Elf_Shdr *sechdrs, ...@@ -764,12 +795,12 @@ static int check_version(Elf_Shdr *sechdrs,
if (strcmp(versions[i].name, symname) != 0) if (strcmp(versions[i].name, symname) != 0)
continue; continue;
if (versions[i].crc == crc) if (versions[i].crc == *crc)
return 1; return 1;
printk("%s: disagrees about version of symbol %s\n", printk("%s: disagrees about version of symbol %s\n",
mod->name, symname); mod->name, symname);
DEBUGP("Found checksum %lX vs module %lX\n", DEBUGP("Found checksum %lX vs module %lX\n",
crc, versions[i].crc); *crc, versions[i].crc);
return 0; return 0;
} }
/* Not in module's version table. OK, but that taints the kernel. */ /* Not in module's version table. OK, but that taints the kernel. */
...@@ -805,8 +836,7 @@ static inline int check_version(Elf_Shdr *sechdrs, ...@@ -805,8 +836,7 @@ static inline int check_version(Elf_Shdr *sechdrs,
unsigned int versindex, unsigned int versindex,
const char *symname, const char *symname,
struct module *mod, struct module *mod,
struct kernel_symbol_group *ksg, const unsigned long *crc)
unsigned int symidx)
{ {
return 1; return 1;
} }
...@@ -831,17 +861,16 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs, ...@@ -831,17 +861,16 @@ static unsigned long resolve_symbol(Elf_Shdr *sechdrs,
const char *name, const char *name,
struct module *mod) struct module *mod)
{ {
struct kernel_symbol_group *ksg; struct module *owner;
unsigned long ret; unsigned long ret;
unsigned int symidx; const unsigned long *crc;
spin_lock_irq(&modlist_lock); spin_lock_irq(&modlist_lock);
ret = __find_symbol(name, &ksg, &symidx, mod->license_gplok); ret = __find_symbol(name, &owner, &crc, mod->license_gplok);
if (ret) { if (ret) {
/* use_module can fail due to OOM, or module unloading */ /* use_module can fail due to OOM, or module unloading */
if (!check_version(sechdrs, versindex, name, mod, if (!check_version(sechdrs, versindex, name, mod, crc) ||
ksg, symidx) || !use_module(mod, owner))
!use_module(mod, ksg->owner))
ret = 0; ret = 0;
} }
spin_unlock_irq(&modlist_lock); spin_unlock_irq(&modlist_lock);
...@@ -854,8 +883,6 @@ static void free_module(struct module *mod) ...@@ -854,8 +883,6 @@ static void free_module(struct module *mod)
/* Delete from various lists */ /* Delete from various lists */
spin_lock_irq(&modlist_lock); spin_lock_irq(&modlist_lock);
list_del(&mod->list); list_del(&mod->list);
list_del(&mod->symbols.list);
list_del(&mod->gpl_symbols.list);
list_del(&mod->extable.list); list_del(&mod->extable.list);
spin_unlock_irq(&modlist_lock); spin_unlock_irq(&modlist_lock);
...@@ -872,12 +899,13 @@ static void free_module(struct module *mod) ...@@ -872,12 +899,13 @@ static void free_module(struct module *mod)
void *__symbol_get(const char *symbol) void *__symbol_get(const char *symbol)
{ {
struct kernel_symbol_group *ksg; struct module *owner;
unsigned long value, flags; unsigned long value, flags;
const unsigned long *crc;
spin_lock_irqsave(&modlist_lock, flags); spin_lock_irqsave(&modlist_lock, flags);
value = __find_symbol(symbol, &ksg, NULL, 1); value = __find_symbol(symbol, &owner, &crc, 1);
if (value && !strong_try_module_get(ksg->owner)) if (value && !strong_try_module_get(owner))
value = 0; value = 0;
spin_unlock_irqrestore(&modlist_lock, flags); spin_unlock_irqrestore(&modlist_lock, flags);
...@@ -1223,21 +1251,17 @@ static struct module *load_module(void *umod, ...@@ -1223,21 +1251,17 @@ static struct module *load_module(void *umod,
goto cleanup; goto cleanup;
/* Set up EXPORTed & EXPORT_GPLed symbols (section 0 is 0 length) */ /* Set up EXPORTed & EXPORT_GPLed symbols (section 0 is 0 length) */
mod->symbols.num_syms = (sechdrs[exportindex].sh_size mod->num_syms = sechdrs[exportindex].sh_size / sizeof(*mod->syms);
/ sizeof(*mod->symbols.syms)); mod->syms = (void *)sechdrs[exportindex].sh_addr;
mod->symbols.syms = (void *)sechdrs[exportindex].sh_addr;
if (crcindex) if (crcindex)
mod->symbols.crcs = (void *)sechdrs[crcindex].sh_addr; mod->crcs = (void *)sechdrs[crcindex].sh_addr;
mod->num_gpl_syms = sechdrs[gplindex].sh_size / sizeof(*mod->gpl_syms);
mod->gpl_symbols.num_syms = (sechdrs[gplindex].sh_size mod->gpl_syms = (void *)sechdrs[gplindex].sh_addr;
/ sizeof(*mod->symbols.syms));
mod->gpl_symbols.syms = (void *)sechdrs[gplindex].sh_addr;
if (gplcrcindex) if (gplcrcindex)
mod->gpl_symbols.crcs = (void *)sechdrs[gplcrcindex].sh_addr; mod->gpl_crcs = (void *)sechdrs[gplcrcindex].sh_addr;
#ifdef CONFIG_MODVERSIONS #ifdef CONFIG_MODVERSIONS
if ((mod->symbols.num_syms && !crcindex) if ((mod->num_ksyms&&!crcindex) || (mod->num_gpl_syms&&!gplcrcindex)) {
|| (mod->gpl_symbols.num_syms && !gplcrcindex)) {
printk(KERN_WARNING "%s: No versions for exported symbols." printk(KERN_WARNING "%s: No versions for exported symbols."
" Tainting kernel.\n", mod->name); " Tainting kernel.\n", mod->name);
tainted |= TAINT_FORCED_MODULE; tainted |= TAINT_FORCED_MODULE;
...@@ -1351,8 +1375,6 @@ sys_init_module(void *umod, ...@@ -1351,8 +1375,6 @@ sys_init_module(void *umod,
strong_try_module_get() will fail. */ strong_try_module_get() will fail. */
spin_lock_irq(&modlist_lock); spin_lock_irq(&modlist_lock);
list_add(&mod->extable.list, &extables); list_add(&mod->extable.list, &extables);
list_add_tail(&mod->symbols.list, &symbols);
list_add_tail(&mod->gpl_symbols.list, &symbols);
list_add(&mod->list, &modules); list_add(&mod->list, &modules);
spin_unlock_irq(&modlist_lock); spin_unlock_irq(&modlist_lock);
...@@ -1547,39 +1569,6 @@ struct module *module_text_address(unsigned long addr) ...@@ -1547,39 +1569,6 @@ struct module *module_text_address(unsigned long addr)
return NULL; return NULL;
} }
/* Provided by the linker */
extern const struct kernel_symbol __start___ksymtab[];
extern const struct kernel_symbol __stop___ksymtab[];
extern const struct kernel_symbol __start___ksymtab_gpl[];
extern const struct kernel_symbol __stop___ksymtab_gpl[];
extern const unsigned long __start___kcrctab[];
extern const unsigned long __stop___kcrctab[];
extern const unsigned long __start___kcrctab_gpl[];
extern const unsigned long __stop___kcrctab_gpl[];
static struct kernel_symbol_group kernel_symbols, kernel_gpl_symbols;
static int __init symbols_init(void)
{
/* Add kernel symbols to symbol table */
kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab);
kernel_symbols.syms = __start___ksymtab;
kernel_symbols.crcs = __start___kcrctab;
kernel_symbols.gplonly = 0;
list_add(&kernel_symbols.list, &symbols);
kernel_gpl_symbols.num_syms = (__stop___ksymtab_gpl
- __start___ksymtab_gpl);
kernel_gpl_symbols.syms = __start___ksymtab_gpl;
kernel_gpl_symbols.crcs = __start___kcrctab_gpl;
kernel_gpl_symbols.gplonly = 1;
list_add(&kernel_gpl_symbols.list, &symbols);
return 0;
}
__initcall(symbols_init);
#ifdef CONFIG_MODVERSIONS #ifdef CONFIG_MODVERSIONS
/* Generate the signature for struct module here, too, for modversions. */ /* Generate the signature for struct module here, too, for modversions. */
void struct_module(struct module *mod) { return; } void struct_module(struct module *mod) { return; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment