]> git.hungrycats.org Git - linux/commitdiff
[PATCH] Add kallsyms_lookupname()
authorAndrew Morton <akpm@osdl.org>
Thu, 26 Feb 2004 14:44:18 +0000 (06:44 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 26 Feb 2004 14:44:18 +0000 (06:44 -0800)
From: Rusty Russell <rusty@au1.ibm.com>

Attached patch adds a kallsyms_lookupname() function for lookups of a
symbol name to an address.  Debuggers such as ppc[64] xmon can use this.

It's intentionally not exported as a symbol for module use, since it
can be used to circumvent other symbol export restrictions.

include/linux/kallsyms.h
include/linux/module.h
kernel/kallsyms.c
kernel/module.c

index d2a90b7766a1880ce81c7e88b961b3176a399d35..87b9bbbb485e0e67ef58b6804c9929056da55b03 100644 (file)
@@ -8,6 +8,9 @@
 #include <linux/config.h>
 
 #ifdef CONFIG_KALLSYMS
+/* Lookup the address for a symbol. Returns 0 if not found. */
+unsigned long kallsyms_lookup_name(const char *name);
+
 /* Lookup an address.  modname is set to NULL if it's in the kernel. */
 const char *kallsyms_lookup(unsigned long addr,
                            unsigned long *symbolsize,
@@ -19,6 +22,11 @@ extern void __print_symbol(const char *fmt, unsigned long address);
 
 #else /* !CONFIG_KALLSYMS */
 
+static inline unsigned long kallsyms_lookup_name(const char *name)
+{
+       return 0;
+}
+
 static inline const char *kallsyms_lookup(unsigned long addr,
                                          unsigned long *symbolsize,
                                          unsigned long *offset,
index 95cbc9b4936f0dae7e5202e19804eab045557da4..e01784890022ce4bfbbba17e316fad068446be30 100644 (file)
@@ -282,6 +282,10 @@ struct module *module_get_kallsym(unsigned int symnum,
                                  unsigned long *value,
                                  char *type,
                                  char namebuf[128]);
+
+/* Look for this name: can be of form module:name. */
+unsigned long module_kallsyms_lookup_name(const char *name);
+
 int is_exported(const char *name, const struct module *mod);
 
 extern void __module_put_and_exit(struct module *mod, long code)
@@ -434,6 +438,11 @@ static inline struct module *module_get_kallsym(unsigned int symnum,
        return NULL;
 }
 
+static inline unsigned long module_kallsyms_lookup_name(const char *name)
+{
+       return 0;
+}
+
 static inline int is_exported(const char *name, const struct module *mod)
 {
        return 0;
index 9b8903267a3e327276fbf794718672c391d9372d..ab39819f0e342c9df9c8c0ba264487513d0e0af6 100644 (file)
@@ -37,6 +37,25 @@ static inline int is_kernel_text(unsigned long addr)
        return 0;
 }
 
+/* Lookup the address for this symbol. Returns 0 if not found. */
+unsigned long kallsyms_lookup_name(const char *name)
+{
+       char namebuf[128];
+       unsigned long i;
+       char *knames;
+
+       for (i = 0, knames = kallsyms_names; i < kallsyms_num_syms; i++) {
+               unsigned prefix = *knames++;
+
+               strlcpy(namebuf + prefix, knames, 127 - prefix);
+               if (strcmp(namebuf, name) == 0)
+                       return kallsyms_addresses[i];
+
+               knames += strlen(knames) + 1;
+       }
+       return module_kallsyms_lookup_name(name);
+}
+
 /* Lookup an address.  modname is set to NULL if it's in the kernel. */
 const char *kallsyms_lookup(unsigned long addr,
                            unsigned long *symbolsize,
index 50746c0305067472b9cb4d7ebc48be30dc5b4623..853f5818761eaa48be04c34d7c85f5705aefd506 100644 (file)
@@ -1893,6 +1893,37 @@ struct module *module_get_kallsym(unsigned int symnum,
        up(&module_mutex);
        return NULL;
 }
+
+static unsigned long mod_find_symname(struct module *mod, const char *name)
+{
+       unsigned int i;
+
+       for (i = 0; i < mod->num_symtab; i++)
+               if (strcmp(name, mod->strtab+mod->symtab[i].st_name) == 0)
+                       return mod->symtab[i].st_value;
+       return 0;
+}
+
+/* Look for this name: can be of form module:name. */
+unsigned long module_kallsyms_lookup_name(const char *name)
+{
+       struct module *mod;
+       char *colon;
+       unsigned long ret = 0;
+
+       /* Don't lock: we're in enough trouble already. */
+       if ((colon = strchr(name, ':')) != NULL) {
+               *colon = '\0';
+               if ((mod = find_module(name)) != NULL)
+                       ret = mod_find_symname(mod, colon+1);
+               *colon = ':';
+       } else {
+               list_for_each_entry(mod, &modules, list)
+                       if ((ret = mod_find_symname(mod, name)) != 0)
+                               break;
+       }
+       return ret;
+}
 #endif /* CONFIG_KALLSYMS */
 
 /* Called by the /proc file system to return a list of modules. */