|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * Author: David B. Golub, Carnegie Mellon University ! 28: * Date: 7/90 ! 29: */ ! 30: #include "mach_kdb.h" ! 31: #if MACH_KDB ! 32: ! 33: /* ! 34: * Symbol table routines for a.out format files. ! 35: */ ! 36: ! 37: #include <mach/std_types.h> ! 38: #include <machine/db_machdep.h> /* data types */ ! 39: #include <ddb/db_sym.h> ! 40: ! 41: #ifndef DB_NO_AOUT ! 42: ! 43: #include <ddb/nlist.h> /* a.out symbol table */ ! 44: #include <ddb/stab.h> ! 45: ! 46: #define private static ! 47: ! 48: /* ! 49: * An a.out symbol table as loaded into the kernel debugger: ! 50: * ! 51: * symtab -> size of symbol entries, in bytes ! 52: * sp -> first symbol entry ! 53: * ... ! 54: * ep -> last symbol entry + 1 ! 55: * strtab == start of string table ! 56: * size of string table in bytes, ! 57: * including this word ! 58: * -> strings ! 59: */ ! 60: ! 61: /* ! 62: * Find pointers to the start and end of the symbol entries, ! 63: * given a pointer to the start of the symbol table. ! 64: */ ! 65: #define db_get_aout_symtab(symtab, sp, ep) \ ! 66: (sp = (struct nlist *)((vm_offset_t *)(symtab) + 1), \ ! 67: ep = (struct nlist *)((char *)sp + *((int*)symtab))) ! 68: ! 69: boolean_t ! 70: aout_db_sym_init(symtab, esymtab, name, task_addr) ! 71: char * symtab; /* pointer to start of symbol table */ ! 72: char * esymtab; /* pointer to end of string table, ! 73: for checking - may be rounded up to ! 74: integer boundary */ ! 75: char * name; ! 76: char * task_addr; /* use for this task only */ ! 77: { ! 78: register struct nlist *sym_start, *sym_end; ! 79: register struct nlist *sp; ! 80: register char * strtab; ! 81: register int strlen; ! 82: char * estrtab; ! 83: ! 84: db_get_aout_symtab(symtab, sym_start, sym_end); ! 85: ! 86: strtab = (char *)sym_end; ! 87: strlen = *(int *)strtab; ! 88: estrtab = strtab + strlen; ! 89: ! 90: #define round_to_size(x) \ ! 91: (((vm_offset_t)(x) + sizeof(vm_size_t) - 1) & ~(sizeof(vm_size_t) - 1)) ! 92: ! 93: if (round_to_size(estrtab) != round_to_size(esymtab)) { ! 94: db_printf("[ %s symbol table not valid ]\n", name); ! 95: return (FALSE); ! 96: } ! 97: ! 98: #undef round_to_size ! 99: ! 100: for (sp = sym_start; sp < sym_end; sp++) { ! 101: register long strx; ! 102: strx = sp->n_un.n_strx; ! 103: if (strx != 0) { ! 104: if (strx > strlen) { ! 105: db_printf("Bad string table index (%#x)\n", strx); ! 106: sp->n_un.n_name = 0; ! 107: continue; ! 108: } ! 109: sp->n_un.n_name = strtab + strx; ! 110: } ! 111: } ! 112: ! 113: if (db_add_symbol_table(SYMTAB_AOUT, ! 114: (char *)sym_start, ! 115: (char *)sym_end, ! 116: name, ! 117: symtab, ! 118: task_addr)) ! 119: { ! 120: /* Successfully added symbol table */ ! 121: db_printf("[ preserving %d bytes of %s symbol table ]\n", ! 122: esymtab - (char *)symtab, name); ! 123: return TRUE; ! 124: } ! 125: else ! 126: return FALSE; ! 127: } ! 128: ! 129: /* ! 130: * check file name or not (check xxxx.x pattern) ! 131: */ ! 132: private boolean_t ! 133: aout_db_is_filename(name) ! 134: register char *name; ! 135: { ! 136: while (*name) { ! 137: if (*name == '.') { ! 138: if (name[1]) ! 139: return(TRUE); ! 140: } ! 141: name++; ! 142: } ! 143: return(FALSE); ! 144: } ! 145: ! 146: /* ! 147: * special name comparison routine with a name in the symbol table entry ! 148: */ ! 149: private boolean_t ! 150: aout_db_eq_name(sp, name) ! 151: struct nlist *sp; ! 152: char *name; ! 153: { ! 154: register char *s1, *s2; ! 155: ! 156: s1 = sp->n_un.n_name; ! 157: s2 = name; ! 158: if (*s1 == '_' && *s2 && *s2 != '_') ! 159: s1++; ! 160: while (*s2) { ! 161: if (*s1++ != *s2++) { ! 162: /* ! 163: * check .c .o file name comparison case ! 164: */ ! 165: if (*s2 == 0 && sp->n_un.n_name <= s1 - 2 ! 166: && s1[-2] == '.' && s1[-1] == 'o') ! 167: return(TRUE); ! 168: return(FALSE); ! 169: } ! 170: } ! 171: /* ! 172: * do special check for ! 173: * xxx:yyy for N_FUN ! 174: * xxx.ttt for N_DATA and N_BSS ! 175: */ ! 176: return(*s1 == 0 || (*s1 == ':' && sp->n_type == N_FUN) || ! 177: (*s1 == '.' && (sp->n_type == N_DATA || sp->n_type == N_BSS))); ! 178: } ! 179: ! 180: /* ! 181: * search a symbol table with name and type ! 182: * fp(in,out): last found text file name symbol entry ! 183: */ ! 184: private struct nlist * ! 185: aout_db_search_name(sp, ep, name, type, fp) ! 186: register struct nlist *sp; ! 187: struct nlist *ep; ! 188: char *name; ! 189: int type; ! 190: struct nlist **fp; ! 191: { ! 192: struct nlist *file_sp = *fp; ! 193: struct nlist *found_sp = 0; ! 194: ! 195: for ( ; sp < ep; sp++) { ! 196: if (sp->n_type == N_TEXT && aout_db_is_filename(sp->n_un.n_name)) ! 197: *fp = sp; ! 198: if (type) { ! 199: if (sp->n_type == type) { ! 200: if (aout_db_eq_name(sp, name)) ! 201: return(sp); ! 202: } ! 203: if (sp->n_type == N_SO) ! 204: *fp = sp; ! 205: continue; ! 206: } ! 207: if (sp->n_type & N_STAB) ! 208: continue; ! 209: if (sp->n_un.n_name && aout_db_eq_name(sp, name)) { ! 210: /* ! 211: * In case of qaulified search by a file, ! 212: * return it immediately with some check. ! 213: * Otherwise, search external one ! 214: */ ! 215: if (file_sp) { ! 216: if ((file_sp == *fp) || (sp->n_type & N_EXT)) ! 217: return(sp); ! 218: } else if (sp->n_type & N_EXT) ! 219: return(sp); ! 220: else ! 221: found_sp = sp; ! 222: } ! 223: } ! 224: return(found_sp); ! 225: } ! 226: ! 227: /* ! 228: * search a symbol with file, func and line qualification ! 229: */ ! 230: private db_sym_t ! 231: aout_db_qualified_search(stab, file, sym, line) ! 232: db_symtab_t *stab; ! 233: char *file; ! 234: char *sym; ! 235: int line; ! 236: { ! 237: register struct nlist *sp = (struct nlist *)stab->start; ! 238: struct nlist *ep = (struct nlist *)stab->end; ! 239: struct nlist *fp = 0; ! 240: struct nlist *found_sp; ! 241: unsigned long func_top; ! 242: boolean_t in_file; ! 243: ! 244: if (file == 0 && sym == 0) ! 245: return(0); ! 246: if (file) { ! 247: if ((sp = aout_db_search_name(sp, ep, file, N_TEXT, &fp)) == 0) ! 248: return(0); ! 249: } ! 250: if (sym) { ! 251: sp = aout_db_search_name(sp, ep, sym, (line > 0)? N_FUN: 0, &fp); ! 252: if (sp == 0) ! 253: return(0); ! 254: } ! 255: if (line > 0) { ! 256: if (file && !aout_db_eq_name(fp, file)) ! 257: return(0); ! 258: found_sp = 0; ! 259: if (sp->n_type == N_FUN) { ! 260: /* ! 261: * qualified by function name ! 262: * search backward because line number entries ! 263: * for the function are above it in this case. ! 264: */ ! 265: func_top = sp->n_value; ! 266: for (sp--; sp >= (struct nlist *)stab->start; sp--) { ! 267: if (sp->n_type != N_SLINE) ! 268: continue; ! 269: if (sp->n_value < func_top) ! 270: break; ! 271: if (sp->n_desc <= line) { ! 272: if (found_sp == 0 || found_sp->n_desc < sp->n_desc) ! 273: found_sp = sp; ! 274: if (sp->n_desc == line) ! 275: break; ! 276: } ! 277: } ! 278: if (sp->n_type != N_SLINE || sp->n_value < func_top) ! 279: return(0); ! 280: } else { ! 281: /* ! 282: * qualified by only file name ! 283: * search forward in this case ! 284: */ ! 285: in_file = TRUE; ! 286: for (sp++; sp < ep; sp++) { ! 287: if (sp->n_type == N_TEXT ! 288: && aout_db_is_filename(sp->n_un.n_name)) ! 289: break; /* enter into another file */ ! 290: if (sp->n_type == N_SOL) { ! 291: in_file = aout_db_eq_name(sp, file); ! 292: continue; ! 293: } ! 294: if (!in_file || sp->n_type != N_SLINE) ! 295: continue; ! 296: if (sp->n_desc <= line) { ! 297: if (found_sp == 0 || found_sp->n_desc < sp->n_desc) ! 298: found_sp = sp; ! 299: if (sp->n_desc == line) ! 300: break; ! 301: } ! 302: } ! 303: } ! 304: sp = found_sp; ! 305: } ! 306: return((db_sym_t) sp); ! 307: } ! 308: ! 309: /* ! 310: * lookup symbol by name ! 311: */ ! 312: db_sym_t ! 313: aout_db_lookup(stab, symstr) ! 314: db_symtab_t *stab; ! 315: char * symstr; ! 316: { ! 317: db_sym_t db_sym_parse_and_lookup(); ! 318: ! 319: return(db_sym_parse_and_lookup(aout_db_qualified_search, stab, symstr)); ! 320: } ! 321: ! 322: db_sym_t ! 323: aout_db_search_symbol(symtab, off, strategy, diffp) ! 324: db_symtab_t * symtab; ! 325: register ! 326: db_addr_t off; ! 327: db_strategy_t strategy; ! 328: db_expr_t *diffp; /* in/out */ ! 329: { ! 330: register unsigned long diff = *diffp; ! 331: register struct nlist *symp = 0; ! 332: register struct nlist *sp, *ep; ! 333: ! 334: sp = (struct nlist *)symtab->start; ! 335: ep = (struct nlist *)symtab->end; ! 336: ! 337: for (; sp < ep; sp++) { ! 338: if (sp->n_un.n_name == 0) ! 339: continue; ! 340: if ((sp->n_type & N_STAB) != 0) ! 341: continue; ! 342: if (strategy == DB_STGY_XTRN && (sp->n_type & N_EXT) == 0) ! 343: continue; ! 344: if (off >= sp->n_value) { ! 345: ! 346: unsigned int type = sp->n_type; ! 347: ! 348: if (type == N_FN) continue; ! 349: if (off - sp->n_value < diff) { ! 350: diff = off - sp->n_value; ! 351: symp = sp; ! 352: if (diff == 0 && (type & N_EXT)) ! 353: break; ! 354: } ! 355: else if (off - sp->n_value == diff) { ! 356: if (symp == 0) ! 357: symp = sp; ! 358: else if ((symp->n_type & N_EXT) == 0 && ! 359: (type & N_EXT) != 0) ! 360: symp = sp; /* pick the external symbol */ ! 361: } ! 362: } ! 363: } ! 364: if (symp == 0) { ! 365: *diffp = off; ! 366: } ! 367: else { ! 368: *diffp = diff; ! 369: } ! 370: return ((db_sym_t)symp); ! 371: } ! 372: ! 373: /* ! 374: * Return the name and value for a symbol. ! 375: */ ! 376: void ! 377: aout_db_symbol_values(sym, namep, valuep) ! 378: db_sym_t sym; ! 379: char **namep; ! 380: db_expr_t *valuep; ! 381: { ! 382: register struct nlist *sp; ! 383: ! 384: sp = (struct nlist *)sym; ! 385: if (namep) ! 386: *namep = sp->n_un.n_name; ! 387: if (valuep) ! 388: *valuep = sp->n_value; ! 389: } ! 390: ! 391: #define X_DB_MAX_DIFF 8 /* maximum allowable diff at the end of line */ ! 392: ! 393: /* ! 394: * search symbol by value ! 395: */ ! 396: private boolean_t ! 397: aout_db_search_by_addr(stab, addr, file, func, line, diff) ! 398: db_symtab_t *stab; ! 399: register vm_offset_t addr; ! 400: char **file; ! 401: char **func; ! 402: int *line; ! 403: unsigned long *diff; ! 404: { ! 405: register struct nlist *sp; ! 406: register struct nlist *line_sp, *func_sp, *file_sp, *line_func; ! 407: register vm_size_t func_diff, line_diff; ! 408: boolean_t found_line = FALSE; ! 409: struct nlist *ep = (struct nlist *)stab->end; ! 410: ! 411: line_sp = func_sp = file_sp = line_func = 0; ! 412: *file = *func = 0; ! 413: *line = 0; ! 414: func_diff = line_diff = ~0; ! 415: for (sp = (struct nlist *)stab->start; sp < ep; sp++) { ! 416: switch(sp->n_type) { ! 417: case N_SLINE: ! 418: if (sp->n_value <= addr) { ! 419: if (line_sp == 0 || line_diff >= addr - sp->n_value) { ! 420: if (line_func) ! 421: line_func = 0; ! 422: line_sp = sp; ! 423: line_diff = addr - sp->n_value; ! 424: } ! 425: } ! 426: if (sp->n_value >= addr && line_sp) ! 427: found_line = TRUE; ! 428: continue; ! 429: case N_FUN: ! 430: if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF)) ! 431: && line_func == 0) ! 432: line_func = sp; ! 433: continue; ! 434: case N_SO: ! 435: if (sp->n_value > addr) ! 436: continue; ! 437: if (file_sp == 0 || file_sp->n_value <= sp->n_value) ! 438: file_sp = sp; ! 439: continue; ! 440: case N_TEXT: ! 441: if (aout_db_is_filename(sp->n_un.n_name)) { ! 442: if (sp->n_value > addr) ! 443: continue; ! 444: if (file_sp == 0 || file_sp->n_value <= sp->n_value) ! 445: file_sp = sp; ! 446: } else if (sp->n_value <= addr && ! 447: (func_sp == 0 || func_diff > addr - sp->n_value)) { ! 448: func_sp = sp; ! 449: func_diff = addr - sp->n_value; ! 450: } ! 451: continue; ! 452: case N_TEXT|N_EXT: ! 453: if (sp->n_value <= addr && ! 454: (func_sp == 0 || func_diff >= addr - sp->n_value)) { ! 455: func_sp = sp; ! 456: func_diff = addr - sp->n_value; ! 457: if (func_diff == 0 && file_sp && func_sp) ! 458: break; ! 459: } ! 460: default: ! 461: continue; ! 462: } ! 463: break; ! 464: } ! 465: if (line_sp) { ! 466: if (line_func == 0 || func_sp == 0 ! 467: || line_func->n_value != func_sp->n_value) ! 468: line_sp = 0; ! 469: } ! 470: if (file_sp) { ! 471: *diff = addr - file_sp->n_value; ! 472: *file = file_sp->n_un.n_name; ! 473: } ! 474: if (func_sp) { ! 475: *diff = addr - func_sp->n_value; ! 476: *func = (func_sp->n_un.n_name[0] == '_')? ! 477: func_sp->n_un.n_name + 1: func_sp->n_un.n_name; ! 478: } ! 479: if (line_sp) { ! 480: *diff = addr - line_sp->n_value; ! 481: *line = line_sp->n_desc; ! 482: } ! 483: return(file_sp || func_sp || line_sp); ! 484: } ! 485: ! 486: /* ! 487: * Find filename and lineno within, given the current pc. ! 488: */ ! 489: boolean_t ! 490: aout_db_line_at_pc(stab, sym, file, line, pc) ! 491: db_symtab_t *stab; ! 492: db_sym_t sym; ! 493: char **file; ! 494: int *line; ! 495: db_expr_t pc; ! 496: { ! 497: char *func; ! 498: unsigned long diff; ! 499: boolean_t found; ! 500: ! 501: found = aout_db_search_by_addr(stab,(vm_offset_t)pc,file,&func,line,&diff); ! 502: return(found && func && *file); ! 503: } ! 504: ! 505: #endif /* DB_NO_AOUT */ ! 506: ! 507: #endif MACH_KDB
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.