1: static char sccsid[] = "@(#)symt.c 4.3 8/17/82"; 2: #include "head.h" 3: #include <a.out.h> 4: #include <stab.h> 5: 6: #ifndef STABTYPES 7: #define STABTYPES N_STAB 8: #endif 9: #include <sys/stat.h> 10: 11: struct user u; 12: int compar(); 13: char *symfil; 14: 15: #ifdef FLEXNAMES 16: 17: struct nlist *symtab; 18: char nullname[] = {0,0,0,0,0,0,0,0,0}; /* a few 0 bytes */ 19: off_t stoff; 20: 21: stread(buff, nbytes) 22: struct nlist *buff; 23: int nbytes; 24: { 25: register int from = stoff; 26: 27: stoff += nbytes; 28: if (stoff >= gstart) 29: return (-1); 30: if (nbytes < 0) { 31: from = stoff; 32: buff--; 33: } 34: from = (from - ststart); 35: *buff = symtab[from/sizeof (struct nlist)]; 36: return (sizeof (struct nlist)); 37: } 38: 39: stseek(off, rel) 40: long off; 41: { 42: 43: if (rel == 1) 44: stoff += off; 45: else 46: stoff = off; 47: } 48: #define bread(a,b,c) stread(b,c) 49: #define blseek(a,b,c) stseek(b,c) 50: #endif 51: 52: /* initialize file and procedure tables */ 53: initfp() { 54: struct nlist stentry; 55: register struct proct *procp; 56: register struct filet *filep; 57: struct stat stbuf; 58: 59: long soffset; 60: int i, gflag = 0; 61: u_char class; 62: register char *p, *q; 63: 64: #ifdef FLEXNAMES 65: register struct nlist *sp; 66: int malformed = 0; 67: lseek(txtmap.ufd, gstart, 0); 68: if (read(txtmap.ufd, &ssiz, sizeof(ssiz)) != sizeof (ssiz)) { 69: printf("%s: no string table (old format?)\n", symfil); 70: exit(1); 71: } 72: strtab = (char *)malloc(ssiz); 73: if (strtab == 0) { 74: printf("no room for %d bytes of string table\n", ssiz); 75: exit(1); 76: } 77: ssiz -= sizeof (ssiz); 78: if (read(txtmap.ufd, strtab+sizeof (ssiz), ssiz) != ssiz) { 79: printf("%s: error reading string table\n", symfil); 80: exit(1); 81: } 82: i = gstart - ststart; 83: symtab = (struct nlist *)malloc(i); 84: if (symtab == 0) { 85: printf("no room for %d bytes of symbol table\n", i); 86: exit(1); 87: } 88: lseek(txtmap.ufd, ststart, 0); 89: if (read(txtmap.ufd, symtab, i) != i) { 90: printf("%s: error reading symbol table\n", symfil); 91: exit(1); 92: } 93: for (sp = &symtab[i/sizeof (struct nlist)]; --sp >= symtab; ) 94: if (sp->n_un.n_strx != 0) { 95: if (sp->n_un.n_strx < sizeof (ssiz) || sp->n_un.n_strx >= ssiz) { 96: if (malformed == 0) { 97: printf("danger: mangled symbol table\n"); 98: malformed = 1; 99: } 100: sp->n_un.n_name = nullname; 101: } else 102: sp->n_un.n_name = strtab + sp->n_un.n_strx; 103: } else 104: sp->n_un.n_name = nullname; 105: #endif 106: #ifndef VMUNIX 107: sbuf.fd = txtmap.ufd; 108: #endif 109: firstdata = MAXPOS; 110: soffset = ststart; 111: blseek(&sbuf,ststart,0); 112: filep = files = badfile = (struct filet *) sbrk(sizeof filep[0]); 113: procp = procs = badproc = (struct proct *) sbrk(sizeof procp[0]); 114: 115: for(;;) { 116: if (bread(&sbuf, &stentry, sizeof stentry) < 117: sizeof stentry) break; 118: class = stentry.n_type & STABMASK; 119: switch (class & STABMASK) { 120: case N_SO: 121: case N_SOL: 122: gflag++; 123: if (filep == badfile) { 124: p = sbrk(FILEINCR*sizeof filep[0]); 125: if (p < 0) { 126: perror("sdb"); 127: exit(4); 128: } 129: q = p + FILEINCR*sizeof filep[0]; 130: while (p > (char *) procs) 131: *--q = *--p; 132: badfile += FILEINCR; 133: procp = (struct proct *) 134: ((char *) procp + 135: FILEINCR*sizeof filep[0]); 136: procs = (struct proct *) 137: ((char *) procs + 138: FILEINCR*sizeof filep[0]); 139: badproc = (struct proct *) 140: ((char *)badproc + 141: FILEINCR*sizeof filep[0]); 142: } 143: filep->faddr = stentry.n_value; 144: filep->lineflag = (class == N_SOL); 145: filep->stf_offset = soffset; 146: #ifndef FLEXNAMES 147: p = filep->sfilename; 148: for (;;) { 149: for (i=0; i<8; i++) *p++ = stentry.n_un.n_name[i]; 150: if (*(p-1) == '\0') break; 151: if (bread(&sbuf, &stentry, sizeof stentry) 152: < sizeof stentry) 153: error("Bad N_SO entry (1)"); 154: if ((stentry.n_type & STABMASK) != class) 155: error("Bad N_SO entry (2)"); 156: soffset += sizeof stentry; 157: } 158: #else 159: filep->sfilename = stentry.n_un.n_name; 160: #endif 161: q = filep->sfilename; 162: for (p=fp; *q; *p++ = *q++) ; 163: *p = 0; 164: if (stat(filework, &stbuf) == -1) 165: printf("Warning: `%s' not found\n", 166: filep->sfilename); 167: else if (stbuf.st_mtime > symtime) 168: printf("Warning: `%s' newer than `%s'\n", 169: filep->sfilename, 170: symfil); 171: filep++; 172: break; 173: 174: case N_TEXT: 175: if (stentry.n_un.n_name[0] != '_') break; 176: case N_FUN: 177: case N_ENTRY: 178: if (procp == badproc) { 179: if (sbrk(PROCINCR*sizeof procp[0]) < 0) { 180: perror("sdb"); 181: exit(4); 182: } 183: badproc += PROCINCR; 184: } 185: #ifndef FLEXNAMES 186: for(i=0; i<8; i++) 187: procp->pname[i] = stentry.n_un.n_name[i]; 188: #else 189: procp->pname = stentry.n_un.n_name; 190: #endif 191: procp->paddr = stentry.n_value; 192: procp->st_offset = soffset; 193: procp->sfptr = (class != N_TEXT) ? filep - 1 : badfile; 194: procp->lineno = (class != N_TEXT) ? stentry.n_desc : 0; 195: procp->entrypt = (class & STABMASK) == N_ENTRY; 196: procp++; 197: break; 198: } 199: if (stentry.n_type & N_EXT) { 200: if (!extstart) 201: extstart = soffset; 202: if (stentry.n_type == N_DATA | N_EXT || 203: stentry.n_type == N_BSS | N_EXT || 204: stentry.n_value < firstdata) 205: firstdata = stentry.n_value; 206: } 207: soffset += sizeof stentry; 208: } 209: qsort(procs, procp-procs, sizeof procs[0], compar); 210: badproc->st_offset = badfile->stf_offset = soffset; 211: badproc->sfptr = procp->sfptr = badfile; 212: #ifndef FLEXNAMES 213: badproc->pname[0] = badfile->sfilename[0]= 214: procp->pname[0] = filep->sfilename[0] = '\0'; 215: #else 216: badproc->pname = badfile->sfilename= 217: procp->pname = filep->sfilename = nullname; 218: #endif 219: 220: if (!gflag) 221: printf("Warning: `%s' not compiled with -g\n", symfil); 222: setcur(1); 223: } 224: 225: /* returns current procedure from state (curfile, fline) */ 226: struct proct * 227: curproc() { 228: register ADDR addr; 229: 230: addr = getaddr("", fline ? fline : 1); 231: if (addr == -1) return(badproc); 232: return(adrtoprocp(addr)); 233: 234: } 235: 236: /* returns procedure s, uses curproc() if s == NULL */ 237: 238: struct proct * 239: findproc(s) 240: char *s; { 241: register struct proct *p, *altproc; 242: 243: if (s[0] == '\0') return(curproc()); 244: altproc = badproc; 245: 246: for (p=procs; p->pname[0]; p++) { 247: if (eqpat(s, p->pname)) return(p); 248: if (p->pname[0] == '_' && eqpatr(s, p->pname+1, 1)) 249: altproc = p; 250: } 251: return(altproc); 252: } 253: 254: /* returns file s containing filename */ 255: struct filet * 256: findfile(s) 257: char *s; { 258: register struct filet *f; 259: if (s == 0 || *s == 0) 260: return(files); /* start at beginning if no cur file */ 261: for (f=files; f->sfilename[0]; f++) { 262: if (eqpat(f->sfilename, s)) { 263: for( ; f->lineflag; f--) ; 264: if (f < files) error("Bad file array"); 265: return(f); 266: } 267: } 268: return(f); 269: } 270: 271: /* 272: * slookup(): 273: * looks up variable matching pat starting at (offset + sizeof stentry) 274: * in a.out, searching backwards, 275: * ignoring nested blocks to beginning to procedure. 276: * Returns its offset and symbol table entries decoded in sl_* 277: * 278: * If comblk == "*" then match both within and outside common blocks, 279: * if comblk == "" then match only outside common blocks, 280: * else match only within comblk. 281: */ 282: 283: long 284: slookup(pat, poffset, stelt) 285: long poffset; char *pat; { 286: slookinit(); 287: slooknext(pat, poffset, stelt, "*"); 288: } 289: 290: int clevel, level, fnameflag, comfound, incomm; 291: 292: slookinit() { 293: clevel = level = fnameflag = comfound = incomm = 0; 294: } 295: 296: long 297: slooknext(pat, poffset, stelt, comblk) 298: long poffset; char *pat, *comblk; { 299: register int i; 300: register long offset; 301: char *q; 302: u_char class; 303: struct nlist stentry; 304: struct proct *procp, *p; 305: 306: offset = poffset + sizeof stentry; 307: if (debug) printf("slookup(%s,%d)\n",pat,offset); 308: blseek(&sbuf, offset, 0); 309: 310: for (;;) { 311: offset -= sizeof stentry; 312: if (offset < ststart) break; 313: if (bread(&sbuf, &stentry+1, -sizeof stentry) 314: < sizeof stentry) break; 315: class = stentry.n_type & STABMASK; 316: switch (class & STABMASK) { 317: case 0: 318: break; 319: case N_FUN: 320: return(-1); 321: case N_RBRAC: 322: level++; 323: break; 324: case N_LBRAC: 325: level--; 326: break; 327: case N_ECOMM: 328: i = 0; 329: #ifndef FLEXNAMES 330: for (q = &stentry.n_un.n_name[7]; q>=stentry.n_un.n_name; q--) { 331: if (*q == '_') { 332: *q = '\0'; 333: i++; 334: break; 335: } 336: } 337: #else 338: for (q = stentry.n_un.n_name; *q; q++) 339: continue; 340: if (*--q == '_') 341: *q = 0, i++; 342: #endif 343: if (eqpat(comblk, stentry.n_un.n_name)) 344: comfound = 1; 345: if (i) 346: *q = '_'; 347: incomm = 1; 348: case N_ECOML: 349: clevel++; 350: break; 351: case N_BCOMM: 352: comfound = incomm = 0; 353: clevel--; 354: break; 355: case N_FNAME: 356: if (fnameflag) 357: break; 358: procp = findproc(stentry.n_un.n_name); 359: for (p=procs; p->pname[0]; p++) { 360: if (p->entrypt == 0 && 361: p->st_offset > procp->st_offset && 362: p->st_offset < offset) 363: offset = p->st_offset; 364: } 365: clevel = level = 0; 366: fnameflag++; 367: blseek(&sbuf, offset, 0); 368: break; 369: default: 370: if (level <= 0 && eqpat(pat, stentry.n_un.n_name) && 371: stentry.n_un.n_name[0] && class & STABTYPES && 372: (eqstr("*", comblk) || 373: (comblk[0] == '\0' && incomm == 0) || 374: comfound) && 375: (stelt == (class == N_SSYM))) { 376: if (class == N_LENG) { 377: sl_size = stentry.n_value; 378: offset -= sizeof stentry; 379: bread(&sbuf, &stentry+1, 380: -sizeof stentry); 381: if (stentry.n_type&~N_EXT == N_BSS) { 382: bread(&sbuf, &stentry+1, 383: -sizeof stentry); 384: offset -= sizeof stentry; 385: } 386: } 387: else sl_size = 0; 388: sl_class = stentry.n_type & STABMASK; 389: sl_type = stentry.n_desc; 390: sl_addr = stentry.n_value; 391: #ifndef FLEXNAMES 392: for (i=0; i<8; i++) sl_name[i] = 393: stentry.n_un.n_name[i]; 394: #else 395: sl_name = stentry.n_un.n_name; 396: #endif 397: if (clevel != 0) docomm(offset); 398: return(offset - sizeof stentry); 399: } 400: } 401: } 402: return(-1); 403: } 404: 405: /* 406: * Look up global variable matching pat starting at (filestart+sizeof stentry) 407: * Return its offset and symbol table entries decoded in sl_* 408: */ 409: long 410: globallookup(pat, filestart, stelt) 411: char *pat; long filestart; { 412: register int offset, i; 413: struct nlist stentry; 414: int clevel; 415: u_char class; 416: 417: if (debug) printf("globallookup(%s,%d)\n", pat,filestart); 418: blseek(&sbuf, filestart, 0); 419: offset = filestart - sizeof stentry; 420: clevel = 0; 421: do { 422: if (bread(&sbuf, &stentry, sizeof stentry) < 423: sizeof stentry) return(-1); 424: offset += sizeof stentry; 425: } while ((stentry.n_type & STABMASK) == N_SO); 426: for (;;) { 427: class = stentry.n_type & STABMASK; 428: switch (class & STABMASK) { 429: case N_SO: 430: return(-1); 431: case N_ECOMM: 432: clevel--; 433: break; 434: case N_BCOMM: 435: clevel++; 436: break; 437: default: 438: if (eqpat(pat, stentry.n_un.n_name) 439: && stentry.n_un.n_name[0] && class & STABTYPES) { 440: sl_class = stentry.n_type & STABMASK; 441: if (sl_class != N_GSYM && sl_class != N_SSYM && 442: sl_class != N_STSYM && sl_class != N_LCSYM) goto g1; 443: if (stelt != (sl_class == N_SSYM)) goto g1; 444: sl_size = 0; 445: sl_type = stentry.n_desc; 446: sl_addr = stentry.n_value; 447: #ifndef FLEXNAMES 448: for (i=0; i<8; i++) sl_name[i] = stentry.n_un.n_name[i]; 449: #else 450: sl_name = stentry.n_un.n_name; 451: #endif 452: if (clevel != 0) docomm(offset); 453: goto g2; 454: } 455: } 456: g1: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) 457: return(-1); 458: offset += sizeof stentry; 459: } 460: g2: bread(&sbuf, &stentry, sizeof stentry); 461: if (stentry.n_type&~N_EXT==N_BSS) { 462: bread(&sbuf, &stentry, sizeof stentry); 463: offset += sizeof stentry; 464: } 465: if (((stentry.n_type & STABMASK) == N_LENG) && 466: (eqpat(sl_name, stentry.n_un.n_name))) 467: sl_size = stentry.n_value; 468: 469: if (sl_class == N_GSYM && (clevel == 0)) { 470: blseek(&sbuf, extstart, 0); 471: for(;;) { 472: if (bread(&sbuf, &stentry, sizeof stentry) 473: < sizeof stentry) 474: return(-1); 475: if (stentry.n_un.n_name[0] != '_') continue; 476: if (eqpatr(sl_name, stentry.n_un.n_name+1, 1)) { 477: sl_addr = stentry.n_value; 478: break; 479: } 480: } 481: } 482: return(offset + sizeof stentry); 483: } 484: 485: /* core address to procedure (pointer to proc array) */ 486: struct proct * 487: adrtoprocp(addr) 488: ADDR addr; { 489: register struct proct *procp, *lastproc; 490: lastproc = badproc; 491: for (procp=procs; procp->pname[0]; procp++) { 492: if (procp->paddr > addr) break; 493: if (procp->entrypt == 0) 494: lastproc = procp; 495: } 496: return (lastproc); 497: } 498: 499: 500: /* core address to file (pointer to file array) */ 501: struct filet * 502: adrtofilep(addr) 503: ADDR addr; { 504: register struct filet *filep; 505: for (filep=files; filep->sfilename[0]; filep++) { 506: if (filep->faddr > addr) break; 507: } 508: return (filep != files ? filep-1 : badfile); 509: } 510: 511: /* 512: * core address to linenumber 513: * Sets external exactaddr to addr if addr is NOT the first instruction 514: * of a line, set to -1 otherwise. 515: * Sets external lnfaddr to address of first statement in line. 516: */ 517: long lastoffset; 518: 519: adrtolineno(addr) 520: ADDR addr; { 521: register int lineno; 522: long offset; 523: struct nlist stentry; 524: 525: exactaddr = addr; 526: lineno = lastoffset = -1; 527: offset = adrtoprocp(addr)->st_offset; 528: blseek(&sbuf, offset, 0); 529: for (;;) { 530: if (bread(&sbuf, &stentry, sizeof stentry) 531: < sizeof stentry) break; 532: if (stentry.n_type == N_SO) 533: break; 534: if (stentry.n_type == N_SLINE) { 535: if (stentry.n_value > addr) 536: break; 537: lastoffset = offset; 538: lineno = stentry.n_desc; 539: lnfaddr = stentry.n_value; 540: if (stentry.n_value == addr) 541: exactaddr = -1; 542: } 543: offset += sizeof stentry; 544: } 545: return (lineno); 546: } 547: 548: 549: /* address to a.out offset */ 550: long 551: adrtostoffset(addr) 552: ADDR addr; { 553: adrtolineno(addr); 554: return(lastoffset); 555: } 556: 557: 558: /* 559: * Set (curfile, lineno) from core image. 560: * Returns 1 if there is a core image, 0 otherwise. 561: * 562: * Print the current line iff verbose is set. 563: */ 564: setcur(verbose) { 565: register struct proct *procp; 566: 567: dot = *(ADDR *) (((ADDR) &u) + PC); 568: 569: if (dot == 0) { 570: printf("No core image\n"); 571: goto setmain; 572: } 573: procp = adrtoprocp(dot); 574: if ((procp->sfptr) != badfile) { 575: finit(adrtofilep(procp->paddr)->sfilename); 576: ffind(adrtolineno(dot)); 577: if (verbose) { 578: if (exactaddr != -1) 579: printf("0x%x in ", exactaddr); 580: #ifndef FLEXNAMES 581: printf("%.8s:", procp->pname); 582: #else 583: printf("%s:", procp->pname); 584: #endif 585: fprint(); 586: } 587: return(1); 588: } 589: if (verbose) { 590: if (procp->pname[0] == '_') 591: #ifndef FLEXNAMES 592: printf("%.7s: address 0x%x\n", procp->pname+1, dot); 593: #else 594: printf("%s: address 0x%x\n", procp->pname+1, dot); 595: #endif 596: else 597: #ifndef FLEXNAMES 598: printf("%.8s: address %d\n", procp->pname, dot); 599: #else 600: printf("%s: address %d\n", procp->pname, dot); 601: #endif 602: } 603: 604: setmain: 605: procp = findproc("MAIN_"); 606: if ((procp->pname[0] != 'M') || (procp->sfptr == badfile)) { 607: procp = findproc("main"); 608: if ((procp->pname[0] != 'm') || (procp->sfptr == badfile)) { 609: /* printf("main not compiled with debug flag\n"); */ 610: return(0); 611: } 612: } 613: finit(procp->sfptr->sfilename); 614: ffind(procp->lineno); 615: return(0); 616: } 617: 618: compar(a, b) 619: struct proct *a, *b; { 620: if (a->paddr == b->paddr) { 621: if (a->pname[0] == '_') return(-1); 622: if (b->pname[0] == '_') return(1); 623: return(0); 624: } 625: return(a->paddr < b->paddr ? -1 : 1); 626: } 627: 628: /* gets offset of file or procedure named s */ 629: nametooffset(s) 630: char *s; { 631: register struct filet *f; 632: register struct proct *p; 633: 634: if (*s == '\0') 635: return(-1); 636: if (eqany('.', s)) { 637: f = findfile(s); 638: return(f->sfilename[0] ? f->stf_offset : -1); 639: } 640: p = findproc(s); 641: return(p->pname[0] ? p->st_offset : -1); 642: } 643: 644: /* returns s if its a filename, its file otherwise */ 645: char * 646: nametofile(s) 647: char *s; { 648: register struct proct *p; 649: 650: if (eqany('.', s)) { 651: return(s); 652: } 653: p = findproc(s); 654: return(adrtofilep(p->paddr)->sfilename); 655: } 656: 657: 658: /* line number to address, starting at offset in a.out */ 659: /* assumes that offset is within file */ 660: lntoaddr(lineno, offset, file) 661: long offset; char *file; { 662: struct nlist stentry; 663: register int i, ignore = 0; 664: register int bestln=BIGNUM; 665: ADDR bestaddr; 666: char *p; 667: 668: blseek(&sbuf, offset, 0); 669: 670: do { 671: if (bread(&sbuf, &stentry, sizeof stentry) < 672: sizeof stentry) return(-1); 673: } while ((stentry.n_type & STABMASK) == N_SO); 674: for (;;) { 675: switch(stentry.n_type & STABMASK) { 676: case N_SLINE: 677: if (!ignore) { 678: if (stentry.n_desc == lineno) 679: return(stentry.n_value); 680: if (stentry.n_desc > lineno && 681: stentry.n_desc < bestln) { 682: bestln = stentry.n_desc; 683: bestaddr = stentry.n_value; 684: } 685: } 686: break; 687: 688: case N_SO: 689: goto ret; 690: 691: case N_SOL: 692: p = file; 693: #ifndef FLEXNAMES 694: for (;;) { 695: for (i=0; i<8; i++) { 696: if (*p != stentry.n_un.n_name[i]) goto neq; 697: if (*p++ == '\0') break; 698: } 699: if (stentry.n_un.n_name[7] == '\0') 700: break; 701: if (bread(&sbuf, &stentry, sizeof stentry) 702: < sizeof stentry) 703: error("Bad N_SO entry (1)"); 704: if ((stentry.n_type & STABMASK) != (u_char)N_SOL) 705: error("Bad N_SO entry (2)"); 706: } 707: #else 708: if (strcmp(file, stentry.n_un.n_name)) 709: goto neq; 710: #endif 711: ignore = 0; 712: break; 713: 714: neq: ignore++; 715: break; 716: } 717: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) 718: break; 719: } 720: ret: return(bestln == BIGNUM ? -1 : bestaddr); 721: } 722: 723: /* gets address of proc:number */ 724: getaddr(proc,integ) 725: char *proc; { 726: register long offset; 727: register char *s, *f; 728: ADDR addr; 729: 730: s = proc[0] ? proc : curfile; 731: if (*s == '\0') 732: return(-1); 733: offset = nametooffset(s); 734: f = nametofile(s); 735: if (debug) printf("getaddr() computed offset %d", offset); 736: if (offset == -1) { 737: addr = extaddr(proc); 738: if (addr != -1) addr += 2; /* MACHINE DEPENDENT */ 739: if (debug) printf(" extaddr computed %d\n", addr); 740: return(addr); 741: } 742: if (integ) 743: addr = lntoaddr(integ, offset, s); 744: else { 745: ADDR oldaddr; 746: oldaddr = findproc(proc)->paddr + 2; /* MACHINE DEPENDENT */ 747: addr = lntoaddr(adrtolineno(addr)+1, offset, f); 748: if (addr == -1) 749: addr = oldaddr; 750: } 751: if (debug) printf(" and addr %d\n", addr); 752: if (addr == -1) return(-1); 753: return(addr); 754: } 755: 756: /* returns address of external */ 757: ADDR 758: extaddr(name) 759: char *name; { 760: struct nlist stentry; 761: blseek(&sbuf, extstart, 0); 762: 763: for (;;) { 764: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) 765: return(-1); 766: if (stentry.n_un.n_name[0] == '_' && 767: eqpatr(name, stentry.n_un.n_name+1, 1)) 768: return(stentry.n_value); 769: } 770: } 771: 772: 773: /* 774: * Look up external data symbol matching pat starting at 775: * (filestart+sizeof stentry) 776: * Return its address in sl_addr and name in sl_name. 777: */ 778: long 779: extlookup(pat, filestart) 780: char *pat; long filestart; { 781: register int offset, i; 782: struct nlist stentry; 783: 784: blseek(&sbuf, filestart, 0); 785: offset = filestart - sizeof stentry; 786: do { 787: if (bread(&sbuf, &stentry, sizeof stentry) < 788: sizeof stentry) return(-1); 789: offset += sizeof stentry; 790: } while ((stentry.n_type & STABMASK) == N_SO); 791: for (;;) { 792: if (stentry.n_un.n_name[0] == '_' && 793: stentry.n_type == (N_DATA | N_EXT) && 794: eqpatr(pat, stentry.n_un.n_name+1, 1)) { 795: sl_addr = stentry.n_value; 796: #ifndef FLEXNAMES 797: for (i=0; i<7; i++) sl_name[i] = stentry.n_un.n_name[i+1]; 798: #else 799: sl_name = stentry.n_un.n_name; 800: #endif 801: return(offset + sizeof stentry); 802: } 803: g1: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) 804: return(-1); 805: offset += sizeof stentry; 806: } 807: } 808: 809: /* find enclosing common blocks and fix up addresses */ 810: docomm(offset) 811: long offset; { 812: struct nlist stentry; 813: ADDR addr; 814: 815: for (;;) { 816: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) { 817: error("Bad common block"); 818: return; 819: } 820: sl_class = N_GSYM; 821: if ((stentry.n_type & STABMASK) == N_ECOMM) { 822: addr = extaddr(stentry.n_un.n_name); 823: if (addr == -1) 824: error("Lost common block"); 825: sl_addr +=addr; 826: blseek(&sbuf, offset, 0); 827: return; 828: } 829: if ((stentry.n_type & STABMASK) == N_ECOML) { 830: sl_addr += stentry.n_value; 831: blseek(&sbuf, offset, 0); 832: return; 833: } 834: } 835: } 836: 837: /* determine if class is that of a variable */ 838: char pctypes[] = {N_GSYM, N_STSYM, N_LCSYM, N_RSYM, N_SSYM, N_LSYM, 839: N_PSYM, 0}; 840: varclass(class) 841: u_char class; { 842: char *p; 843: 844: for (p=pctypes; *p; p++) { 845: if (class == *p) 846: return(1); 847: } 848: return(0); 849: } 850: 851: /* 852: * address to external name 853: * returns difference between addr and address of external 854: * name returned in sl_name 855: */ 856: adrtoext(addr) 857: ADDR addr; { 858: struct nlist stentry; 859: register int i, prevdiff = MAXPOS, diff; 860: 861: blseek(&sbuf, extstart, 0); 862: for (;;) { 863: if (bread(&sbuf, &stentry, sizeof stentry) 864: < sizeof stentry) 865: return (prevdiff!=MAXPOS ? prevdiff : -1); 866: if (stentry.n_type == (N_DATA | N_EXT) || 867: stentry.n_type == (N_BSS | N_EXT)) { 868: diff = addr - stentry.n_value; 869: if (diff >= 0 && diff < prevdiff) { 870: #ifndef FLEXNAMES 871: for (i=0; i<7; i++) 872: sl_name[i] = stentry.n_un.n_name[i+1]; 873: #else 874: sl_name = stentry.n_un.n_name; 875: #endif 876: if (diff == 0) 877: return(0); 878: prevdiff = diff; 879: } 880: } 881: } 882: } 883: 884: /* 885: * address to local name in procp 886: * returns difference between addr and address of local 887: * returned in sl_name 888: */ 889: adrtolocal(addr, procp) 890: ADDR addr; struct proct *procp; { 891: struct nlist stentry; 892: register int i, prevdiff = MAXPOS, diff; 893: 894: blseek(&sbuf, procp->st_offset + sizeof stentry, 0); 895: for (;;) { 896: if (bread(&sbuf, &stentry, sizeof stentry) 897: < sizeof stentry) 898: return(prevdiff!=MAXPOS ? prevdiff : -1); 899: if (stentry.n_type == N_FUN) 900: return(prevdiff!=MAXPOS ? prevdiff : -1); 901: if (stentry.n_type == N_LSYM) { 902: diff = addr - stentry.n_value; 903: if (diff >= 0 && diff < prevdiff) { 904: #ifndef FLEXNAMES 905: for (i=0; i<8; i++) 906: sl_name[i] = stentry.n_un.n_name[i]; 907: #else 908: sl_name = stentry.n_un.n_name; 909: #endif 910: if (diff == 0) 911: return(0); 912: prevdiff = diff; 913: } 914: } 915: } 916: } 917: 918: /* 919: * address to parameter name in procp 920: * returns difference between addr and address of local 921: * returned in sl_name 922: */ 923: adrtoparam(addr, procp) 924: ADDR addr; struct proct *procp; { 925: struct nlist stentry; 926: register int i, prevdiff = MAXPOS, diff; 927: 928: blseek(&sbuf, procp->st_offset + sizeof stentry, 0); 929: for (;;) { 930: if (bread(&sbuf, &stentry, sizeof stentry) 931: < sizeof stentry) 932: return(prevdiff!=MAXPOS ? prevdiff : -1); 933: if (stentry.n_type == N_FUN) 934: return(prevdiff!=MAXPOS ? prevdiff : -1); 935: if (stentry.n_type == N_PSYM) { 936: diff = addr - stentry.n_value; 937: if (diff >= 0 && diff < prevdiff) { 938: #ifndef FLEXNAMES 939: for (i=0; i<8; i++) 940: sl_name[i] = stentry.n_un.n_name[i]; 941: #else 942: sl_name = stentry.n_un.n_name; 943: #endif 944: if (diff == 0) 945: return(0); 946: prevdiff = diff; 947: } 948: } 949: } 950: } 951: 952: /* 953: * register number to register variable name in procp 954: * returned in sl_name 955: */ 956: adrtoregvar(regno, procp) 957: ADDR regno; struct proct *procp; { 958: struct nlist stentry; 959: register int i; 960: 961: blseek(&sbuf, procp->st_offset + sizeof stentry, 0); 962: for (;;) { 963: if (bread(&sbuf, &stentry, sizeof stentry) 964: < sizeof stentry) return(-1); 965: if (stentry.n_type == N_FUN) 966: return(-1); 967: if (stentry.n_type == N_RSYM) { 968: if (stentry.n_value == regno) { 969: #ifndef FLEXNAMES 970: for (i=0; i<8; i++) 971: sl_name[i] = stentry.n_un.n_name[i]; 972: #else 973: sl_name = stentry.n_un.n_name; 974: #endif 975: return(0); 976: } 977: } 978: } 979: } 980: 981: /* sets file map for M command */ 982: setmap(s) 983: char *s; { 984: union { 985: MAP *m; 986: L_INT *mp; 987: } amap; 988: int starflag = 0; 989: 990: amap.mp = 0; 991: for (; *s; s++) { 992: switch (*s) { 993: case '/': 994: amap.m = &datmap; 995: break; 996: case '?': 997: amap.m = &txtmap; 998: break; 999: case '*': 1000: starflag++; 1001: break; 1002: default: 1003: goto sout; 1004: } 1005: } 1006: 1007: sout: if (amap.mp == 0) { 1008: error("Map `?' or `/' must be specified"); 1009: return; 1010: } 1011: if (starflag) 1012: amap.mp += 3; 1013: for (; *s; s++) { 1014: if (*s >= '0' && *s <= '9') 1015: *(amap.mp)++ = readint(&s); 1016: } 1017: }