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