]> git.karo-electronics.de Git - karo-tx-linux.git/blob - kernel/kallsyms.c
10a8af9d574447b6608758c7a61d228f32ff34ab
[karo-tx-linux.git] / kernel / kallsyms.c
1 /*
2  * kallsyms.c: in-kernel printing of symbolic oopses and stack traces.
3  *
4  * Rewritten and vastly simplified by Rusty Russell for in-kernel
5  * module loader:
6  *   Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
7  *
8  * ChangeLog:
9  *
10  * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com>
11  *      Changed the compression method from stem compression to "table lookup"
12  *      compression (see scripts/kallsyms.c for a more complete description)
13  */
14 #include <linux/kallsyms.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17 #include <linux/seq_file.h>
18 #include <linux/fs.h>
19 #include <linux/kdb.h>
20 #include <linux/err.h>
21 #include <linux/proc_fs.h>
22 #include <linux/sched.h>        /* for cond_resched */
23 #include <linux/mm.h>
24 #include <linux/ctype.h>
25 #include <linux/slab.h>
26 #include <linux/compiler.h>
27
28 #include <asm/sections.h>
29
30 #ifdef CONFIG_KALLSYMS_ALL
31 #define all_var 1
32 #else
33 #define all_var 0
34 #endif
35
36 /*
37  * These will be re-linked against their real values
38  * during the second link stage.
39  */
40 extern const unsigned long kallsyms_addresses[] __weak;
41 extern const int kallsyms_offsets[] __weak;
42 extern const u8 kallsyms_names[] __weak;
43
44 /*
45  * Tell the compiler that the count isn't in the small data section if the arch
46  * has one (eg: FRV).
47  */
48 extern const unsigned long kallsyms_num_syms
49 __attribute__((weak, section(".rodata")));
50
51 extern const unsigned long kallsyms_relative_base
52 __attribute__((weak, section(".rodata")));
53
54 extern const u8 kallsyms_token_table[] __weak;
55 extern const u16 kallsyms_token_index[] __weak;
56
57 extern const unsigned long kallsyms_markers[] __weak;
58
59 static inline int is_kernel_inittext(unsigned long addr)
60 {
61         if (addr >= (unsigned long)_sinittext
62             && addr <= (unsigned long)_einittext)
63                 return 1;
64         return 0;
65 }
66
67 static inline int is_kernel_text(unsigned long addr)
68 {
69         if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) ||
70             arch_is_kernel_text(addr))
71                 return 1;
72         return in_gate_area_no_mm(addr);
73 }
74
75 static inline int is_kernel(unsigned long addr)
76 {
77         if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
78                 return 1;
79         return in_gate_area_no_mm(addr);
80 }
81
82 static int is_ksym_addr(unsigned long addr)
83 {
84         if (all_var)
85                 return is_kernel(addr);
86
87         return is_kernel_text(addr) || is_kernel_inittext(addr);
88 }
89
90 /*
91  * Expand a compressed symbol data into the resulting uncompressed string,
92  * if uncompressed string is too long (>= maxlen), it will be truncated,
93  * given the offset to where the symbol is in the compressed stream.
94  */
95 static unsigned int kallsyms_expand_symbol(unsigned int off,
96                                            char *result, size_t maxlen)
97 {
98         int len, skipped_first = 0;
99         const u8 *tptr, *data;
100
101         /* Get the compressed symbol length from the first symbol byte. */
102         data = &kallsyms_names[off];
103         len = *data;
104         data++;
105
106         /*
107          * Update the offset to return the offset for the next symbol on
108          * the compressed stream.
109          */
110         off += len + 1;
111
112         /*
113          * For every byte on the compressed symbol data, copy the table
114          * entry for that byte.
115          */
116         while (len) {
117                 tptr = &kallsyms_token_table[kallsyms_token_index[*data]];
118                 data++;
119                 len--;
120
121                 while (*tptr) {
122                         if (skipped_first) {
123                                 if (maxlen <= 1)
124                                         goto tail;
125                                 *result = *tptr;
126                                 result++;
127                                 maxlen--;
128                         } else
129                                 skipped_first = 1;
130                         tptr++;
131                 }
132         }
133
134 tail:
135         if (maxlen)
136                 *result = '\0';
137
138         /* Return to offset to the next symbol. */
139         return off;
140 }
141
142 /*
143  * Get symbol type information. This is encoded as a single char at the
144  * beginning of the symbol name.
145  */
146 static char kallsyms_get_symbol_type(unsigned int off)
147 {
148         /*
149          * Get just the first code, look it up in the token table,
150          * and return the first char from this token.
151          */
152         return kallsyms_token_table[kallsyms_token_index[kallsyms_names[off + 1]]];
153 }
154
155
156 /*
157  * Find the offset on the compressed stream given and index in the
158  * kallsyms array.
159  */
160 static unsigned int get_symbol_offset(unsigned long pos)
161 {
162         const u8 *name;
163         int i;
164
165         /*
166          * Use the closest marker we have. We have markers every 256 positions,
167          * so that should be close enough.
168          */
169         name = &kallsyms_names[kallsyms_markers[pos >> 8]];
170
171         /*
172          * Sequentially scan all the symbols up to the point we're searching
173          * for. Every symbol is stored in a [<len>][<len> bytes of data] format,
174          * so we just need to add the len to the current pointer for every
175          * symbol we wish to skip.
176          */
177         for (i = 0; i < (pos & 0xFF); i++)
178                 name = name + (*name) + 1;
179
180         return name - kallsyms_names;
181 }
182
183 static unsigned long kallsyms_sym_address(int idx)
184 {
185         if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
186                 return kallsyms_addresses[idx];
187
188         /* positive offsets are absolute values */
189         if (kallsyms_offsets[idx] >= 0)
190                 return kallsyms_offsets[idx];
191
192         /* negative offsets are relative to kallsyms_relative_base - 1 */
193         return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
194 }
195
196 /* Lookup the address for this symbol. Returns 0 if not found. */
197 unsigned long kallsyms_lookup_name(const char *name)
198 {
199         char namebuf[KSYM_NAME_LEN];
200         unsigned long i;
201         unsigned int off;
202
203         for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
204                 off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
205
206                 if (strcmp(namebuf, name) == 0)
207                         return kallsyms_sym_address(i);
208         }
209         return module_kallsyms_lookup_name(name);
210 }
211 EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
212
213 int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
214                                       unsigned long),
215                             void *data)
216 {
217         char namebuf[KSYM_NAME_LEN];
218         unsigned long i;
219         unsigned int off;
220         int ret;
221
222         for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
223                 off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
224                 ret = fn(data, namebuf, NULL, kallsyms_sym_address(i));
225                 if (ret != 0)
226                         return ret;
227         }
228         return module_kallsyms_on_each_symbol(fn, data);
229 }
230 EXPORT_SYMBOL_GPL(kallsyms_on_each_symbol);
231
232 static unsigned long get_symbol_pos(unsigned long addr,
233                                     unsigned long *symbolsize,
234                                     unsigned long *offset)
235 {
236         unsigned long symbol_start = 0, symbol_end = 0;
237         unsigned long i, low, high, mid;
238
239         /* This kernel should never had been booted. */
240         if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
241                 BUG_ON(!kallsyms_addresses);
242         else
243                 BUG_ON(!kallsyms_offsets);
244
245         /* Do a binary search on the sorted kallsyms_addresses array. */
246         low = 0;
247         high = kallsyms_num_syms;
248
249         while (high - low > 1) {
250                 mid = low + (high - low) / 2;
251                 if (kallsyms_sym_address(mid) <= addr)
252                         low = mid;
253                 else
254                         high = mid;
255         }
256
257         /*
258          * Search for the first aliased symbol. Aliased
259          * symbols are symbols with the same address.
260          */
261         while (low && kallsyms_sym_address(low-1) == kallsyms_sym_address(low))
262                 --low;
263
264         symbol_start = kallsyms_sym_address(low);
265
266         /* Search for next non-aliased symbol. */
267         for (i = low + 1; i < kallsyms_num_syms; i++) {
268                 if (kallsyms_sym_address(i) > symbol_start) {
269                         symbol_end = kallsyms_sym_address(i);
270                         break;
271                 }
272         }
273
274         /* If we found no next symbol, we use the end of the section. */
275         if (!symbol_end) {
276                 if (is_kernel_inittext(addr))
277                         symbol_end = (unsigned long)_einittext;
278                 else if (all_var)
279                         symbol_end = (unsigned long)_end;
280                 else
281                         symbol_end = (unsigned long)_etext;
282         }
283
284         if (symbolsize)
285                 *symbolsize = symbol_end - symbol_start;
286         if (offset)
287                 *offset = addr - symbol_start;
288
289         return low;
290 }
291
292 /*
293  * Lookup an address but don't bother to find any names.
294  */
295 int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
296                                 unsigned long *offset)
297 {
298         char namebuf[KSYM_NAME_LEN];
299         if (is_ksym_addr(addr))
300                 return !!get_symbol_pos(addr, symbolsize, offset);
301
302         return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf);
303 }
304
305 /*
306  * Lookup an address
307  * - modname is set to NULL if it's in the kernel.
308  * - We guarantee that the returned name is valid until we reschedule even if.
309  *   It resides in a module.
310  * - We also guarantee that modname will be valid until rescheduled.
311  */
312 const char *kallsyms_lookup(unsigned long addr,
313                             unsigned long *symbolsize,
314                             unsigned long *offset,
315                             char **modname, char *namebuf)
316 {
317         namebuf[KSYM_NAME_LEN - 1] = 0;
318         namebuf[0] = 0;
319
320         if (is_ksym_addr(addr)) {
321                 unsigned long pos;
322
323                 pos = get_symbol_pos(addr, symbolsize, offset);
324                 /* Grab name */
325                 kallsyms_expand_symbol(get_symbol_offset(pos),
326                                        namebuf, KSYM_NAME_LEN);
327                 if (modname)
328                         *modname = NULL;
329                 return namebuf;
330         }
331
332         /* See if it's in a module. */
333         return module_address_lookup(addr, symbolsize, offset, modname,
334                                      namebuf);
335 }
336
337 int lookup_symbol_name(unsigned long addr, char *symname)
338 {
339         symname[0] = '\0';
340         symname[KSYM_NAME_LEN - 1] = '\0';
341
342         if (is_ksym_addr(addr)) {
343                 unsigned long pos;
344
345                 pos = get_symbol_pos(addr, NULL, NULL);
346                 /* Grab name */
347                 kallsyms_expand_symbol(get_symbol_offset(pos),
348                                        symname, KSYM_NAME_LEN);
349                 return 0;
350         }
351         /* See if it's in a module. */
352         return lookup_module_symbol_name(addr, symname);
353 }
354
355 int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
356                         unsigned long *offset, char *modname, char *name)
357 {
358         name[0] = '\0';
359         name[KSYM_NAME_LEN - 1] = '\0';
360
361         if (is_ksym_addr(addr)) {
362                 unsigned long pos;
363
364                 pos = get_symbol_pos(addr, size, offset);
365                 /* Grab name */
366                 kallsyms_expand_symbol(get_symbol_offset(pos),
367                                        name, KSYM_NAME_LEN);
368                 modname[0] = '\0';
369                 return 0;
370         }
371         /* See if it's in a module. */
372         return lookup_module_symbol_attrs(addr, size, offset, modname, name);
373 }
374
375 /* Look up a kernel symbol and return it in a text buffer. */
376 static int __sprint_symbol(char *buffer, unsigned long address,
377                            int symbol_offset, int add_offset)
378 {
379         char *modname;
380         const char *name;
381         unsigned long offset, size;
382         int len;
383
384         address += symbol_offset;
385         name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
386         if (!name)
387                 return sprintf(buffer, "0x%lx", address - symbol_offset);
388
389         if (name != buffer)
390                 strcpy(buffer, name);
391         len = strlen(buffer);
392         offset -= symbol_offset;
393
394         if (add_offset)
395                 len += sprintf(buffer + len, "+%#lx/%#lx", offset, size);
396
397         if (modname)
398                 len += sprintf(buffer + len, " [%s]", modname);
399
400         return len;
401 }
402
403 /**
404  * sprint_symbol - Look up a kernel symbol and return it in a text buffer
405  * @buffer: buffer to be stored
406  * @address: address to lookup
407  *
408  * This function looks up a kernel symbol with @address and stores its name,
409  * offset, size and module name to @buffer if possible. If no symbol was found,
410  * just saves its @address as is.
411  *
412  * This function returns the number of bytes stored in @buffer.
413  */
414 int sprint_symbol(char *buffer, unsigned long address)
415 {
416         return __sprint_symbol(buffer, address, 0, 1);
417 }
418 EXPORT_SYMBOL_GPL(sprint_symbol);
419
420 /**
421  * sprint_symbol_no_offset - Look up a kernel symbol and return it in a text buffer
422  * @buffer: buffer to be stored
423  * @address: address to lookup
424  *
425  * This function looks up a kernel symbol with @address and stores its name
426  * and module name to @buffer if possible. If no symbol was found, just saves
427  * its @address as is.
428  *
429  * This function returns the number of bytes stored in @buffer.
430  */
431 int sprint_symbol_no_offset(char *buffer, unsigned long address)
432 {
433         return __sprint_symbol(buffer, address, 0, 0);
434 }
435 EXPORT_SYMBOL_GPL(sprint_symbol_no_offset);
436
437 /**
438  * sprint_backtrace - Look up a backtrace symbol and return it in a text buffer
439  * @buffer: buffer to be stored
440  * @address: address to lookup
441  *
442  * This function is for stack backtrace and does the same thing as
443  * sprint_symbol() but with modified/decreased @address. If there is a
444  * tail-call to the function marked "noreturn", gcc optimized out code after
445  * the call so that the stack-saved return address could point outside of the
446  * caller. This function ensures that kallsyms will find the original caller
447  * by decreasing @address.
448  *
449  * This function returns the number of bytes stored in @buffer.
450  */
451 int sprint_backtrace(char *buffer, unsigned long address)
452 {
453         return __sprint_symbol(buffer, address, -1, 1);
454 }
455
456 /* Look up a kernel symbol and print it to the kernel messages. */
457 void __print_symbol(const char *fmt, unsigned long address)
458 {
459         char buffer[KSYM_SYMBOL_LEN];
460
461         sprint_symbol(buffer, address);
462
463         printk(fmt, buffer);
464 }
465 EXPORT_SYMBOL(__print_symbol);
466
467 /* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
468 struct kallsym_iter {
469         loff_t pos;
470         unsigned long value;
471         unsigned int nameoff; /* If iterating in core kernel symbols. */
472         char type;
473         char name[KSYM_NAME_LEN];
474         char module_name[MODULE_NAME_LEN];
475         int exported;
476 };
477
478 static int get_ksymbol_mod(struct kallsym_iter *iter)
479 {
480         if (module_get_kallsym(iter->pos - kallsyms_num_syms, &iter->value,
481                                 &iter->type, iter->name, iter->module_name,
482                                 &iter->exported) < 0)
483                 return 0;
484         return 1;
485 }
486
487 /* Returns space to next name. */
488 static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
489 {
490         unsigned off = iter->nameoff;
491
492         iter->module_name[0] = '\0';
493         iter->value = kallsyms_sym_address(iter->pos);
494
495         iter->type = kallsyms_get_symbol_type(off);
496
497         off = kallsyms_expand_symbol(off, iter->name, ARRAY_SIZE(iter->name));
498
499         return off - iter->nameoff;
500 }
501
502 static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
503 {
504         iter->name[0] = '\0';
505         iter->nameoff = get_symbol_offset(new_pos);
506         iter->pos = new_pos;
507 }
508
509 /* Returns false if pos at or past end of file. */
510 static int update_iter(struct kallsym_iter *iter, loff_t pos)
511 {
512         /* Module symbols can be accessed randomly. */
513         if (pos >= kallsyms_num_syms) {
514                 iter->pos = pos;
515                 return get_ksymbol_mod(iter);
516         }
517
518         /* If we're not on the desired position, reset to new position. */
519         if (pos != iter->pos)
520                 reset_iter(iter, pos);
521
522         iter->nameoff += get_ksymbol_core(iter);
523         iter->pos++;
524
525         return 1;
526 }
527
528 static void *s_next(struct seq_file *m, void *p, loff_t *pos)
529 {
530         (*pos)++;
531
532         if (!update_iter(m->private, *pos))
533                 return NULL;
534         return p;
535 }
536
537 static void *s_start(struct seq_file *m, loff_t *pos)
538 {
539         if (!update_iter(m->private, *pos))
540                 return NULL;
541         return m->private;
542 }
543
544 static void s_stop(struct seq_file *m, void *p)
545 {
546 }
547
548 static int s_show(struct seq_file *m, void *p)
549 {
550         struct kallsym_iter *iter = m->private;
551
552         /* Some debugging symbols have no name.  Ignore them. */
553         if (!iter->name[0])
554                 return 0;
555
556         if (iter->module_name[0]) {
557                 char type;
558
559                 /*
560                  * Label it "global" if it is exported,
561                  * "local" if not exported.
562                  */
563                 type = iter->exported ? toupper(iter->type) :
564                                         tolower(iter->type);
565                 seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value,
566                            type, iter->name, iter->module_name);
567         } else
568                 seq_printf(m, "%pK %c %s\n", (void *)iter->value,
569                            iter->type, iter->name);
570         return 0;
571 }
572
573 static const struct seq_operations kallsyms_op = {
574         .start = s_start,
575         .next = s_next,
576         .stop = s_stop,
577         .show = s_show
578 };
579
580 static int kallsyms_open(struct inode *inode, struct file *file)
581 {
582         /*
583          * We keep iterator in m->private, since normal case is to
584          * s_start from where we left off, so we avoid doing
585          * using get_symbol_offset for every symbol.
586          */
587         struct kallsym_iter *iter;
588         iter = __seq_open_private(file, &kallsyms_op, sizeof(*iter));
589         if (!iter)
590                 return -ENOMEM;
591         reset_iter(iter, 0);
592
593         return 0;
594 }
595
596 #ifdef  CONFIG_KGDB_KDB
597 const char *kdb_walk_kallsyms(loff_t *pos)
598 {
599         static struct kallsym_iter kdb_walk_kallsyms_iter;
600         if (*pos == 0) {
601                 memset(&kdb_walk_kallsyms_iter, 0,
602                        sizeof(kdb_walk_kallsyms_iter));
603                 reset_iter(&kdb_walk_kallsyms_iter, 0);
604         }
605         while (1) {
606                 if (!update_iter(&kdb_walk_kallsyms_iter, *pos))
607                         return NULL;
608                 ++*pos;
609                 /* Some debugging symbols have no name.  Ignore them. */
610                 if (kdb_walk_kallsyms_iter.name[0])
611                         return kdb_walk_kallsyms_iter.name;
612         }
613 }
614 #endif  /* CONFIG_KGDB_KDB */
615
616 static const struct file_operations kallsyms_operations = {
617         .open = kallsyms_open,
618         .read = seq_read,
619         .llseek = seq_lseek,
620         .release = seq_release_private,
621 };
622
623 static int __init kallsyms_init(void)
624 {
625         proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
626         return 0;
627 }
628 device_initcall(kallsyms_init);