1 static char sccsid[] = "@(#)symt.c 4.3 08/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 } 1018