Commit f46981b2 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Add kallsyms_lookupname()

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.
parent ef2dbb54
...@@ -8,6 +8,9 @@ ...@@ -8,6 +8,9 @@
#include <linux/config.h> #include <linux/config.h>
#ifdef CONFIG_KALLSYMS #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. */ /* Lookup an address. modname is set to NULL if it's in the kernel. */
const char *kallsyms_lookup(unsigned long addr, const char *kallsyms_lookup(unsigned long addr,
unsigned long *symbolsize, unsigned long *symbolsize,
...@@ -19,6 +22,11 @@ extern void __print_symbol(const char *fmt, unsigned long address); ...@@ -19,6 +22,11 @@ extern void __print_symbol(const char *fmt, unsigned long address);
#else /* !CONFIG_KALLSYMS */ #else /* !CONFIG_KALLSYMS */
static inline unsigned long kallsyms_lookup_name(const char *name)
{
return 0;
}
static inline const char *kallsyms_lookup(unsigned long addr, static inline const char *kallsyms_lookup(unsigned long addr,
unsigned long *symbolsize, unsigned long *symbolsize,
unsigned long *offset, unsigned long *offset,
......
...@@ -282,6 +282,10 @@ struct module *module_get_kallsym(unsigned int symnum, ...@@ -282,6 +282,10 @@ struct module *module_get_kallsym(unsigned int symnum,
unsigned long *value, unsigned long *value,
char *type, char *type,
char namebuf[128]); 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); int is_exported(const char *name, const struct module *mod);
extern void __module_put_and_exit(struct module *mod, long code) 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, ...@@ -434,6 +438,11 @@ static inline struct module *module_get_kallsym(unsigned int symnum,
return NULL; 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) static inline int is_exported(const char *name, const struct module *mod)
{ {
return 0; return 0;
......
...@@ -37,6 +37,25 @@ static inline int is_kernel_text(unsigned long addr) ...@@ -37,6 +37,25 @@ static inline int is_kernel_text(unsigned long addr)
return 0; 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. */ /* Lookup an address. modname is set to NULL if it's in the kernel. */
const char *kallsyms_lookup(unsigned long addr, const char *kallsyms_lookup(unsigned long addr,
unsigned long *symbolsize, unsigned long *symbolsize,
......
...@@ -1893,6 +1893,37 @@ struct module *module_get_kallsym(unsigned int symnum, ...@@ -1893,6 +1893,37 @@ struct module *module_get_kallsym(unsigned int symnum,
up(&module_mutex); up(&module_mutex);
return NULL; 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 */ #endif /* CONFIG_KALLSYMS */
/* Called by the /proc file system to return a list of modules. */ /* Called by the /proc file system to return a list of modules. */
......
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