1 /* $OpenBSD: db_sym.c,v 1.32 2006/03/13 06:23:20 jsg Exp $ */ 2 /* $NetBSD: db_sym.c,v 1.24 2000/08/11 22:50:47 tv Exp $ */ 3 4 /* 5 * Mach Operating System 6 * Copyright (c) 1993,1992,1991,1990 Carnegie Mellon University 7 * All Rights Reserved. 8 * 9 * Permission to use, copy, modify and distribute this software and its 10 * documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 17 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie Mellon 27 * the rights to redistribute these changes. 28 */ 29 30 #include <sys/param.h> 31 #include <sys/proc.h> 32 #include <sys/systm.h> 33 34 #include <machine/db_machdep.h> 35 36 #include <ddb/db_lex.h> 37 #include <ddb/db_sym.h> 38 #include <ddb/db_output.h> 39 #include <ddb/db_extern.h> 40 #include <ddb/db_command.h> 41 42 /* 43 * Multiple symbol tables 44 */ 45 #ifndef MAXLKMS 46 #define MAXLKMS 20 47 #endif 48 49 #ifndef MAXNOSYMTABS 50 #define MAXNOSYMTABS MAXLKMS+1 /* Room for kernel + LKM's */ 51 #endif 52 53 db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},}; 54 55 db_symtab_t *db_last_symtab; 56 57 static db_forall_func_t db_sift; 58 59 extern char end[]; 60 61 /* 62 * Put the most picky symbol table formats at the top! 63 */ 64 const db_symformat_t *db_symformats[] = { 65 #ifdef DB_ELF_SYMBOLS 66 &db_symformat_elf, 67 #endif 68 #ifdef DB_AOUT_SYMBOLS 69 &db_symformat_aout, 70 #endif 71 NULL, 72 }; 73 74 const db_symformat_t *db_symformat; 75 76 boolean_t X_db_sym_init(int, void *, void *, const char *); 77 db_sym_t X_db_lookup(db_symtab_t *, char *); 78 db_sym_t X_db_search_symbol(db_symtab_t *, db_addr_t, 79 db_strategy_t, db_expr_t *); 80 void X_db_symbol_values(db_symtab_t *, db_sym_t, char **, 81 db_expr_t *); 82 boolean_t X_db_line_at_pc(db_symtab_t *, db_sym_t, char **, 83 int *, db_expr_t); 84 int X_db_sym_numargs(db_symtab_t *, db_sym_t, int *, 85 char **); 86 87 /* 88 * Initialize the kernel debugger by initializing the master symbol 89 * table. Note that if initializing the master symbol table fails, 90 * no other symbol tables can be loaded. 91 */ 92 #if 0 93 void 94 ddb_init(int symsize, void *vss, void *vse) 95 { 96 const db_symformat_t **symf; 97 const char *name = "bsd"; 98 99 if (symsize <= 0) { 100 printf(" [ no symbols available ]\n"); 101 return; 102 } 103 104 /* 105 * Do this check now for the master symbol table to avoid printing 106 * the message N times. 107 */ 108 if (ALIGNED_POINTER(vss, long) == 0) { 109 printf("[ %s symbol table has bad start address %p ]\n", 110 name, vss); 111 return; 112 } 113 114 for (symf = db_symformats; *symf != NULL; symf++) { 115 db_symformat = *symf; 116 if (X_db_sym_init(symsize, vss, vse, name) == TRUE) 117 return; 118 } 119 120 db_symformat = NULL; 121 printf("[ no symbol table formats found ]\n"); 122 } 123 #else 124 void 125 ddb_init(void) 126 { 127 const db_symformat_t **symf; 128 const char *name = "bsd"; 129 extern char *esym; 130 #if defined(__sparc64__) || defined(__mips__) 131 extern char *ssym; 132 #endif 133 char *xssym, *xesym; 134 135 xesym = esym; 136 #if defined(__sparc64__) || defined(__mips__) 137 xssym = ssym; 138 #else 139 xssym = (char *)&end; 140 #endif 141 /* 142 * Do this check now for the master symbol table to avoid printing 143 * the message N times. 144 */ 145 if ((((vaddr_t)xssym) & (sizeof(long) - 1)) != 0) { 146 printf("[ %s symbol table has bad start address %p ]\n", 147 name, xssym); 148 return; 149 } 150 151 if (xesym != NULL && xesym != xssym) 152 for (symf = db_symformats; *symf != NULL; symf++) { 153 db_symformat = *symf; 154 if (X_db_sym_init((vaddr_t)xesym - (vaddr_t)xssym, 155 xssym, xesym, name) == TRUE) 156 return; 157 } 158 159 db_symformat = NULL; 160 printf("[ no symbol table formats found ]\n"); 161 } 162 #endif 163 164 /* 165 * Add symbol table, with given name, to list of symbol tables. 166 */ 167 int 168 db_add_symbol_table(char *start, char *end, const char *name, char *ref) 169 { 170 int slot; 171 172 for (slot = 0; slot < MAXNOSYMTABS; slot++) { 173 if (db_symtabs[slot].name == NULL) 174 break; 175 } 176 if (slot >= MAXNOSYMTABS) { 177 db_printf("No slots left for %s symbol table", name); 178 return(-1); 179 } 180 181 db_symtabs[slot].start = start; 182 db_symtabs[slot].end = end; 183 db_symtabs[slot].name = name; 184 db_symtabs[slot].private = ref; 185 186 return(slot); 187 } 188 189 /* 190 * Delete a symbol table. Caller is responsible for freeing storage. 191 */ 192 void 193 db_del_symbol_table(char *name) 194 { 195 int slot; 196 197 for (slot = 0; slot < MAXNOSYMTABS; slot++) { 198 if (db_symtabs[slot].name && 199 ! strcmp(db_symtabs[slot].name, name)) 200 break; 201 } 202 if (slot >= MAXNOSYMTABS) { 203 db_printf("Unable to find symbol table slot for %s.", name); 204 return; 205 } 206 207 db_symtabs[slot].start = 0; 208 db_symtabs[slot].end = 0; 209 db_symtabs[slot].name = 0; 210 db_symtabs[slot].private = 0; 211 } 212 213 /* 214 * db_qualify("vm_map", "bsd") returns "bsd:vm_map". 215 * 216 * Note: return value points to static data whose content is 217 * overwritten by each call... but in practice this seems okay. 218 */ 219 char * 220 db_qualify(db_sym_t sym, const char *symtabname) 221 { 222 char *symname; 223 static char tmp[256]; 224 char *s; 225 226 db_symbol_values(sym, &symname, 0); 227 s = tmp; 228 while ((*s++ = *symtabname++) != '\0') 229 ; 230 s[-1] = ':'; 231 while ((*s++ = *symname++) != '\0') 232 ; 233 return tmp; 234 } 235 236 237 boolean_t 238 db_eqname(char *src, char *dst, int c) 239 { 240 if (!strcmp(src, dst)) 241 return (TRUE); 242 if (src[0] == c) 243 return (!strcmp(src+1,dst)); 244 return (FALSE); 245 } 246 247 boolean_t 248 db_value_of_name(char *name, db_expr_t *valuep) 249 { 250 db_sym_t sym; 251 252 sym = db_lookup(name); 253 if (sym == DB_SYM_NULL) 254 return (FALSE); 255 db_symbol_values(sym, &name, valuep); 256 return (TRUE); 257 } 258 259 260 /* 261 * Lookup a symbol. 262 * If the symbol has a qualifier (e.g., ux:vm_map), 263 * then only the specified symbol table will be searched; 264 * otherwise, all symbol tables will be searched. 265 */ 266 db_sym_t 267 db_lookup(char *symstr) 268 { 269 db_sym_t sp; 270 int i; 271 int symtab_start = 0; 272 int symtab_end = MAXNOSYMTABS; 273 char *cp; 274 275 /* 276 * Look for, remove, and remember any symbol table specifier. 277 */ 278 for (cp = symstr; *cp; cp++) { 279 if (*cp == ':') { 280 *cp = '\0'; 281 for (i = 0; i < MAXNOSYMTABS; i++) { 282 if (db_symtabs[i].name && 283 ! strcmp(symstr, db_symtabs[i].name)) { 284 symtab_start = i; 285 symtab_end = i + 1; 286 break; 287 } 288 } 289 *cp = ':'; 290 if (i == MAXNOSYMTABS) { 291 db_error("invalid symbol table name"); 292 /*NOTREACHED*/ 293 } 294 symstr = cp+1; 295 } 296 } 297 298 /* 299 * Look in the specified set of symbol tables. 300 * Return on first match. 301 */ 302 for (i = symtab_start; i < symtab_end; i++) { 303 if (db_symtabs[i].name && 304 (sp = X_db_lookup(&db_symtabs[i], symstr))) { 305 db_last_symtab = &db_symtabs[i]; 306 return sp; 307 } 308 } 309 return 0; 310 } 311 312 /* Private structure for passing args to db_sift() from db_sifting(). */ 313 struct db_sift_args { 314 char *symstr; 315 int mode; 316 }; 317 318 /* 319 * Does the work of db_sifting(), called once for each 320 * symbol via X_db_forall(), prints out symbols matching 321 * criteria. 322 */ 323 static void 324 db_sift(db_symtab_t *stab, db_sym_t sym, char *name, char *suffix, int prefix, 325 void *arg) 326 { 327 char c, sc; 328 char *find, *p; 329 size_t len; 330 struct db_sift_args *dsa; 331 332 dsa = (struct db_sift_args*)arg; 333 334 find = dsa->symstr; /* String we're looking for. */ 335 p = name; /* String we're searching within. */ 336 337 /* Matching algorithm cribbed from strstr(), which is not 338 in the kernel. */ 339 if ((c = *find++) != 0) { 340 len = strlen(find); 341 do { 342 do { 343 if ((sc = *p++) == 0) 344 return; 345 } while (sc != c); 346 } while (strncmp(p, find, len) != 0); 347 } 348 if (dsa->mode=='F') /* ala ls -F */ 349 db_printf("%s%s ", name, suffix); 350 else 351 db_printf("%s ", name); 352 } 353 354 /* 355 * "Sift" for a partial symbol. 356 * Named for the Sun OpenPROM command ("sifting"). 357 * If the symbol has a qualifier (e.g., ux:vm_map), 358 * then only the specified symbol table will be searched; 359 * otherwise, all symbol tables will be searched.. 360 * 361 * "mode" is how-to-display, set from modifiers. 362 */ 363 void 364 db_sifting(char *symstr, int mode) 365 { 366 char *cp; 367 int i; 368 int symtab_start = 0; 369 int symtab_end = MAXNOSYMTABS; 370 struct db_sift_args dsa; 371 372 /* 373 * Look for, remove, and remember any symbol table specifier. 374 */ 375 for (cp = symstr; *cp; cp++) { 376 if (*cp == ':') { 377 *cp = '\0'; 378 for (i = 0; i < MAXNOSYMTABS; i++) { 379 if (db_symtabs[i].name && 380 ! strcmp(symstr, db_symtabs[i].name)) { 381 symtab_start = i; 382 symtab_end = i + 1; 383 break; 384 } 385 } 386 *cp = ':'; 387 if (i == MAXNOSYMTABS) { 388 db_error("invalid symbol table name"); 389 /*NOTREACHED*/ 390 } 391 symstr = cp+1; 392 } 393 } 394 395 /* Pass args to db_sift(). */ 396 dsa.symstr = symstr; 397 dsa.mode = mode; 398 399 /* 400 * Look in the specified set of symbol tables. 401 */ 402 for (i = symtab_start; i < symtab_end; i++) 403 if (db_symtabs[i].name) { 404 db_printf("Sifting table %s:\n", db_symtabs[i].name); 405 X_db_forall(&db_symtabs[i], db_sift, &dsa); 406 } 407 408 return; 409 } 410 411 412 /* 413 * Does this symbol name appear in more than one symbol table? 414 * Used by db_symbol_values to decide whether to qualify a symbol. 415 */ 416 boolean_t db_qualify_ambiguous_names = FALSE; 417 418 boolean_t 419 db_symbol_is_ambiguous(db_sym_t sym) 420 { 421 char *sym_name; 422 int i; 423 boolean_t found_once = FALSE; 424 425 if (!db_qualify_ambiguous_names) 426 return FALSE; 427 428 db_symbol_values(sym, &sym_name, 0); 429 for (i = 0; i < MAXNOSYMTABS; i++) { 430 if (db_symtabs[i].name && 431 X_db_lookup(&db_symtabs[i], sym_name)) { 432 if (found_once) 433 return TRUE; 434 found_once = TRUE; 435 } 436 } 437 return FALSE; 438 } 439 440 /* 441 * Find the closest symbol to val, and return its name 442 * and the difference between val and the symbol found. 443 */ 444 db_sym_t 445 db_search_symbol(db_addr_t val, db_strategy_t strategy, db_expr_t *offp) 446 { 447 unsigned int diff; 448 db_expr_t newdiff; 449 int i; 450 db_sym_t ret = DB_SYM_NULL, sym; 451 452 newdiff = diff = ~0; 453 db_last_symtab = 0; 454 for (i = 0; i < MAXNOSYMTABS; i++) { 455 if (!db_symtabs[i].name) 456 continue; 457 sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff); 458 if (newdiff < diff) { 459 db_last_symtab = &db_symtabs[i]; 460 diff = newdiff; 461 ret = sym; 462 } 463 } 464 *offp = diff; 465 return ret; 466 } 467 468 /* 469 * Return name and value of a symbol 470 */ 471 void 472 db_symbol_values(db_sym_t sym, char **namep, db_expr_t *valuep) 473 { 474 db_expr_t value; 475 476 if (sym == DB_SYM_NULL) { 477 *namep = 0; 478 return; 479 } 480 481 X_db_symbol_values(db_last_symtab, sym, namep, &value); 482 483 if (db_symbol_is_ambiguous(sym)) 484 *namep = db_qualify(sym, db_last_symtab->name); 485 if (valuep) 486 *valuep = value; 487 } 488 489 490 /* 491 * Print a the closest symbol to value 492 * 493 * After matching the symbol according to the given strategy 494 * we print it in the name+offset format, provided the symbol's 495 * value is close enough (eg smaller than db_maxoff). 496 * We also attempt to print [filename:linenum] when applicable 497 * (eg for procedure names). 498 * 499 * If we could not find a reasonable name+offset representation, 500 * then we just print the value in hex. Small values might get 501 * bogus symbol associations, e.g. 3 might get some absolute 502 * value like _INCLUDE_VERSION or something, therefore we do 503 * not accept symbols whose value is zero (and use plain hex). 504 * Also, avoid printing as "end+0x????" which is useless. 505 * The variable db_lastsym is used instead of "end" in case we 506 * add support for symbols in loadable driver modules. 507 */ 508 unsigned long db_lastsym = (unsigned long)end; 509 unsigned int db_maxoff = 0x10000000; 510 511 512 void 513 db_printsym(db_expr_t off, db_strategy_t strategy, 514 int (*pr)(const char *, ...)) 515 { 516 db_expr_t d; 517 char *filename; 518 char *name; 519 db_expr_t value; 520 int linenum; 521 db_sym_t cursym; 522 char buf[DB_FORMAT_BUF_SIZE]; 523 524 if (off <= db_lastsym) { 525 cursym = db_search_symbol(off, strategy, &d); 526 db_symbol_values(cursym, &name, &value); 527 if (name && (d < db_maxoff) && value) { 528 (*pr)("%s", name); 529 if (d) { 530 (*pr)("+%s", db_format(buf, sizeof(buf), 531 d, DB_FORMAT_R, 1, 0)); 532 } 533 if (strategy == DB_STGY_PROC) { 534 if (db_line_at_pc(cursym, &filename, &linenum, off)) 535 (*pr)(" [%s:%d]", filename, linenum); 536 } 537 return; 538 } 539 } 540 541 (*pr)("%s", db_format(buf, sizeof(buf), off, DB_FORMAT_N, 1, 0)); 542 return; 543 } 544 545 546 boolean_t 547 db_line_at_pc(db_sym_t sym, char **filename, int *linenum, db_expr_t pc) 548 { 549 return X_db_line_at_pc(db_last_symtab, sym, filename, linenum, pc); 550 } 551 552 int 553 db_sym_numargs(db_sym_t sym, int *nargp, char **argnames) 554 { 555 return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames); 556 } 557 558 boolean_t 559 X_db_sym_init(int symsize, void *vss, void *vse, const char *name) 560 { 561 562 if (db_symformat != NULL) 563 return ((*db_symformat->sym_init)(symsize, vss, vse, name)); 564 return (FALSE); 565 } 566 567 db_sym_t 568 X_db_lookup(db_symtab_t *stab, char *symstr) 569 { 570 571 if (db_symformat != NULL) 572 return ((*db_symformat->sym_lookup)(stab, symstr)); 573 return ((db_sym_t)0); 574 } 575 576 db_sym_t 577 X_db_search_symbol(db_symtab_t *stab, db_addr_t off, db_strategy_t strategy, 578 db_expr_t *diffp) 579 { 580 581 if (db_symformat != NULL) 582 return ((*db_symformat->sym_search)(stab, off, strategy, 583 diffp)); 584 return ((db_sym_t)0); 585 } 586 587 void 588 X_db_symbol_values(db_symtab_t *stab, db_sym_t sym, char **namep, 589 db_expr_t *valuep) 590 { 591 592 if (db_symformat != NULL) 593 (*db_symformat->sym_value)(stab, sym, namep, valuep); 594 } 595 596 boolean_t 597 X_db_line_at_pc(db_symtab_t *stab, db_sym_t cursym, char **filename, 598 int *linenum, db_expr_t off) 599 { 600 601 if (db_symformat != NULL) 602 return ((*db_symformat->sym_line_at_pc)(stab, cursym, 603 filename, linenum, off)); 604 return (FALSE); 605 } 606 607 boolean_t 608 X_db_sym_numargs(db_symtab_t *stab, db_sym_t cursym, int *nargp, 609 char **argnamep) 610 { 611 612 if (db_symformat != NULL) 613 return ((*db_symformat->sym_numargs)(stab, cursym, nargp, 614 argnamep)); 615 return (FALSE); 616 } 617 618 void 619 X_db_forall(db_symtab_t *stab, db_forall_func_t db_forall_func, void *arg) 620 { 621 if (db_symformat != NULL) 622 (*db_symformat->sym_forall)(stab, db_forall_func, arg); 623 } 624