module: Make find_symbol return a struct kernel_symbol

Impact: Cleanup, internal API change

Ksplice needs access to the kernel_symbol structure in order to support
modifications to the exported symbol table.

Cc: Anders Kaseorg <andersk@mit.edu>
Cc: Jeff Arnold <jbarnold@mit.edu>
Signed-off-by: Tim Abbott <tabbott@mit.edu>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au> (bugfix and style)
This commit is contained in:
Tim Abbott 2008-12-05 19:03:56 -05:00 committed by Rusty Russell
parent b10153fe31
commit 414fd31b25

View file

@ -283,7 +283,7 @@ struct find_symbol_arg {
/* Output */ /* Output */
struct module *owner; struct module *owner;
const unsigned long *crc; const unsigned long *crc;
unsigned long value; const struct kernel_symbol *sym;
}; };
static bool find_symbol_in_section(const struct symsearch *syms, static bool find_symbol_in_section(const struct symsearch *syms,
@ -324,17 +324,17 @@ static bool find_symbol_in_section(const struct symsearch *syms,
fsa->owner = owner; fsa->owner = owner;
fsa->crc = symversion(syms->crcs, symnum); fsa->crc = symversion(syms->crcs, symnum);
fsa->value = syms->start[symnum].value; fsa->sym = &syms->start[symnum];
return true; return true;
} }
/* Find a symbol, return value, (optional) crc and (optional) module /* Find a symbol and return it, along with, (optional) crc and
* which owns it */ * (optional) module which owns it */
static unsigned long find_symbol(const char *name, static const struct kernel_symbol *find_symbol(const char *name,
struct module **owner, struct module **owner,
const unsigned long **crc, const unsigned long **crc,
bool gplok, bool gplok,
bool warn) bool warn)
{ {
struct find_symbol_arg fsa; struct find_symbol_arg fsa;
@ -347,11 +347,11 @@ static unsigned long find_symbol(const char *name,
*owner = fsa.owner; *owner = fsa.owner;
if (crc) if (crc)
*crc = fsa.crc; *crc = fsa.crc;
return fsa.value; return fsa.sym;
} }
DEBUGP("Failed to find symbol %s\n", name); DEBUGP("Failed to find symbol %s\n", name);
return -ENOENT; return NULL;
} }
/* Search for module by name: must hold module_mutex. */ /* Search for module by name: must hold module_mutex. */
@ -894,7 +894,7 @@ void __symbol_put(const char *symbol)
struct module *owner; struct module *owner;
preempt_disable(); preempt_disable();
if (IS_ERR_VALUE(find_symbol(symbol, &owner, NULL, true, false))) if (!find_symbol(symbol, &owner, NULL, true, false))
BUG(); BUG();
module_put(owner); module_put(owner);
preempt_enable(); preempt_enable();
@ -1057,7 +1057,7 @@ static inline int check_modstruct_version(Elf_Shdr *sechdrs,
{ {
const unsigned long *crc; const unsigned long *crc;
if (IS_ERR_VALUE(find_symbol("struct_module", NULL, &crc, true, false))) if (!find_symbol("struct_module", NULL, &crc, true, false))
BUG(); BUG();
return check_version(sechdrs, versindex, "struct_module", mod, crc); return check_version(sechdrs, versindex, "struct_module", mod, crc);
} }
@ -1098,25 +1098,25 @@ static inline int same_magic(const char *amagic, const char *bmagic,
/* Resolve a symbol for this module. I.e. if we find one, record usage. /* Resolve a symbol for this module. I.e. if we find one, record usage.
Must be holding module_mutex. */ Must be holding module_mutex. */
static unsigned long resolve_symbol(Elf_Shdr *sechdrs, static const struct kernel_symbol *resolve_symbol(Elf_Shdr *sechdrs,
unsigned int versindex, unsigned int versindex,
const char *name, const char *name,
struct module *mod) struct module *mod)
{ {
struct module *owner; struct module *owner;
unsigned long ret; const struct kernel_symbol *sym;
const unsigned long *crc; const unsigned long *crc;
ret = find_symbol(name, &owner, &crc, sym = find_symbol(name, &owner, &crc,
!(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true); !(mod->taints & (1 << TAINT_PROPRIETARY_MODULE)), true);
if (!IS_ERR_VALUE(ret)) { /* use_module can fail due to OOM,
/* use_module can fail due to OOM, or module initialization or unloading */
or module initialization or unloading */ if (sym) {
if (!check_version(sechdrs, versindex, name, mod, crc) || if (!check_version(sechdrs, versindex, name, mod, crc) ||
!use_module(mod, owner)) !use_module(mod, owner))
ret = -EINVAL; sym = NULL;
} }
return ret; return sym;
} }
/* /*
@ -1516,17 +1516,15 @@ static void free_module(struct module *mod)
void *__symbol_get(const char *symbol) void *__symbol_get(const char *symbol)
{ {
struct module *owner; struct module *owner;
unsigned long value; const struct kernel_symbol *sym;
preempt_disable(); preempt_disable();
value = find_symbol(symbol, &owner, NULL, true, true); sym = find_symbol(symbol, &owner, NULL, true, true);
if (IS_ERR_VALUE(value)) if (sym && strong_try_module_get(owner))
value = 0; sym = NULL;
else if (strong_try_module_get(owner))
value = 0;
preempt_enable(); preempt_enable();
return (void *)value; return sym ? (void *)sym->value : NULL;
} }
EXPORT_SYMBOL_GPL(__symbol_get); EXPORT_SYMBOL_GPL(__symbol_get);
@ -1554,8 +1552,7 @@ static int verify_export_symbols(struct module *mod)
for (i = 0; i < ARRAY_SIZE(arr); i++) { for (i = 0; i < ARRAY_SIZE(arr); i++) {
for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) { for (s = arr[i].sym; s < arr[i].sym + arr[i].num; s++) {
if (!IS_ERR_VALUE(find_symbol(s->name, &owner, if (find_symbol(s->name, &owner, NULL, true, false)) {
NULL, true, false))) {
printk(KERN_ERR printk(KERN_ERR
"%s: exports duplicate symbol %s" "%s: exports duplicate symbol %s"
" (owned by %s)\n", " (owned by %s)\n",
@ -1579,6 +1576,7 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
unsigned long secbase; unsigned long secbase;
unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym); unsigned int i, n = sechdrs[symindex].sh_size / sizeof(Elf_Sym);
int ret = 0; int ret = 0;
const struct kernel_symbol *ksym;
for (i = 1; i < n; i++) { for (i = 1; i < n; i++) {
switch (sym[i].st_shndx) { switch (sym[i].st_shndx) {
@ -1598,13 +1596,14 @@ static int simplify_symbols(Elf_Shdr *sechdrs,
break; break;
case SHN_UNDEF: case SHN_UNDEF:
sym[i].st_value ksym = resolve_symbol(sechdrs, versindex,
= resolve_symbol(sechdrs, versindex, strtab + sym[i].st_name, mod);
strtab + sym[i].st_name, mod);
/* Ok if resolved. */ /* Ok if resolved. */
if (!IS_ERR_VALUE(sym[i].st_value)) if (ksym) {
sym[i].st_value = ksym->value;
break; break;
}
/* Ok if weak. */ /* Ok if weak. */
if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK) if (ELF_ST_BIND(sym[i].st_info) == STB_WEAK)
break; break;