db_sym.c revision 1.20
1/* $NetBSD: db_sym.c,v 1.20 2000/05/22 14:49:10 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 52db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},}; 53 54db_symtab_t *db_last_symtab; 55 56static char *db_qualify __P((db_sym_t, const char *)); 57static db_forall_func_t db_sift; 58 59/* 60 * Put the most picky symbol table formats at the top! 61 */ 62const 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 72const db_symformat_t *db_symformat; 73 74boolean_t X_db_sym_init __P((int, void *, void *, const char *)); 75db_sym_t X_db_lookup __P((db_symtab_t *, char *)); 76db_sym_t X_db_search_symbol __P((db_symtab_t *, db_addr_t, 77 db_strategy_t, db_expr_t *)); 78void X_db_symbol_values __P((db_symtab_t *, db_sym_t, char **, 79 db_expr_t *)); 80boolean_t X_db_line_at_pc __P((db_symtab_t *, db_sym_t, char **, 81 int *, db_expr_t)); 82int X_db_sym_numargs __P((db_symtab_t *, db_sym_t, int *, 83 char **)); 84void 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 */ 92void 93ddb_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 */ 128int 129db_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 */ 157void 158db_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 */ 185static char * 186db_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 205boolean_t 206db_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 218boolean_t 219db_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 */ 239db_sym_t 240db_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(). */ 287struct 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 */ 297static void 298db_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 */ 342void 343db_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 */ 397boolean_t db_qualify_ambiguous_names = FALSE; 398 399boolean_t 400db_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 */ 426db_sym_t 427db_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 */ 456void 457db_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 */ 496extern char end[]; 497unsigned long db_lastsym = (unsigned long)end; 498unsigned int db_maxoff = 0x10000000; 499 500 501void 502db_printsym(off, strategy) 503 db_expr_t off; 504 db_strategy_t strategy; 505{ 506 db_expr_t d; 507 char *filename; 508 char *name; 509 db_expr_t value; 510 int linenum; 511 db_sym_t cursym; 512 513 if (off <= db_lastsym) { 514 cursym = db_search_symbol(off, strategy, &d); 515 db_symbol_values(cursym, &name, &value); 516 if (name && (d < db_maxoff) && value) { 517 db_printf("%s", name); 518 if (d) 519 db_printf("+%#lr", d); 520 if (strategy == DB_STGY_PROC) { 521 if (db_line_at_pc(cursym, &filename, &linenum, off)) 522 db_printf(" [%s:%d]", filename, linenum); 523 } 524 return; 525 } 526 } 527 db_printf("%#ln", off); 528 return; 529} 530 531 532boolean_t 533db_line_at_pc( sym, filename, linenum, pc) 534 db_sym_t sym; 535 char **filename; 536 int *linenum; 537 db_expr_t pc; 538{ 539 return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc); 540} 541 542int 543db_sym_numargs(sym, nargp, argnames) 544 db_sym_t sym; 545 int *nargp; 546 char **argnames; 547{ 548 return X_db_sym_numargs(db_last_symtab, sym, nargp, argnames); 549} 550 551boolean_t 552X_db_sym_init(symsize, vss, vse, name) 553 int symsize; 554 void *vss, *vse; 555 const char *name; 556{ 557 558 if (db_symformat != NULL) 559 return ((*db_symformat->sym_init)(symsize, vss, vse, name)); 560 return (FALSE); 561} 562 563db_sym_t 564X_db_lookup(stab, symstr) 565 db_symtab_t *stab; 566 char *symstr; 567{ 568 569 if (db_symformat != NULL) 570 return ((*db_symformat->sym_lookup)(stab, symstr)); 571 return ((db_sym_t)0); 572} 573 574db_sym_t 575X_db_search_symbol(stab, off, strategy, diffp) 576 db_symtab_t *stab; 577 db_addr_t off; 578 db_strategy_t strategy; 579 db_expr_t *diffp; 580{ 581 582 if (db_symformat != NULL) 583 return ((*db_symformat->sym_search)(stab, off, strategy, 584 diffp)); 585 return ((db_sym_t)0); 586} 587 588void 589X_db_symbol_values(stab, sym, namep, valuep) 590 db_symtab_t *stab; 591 db_sym_t sym; 592 char **namep; 593 db_expr_t *valuep; 594{ 595 596 if (db_symformat != NULL) 597 (*db_symformat->sym_value)(stab, sym, namep, valuep); 598} 599 600boolean_t 601X_db_line_at_pc(stab, cursym, filename, linenum, off) 602 db_symtab_t *stab; 603 db_sym_t cursym; 604 char **filename; 605 int *linenum; 606 db_expr_t off; 607{ 608 609 if (db_symformat != NULL) 610 return ((*db_symformat->sym_line_at_pc)(stab, cursym, 611 filename, linenum, off)); 612 return (FALSE); 613} 614 615boolean_t 616X_db_sym_numargs(stab, cursym, nargp, argnamep) 617 db_symtab_t *stab; 618 db_sym_t cursym; 619 int *nargp; 620 char **argnamep; 621{ 622 623 if (db_symformat != NULL) 624 return ((*db_symformat->sym_numargs)(stab, cursym, nargp, 625 argnamep)); 626 return (FALSE); 627} 628 629void 630X_db_forall(stab, db_forall_func, arg) 631 db_symtab_t *stab; 632 db_forall_func_t db_forall_func; 633 void *arg; 634{ 635 if (db_symformat != NULL) 636 (*db_symformat->sym_forall)(stab, db_forall_func, arg); 637} 638