15 #include <linux/module.h>
22 #include <linux/sched.h>
24 #include <linux/ctype.h>
25 #include <linux/slab.h>
27 #include <asm/sections.h>
29 #ifdef CONFIG_KALLSYMS_ALL
39 extern const unsigned long kallsyms_addresses[]
__attribute__((weak));
46 extern const unsigned long kallsyms_num_syms
52 extern const unsigned long kallsyms_markers[]
__attribute__((weak));
54 static inline int is_kernel_inittext(
unsigned long addr)
56 if (addr >= (
unsigned long)_sinittext
57 && addr <= (
unsigned long)_einittext)
62 static inline int is_kernel_text(
unsigned long addr)
64 if ((addr >= (
unsigned long)_stext && addr <= (
unsigned long)_etext) ||
70 static inline int is_kernel(
unsigned long addr)
72 if (addr >= (
unsigned long)_stext && addr <= (
unsigned long)_end)
77 static int is_ksym_addr(
unsigned long addr)
80 return is_kernel(addr);
82 return is_kernel_text(addr) || is_kernel_inittext(addr);
89 static unsigned int kallsyms_expand_symbol(
unsigned int off,
char *
result)
91 int len, skipped_first = 0;
95 data = &kallsyms_names[off];
110 tptr = &kallsyms_token_table[kallsyms_token_index[*
data]];
134 static char kallsyms_get_symbol_type(
unsigned int off)
140 return kallsyms_token_table[kallsyms_token_index[kallsyms_names[off + 1]]];
148 static unsigned int get_symbol_offset(
unsigned long pos)
157 name = &kallsyms_names[kallsyms_markers[pos >> 8]];
165 for (i = 0; i < (pos & 0xFF); i++)
166 name = name + (*name) + 1;
168 return name - kallsyms_names;
178 for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
179 off = kallsyms_expand_symbol(off, namebuf);
181 if (
strcmp(namebuf, name) == 0)
182 return kallsyms_addresses[
i];
184 return module_kallsyms_lookup_name(name);
197 for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
198 off = kallsyms_expand_symbol(off, namebuf);
199 ret =
fn(data, namebuf,
NULL, kallsyms_addresses[i]);
203 return module_kallsyms_on_each_symbol(
fn, data);
207 static unsigned long get_symbol_pos(
unsigned long addr,
208 unsigned long *symbolsize,
211 unsigned long symbol_start = 0, symbol_end = 0;
215 BUG_ON(!kallsyms_addresses);
219 high = kallsyms_num_syms;
221 while (high - low > 1) {
222 mid = low + (high -
low) / 2;
223 if (kallsyms_addresses[mid] <= addr)
233 while (low && kallsyms_addresses[low-1] == kallsyms_addresses[low])
236 symbol_start = kallsyms_addresses[
low];
239 for (i = low + 1; i < kallsyms_num_syms; i++) {
240 if (kallsyms_addresses[i] > symbol_start) {
241 symbol_end = kallsyms_addresses[
i];
248 if (is_kernel_inittext(addr))
251 symbol_end = (
unsigned long)_end;
253 symbol_end = (
unsigned long)_etext;
257 *symbolsize = symbol_end - symbol_start;
259 *offset = addr - symbol_start;
268 unsigned long *offset)
271 if (is_ksym_addr(addr))
272 return !!get_symbol_pos(addr, symbolsize, offset);
274 return !!module_address_lookup(addr, symbolsize, offset,
NULL, namebuf);
285 unsigned long *symbolsize,
286 unsigned long *offset,
292 if (is_ksym_addr(addr)) {
295 pos = get_symbol_pos(addr, symbolsize, offset);
297 kallsyms_expand_symbol(get_symbol_offset(pos), namebuf);
304 return module_address_lookup(addr, symbolsize, offset, modname,
313 if (is_ksym_addr(addr)) {
316 pos = get_symbol_pos(addr,
NULL,
NULL);
318 kallsyms_expand_symbol(get_symbol_offset(pos), symname);
322 return lookup_module_symbol_name(addr, symname);
326 unsigned long *offset,
char *
modname,
char *name)
331 if (is_ksym_addr(addr)) {
334 pos = get_symbol_pos(addr, size, offset);
336 kallsyms_expand_symbol(get_symbol_offset(pos), name);
341 return lookup_module_symbol_attrs(addr, size, offset, modname, name);
345 static int __sprint_symbol(
char *
buffer,
unsigned long address,
346 int symbol_offset,
int add_offset)
353 address += symbol_offset;
356 return sprintf(buffer,
"0x%lx", address);
361 offset -= symbol_offset;
364 len +=
sprintf(buffer + len,
"+%#lx/%#lx", offset, size);
367 len +=
sprintf(buffer + len,
" [%s]", modname);
385 return __sprint_symbol(buffer, address, 0, 1);
402 return __sprint_symbol(buffer, address, 0, 0);
422 return __sprint_symbol(buffer, address, -1, 1);
449 if (module_get_kallsym(iter->
pos - kallsyms_num_syms, &iter->
value,
457 static unsigned long get_ksymbol_core(
struct kallsym_iter *iter)
462 iter->
value = kallsyms_addresses[iter->
pos];
464 iter->
type = kallsyms_get_symbol_type(off);
466 off = kallsyms_expand_symbol(off, iter->
name);
471 static void reset_iter(
struct kallsym_iter *iter, loff_t new_pos)
473 iter->
name[0] =
'\0';
474 iter->
nameoff = get_symbol_offset(new_pos);
479 static int update_iter(
struct kallsym_iter *iter, loff_t pos)
482 if (pos >= kallsyms_num_syms) {
484 return get_ksymbol_mod(iter);
488 if (pos != iter->
pos)
489 reset_iter(iter, pos);
491 iter->
nameoff += get_ksymbol_core(iter);
497 static void *s_next(
struct seq_file *
m,
void *
p, loff_t *pos)
501 if (!update_iter(m->
private, *pos))
506 static void *s_start(
struct seq_file *m, loff_t *pos)
508 if (!update_iter(m->
private, *pos))
513 static void s_stop(
struct seq_file *m,
void *p)
517 static int s_show(
struct seq_file *m,
void *p)
572 #ifdef CONFIG_KGDB_KDB
573 const char *kdb_walk_kallsyms(loff_t *pos)
577 memset(&kdb_walk_kallsyms_iter, 0,
578 sizeof(kdb_walk_kallsyms_iter));
579 reset_iter(&kdb_walk_kallsyms_iter, 0);
582 if (!update_iter(&kdb_walk_kallsyms_iter, *pos))
586 if (kdb_walk_kallsyms_iter.name[0])
587 return kdb_walk_kallsyms_iter.name;
593 .open = kallsyms_open,
599 static int __init kallsyms_init(
void)
601 proc_create(
"kallsyms", 0444,
NULL, &kallsyms_operations);