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