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