|
|
1.1.1.2 ! root 1: /* 1.1 root 2: * Mach Operating System 3: * Copyright (c) 1991,1990 Carnegie Mellon University 4: * All Rights Reserved. 1.1.1.2 ! root 5: * 1.1 root 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. 1.1.1.2 ! root 11: * 1.1 root 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. 1.1.1.2 ! root 15: * 1.1 root 16: * Carnegie Mellon requests users of this software to return to 1.1.1.2 ! root 17: * 1.1 root 18: * Software Distribution Coordinator or [email protected] 19: * School of Computer Science 20: * Carnegie Mellon University 21: * Pittsburgh PA 15213-3890 1.1.1.2 ! root 22: * 1.1 root 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: */ 1.1.1.2 ! root 165: if (*s2 == 0 && sp->n_un.n_name <= s1 - 2 1.1 root 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: */ 1.1.1.2 ! root 176: return(*s1 == 0 || (*s1 == ':' && sp->n_type == N_FUN) || 1.1 root 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++) { 1.1.1.2 ! root 287: if (sp->n_type == N_TEXT 1.1 root 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: 1.1.1.2 ! root 507: #endif /* MACH_KDB */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.