|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * @OSF_COPYRIGHT@ ! 24: */ ! 25: /* ! 26: * Mach Operating System ! 27: * Copyright (c) 1991,1990 Carnegie Mellon University ! 28: * All Rights Reserved. ! 29: * ! 30: * Permission to use, copy, modify and distribute this software and its ! 31: * documentation is hereby granted, provided that both the copyright ! 32: * notice and this permission notice appear in all copies of the ! 33: * software, derivative works or modified versions, and any portions ! 34: * thereof, and that both notices appear in supporting documentation. ! 35: * ! 36: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 37: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 38: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 39: * ! 40: * Carnegie Mellon requests users of this software to return to ! 41: * ! 42: * Software Distribution Coordinator or [email protected] ! 43: * School of Computer Science ! 44: * Carnegie Mellon University ! 45: * Pittsburgh PA 15213-3890 ! 46: * ! 47: * any improvements or extensions that they make and grant Carnegie Mellon ! 48: * the rights to redistribute these changes. ! 49: */ ! 50: /* ! 51: */ ! 52: /* ! 53: * Author: David B. Golub, Carnegie Mellon University ! 54: * Date: 7/90 ! 55: */ ! 56: /* ! 57: * Symbol table routines for a.out format files. ! 58: */ ! 59: #include <mach/boolean.h> ! 60: #include <mach/std_types.h> ! 61: #include <machine/db_machdep.h> /* data types */ ! 62: #include <string.h> /* For strcpy(), strcmp() */ ! 63: #include <ddb/db_aout.h> ! 64: #include <ddb/db_output.h> /* For db_printf() */ ! 65: #include <ddb/db_sym.h> ! 66: ! 67: #ifndef DB_NO_AOUT ! 68: ! 69: #include <ddb/nlist.h> /* a.out symbol table */ ! 70: #include <ddb/stab.h> ! 71: ! 72: #define private static ! 73: ! 74: private int aout_db_order_symbols(char *, char *); ! 75: private int aout_db_compare_symbols(char *, char *); ! 76: private boolean_t aout_db_is_filename(char *); ! 77: private boolean_t aout_db_eq_name(struct nlist *, char *, int); ! 78: ! 79: /* ! 80: * An a.out symbol table as loaded into the kernel debugger: ! 81: * ! 82: * symtab -> size of symbol entries, in bytes ! 83: * sp -> first symbol entry ! 84: * ... ! 85: * ep -> last symbol entry + 1 ! 86: * strtab == start of string table ! 87: * size of string table in bytes, ! 88: * including this word ! 89: * -> strings ! 90: */ ! 91: ! 92: /* ! 93: * Find pointers to the start and end of the symbol entries, ! 94: * given a pointer to the start of the symbol table. ! 95: */ ! 96: #define db_get_aout_symtab(symtab, sp, ep) \ ! 97: (sp = (struct nlist *)(((vm_offset_t *)(symtab)) + 1), \ ! 98: ep = (struct nlist *)((char *)sp + *((int *)(symtab)))) ! 99: ! 100: char *db_sorting_sym_end; ! 101: ! 102: private int ! 103: aout_db_order_symbols( ! 104: char *s1, ! 105: char *s2) ! 106: { ! 107: struct nlist *sym1 = (struct nlist *) s1; ! 108: struct nlist *sym2 = (struct nlist *) s2; ! 109: ! 110: if (sym1->n_value != sym2->n_value) ! 111: return (sym1->n_value - sym2->n_value); ! 112: else { ! 113: return (sym1->n_un.n_name - sym2->n_un.n_name); ! 114: } ! 115: } ! 116: ! 117: private int ! 118: aout_db_compare_symbols( ! 119: char *sym1, ! 120: char *sym2) ! 121: { ! 122: return (((struct nlist *) sym1)->n_value - ! 123: ((struct nlist *) sym2)->n_value); ! 124: } ! 125: ! 126: int db_sorting_limit = 50000; ! 127: ! 128: boolean_t ! 129: aout_db_sym_init( ! 130: char * symtab, /* pointer to start of symbol table */ ! 131: char * esymtab, /* pointer to end of string table, ! 132: for checking - may be rounded up to ! 133: integer boundary */ ! 134: char * name, ! 135: char * task_addr) /* use for this task only */ ! 136: { ! 137: struct nlist *sym_start, *sym_end; ! 138: struct nlist *sp; ! 139: char * strtab; ! 140: int strlen; ! 141: char * estrtab; ! 142: unsigned long minsym = ~0; ! 143: unsigned long maxsym = 0; ! 144: boolean_t sorted; ! 145: boolean_t sorting; ! 146: #ifdef __MACHO__ ! 147: extern boolean_t getsymtab(char *, ! 148: vm_offset_t *, int *, ! 149: vm_offset_t *, vm_size_t *); ! 150: int nsyms; ! 151: #endif ! 152: ! 153: ! 154: #ifdef __MACHO__ ! 155: if (!getsymtab(symtab, ! 156: (vm_offset_t *)&sym_start, &nsyms, ! 157: (vm_offset_t *)&strtab, (vm_size_t *)&strlen)) { ! 158: return(FALSE); ! 159: } ! 160: sym_end = sym_start + nsyms; ! 161: estrtab = strtab + strlen; ! 162: #else ! 163: db_get_aout_symtab(symtab, sym_start, sym_end); ! 164: ! 165: db_sorting_sym_end = (char *)sym_end; ! 166: strtab = (char *)sym_end; ! 167: strlen = *(int *)strtab; ! 168: estrtab = strtab + strlen; ! 169: #endif ! 170: ! 171: #ifndef __MACHO__ ! 172: #define round_to_size(x) \ ! 173: (((vm_offset_t)(x) + sizeof(vm_size_t) - 1) & ~(sizeof(vm_size_t) - 1)) ! 174: ! 175: if (round_to_size(estrtab) != round_to_size(esymtab)) ! 176: return (FALSE); ! 177: ! 178: #undef round_to_size ! 179: #endif ! 180: ! 181: sorting = ((sym_end - sym_start) < db_sorting_limit); ! 182: ! 183: for (sp = sym_start; sp < sym_end; sp++) { ! 184: register long strx; ! 185: strx = sp->n_un.n_strx; ! 186: if (strx != 0) { ! 187: if (strx > strlen) { ! 188: sp->n_un.n_name = 0; ! 189: continue; ! 190: } ! 191: sp->n_un.n_name = strtab + strx; ! 192: } ! 193: if (sp->n_type != N_ABS) { ! 194: if (sp->n_value > 0 && sp->n_value < minsym) ! 195: minsym = sp->n_value; ! 196: if (sp->n_value > maxsym) ! 197: maxsym = sp->n_value; ! 198: } ! 199: } ! 200: if (maxsym < minsym) ! 201: minsym = maxsym = 0; ! 202: ! 203: if (sorting) { ! 204: db_qsort((char *) sym_start, sym_end - sym_start, ! 205: sizeof (struct nlist), aout_db_order_symbols); ! 206: sorted = TRUE; ! 207: } else ! 208: sorted = FALSE; ! 209: ! 210: if (db_add_symbol_table(SYMTAB_AOUT, ! 211: (char*)sym_start, ! 212: (char*)sym_end, ! 213: name, ! 214: symtab, ! 215: task_addr, ! 216: minsym, ! 217: maxsym, ! 218: sorted)) ! 219: { ! 220: /* Successfully added symbol table */ ! 221: ! 222: pmap_protect(kernel_pmap, ! 223: (vm_offset_t) sym_start, (vm_offset_t) sym_end, ! 224: VM_PROT_READ|VM_PROT_WRITE); ! 225: pmap_protect(kernel_pmap, ! 226: (vm_offset_t) strtab, (vm_offset_t) estrtab, ! 227: VM_PROT_READ|VM_PROT_WRITE); ! 228: return TRUE; ! 229: } ! 230: return FALSE; ! 231: } ! 232: ! 233: /* ! 234: * This KLUDGE offsets the n_values of a copied symbol table ! 235: */ ! 236: void db_clone_offsetXXX(char *, long); ! 237: void ! 238: db_clone_offsetXXX(char * symtab, long offset) ! 239: { ! 240: register struct nlist *sym_start, *sym_end, *sp; ! 241: ! 242: db_get_aout_symtab((int *)symtab, sym_start, sym_end); ! 243: ! 244: for (sp = sym_start; sp < sym_end; sp++) ! 245: if (sp->n_type != N_ABS) ! 246: sp->n_value += offset; ! 247: } ! 248: /* end KLUDGE */ ! 249: ! 250: /* ! 251: * check file name or not (check xxxx.x pattern) ! 252: */ ! 253: private boolean_t ! 254: aout_db_is_filename(char *name) ! 255: { ! 256: while (*name) { ! 257: if (*name == '.') { ! 258: if (name[1]) ! 259: return(TRUE); ! 260: } ! 261: name++; ! 262: } ! 263: return(FALSE); ! 264: } ! 265: ! 266: /* ! 267: * special name comparison routine with a name in the symbol table entry ! 268: */ ! 269: private boolean_t ! 270: aout_db_eq_name( ! 271: struct nlist *sp, ! 272: char *name, ! 273: int incomplete) ! 274: { ! 275: register char *s1, *s2; ! 276: ! 277: s1 = sp->n_un.n_name; ! 278: s2 = name; ! 279: #ifndef __NO_UNDERSCORES__ ! 280: if (*s1 == '_' && *s2 && *s2 != '_') ! 281: s1++; ! 282: #endif /* __NO_UNDERSCORES__ */ ! 283: while (*s2) { ! 284: if (*s1++ != *s2++) { ! 285: /* ! 286: * check .c .o file name comparison case ! 287: */ ! 288: if (*s2 == 0 && sp->n_un.n_name <= s1 - 2 ! 289: && s1[-2] == '.' && s1[-1] == 'o') ! 290: return(TRUE); ! 291: return(FALSE); ! 292: } ! 293: } ! 294: if (incomplete) ! 295: return(TRUE); ! 296: /* ! 297: * do special check for ! 298: * xxx:yyy for N_FUN ! 299: * xxx.ttt for N_DATA and N_BSS ! 300: */ ! 301: return(*s1 == 0 || (*s1 == ':' && sp->n_type == N_FUN) || ! 302: (*s1 == '.' && (sp->n_type == N_DATA || sp->n_type == N_BSS))); ! 303: } ! 304: ! 305: /* ! 306: * search a symbol table with name and type ! 307: * fp(in,out): last found text file name symbol entry ! 308: */ ! 309: private struct nlist * ! 310: aout_db_search_name( ! 311: struct nlist *sp, ! 312: struct nlist *ep, ! 313: char *name, ! 314: int type, ! 315: struct nlist **fp, ! 316: int incomplete) ! 317: { ! 318: struct nlist *file_sp = *fp; ! 319: struct nlist *found_sp = 0; ! 320: ! 321: for ( ; sp < ep; sp++) { ! 322: if (sp->n_other) ! 323: sp->n_other = 0; ! 324: if (sp->n_type == N_TEXT && aout_db_is_filename(sp->n_un.n_name)) ! 325: *fp = sp; ! 326: if (type) { ! 327: if (sp->n_type == type) { ! 328: /* dwm_debug: b26 name, mk6 added last param */ ! 329: if (aout_db_eq_name(sp, name, 0)) ! 330: return(sp); ! 331: } ! 332: if (sp->n_type == N_SO) ! 333: *fp = sp; ! 334: continue; ! 335: } ! 336: if (sp->n_type & N_STAB) ! 337: continue; ! 338: if (sp->n_un.n_name && aout_db_eq_name(sp, name, incomplete)) { ! 339: /* ! 340: * In case of qaulified search by a file, ! 341: * return it immediately with some check. ! 342: * Otherwise, search external one ! 343: */ ! 344: if (file_sp) { ! 345: if ((file_sp == *fp) || (sp->n_type & N_EXT)) ! 346: return(sp); ! 347: } else if ((sp->n_type & N_EXT) || ! 348: (incomplete && !aout_db_is_filename(sp->n_un.n_name))) ! 349: return(sp); ! 350: else ! 351: found_sp = sp; ! 352: } ! 353: } ! 354: return(found_sp); ! 355: } ! 356: ! 357: /* ! 358: * Print sorted possible completions for a symbol. ! 359: * Use n_other field to mark completion symbols in order ! 360: * to speed up sort. ! 361: */ ! 362: int ! 363: aout_db_qualified_print_completion( ! 364: db_symtab_t *stab, ! 365: char *sym) ! 366: { ! 367: struct nlist *sp; ! 368: struct nlist *sp1; ! 369: struct nlist *ep; ! 370: struct nlist *ep1; ! 371: struct nlist *fp = 0; ! 372: int symlen; ! 373: int nsym = 0; ! 374: struct nlist *cur; ! 375: struct nlist *new; ! 376: char *fname; ! 377: int func; ! 378: int line; ! 379: ! 380: sp = aout_db_search_name((struct nlist *)stab->start, ! 381: (struct nlist *)stab->end, ! 382: sym, 0, &fp, 1); ! 383: if (sp == (struct nlist *)0) ! 384: return 0; ! 385: ! 386: symlen = strlen(sym); ! 387: cur = sp; ! 388: while (cur) { ! 389: if (strncmp(cur->n_un.n_name, sym, symlen) == 0) ! 390: cur->n_other = 1; ! 391: else ! 392: cur->n_other = 2; ! 393: ep = cur; ! 394: cur = aout_db_search_name(cur + 1, (struct nlist *)stab->end, ! 395: sym, 0, &fp, 1); ! 396: } ! 397: ! 398: sp1 = sp; ! 399: for (;;) { ! 400: new = cur = sp; ! 401: while (++cur <= ep) ! 402: if (cur->n_other) { ! 403: if (sp1 == sp) ! 404: sp1 = cur; ! 405: if (strcmp(&cur->n_un.n_name[cur->n_other - 1], ! 406: &new->n_un.n_name[new->n_other - 1]) < 0) ! 407: new = cur; ! 408: else ! 409: ep1 = cur; ! 410: } ! 411: ! 412: func = line = 0; ! 413: if ((new->n_type & N_EXT) == 0) { ! 414: for (cur = new - 1; cur > (struct nlist *)stab->start; cur--) { ! 415: if (cur->n_type == N_SO || ! 416: (stab->sorted && cur->n_value < new->n_value)) ! 417: break; ! 418: if (line == 0 && ! 419: cur->n_type == N_SLINE && ! 420: cur->n_value == new->n_value) ! 421: line = cur->n_desc; ! 422: if (func == 0 && ! 423: cur->n_type == N_FUN && ! 424: cur->n_value == new->n_value) ! 425: func = 1; ! 426: } ! 427: ! 428: if (cur->n_type == N_SO) ! 429: fname = cur->n_un.n_name; ! 430: else ! 431: fname = (char *)0; ! 432: ! 433: if (line == 0 || func == 0) ! 434: for (cur = new + 1; ! 435: cur < (struct nlist *)stab->end; cur++) { ! 436: if (cur->n_type == N_SO || ! 437: (stab->sorted && cur->n_value > new->n_value)) ! 438: break; ! 439: if (line == 0 && ! 440: cur->n_type == N_SLINE && ! 441: cur->n_value == new->n_value) { ! 442: line = cur->n_desc; ! 443: if (func) ! 444: break; ! 445: } ! 446: if (func == 0 && ! 447: cur->n_type == N_FUN && ! 448: cur->n_value == new->n_value) { ! 449: func = 1; ! 450: if (line) ! 451: break; ! 452: } ! 453: } ! 454: } else { ! 455: fname = (char *)0; ! 456: for (cur = new - 1; cur > (struct nlist *)stab->start; cur--) { ! 457: if (cur->n_type == N_SO || ! 458: (stab->sorted && cur->n_value < new->n_value)) ! 459: break; ! 460: if (func == 0 && ! 461: cur->n_type == N_FUN && ! 462: cur->n_value == new->n_value) ! 463: func = 1; ! 464: } ! 465: if (func == 0) ! 466: for (cur = new + 1; ! 467: cur < (struct nlist *)stab->end; cur++) { ! 468: if (cur->n_type == N_SO || ! 469: (stab->sorted && cur->n_value > new->n_value)) ! 470: break; ! 471: if (cur->n_type == N_FUN && ! 472: cur->n_value == new->n_value) { ! 473: func = 1; ! 474: break; ! 475: } ! 476: } ! 477: } ! 478: ! 479: db_sym_print_completion(stab, &new->n_un.n_name[new->n_other - 1], ! 480: func, fname, line); ! 481: nsym++; ! 482: new->n_other = 0; ! 483: ! 484: if (new == sp) { ! 485: if (sp1 == sp) ! 486: break; ! 487: sp = sp1; ! 488: } else if (new == sp1) ! 489: sp1 = sp; ! 490: ! 491: if (new == ep) ! 492: ep = ep1; ! 493: } ! 494: return nsym; ! 495: } ! 496: ! 497: /* ! 498: * search a (possibly incomplete) symbol with file, func and line qualification ! 499: */ ! 500: private int ! 501: aout_db_qualified_search( ! 502: db_symtab_t *stab, ! 503: char *file, ! 504: char *sym, ! 505: int line, ! 506: db_sym_t *ret, ! 507: char **name, ! 508: int *len) ! 509: { ! 510: register struct nlist *sp = (struct nlist *)stab->start; ! 511: struct nlist *ep = (struct nlist *)stab->end; ! 512: struct nlist *fp = 0; ! 513: struct nlist *found_sp; ! 514: unsigned long func_top; ! 515: boolean_t in_file; ! 516: int nsym = 0; ! 517: int i; ! 518: char *p; ! 519: ! 520: if (file == 0 && sym == 0) ! 521: return(0); ! 522: if (file) { ! 523: if ((sp = aout_db_search_name(sp, ep, file, N_TEXT, &fp, 0)) == 0) ! 524: return(0); ! 525: } ! 526: if (sym) { ! 527: for (;;) { ! 528: sp = aout_db_search_name(sp, ep, sym, (line > 0)? N_FUN: 0, &fp, ! 529: (ret == (db_sym_t *)0)); ! 530: if (sp == 0) ! 531: return(nsym); ! 532: if (ret) ! 533: break; ! 534: ! 535: if (strncmp(sp->n_un.n_name, sym, strlen(sym)) == 0) ! 536: p = sp->n_un.n_name; ! 537: else ! 538: p = &sp->n_un.n_name[1]; ! 539: ! 540: if (*name == (char *)0) { ! 541: *name = p; ! 542: *len = strlen(p); ! 543: } else { ! 544: for (i = 0; i < *len; i++) ! 545: if ((*name)[i] != p[i]) { ! 546: *len = i; ! 547: break; ! 548: } ! 549: } ! 550: ! 551: nsym++; ! 552: sp++; ! 553: } ! 554: } ! 555: if (line > 0) { ! 556: if (file && !aout_db_eq_name(fp, file, 0)) ! 557: return(0); ! 558: found_sp = 0; ! 559: if (sp->n_type == N_FUN) { ! 560: /* ! 561: * qualfied by function name ! 562: * search backward because line number entries ! 563: * for the function are above it in this case. ! 564: */ ! 565: func_top = sp->n_value; ! 566: if (stab->sorted) { ! 567: /* symbols with the same value may have been mixed up */ ! 568: do { ! 569: sp++; ! 570: } while (sp->n_value == func_top); ! 571: } ! 572: for (sp--; sp >= (struct nlist *)stab->start; sp--) { ! 573: if (sp->n_type != N_SLINE) ! 574: continue; ! 575: if (sp->n_value < func_top) ! 576: break; ! 577: if (sp->n_desc <= line) { ! 578: if (found_sp == 0 || found_sp->n_desc < sp->n_desc) ! 579: found_sp = sp; ! 580: if (sp->n_desc == line) ! 581: break; ! 582: } ! 583: } ! 584: if (sp->n_type != N_SLINE || sp->n_value < func_top) ! 585: return(0); ! 586: } else { ! 587: /* ! 588: * qualified by only file name ! 589: * search forward in this case ! 590: */ ! 591: in_file = TRUE; ! 592: if (stab->sorted) { ! 593: /* symbols with the same value may have been mixed up */ ! 594: func_top = sp->n_value; ! 595: do { ! 596: sp--; ! 597: } while (sp->n_value == func_top); ! 598: } ! 599: for (sp++; sp < ep; sp++) { ! 600: if (sp->n_type == N_TEXT ! 601: && aout_db_is_filename(sp->n_un.n_name)) ! 602: break; /* enter into another file */ ! 603: if (sp->n_type == N_SOL) { ! 604: in_file = aout_db_eq_name(sp, file, 0); ! 605: continue; ! 606: } ! 607: if (!in_file || sp->n_type != N_SLINE) ! 608: continue; ! 609: if (sp->n_desc <= line) { ! 610: if (found_sp == 0 || found_sp->n_desc < sp->n_desc) ! 611: found_sp = sp; ! 612: if (sp->n_desc == line) ! 613: break; ! 614: } ! 615: } ! 616: } ! 617: sp = found_sp; ! 618: } ! 619: *ret = (db_sym_t) sp; ! 620: return(1); ! 621: } ! 622: ! 623: /* ! 624: * lookup symbol by name ! 625: */ ! 626: db_sym_t ! 627: aout_db_lookup( ! 628: db_symtab_t *stab, ! 629: char * symstr) ! 630: { ! 631: return(db_sym_parse_and_lookup(aout_db_qualified_search, stab, symstr)); ! 632: } ! 633: ! 634: /* ! 635: * lookup (possibly incomplete) symbol by name ! 636: */ ! 637: int ! 638: aout_db_lookup_incomplete( ! 639: db_symtab_t *stab, ! 640: char * symstr, ! 641: char ** name, ! 642: int *len, ! 643: int *toadd) ! 644: { ! 645: return(db_sym_parse_and_lookup_incomplete(aout_db_qualified_search, ! 646: stab, symstr, name, len, toadd)); ! 647: } ! 648: ! 649: /* ! 650: * Display possible completion for the symbol ! 651: */ ! 652: int ! 653: aout_db_print_completion(stab, symstr) ! 654: db_symtab_t *stab; ! 655: char * symstr; ! 656: { ! 657: ! 658: return(db_sym_parse_and_print_completion(aout_db_qualified_print_completion, ! 659: stab, symstr)); ! 660: } ! 661: ! 662: db_sym_t ! 663: aout_db_search_symbol( ! 664: db_symtab_t *symtab, ! 665: db_addr_t off, ! 666: db_strategy_t strategy, ! 667: db_expr_t *diffp) /* in/out */ ! 668: { ! 669: register unsigned long diff = *diffp; ! 670: register struct nlist *symp = 0; ! 671: struct nlist *sp, *ep, *cp; ! 672: boolean_t first_pass = FALSE; ! 673: ! 674: sp = (struct nlist *)symtab->start; ! 675: ep = (struct nlist *)symtab->end; ! 676: ! 677: if (symtab->sorted) { ! 678: struct nlist target; ! 679: ! 680: target.n_value = off; ! 681: target.n_un.n_name = (char *) 0; ! 682: target.n_other = (char) 0; ! 683: db_qsort_limit_search((char *) &target, (char **) &sp, (char **) &ep, ! 684: sizeof (struct nlist), aout_db_compare_symbols); ! 685: first_pass = TRUE; ! 686: } ! 687: ! 688: try_again: ! 689: for (cp = ep-1; cp >= sp; cp--) { ! 690: if (cp->n_un.n_name == 0) ! 691: continue; ! 692: if ((cp->n_type & N_STAB) != 0) ! 693: continue; ! 694: if (strategy == DB_STGY_XTRN && (cp->n_type & N_EXT) == 0) ! 695: continue; ! 696: if (off >= cp->n_value) { ! 697: if (off - cp->n_value < diff) { ! 698: diff = off - cp->n_value; ! 699: symp = cp; ! 700: if (diff == 0 && (cp->n_type & N_EXT)) ! 701: break; ! 702: } ! 703: else if (off - cp->n_value == diff) { ! 704: if (symp == 0) ! 705: symp = cp; ! 706: else if ((symp->n_type & N_EXT) == 0 && ! 707: (cp->n_type & N_EXT) != 0) ! 708: symp = cp; /* pick the external symbol */ ! 709: } ! 710: } ! 711: } ! 712: if (symp == 0) { ! 713: if (first_pass) { ! 714: first_pass = FALSE; ! 715: sp = (struct nlist *) symtab->start; ! 716: goto try_again; ! 717: } ! 718: *diffp = off; ! 719: } ! 720: else { ! 721: *diffp = diff; ! 722: } ! 723: return ((db_sym_t)symp); ! 724: } ! 725: ! 726: /* ! 727: * Return the name and value for a symbol. ! 728: */ ! 729: void ! 730: aout_db_symbol_values( ! 731: db_sym_t sym, ! 732: char **namep, ! 733: db_expr_t *valuep) ! 734: { ! 735: register struct nlist *sp; ! 736: ! 737: sp = (struct nlist *)sym; ! 738: if (namep) ! 739: *namep = sp->n_un.n_name; ! 740: if (valuep) ! 741: *valuep = sp->n_value; ! 742: } ! 743: ! 744: #define X_DB_MAX_DIFF 8 /* maximum allowable diff at the end of line */ ! 745: extern int db_search_maxoff; /* maximum acceptable offset */ ! 746: ! 747: /* ! 748: * search symbol by value ! 749: */ ! 750: db_sym_t ! 751: aout_db_search_by_addr( ! 752: db_symtab_t *stab, ! 753: db_addr_t addr, ! 754: char **file, ! 755: char **func, ! 756: int *line, ! 757: db_expr_t *diff, ! 758: int *args) ! 759: { ! 760: struct nlist *sp, *cp; ! 761: register struct nlist *line_sp, *func_sp, *file_sp, *line_func; ! 762: unsigned long func_diff, line_diff; ! 763: boolean_t found_line = FALSE; ! 764: struct nlist *ep = (struct nlist *)stab->end; ! 765: boolean_t first_pass = FALSE; ! 766: ! 767: /* ! 768: * 92-May-16 ! 769: * Added init of these two... not sure if it's correct, but ! 770: * can't be worse than random values.... -- [email protected] ! 771: */ ! 772: func_diff = line_diff = /*HUGE*/0x0fffffff; ! 773: ! 774: line_sp = func_sp = file_sp = line_func = 0; ! 775: *file = *func = 0; ! 776: *line = 0; ! 777: *args = -1; ! 778: ! 779: sp = (struct nlist *)stab->start; ! 780: if (stab->sorted) { ! 781: struct nlist target; ! 782: ! 783: target.n_value = addr; ! 784: target.n_un.n_name = (char *) 0; ! 785: target.n_other = (char) 0; ! 786: db_qsort_limit_search((char *) &target, (char **) &sp, ! 787: (char **) &ep, sizeof (struct nlist), ! 788: aout_db_compare_symbols); ! 789: first_pass = TRUE; ! 790: } ! 791: ! 792: for (cp = sp; cp < ep; cp++) { ! 793: switch(cp->n_type) { ! 794: case N_SLINE: ! 795: if (cp->n_value <= addr) { ! 796: if (line_sp == 0 || line_diff >= addr - cp->n_value) { ! 797: if (line_func) ! 798: line_func = 0; ! 799: line_sp = cp; ! 800: line_diff = addr - cp->n_value; ! 801: } ! 802: } ! 803: if (cp->n_value >= addr && line_sp) ! 804: found_line = TRUE; ! 805: continue; ! 806: case N_FUN: ! 807: if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF)) ! 808: && line_func == 0) ! 809: line_func = cp; ! 810: continue; ! 811: case N_SO: ! 812: if (cp->n_value > addr) ! 813: continue; ! 814: if (file_sp == 0 || file_sp->n_value <= cp->n_value) ! 815: file_sp = cp; ! 816: continue; ! 817: case N_TEXT: ! 818: if (aout_db_is_filename(cp->n_un.n_name)) { ! 819: if (cp->n_value > addr) ! 820: continue; ! 821: if (file_sp == 0 || file_sp->n_value <= cp->n_value) ! 822: file_sp = cp; ! 823: } else if (cp->n_value <= addr && ! 824: (func_sp == 0 || func_diff > addr - cp->n_value)) { ! 825: func_sp = cp; ! 826: func_diff = addr - cp->n_value; ! 827: } ! 828: continue; ! 829: case N_TEXT|N_EXT: ! 830: if (cp->n_value <= addr && ! 831: (func_sp == 0 || func_diff >= addr - cp->n_value)) { ! 832: func_sp = cp; ! 833: func_diff = addr - cp->n_value; ! 834: if (func_diff == 0 && file_sp && func_sp && line_sp == 0) ! 835: break; ! 836: } ! 837: default: ! 838: if (stab->sorted) { ! 839: if ((cp->n_value > addr) && ! 840: (cp->n_value - addr > db_search_maxoff)) ! 841: break; ! 842: } ! 843: continue; ! 844: } ! 845: break; ! 846: } ! 847: if (first_pass && (!file_sp || !line_sp || !func_sp)) { ! 848: first_pass = FALSE; ! 849: cp = sp; ! 850: sp = (struct nlist *)stab->start; ! 851: for (; cp >= sp; cp--) { ! 852: switch(cp->n_type) { ! 853: case N_SLINE: ! 854: if (line_sp) ! 855: found_line = TRUE; ! 856: continue; ! 857: case N_FUN: ! 858: if ((found_line || (line_sp && line_diff < X_DB_MAX_DIFF)) ! 859: && line_func == 0) ! 860: line_func = cp; ! 861: continue; ! 862: case N_SO: ! 863: if (file_sp == 0) ! 864: file_sp = cp; ! 865: continue; ! 866: case N_TEXT: ! 867: if (aout_db_is_filename(cp->n_un.n_name)) { ! 868: if (file_sp == 0) ! 869: file_sp = cp; ! 870: } else if (func_sp == 0) { ! 871: func_sp = cp; ! 872: func_diff = addr - cp->n_value; ! 873: } ! 874: continue; ! 875: case N_TEXT|N_EXT: ! 876: if (func_sp == 0) { ! 877: func_sp = cp; ! 878: func_diff = addr - cp->n_value; ! 879: if (func_diff == 0 && file_sp && func_sp ! 880: && line_sp == 0) ! 881: break; ! 882: } ! 883: default: ! 884: if (line_sp && file_sp && ! 885: addr - cp->n_value > db_search_maxoff) ! 886: break; ! 887: continue; ! 888: } ! 889: break; ! 890: } ! 891: } ! 892: #if 0 ! 893: /* ! 894: * XXX - [email protected] ! 895: * I don't know if that code is useful to something, but it makes the -gline ! 896: * option of gcc useless. ! 897: */ ! 898: if (line_sp) { ! 899: if (line_func == 0 || func_sp == 0 ! 900: || line_func->n_value != func_sp->n_value) ! 901: line_sp = 0; ! 902: } ! 903: #else ! 904: if (line_sp && !found_line) { ! 905: line_sp = 0; ! 906: } ! 907: #endif ! 908: *diff = 0; ! 909: if (file_sp) { ! 910: *diff = addr - file_sp->n_value; ! 911: *file = file_sp->n_un.n_name; ! 912: } ! 913: if (line_sp) { ! 914: *diff = addr - line_sp->n_value; ! 915: *line = line_sp->n_desc; ! 916: } ! 917: if (func_sp) { ! 918: *diff = addr - func_sp->n_value; ! 919: *func = (func_sp->n_un.n_name[0] == '_')? ! 920: func_sp->n_un.n_name + 1: func_sp->n_un.n_name; ! 921: if (line_func && (line_func->n_desc & 0x4000)) ! 922: *args = line_func->n_desc & 0x3ff; ! 923: } ! 924: return((db_sym_t) func_sp); ! 925: } ! 926: ! 927: /* ! 928: * Find filename and lineno within, given the current pc. ! 929: */ ! 930: boolean_t ! 931: aout_db_line_at_pc( ! 932: db_symtab_t *stab, ! 933: db_sym_t sym, ! 934: char **file, ! 935: int *line, ! 936: db_expr_t pc) ! 937: { ! 938: char *func; ! 939: db_expr_t diff; ! 940: boolean_t found; ! 941: int args; ! 942: ! 943: found = (aout_db_search_by_addr(stab, (unsigned)pc, file, &func, line, ! 944: &diff, &args) ! 945: != DB_SYM_NULL); ! 946: return(found && func && *file); ! 947: } ! 948: ! 949: /* ! 950: * Initialization routine for a.out files. ! 951: */ ! 952: void ! 953: aout_db_init(void) ! 954: { ! 955: #ifndef __MACHO__ ! 956: extern vm_offset_t kern_sym_start; ! 957: extern vm_size_t kern_sym_size; ! 958: #else ! 959: extern struct mach_header _mh_execute_header; ! 960: #endif ! 961: ! 962: #ifndef __MACHO__ ! 963: if (kern_sym_size != 0) ! 964: aout_db_sym_init((char *) kern_sym_start, ! 965: (char *)(kern_sym_start + kern_sym_size), ! 966: "mach", ! 967: (char *)0); ! 968: #else ! 969: aout_db_sym_init((char *) &_mh_execute_header, ! 970: (char *)0, "mach", (char *)0); ! 971: #endif ! 972: } ! 973: ! 974: #endif /* DB_NO_AOUT */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.