Commit a5c43dae7ae38c2a6b3e9a819bcf45f010bf6a4a
Committed by
Linus Torvalds
1 parent
9d65cb4a17
Fix race between cat /proc/slab_allocators and rmmod
Same story as with cat /proc/*/wchan race vs rmmod race, only /proc/slab_allocators want more info than just symbol name. Signed-off-by: Alexey Dobriyan <adobriyan@sw.ru> Acked-by: Rusty Russell <rusty@rustcorp.com.au> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 5 changed files with 61 additions and 7 deletions Side-by-side Diff
include/linux/kallsyms.h
... | ... | @@ -31,6 +31,7 @@ |
31 | 31 | extern void __print_symbol(const char *fmt, unsigned long address); |
32 | 32 | |
33 | 33 | int lookup_symbol_name(unsigned long addr, char *symname); |
34 | +int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name); | |
34 | 35 | |
35 | 36 | #else /* !CONFIG_KALLSYMS */ |
36 | 37 | |
... | ... | @@ -61,6 +62,11 @@ |
61 | 62 | } |
62 | 63 | |
63 | 64 | static inline int lookup_symbol_name(unsigned long addr, char *symname) |
65 | +{ | |
66 | + return -ERANGE; | |
67 | +} | |
68 | + | |
69 | +static inline int lookup_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name) | |
64 | 70 | { |
65 | 71 | return -ERANGE; |
66 | 72 | } |
include/linux/module.h
... | ... | @@ -455,6 +455,7 @@ |
455 | 455 | unsigned long *offset, |
456 | 456 | char **modname); |
457 | 457 | int lookup_module_symbol_name(unsigned long addr, char *symname); |
458 | +int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name); | |
458 | 459 | |
459 | 460 | /* For extable.c to search modules' exception tables. */ |
460 | 461 | const struct exception_table_entry *search_module_extables(unsigned long addr); |
... | ... | @@ -527,6 +528,11 @@ |
527 | 528 | } |
528 | 529 | |
529 | 530 | static inline int lookup_module_symbol_name(unsigned long addr, char *symname) |
531 | +{ | |
532 | + return -ERANGE; | |
533 | +} | |
534 | + | |
535 | +static inline int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, unsigned long *offset, char *modname, char *name) | |
530 | 536 | { |
531 | 537 | return -ERANGE; |
532 | 538 | } |
kernel/kallsyms.c
... | ... | @@ -286,6 +286,25 @@ |
286 | 286 | return lookup_module_symbol_name(addr, symname); |
287 | 287 | } |
288 | 288 | |
289 | +int lookup_symbol_attrs(unsigned long addr, unsigned long *size, | |
290 | + unsigned long *offset, char *modname, char *name) | |
291 | +{ | |
292 | + name[0] = '\0'; | |
293 | + name[KSYM_NAME_LEN] = '\0'; | |
294 | + | |
295 | + if (is_ksym_addr(addr)) { | |
296 | + unsigned long pos; | |
297 | + | |
298 | + pos = get_symbol_pos(addr, size, offset); | |
299 | + /* Grab name */ | |
300 | + kallsyms_expand_symbol(get_symbol_offset(pos), name); | |
301 | + modname[0] = '\0'; | |
302 | + return 0; | |
303 | + } | |
304 | + /* see if it's in a module */ | |
305 | + return lookup_module_symbol_attrs(addr, size, offset, modname, name); | |
306 | +} | |
307 | + | |
289 | 308 | /* Look up a kernel symbol and return it in a text buffer. */ |
290 | 309 | int sprint_symbol(char *buffer, unsigned long address) |
291 | 310 | { |
kernel/module.c
... | ... | @@ -2149,6 +2149,33 @@ |
2149 | 2149 | return -ERANGE; |
2150 | 2150 | } |
2151 | 2151 | |
2152 | +int lookup_module_symbol_attrs(unsigned long addr, unsigned long *size, | |
2153 | + unsigned long *offset, char *modname, char *name) | |
2154 | +{ | |
2155 | + struct module *mod; | |
2156 | + | |
2157 | + mutex_lock(&module_mutex); | |
2158 | + list_for_each_entry(mod, &modules, list) { | |
2159 | + if (within(addr, mod->module_init, mod->init_size) || | |
2160 | + within(addr, mod->module_core, mod->core_size)) { | |
2161 | + const char *sym; | |
2162 | + | |
2163 | + sym = get_ksymbol(mod, addr, size, offset); | |
2164 | + if (!sym) | |
2165 | + goto out; | |
2166 | + if (modname) | |
2167 | + strlcpy(modname, mod->name, MODULE_NAME_LEN + 1); | |
2168 | + if (name) | |
2169 | + strlcpy(name, sym, KSYM_NAME_LEN + 1); | |
2170 | + mutex_unlock(&module_mutex); | |
2171 | + return 0; | |
2172 | + } | |
2173 | + } | |
2174 | +out: | |
2175 | + mutex_unlock(&module_mutex); | |
2176 | + return -ERANGE; | |
2177 | +} | |
2178 | + | |
2152 | 2179 | int module_get_kallsym(unsigned int symnum, unsigned long *value, char *type, |
2153 | 2180 | char *name, char *module_name, int *exported) |
2154 | 2181 | { |
mm/slab.c
... | ... | @@ -4432,16 +4432,12 @@ |
4432 | 4432 | static void show_symbol(struct seq_file *m, unsigned long address) |
4433 | 4433 | { |
4434 | 4434 | #ifdef CONFIG_KALLSYMS |
4435 | - char *modname; | |
4436 | - const char *name; | |
4437 | 4435 | unsigned long offset, size; |
4438 | - char namebuf[KSYM_NAME_LEN+1]; | |
4436 | + char modname[MODULE_NAME_LEN + 1], name[KSYM_NAME_LEN + 1]; | |
4439 | 4437 | |
4440 | - name = kallsyms_lookup(address, &size, &offset, &modname, namebuf); | |
4441 | - | |
4442 | - if (name) { | |
4438 | + if (lookup_symbol_attrs(address, &size, &offset, modname, name) == 0) { | |
4443 | 4439 | seq_printf(m, "%s+%#lx/%#lx", name, offset, size); |
4444 | - if (modname) | |
4440 | + if (modname[0]) | |
4445 | 4441 | seq_printf(m, " [%s]", modname); |
4446 | 4442 | return; |
4447 | 4443 | } |