module: Make find_symbol return a struct kernel_symbol
authorTim Abbott <tabbott@mit.edu>
Sat, 6 Dec 2008 00:03:56 +0000 (19:03 -0500)
committerRusty Russell <rusty@rustcorp.com.au>
Tue, 31 Mar 2009 02:35:31 +0000 (13:05 +1030)
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)
kernel/module.c

index 7af72bb..2f0fddf 100644 (file)
@@ -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;