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