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