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