kallsyms.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  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/err.h>
  20. #include <linux/proc_fs.h>
  21. #include <linux/sched.h> /* for cond_resched */
  22. #include <linux/mm.h>
  23. #include <linux/ctype.h>
  24. #include <asm/sections.h>
  25. #ifdef CONFIG_KALLSYMS_ALL
  26. #define all_var 1
  27. #else
  28. #define all_var 0
  29. #endif
  30. extern const unsigned long kallsyms_addresses[];
  31. extern const u8 kallsyms_names[];
  32. /* tell the compiler that the count isn't in the small data section if the arch
  33. * has one (eg: FRV)
  34. */
  35. extern const unsigned long kallsyms_num_syms
  36. __attribute__((__section__(".rodata")));
  37. extern const u8 kallsyms_token_table[];
  38. extern const u16 kallsyms_token_index[];
  39. extern const unsigned long kallsyms_markers[];
  40. static inline int is_kernel_inittext(unsigned long addr)
  41. {
  42. if (addr >= (unsigned long)_sinittext
  43. && addr <= (unsigned long)_einittext)
  44. return 1;
  45. return 0;
  46. }
  47. static inline int is_kernel_text(unsigned long addr)
  48. {
  49. if (addr >= (unsigned long)_stext && addr <= (unsigned long)_etext)
  50. return 1;
  51. return in_gate_area_no_task(addr);
  52. }
  53. static inline int is_kernel(unsigned long addr)
  54. {
  55. if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
  56. return 1;
  57. return in_gate_area_no_task(addr);
  58. }
  59. static int is_ksym_addr(unsigned long addr)
  60. {
  61. if (all_var)
  62. return is_kernel(addr);
  63. return is_kernel_text(addr) || is_kernel_inittext(addr);
  64. }
  65. /* expand a compressed symbol data into the resulting uncompressed string,
  66. given the offset to where the symbol is in the compressed stream */
  67. static unsigned int kallsyms_expand_symbol(unsigned int off, char *result)
  68. {
  69. int len, skipped_first = 0;
  70. const u8 *tptr, *data;
  71. /* get the compressed symbol length from the first symbol byte */
  72. data = &kallsyms_names[off];
  73. len = *data;
  74. data++;
  75. /* update the offset to return the offset for the next symbol on
  76. * the compressed stream */
  77. off += len + 1;
  78. /* for every byte on the compressed symbol data, copy the table
  79. entry for that byte */
  80. while(len) {
  81. tptr = &kallsyms_token_table[ kallsyms_token_index[*data] ];
  82. data++;
  83. len--;
  84. while (*tptr) {
  85. if(skipped_first) {
  86. *result = *tptr;
  87. result++;
  88. } else
  89. skipped_first = 1;
  90. tptr++;
  91. }
  92. }
  93. *result = '\0';
  94. /* return to offset to the next symbol */
  95. return off;
  96. }
  97. /* get symbol type information. This is encoded as a single char at the
  98. * begining of the symbol name */
  99. static char kallsyms_get_symbol_type(unsigned int off)
  100. {
  101. /* get just the first code, look it up in the token table, and return the
  102. * first char from this token */
  103. return kallsyms_token_table[ kallsyms_token_index[ kallsyms_names[off+1] ] ];
  104. }
  105. /* find the offset on the compressed stream given and index in the
  106. * kallsyms array */
  107. static unsigned int get_symbol_offset(unsigned long pos)
  108. {
  109. const u8 *name;
  110. int i;
  111. /* use the closest marker we have. We have markers every 256 positions,
  112. * so that should be close enough */
  113. name = &kallsyms_names[ kallsyms_markers[pos>>8] ];
  114. /* sequentially scan all the symbols up to the point we're searching for.
  115. * Every symbol is stored in a [<len>][<len> bytes of data] format, so we
  116. * just need to add the len to the current pointer for every symbol we
  117. * wish to skip */
  118. for(i = 0; i < (pos&0xFF); i++)
  119. name = name + (*name) + 1;
  120. return name - kallsyms_names;
  121. }
  122. /* Lookup the address for this symbol. Returns 0 if not found. */
  123. unsigned long kallsyms_lookup_name(const char *name)
  124. {
  125. char namebuf[KSYM_NAME_LEN];
  126. unsigned long i;
  127. unsigned int off;
  128. for (i = 0, off = 0; i < kallsyms_num_syms; i++) {
  129. off = kallsyms_expand_symbol(off, namebuf);
  130. if (strcmp(namebuf, name) == 0)
  131. return kallsyms_addresses[i];
  132. }
  133. return module_kallsyms_lookup_name(name);
  134. }
  135. static unsigned long get_symbol_pos(unsigned long addr,
  136. unsigned long *symbolsize,
  137. unsigned long *offset)
  138. {
  139. unsigned long symbol_start = 0, symbol_end = 0;
  140. unsigned long i, low, high, mid;
  141. /* do a binary search on the sorted kallsyms_addresses array */
  142. low = 0;
  143. high = kallsyms_num_syms;
  144. while (high - low > 1) {
  145. mid = low + (high - low) / 2;
  146. if (kallsyms_addresses[mid] <= addr)
  147. low = mid;
  148. else
  149. high = mid;
  150. }
  151. /*
  152. * search for the first aliased symbol. Aliased
  153. * symbols are symbols with the same address
  154. */
  155. while (low && kallsyms_addresses[low-1] == kallsyms_addresses[low])
  156. --low;
  157. symbol_start = kallsyms_addresses[low];
  158. /* Search for next non-aliased symbol */
  159. for (i = low + 1; i < kallsyms_num_syms; i++) {
  160. if (kallsyms_addresses[i] > symbol_start) {
  161. symbol_end = kallsyms_addresses[i];
  162. break;
  163. }
  164. }
  165. /* if we found no next symbol, we use the end of the section */
  166. if (!symbol_end) {
  167. if (is_kernel_inittext(addr))
  168. symbol_end = (unsigned long)_einittext;
  169. else if (all_var)
  170. symbol_end = (unsigned long)_end;
  171. else
  172. symbol_end = (unsigned long)_etext;
  173. }
  174. if (symbolsize)
  175. *symbolsize = symbol_end - symbol_start;
  176. if (offset)
  177. *offset = addr - symbol_start;
  178. return low;
  179. }
  180. /*
  181. * Lookup an address but don't bother to find any names.
  182. */
  183. int kallsyms_lookup_size_offset(unsigned long addr, unsigned long *symbolsize,
  184. unsigned long *offset)
  185. {
  186. char namebuf[KSYM_NAME_LEN];
  187. if (is_ksym_addr(addr))
  188. return !!get_symbol_pos(addr, symbolsize, offset);
  189. return !!module_address_lookup(addr, symbolsize, offset, NULL, namebuf);
  190. }
  191. /*
  192. * Lookup an address
  193. * - modname is set to NULL if it's in the kernel
  194. * - we guarantee that the returned name is valid until we reschedule even if
  195. * it resides in a module
  196. * - we also guarantee that modname will be valid until rescheduled
  197. */
  198. const char *kallsyms_lookup(unsigned long addr,
  199. unsigned long *symbolsize,
  200. unsigned long *offset,
  201. char **modname, char *namebuf)
  202. {
  203. namebuf[KSYM_NAME_LEN - 1] = 0;
  204. namebuf[0] = 0;
  205. if (is_ksym_addr(addr)) {
  206. unsigned long pos;
  207. pos = get_symbol_pos(addr, symbolsize, offset);
  208. /* Grab name */
  209. kallsyms_expand_symbol(get_symbol_offset(pos), namebuf);
  210. if (modname)
  211. *modname = NULL;
  212. return namebuf;
  213. }
  214. /* see if it's in a module */
  215. return module_address_lookup(addr, symbolsize, offset, modname,
  216. namebuf);
  217. }
  218. int lookup_symbol_name(unsigned long addr, char *symname)
  219. {
  220. symname[0] = '\0';
  221. symname[KSYM_NAME_LEN - 1] = '\0';
  222. if (is_ksym_addr(addr)) {
  223. unsigned long pos;
  224. pos = get_symbol_pos(addr, NULL, NULL);
  225. /* Grab name */
  226. kallsyms_expand_symbol(get_symbol_offset(pos), symname);
  227. return 0;
  228. }
  229. /* see if it's in a module */
  230. return lookup_module_symbol_name(addr, symname);
  231. }
  232. int lookup_symbol_attrs(unsigned long addr, unsigned long *size,
  233. unsigned long *offset, char *modname, char *name)
  234. {
  235. name[0] = '\0';
  236. name[KSYM_NAME_LEN - 1] = '\0';
  237. if (is_ksym_addr(addr)) {
  238. unsigned long pos;
  239. pos = get_symbol_pos(addr, size, offset);
  240. /* Grab name */
  241. kallsyms_expand_symbol(get_symbol_offset(pos), name);
  242. modname[0] = '\0';
  243. return 0;
  244. }
  245. /* see if it's in a module */
  246. return lookup_module_symbol_attrs(addr, size, offset, modname, name);
  247. }
  248. /* Look up a kernel symbol and return it in a text buffer. */
  249. int sprint_symbol(char *buffer, unsigned long address)
  250. {
  251. char *modname;
  252. const char *name;
  253. unsigned long offset, size;
  254. int len;
  255. name = kallsyms_lookup(address, &size, &offset, &modname, buffer);
  256. if (!name)
  257. return sprintf(buffer, "0x%lx", address);
  258. if (name != buffer)
  259. strcpy(buffer, name);
  260. len = strlen(buffer);
  261. buffer += len;
  262. if (modname)
  263. len += sprintf(buffer, "+%#lx/%#lx [%s]",
  264. offset, size, modname);
  265. else
  266. len += sprintf(buffer, "+%#lx/%#lx", offset, size);
  267. return len;
  268. }
  269. /* Look up a kernel symbol and print it to the kernel messages. */
  270. void __print_symbol(const char *fmt, unsigned long address)
  271. {
  272. char buffer[KSYM_SYMBOL_LEN];
  273. sprint_symbol(buffer, address);
  274. printk(fmt, buffer);
  275. }
  276. /* To avoid using get_symbol_offset for every symbol, we carry prefix along. */
  277. struct kallsym_iter
  278. {
  279. loff_t pos;
  280. unsigned long value;
  281. unsigned int nameoff; /* If iterating in core kernel symbols */
  282. char type;
  283. char name[KSYM_NAME_LEN];
  284. char module_name[MODULE_NAME_LEN];
  285. int exported;
  286. };
  287. static int get_ksymbol_mod(struct kallsym_iter *iter)
  288. {
  289. if (module_get_kallsym(iter->pos - kallsyms_num_syms, &iter->value,
  290. &iter->type, iter->name, iter->module_name,
  291. &iter->exported) < 0)
  292. return 0;
  293. return 1;
  294. }
  295. /* Returns space to next name. */
  296. static unsigned long get_ksymbol_core(struct kallsym_iter *iter)
  297. {
  298. unsigned off = iter->nameoff;
  299. iter->module_name[0] = '\0';
  300. iter->value = kallsyms_addresses[iter->pos];
  301. iter->type = kallsyms_get_symbol_type(off);
  302. off = kallsyms_expand_symbol(off, iter->name);
  303. return off - iter->nameoff;
  304. }
  305. static void reset_iter(struct kallsym_iter *iter, loff_t new_pos)
  306. {
  307. iter->name[0] = '\0';
  308. iter->nameoff = get_symbol_offset(new_pos);
  309. iter->pos = new_pos;
  310. }
  311. /* Returns false if pos at or past end of file. */
  312. static int update_iter(struct kallsym_iter *iter, loff_t pos)
  313. {
  314. /* Module symbols can be accessed randomly. */
  315. if (pos >= kallsyms_num_syms) {
  316. iter->pos = pos;
  317. return get_ksymbol_mod(iter);
  318. }
  319. /* If we're not on the desired position, reset to new position. */
  320. if (pos != iter->pos)
  321. reset_iter(iter, pos);
  322. iter->nameoff += get_ksymbol_core(iter);
  323. iter->pos++;
  324. return 1;
  325. }
  326. static void *s_next(struct seq_file *m, void *p, loff_t *pos)
  327. {
  328. (*pos)++;
  329. if (!update_iter(m->private, *pos))
  330. return NULL;
  331. return p;
  332. }
  333. static void *s_start(struct seq_file *m, loff_t *pos)
  334. {
  335. if (!update_iter(m->private, *pos))
  336. return NULL;
  337. return m->private;
  338. }
  339. static void s_stop(struct seq_file *m, void *p)
  340. {
  341. }
  342. static int s_show(struct seq_file *m, void *p)
  343. {
  344. struct kallsym_iter *iter = m->private;
  345. /* Some debugging symbols have no name. Ignore them. */
  346. if (!iter->name[0])
  347. return 0;
  348. if (iter->module_name[0]) {
  349. char type;
  350. /* Label it "global" if it is exported,
  351. * "local" if not exported. */
  352. type = iter->exported ? toupper(iter->type) :
  353. tolower(iter->type);
  354. seq_printf(m, "%0*lx %c %s\t[%s]\n",
  355. (int)(2*sizeof(void*)),
  356. iter->value, type, iter->name, iter->module_name);
  357. } else
  358. seq_printf(m, "%0*lx %c %s\n",
  359. (int)(2*sizeof(void*)),
  360. iter->value, iter->type, iter->name);
  361. return 0;
  362. }
  363. static const struct seq_operations kallsyms_op = {
  364. .start = s_start,
  365. .next = s_next,
  366. .stop = s_stop,
  367. .show = s_show
  368. };
  369. static int kallsyms_open(struct inode *inode, struct file *file)
  370. {
  371. /* We keep iterator in m->private, since normal case is to
  372. * s_start from where we left off, so we avoid doing
  373. * using get_symbol_offset for every symbol */
  374. struct kallsym_iter *iter;
  375. int ret;
  376. iter = kmalloc(sizeof(*iter), GFP_KERNEL);
  377. if (!iter)
  378. return -ENOMEM;
  379. reset_iter(iter, 0);
  380. ret = seq_open(file, &kallsyms_op);
  381. if (ret == 0)
  382. ((struct seq_file *)file->private_data)->private = iter;
  383. else
  384. kfree(iter);
  385. return ret;
  386. }
  387. static const struct file_operations kallsyms_operations = {
  388. .open = kallsyms_open,
  389. .read = seq_read,
  390. .llseek = seq_lseek,
  391. .release = seq_release_private,
  392. };
  393. static int __init kallsyms_init(void)
  394. {
  395. proc_create("kallsyms", 0444, NULL, &kallsyms_operations);
  396. return 0;
  397. }
  398. __initcall(kallsyms_init);
  399. EXPORT_SYMBOL(__print_symbol);
  400. EXPORT_SYMBOL_GPL(sprint_symbol);