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