Annotation of sys/ddb/db_sym.c, Revision 1.1
1.1 ! nbrk 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: }
CVSweb