Back to home page

LXR

 
 

    


0001 /*
0002  * kallsyms.c: in-kernel printing of symbolic oopses and stack traces.
0003  *
0004  * Rewritten and vastly simplified by Rusty Russell for in-kernel
0005  * module loader:
0006  *   Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
0007  *
0008  * ChangeLog:
0009  *
0010  * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com>
0011  *      Changed the compression method from stem compression to "table lookup"
0012  *      compression (see scripts/kallsyms.c for a more complete description)
0013  */
0014 #include <linux/kallsyms.h>
0015 #include <linux/module.h>
0016 #include <linux/init.h>
0017 #include <linux/seq_file.h>
0018 #include <linux/fs.h>
0019 #include <linux/kdb.h>
0020 #include <linux/err.h>
0021 #include <linux/proc_fs.h>
0022 #include <linux/sched.h>    /* for cond_resched */
0023 #include <linux/mm.h>
0024 #include <linux/ctype.h>
0025 #include <linux/slab.h>
0026 #include <linux/compiler.h>
0027 
0028 #include <asm/sections.h>
0029 
0030 #ifdef CONFIG_KALLSYMS_ALL
0031 #define all_var 1
0032 #else
0033 #define all_var 0
0034 #endif
0035 
0036 /*
0037  * These will be re-linked against their real values
0038  * during the second link stage.
0039  */
0040 extern const unsigned long kallsyms_addresses[] __weak;
0041 extern const int kallsyms_offsets[] __weak;
0042 extern const u8 kallsyms_names[] __weak;
0043 
0044 /*
0045  * Tell the compiler that the count isn't in the small data section if the arch
0046  * has one (eg: FRV).
0047  */
0048 extern const unsigned long kallsyms_num_syms
0049 __attribute__((weak, section(".rodata")));
0050 
0051 extern const unsigned long kallsyms_relative_base
0052 __attribute__((weak, section(".rodata")));
0053 
0054 extern const u8 kallsyms_token_table[] __weak;
0055 extern const u16 kallsyms_token_index[] __weak;
0056 
0057 extern const unsigned long kallsyms_markers[] __weak;
0058 
0059 static inline int is_kernel_inittext(unsigned long addr)
0060 {
0061     if (addr >= (unsigned long)_sinittext
0062         && addr <= (unsigned long)_einittext)
0063         return 1;
0064     return 0;
0065 }
0066 
0067 static inline int is_kernel_text(unsigned long addr)
0068 {
0069     if ((addr >= (unsigned long)_stext && addr <= (unsigned long)_etext) ||
0070         arch_is_kernel_text(addr))
0071         return 1;
0072     return in_gate_area_no_mm(addr);
0073 }
0074 
0075 static inline int is_kernel(unsigned long addr)
0076 {
0077     if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
0078         return 1;
0079     return in_gate_area_no_mm(addr);
0080 }
0081 
0082 static int is_ksym_addr(unsigned long addr)
0083 {
0084     if (all_var)
0085         return is_kernel(addr);
0086 
0087     return is_kernel_text(addr) || is_kernel_inittext(addr);
0088 }
0089 
0090 /*
0091  * Expand a compressed symbol data into the resulting uncompressed string,
0092  * if uncompressed string is too long (>= maxlen), it will be truncated,
0093  * given the offset to where the symbol is in the compressed stream.
0094  */
0095 static unsigned int kallsyms_expand_symbol(unsigned int off,
0096                        char *result, size_t maxlen)
0097 {
0098     int len, skipped_first = 0;
0099     const u8 *tptr, *data;
0100 
0101     /* Get the compressed symbol length from the first symbol byte. */
0102     data = &kallsyms_names[off];
0103     len = *data;
0104     data++;
0105 
0106     /*
0107      * Update the offset to return the offset for the next symbol on
0108      * the compressed stream.
0109      */
0110     off += len + 1;
0111 
0112     /*
0113      * For every byte on the compressed symbol data, copy the table
0114      * entry for that byte.
0115      */
0116     while (len) {
0117         tptr = &kallsyms_token_table[kallsyms_token_index[*data]];
0118         data++;
0119         len--;
0120 
0121         while (*tptr) {
0122             if (skipped_first) {
0123                 if (maxlen <= 1)
0124                     goto tail;
0125                 *result = *tptr;
0126                 result++;
0127                 maxlen--;
0128             } else
0129                 skipped_first = 1;
0130             tptr++;
0131         }
0132     }
0133 
0134 tail:
0135     if (maxlen)
0136         *result = '\0';
0137 
0138     /* Return to offset to the next symbol. */
0139     return off;
0140 }
0141 
0142 /*
0143  * Get symbol type information. This is encoded as a single char at the
0144  * beginning of the symbol name.
0145  */
0146 static char kallsyms_get_symbol_type(unsigned int off)
0147 {
0148     /*
0149      * Get just the first code, look it up in the token table,
0150      * and return the first char from this token.
0151      */
0152     return kallsyms_token_table[kallsyms_token_index[kallsyms_names[off + 1]]];
0153 }
0154 
0155 
0156 /*
0157  * Find the offset on the compressed stream given and index in the
0158  * kallsyms array.
0159  */
0160 static unsigned int get_symbol_offset(unsigned long pos)
0161 {
0162     const u8 *name;
0163     int i;
0164 
0165     /*
0166      * Use the closest marker we have. We have markers every 256 positions,
0167      * so that should be close enough.
0168      */
0169     name = &kallsyms_names[kallsyms_markers[pos >> 8]];
0170 
0171     /*
0172      * Sequentially scan all the symbols up to the point we're searching
0173      * for. Every symbol is stored in a [<len>][<len> bytes of data] format,
0174      * so we just need to add the len to the current pointer for every
0175      * symbol we wish to skip.
0176      */
0177     for (i = 0; i < (pos & 0xFF); i++)
0178         name = name + (*name) + 1;
0179 
0180     return name - kallsyms_names;
0181 }
0182 
0183 static unsigned long kallsyms_sym_address(int idx)
0184 {
0185     if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
0186         return kallsyms_addresses[idx];
0187 
0188     /* values are unsigned offsets if --absolute-percpu is not in effect */
0189     if (!IS_ENABLED(CONFIG_KALLSYMS_ABSOLUTE_PERCPU))
0190         return kallsyms_relative_base + (u32)kallsyms_offsets[idx];
0191 
0192     /* ...otherwise, positive offsets are absolute values */
0193     if (kallsyms_offsets[idx] >= 0)
0194         return kallsyms_offsets[idx];
0195 
0196     /* ...and negative offsets are relative to kallsyms_relative_base - 1 */
0197     return kallsyms_relative_base - 1 - kallsyms_offsets[idx];
0198 }
0199 
0200 /* Lookup the address for this symbol. Returns 0 if not found. */
0201 unsigned long kallsyms_lookup_name(const char *name)
0202 {
0203     char namebuf[KSYM_NAME_LEN];
0204     unsigned long i;
0205     unsigned int off;
0206 
0207     for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
0208         off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
0209 
0210         if (strcmp(namebuf, name) == 0)
0211             return kallsyms_sym_address(i);
0212     }
0213     return module_kallsyms_lookup_name(name);
0214 }
0215 EXPORT_SYMBOL_GPL(kallsyms_lookup_name);
0216 
0217 int kallsyms_on_each_symbol(int (*fn)(void *, const char *, struct module *,
0218                       unsigned long),
0219                 void *data)
0220 {
0221     char namebuf[KSYM_NAME_LEN];
0222     unsigned long i;
0223     unsigned int off;
0224     int ret;
0225 
0226     for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
0227         off = kallsyms_expand_symbol(off, namebuf, ARRAY_SIZE(namebuf));
0228         ret = fn(data, namebuf, NULL, kallsyms_sym_address(i));
0229         if (ret != 0)
0230             return ret;
0231     }
0232     return module_kallsyms_on_each_symbol(fn, data);
0233 }
0234 EXPORT_SYMBOL_GPL(kallsyms_on_each_symbol);
0235 
0236 static unsigned long get_symbol_pos(unsigned long addr,
0237                     unsigned long *symbolsize,
0238                     unsigned long *offset)
0239 {
0240     unsigned long symbol_start = 0, symbol_end = 0;
0241     unsigned long i, low, high, mid;
0242 
0243     /* This kernel should never had been booted. */
0244     if (!IS_ENABLED(CONFIG_KALLSYMS_BASE_RELATIVE))
0245         BUG_ON(!kallsyms_addresses);
0246     else
0247         BUG_ON(!kallsyms_offsets);
0248 
0249     /* Do a binary search on the sorted kallsyms_addresses array. */
0250     low = 0;
0251     high = kallsyms_num_syms;
0252 
0253     while (high - low > 1) {
0254         mid = low + (high - low) / 2;
0255         if (kallsyms_sym_address(mid) <= addr)
0256             low = mid;
0257         else
0258             high = mid;
0259     }
0260 
0261     /*
0262      * Search for the first aliased symbol. Aliased
0263      * symbols are symbols with the same address.
0264      */
0265     while (low && kallsyms_sym_address(low-1) == kallsyms_sym_address(low))
0266         --low;
0267 
0268     symbol_start = kallsyms_sym_address(low);
0269 
0270     /* Search for next non-aliased symbol. */
0271     for (i = low + 1; i < kallsyms_num_syms; i++) {
0272         if (kallsyms_sym_address(i) > symbol_start) {
0273             symbol_end = kallsyms_sym_address(i);
0274             break;
0275         }
0276     }
0277 
0278     /* If we found no next symbol, we use the end of the section. */
0279     if (!symbol_end) {
0280         if (is_kernel_inittext(addr))
0281             symbol_end = (unsigned long)_einittext;
0282         else if (all_var)
0283             symbol_end = (unsigned long)_end;
0284         else
0285             symbol_end = (unsigned long)_etext;
0286     }
0287 
0288     if (symbolsize)
0289         *symbolsize = symbol_end - symbol_start;
0290     if (offset)
0291         *offset = addr - symbol_start;
0292 
0293     return low;
0294 }
0295 
0296 /*
0297  * Lookup an address but don't bother to find any names.
0298  */
0299 int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
0300                 unsigned long *offset)
0301 {
0302     char namebuf[KSYM_NAME_LEN];
0303     if (is_ksym_addr(addr))
0304         return !!get_symbol_pos(addr, symbolsize, offset);
0305 
0306     return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf);
0307 }
0308 
0309 /*
0310  * Lookup an address
0311  * - modname is set to NULL if it's in the kernel.
0312  * - We guarantee that the returned name is valid until we reschedule even if.
0313  *   It resides in a module.
0314  * - We also guarantee that modname will be valid until rescheduled.
0315  */
0316 const char *kallsyms_lookup(unsigned long addr,
0317                 unsigned long *symbolsize,
0318                 unsigned long *offset,
0319                 char **modname, char *namebuf)
0320 {
0321     namebuf[KSYM_NAME_LEN - 1] = 0;
0322     namebuf[0] = 0;
0323 
0324     if (is_ksym_addr(addr)) {
0325         unsigned long pos;
0326 
0327         pos = get_symbol_pos(addr, symbolsize, offset);
0328         /* Grab name */
0329         kallsyms_expand_symbol(get_symbol_offset(pos),
0330                        namebuf, KSYM_NAME_LEN);
0331         if (modname)
0332             *modname = NULL;
0333         return namebuf;
0334     }
0335 
0336     /* See if it's in a module. */
0337     return module_address_lookup(addr, symbolsize, offset, modname,
0338                      namebuf);
0339 }
0340 
0341 int lookup_symbol_name(unsigned long addr, char *symname)
0342 {
0343     symname[0] = '\0';
0344     symname[KSYM_NAME_LEN - 1] = '\0';
0345 
0346     if (is_ksym_addr(addr)) {
0347         unsigned long pos;
0348 
0349         pos = get_symbol_pos(addr, NULL, NULL);
0350         /* Grab name */
0351         kallsyms_expand_symbol(get_symbol_offset(pos),
0352                        symname, KSYM_NAME_LEN);
0353         return 0;
0354     }
0355     /* See if it's in a module. */
0356     return lookup_module_symbol_name(addr, symname);
0357 }
0358 
0359 int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
0360             unsigned long *offset, char *modname, char *name)
0361 {
0362     name[0] = '\0';
0363     name[KSYM_NAME_LEN - 1] = '\0';
0364 
0365     if (is_ksym_addr(addr)) {
0366         unsigned long pos;
0367 
0368         pos = get_symbol_pos(addr, size, offset);
0369         /* Grab name */
0370         kallsyms_expand_symbol(get_symbol_offset(pos),
0371                        name, KSYM_NAME_LEN);
0372         modname[0] = '\0';
0373         return 0;
0374     }
0375     /* See if it's in a module. */
0376     return lookup_module_symbol_attrs(addr, size, offset, modname, name);
0377 }
0378 
0379 /* Look up a kernel symbol and return it in a text buffer. */
0380 static int __sprint_symbol(char *buffer, unsigned long address,
0381                int symbol_offset, int add_offset)
0382 {
0383     char *modname;
0384     const char *name;
0385     unsigned long offset, size;
0386     int len;
0387 
0388     address += symbol_offset;
0389     name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
0390     if (!name)
0391         return sprintf(buffer, "0x%lx", address - symbol_offset);
0392 
0393     if (name != buffer)
0394         strcpy(buffer, name);
0395     len = strlen(buffer);
0396     offset -= symbol_offset;
0397 
0398     if (add_offset)
0399         len += sprintf(buffer + len, "+%#lx/%#lx", offset, size);
0400 
0401     if (modname)
0402         len += sprintf(buffer + len, " [%s]", modname);
0403 
0404     return len;
0405 }
0406 
0407 /**
0408  * sprint_symbol - Look up a kernel symbol and return it in a text buffer
0409  * @buffer: buffer to be stored
0410  * @address: address to lookup
0411  *
0412  * This function looks up a kernel symbol with @address and stores its name,
0413  * offset, size and module name to @buffer if possible. If no symbol was found,
0414  * just saves its @address as is.
0415  *
0416  * This function returns the number of bytes stored in @buffer.
0417  */
0418 int sprint_symbol(char *buffer, unsigned long address)
0419 {
0420     return __sprint_symbol(buffer, address, 0, 1);
0421 }
0422 EXPORT_SYMBOL_GPL(sprint_symbol);
0423 
0424 /**
0425  * sprint_symbol_no_offset - Look up a kernel symbol and return it in a text buffer
0426  * @buffer: buffer to be stored
0427  * @address: address to lookup
0428  *
0429  * This function looks up a kernel symbol with @address and stores its name
0430  * and module name to @buffer if possible. If no symbol was found, just saves
0431  * its @address as is.
0432  *
0433  * This function returns the number of bytes stored in @buffer.
0434  */
0435 int sprint_symbol_no_offset(char *buffer, unsigned long address)
0436 {
0437     return __sprint_symbol(buffer, address, 0, 0);
0438 }
0439 EXPORT_SYMBOL_GPL(sprint_symbol_no_offset);
0440 
0441 /**
0442  * sprint_backtrace - Look up a backtrace symbol and return it in a text buffer
0443  * @buffer: buffer to be stored
0444  * @address: address to lookup
0445  *
0446  * This function is for stack backtrace and does the same thing as
0447  * sprint_symbol() but with modified/decreased @address. If there is a
0448  * tail-call to the function marked "noreturn", gcc optimized out code after
0449  * the call so that the stack-saved return address could point outside of the
0450  * caller. This function ensures that kallsyms will find the original caller
0451  * by decreasing @address.
0452  *
0453  * This function returns the number of bytes stored in @buffer.
0454  */
0455 int sprint_backtrace(char *buffer, unsigned long address)
0456 {
0457     return __sprint_symbol(buffer, address, -1, 1);
0458 }
0459 
0460 /* Look up a kernel symbol and print it to the kernel messages. */
0461 void __print_symbol(const char *fmt, unsigned long address)
0462 {
0463     char buffer[KSYM_SYMBOL_LEN];
0464 
0465     sprint_symbol(buffer, address);
0466 
0467     printk(fmt, buffer);
0468 }
0469 EXPORT_SYMBOL(__print_symbol);
0470 
0471 /* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
0472 struct kallsym_iter {
0473     loff_t pos;
0474     unsigned long value;
0475     unsigned int nameoff; /* If iterating in core kernel symbols. */
0476     char type;
0477     char name[KSYM_NAME_LEN];
0478     char module_name[MODULE_NAME_LEN];
0479     int exported;
0480 };
0481 
0482 static int get_ksymbol_mod(struct kallsym_iter *iter)
0483 {
0484     if (module_get_kallsym(iter->pos - kallsyms_num_syms, &iter->value,
0485                 &iter->type, iter->name, iter->module_name,
0486                 &iter->exported) < 0)
0487         return 0;
0488     return 1;
0489 }
0490 
0491 /* Returns space to next name. */
0492 static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
0493 {
0494     unsigned off = iter->nameoff;
0495 
0496     iter->module_name[0] = '\0';
0497     iter->value = kallsyms_sym_address(iter->pos);
0498 
0499     iter->type = kallsyms_get_symbol_type(off);
0500 
0501     off = kallsyms_expand_symbol(off, iter->name, ARRAY_SIZE(iter->name));
0502 
0503     return off - iter->nameoff;
0504 }
0505 
0506 static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
0507 {
0508     iter->name[0] = '\0';
0509     iter->nameoff = get_symbol_offset(new_pos);
0510     iter->pos = new_pos;
0511 }
0512 
0513 /* Returns false if pos at or past end of file. */
0514 static int update_iter(struct kallsym_iter *iter, loff_t pos)
0515 {
0516     /* Module symbols can be accessed randomly. */
0517     if (pos >= kallsyms_num_syms) {
0518         iter->pos = pos;
0519         return get_ksymbol_mod(iter);
0520     }
0521 
0522     /* If we're not on the desired position, reset to new position. */
0523     if (pos != iter->pos)
0524         reset_iter(iter, pos);
0525 
0526     iter->nameoff += get_ksymbol_core(iter);
0527     iter->pos++;
0528 
0529     return 1;
0530 }
0531 
0532 static void *s_next(struct seq_file *m, void *p, loff_t *pos)
0533 {
0534     (*pos)++;
0535 
0536     if (!update_iter(m->private, *pos))
0537         return NULL;
0538     return p;
0539 }
0540 
0541 static void *s_start(struct seq_file *m, loff_t *pos)
0542 {
0543     if (!update_iter(m->private, *pos))
0544         return NULL;
0545     return m->private;
0546 }
0547 
0548 static void s_stop(struct seq_file *m, void *p)
0549 {
0550 }
0551 
0552 static int s_show(struct seq_file *m, void *p)
0553 {
0554     struct kallsym_iter *iter = m->private;
0555 
0556     /* Some debugging symbols have no name.  Ignore them. */
0557     if (!iter->name[0])
0558         return 0;
0559 
0560     if (iter->module_name[0]) {
0561         char type;
0562 
0563         /*
0564          * Label it "global" if it is exported,
0565          * "local" if not exported.
0566          */
0567         type = iter->exported ? toupper(iter->type) :
0568                     tolower(iter->type);
0569         seq_printf(m, "%pK %c %s\t[%s]\n", (void *)iter->value,
0570                type, iter->name, iter->module_name);
0571     } else
0572         seq_printf(m, "%pK %c %s\n", (void *)iter->value,
0573                iter->type, iter->name);
0574     return 0;
0575 }
0576 
0577 static const struct seq_operations kallsyms_op = {
0578     .start = s_start,
0579     .next = s_next,
0580     .stop = s_stop,
0581     .show = s_show
0582 };
0583 
0584 static int kallsyms_open(struct inode *inode, struct file *file)
0585 {
0586     /*
0587      * We keep iterator in m->private, since normal case is to
0588      * s_start from where we left off, so we avoid doing
0589      * using get_symbol_offset for every symbol.
0590      */
0591     struct kallsym_iter *iter;
0592     iter = __seq_open_private(file, &kallsyms_op, sizeof(*iter));
0593     if (!iter)
0594         return -ENOMEM;
0595     reset_iter(iter, 0);
0596 
0597     return 0;
0598 }
0599 
0600 #ifdef  CONFIG_KGDB_KDB
0601 const char *kdb_walk_kallsyms(loff_t *pos)
0602 {
0603     static struct kallsym_iter kdb_walk_kallsyms_iter;
0604     if (*pos == 0) {
0605         memset(&kdb_walk_kallsyms_iter, 0,
0606                sizeof(kdb_walk_kallsyms_iter));
0607         reset_iter(&kdb_walk_kallsyms_iter, 0);
0608     }
0609     while (1) {
0610         if (!update_iter(&kdb_walk_kallsyms_iter, *pos))
0611             return NULL;
0612         ++*pos;
0613         /* Some debugging symbols have no name.  Ignore them. */
0614         if (kdb_walk_kallsyms_iter.name[0])
0615             return kdb_walk_kallsyms_iter.name;
0616     }
0617 }
0618 #endif  /* CONFIG_KGDB_KDB */
0619 
0620 static const struct file_operations kallsyms_operations = {
0621     .open = kallsyms_open,
0622     .read = seq_read,
0623     .llseek = seq_lseek,
0624     .release = seq_release_private,
0625 };
0626 
0627 static int __init kallsyms_init(void)
0628 {
0629     proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
0630     return 0;
0631 }
0632 device_initcall(kallsyms_init);