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