1*7776Srrh static char sccsid[] = "@(#)symt.c 4.3 08/17/82";
21352Sbill #include "head.h"
31352Sbill #include <a.out.h>
41352Sbill #include <stab.h>
51352Sbill
61352Sbill #ifndef STABTYPES
71352Sbill #define STABTYPES N_STAB
81352Sbill #endif
91352Sbill #include <sys/stat.h>
101352Sbill
111352Sbill struct user u;
121352Sbill int compar();
131352Sbill char *symfil;
141352Sbill
151352Sbill #ifdef FLEXNAMES
161352Sbill
171352Sbill struct nlist *symtab;
181352Sbill char nullname[] = {0,0,0,0,0,0,0,0,0}; /* a few 0 bytes */
191352Sbill off_t stoff;
201352Sbill
211352Sbill stread(buff, nbytes)
221352Sbill struct nlist *buff;
231352Sbill int nbytes;
241352Sbill {
251352Sbill register int from = stoff;
261352Sbill
271352Sbill stoff += nbytes;
281352Sbill if (stoff >= gstart)
291352Sbill return (-1);
301352Sbill if (nbytes < 0) {
311352Sbill from = stoff;
321352Sbill buff--;
331352Sbill }
341352Sbill from = (from - ststart);
351352Sbill *buff = symtab[from/sizeof (struct nlist)];
361352Sbill return (sizeof (struct nlist));
371352Sbill }
381352Sbill
stseek(off,rel)391352Sbill stseek(off, rel)
401352Sbill long off;
411352Sbill {
421352Sbill
431352Sbill if (rel == 1)
441352Sbill stoff += off;
451352Sbill else
461352Sbill stoff = off;
471352Sbill }
481352Sbill #define bread(a,b,c) stread(b,c)
491352Sbill #define blseek(a,b,c) stseek(b,c)
501352Sbill #endif
511352Sbill
521352Sbill /* initialize file and procedure tables */
initfp()531352Sbill initfp() {
541352Sbill struct nlist stentry;
551352Sbill register struct proct *procp;
561352Sbill register struct filet *filep;
571352Sbill struct stat stbuf;
581352Sbill
591352Sbill long soffset;
601352Sbill int i, gflag = 0;
61*7776Srrh u_char class;
621352Sbill register char *p, *q;
631352Sbill
641352Sbill #ifdef FLEXNAMES
651352Sbill register struct nlist *sp;
661352Sbill int malformed = 0;
671352Sbill lseek(txtmap.ufd, gstart, 0);
681352Sbill if (read(txtmap.ufd, &ssiz, sizeof(ssiz)) != sizeof (ssiz)) {
691352Sbill printf("%s: no string table (old format?)\n", symfil);
701352Sbill exit(1);
711352Sbill }
721352Sbill strtab = (char *)malloc(ssiz);
731352Sbill if (strtab == 0) {
741352Sbill printf("no room for %d bytes of string table\n", ssiz);
751352Sbill exit(1);
761352Sbill }
771352Sbill ssiz -= sizeof (ssiz);
781352Sbill if (read(txtmap.ufd, strtab+sizeof (ssiz), ssiz) != ssiz) {
791352Sbill printf("%s: error reading string table\n", symfil);
801352Sbill exit(1);
811352Sbill }
821352Sbill i = gstart - ststart;
831352Sbill symtab = (struct nlist *)malloc(i);
841352Sbill if (symtab == 0) {
851352Sbill printf("no room for %d bytes of symbol table\n", i);
861352Sbill exit(1);
871352Sbill }
881352Sbill lseek(txtmap.ufd, ststart, 0);
891352Sbill if (read(txtmap.ufd, symtab, i) != i) {
901352Sbill printf("%s: error reading symbol table\n", symfil);
911352Sbill exit(1);
921352Sbill }
931352Sbill for (sp = &symtab[i/sizeof (struct nlist)]; --sp >= symtab; )
941352Sbill if (sp->n_un.n_strx != 0) {
951352Sbill if (sp->n_un.n_strx < sizeof (ssiz) || sp->n_un.n_strx >= ssiz) {
961352Sbill if (malformed == 0) {
971352Sbill printf("danger: mangled symbol table\n");
981352Sbill malformed = 1;
991352Sbill }
1001352Sbill sp->n_un.n_name = nullname;
1011352Sbill } else
1021352Sbill sp->n_un.n_name = strtab + sp->n_un.n_strx;
1031352Sbill } else
1041352Sbill sp->n_un.n_name = nullname;
1051352Sbill #endif
1061352Sbill #ifndef VMUNIX
1071352Sbill sbuf.fd = txtmap.ufd;
1081352Sbill #endif
1091352Sbill firstdata = MAXPOS;
1101352Sbill soffset = ststart;
1111352Sbill blseek(&sbuf,ststart,0);
1121352Sbill filep = files = badfile = (struct filet *) sbrk(sizeof filep[0]);
1131352Sbill procp = procs = badproc = (struct proct *) sbrk(sizeof procp[0]);
1141352Sbill
1151352Sbill for(;;) {
1161352Sbill if (bread(&sbuf, &stentry, sizeof stentry) <
1171352Sbill sizeof stentry) break;
1181352Sbill class = stentry.n_type & STABMASK;
1191352Sbill switch (class & STABMASK) {
1201352Sbill case N_SO:
1211352Sbill case N_SOL:
1221352Sbill gflag++;
1231352Sbill if (filep == badfile) {
1241352Sbill p = sbrk(FILEINCR*sizeof filep[0]);
1251352Sbill if (p < 0) {
1261352Sbill perror("sdb");
1271352Sbill exit(4);
1281352Sbill }
1291352Sbill q = p + FILEINCR*sizeof filep[0];
1301352Sbill while (p > (char *) procs)
1311352Sbill *--q = *--p;
1321352Sbill badfile += FILEINCR;
1331352Sbill procp = (struct proct *)
1341352Sbill ((char *) procp +
1351352Sbill FILEINCR*sizeof filep[0]);
1361352Sbill procs = (struct proct *)
1371352Sbill ((char *) procs +
1381352Sbill FILEINCR*sizeof filep[0]);
1391352Sbill badproc = (struct proct *)
1401352Sbill ((char *)badproc +
1411352Sbill FILEINCR*sizeof filep[0]);
1421352Sbill }
1431352Sbill filep->faddr = stentry.n_value;
1441352Sbill filep->lineflag = (class == N_SOL);
1451352Sbill filep->stf_offset = soffset;
1461352Sbill #ifndef FLEXNAMES
1471352Sbill p = filep->sfilename;
1481352Sbill for (;;) {
1491352Sbill for (i=0; i<8; i++) *p++ = stentry.n_un.n_name[i];
1501352Sbill if (*(p-1) == '\0') break;
1511352Sbill if (bread(&sbuf, &stentry, sizeof stentry)
1521352Sbill < sizeof stentry)
1531352Sbill error("Bad N_SO entry (1)");
154*7776Srrh if ((stentry.n_type & STABMASK) != class)
1551352Sbill error("Bad N_SO entry (2)");
1561352Sbill soffset += sizeof stentry;
1571352Sbill }
1581352Sbill #else
1591352Sbill filep->sfilename = stentry.n_un.n_name;
1601352Sbill #endif
1611352Sbill q = filep->sfilename;
1621352Sbill for (p=fp; *q; *p++ = *q++) ;
1631352Sbill *p = 0;
1641352Sbill if (stat(filework, &stbuf) == -1)
1651352Sbill printf("Warning: `%s' not found\n",
1661352Sbill filep->sfilename);
1671352Sbill else if (stbuf.st_mtime > symtime)
1681352Sbill printf("Warning: `%s' newer than `%s'\n",
1691352Sbill filep->sfilename,
1701352Sbill symfil);
1711352Sbill filep++;
1721352Sbill break;
1731352Sbill
1741352Sbill case N_TEXT:
1751352Sbill if (stentry.n_un.n_name[0] != '_') break;
1761352Sbill case N_FUN:
1771352Sbill case N_ENTRY:
1781352Sbill if (procp == badproc) {
1791352Sbill if (sbrk(PROCINCR*sizeof procp[0]) < 0) {
1801352Sbill perror("sdb");
1811352Sbill exit(4);
1821352Sbill }
1831352Sbill badproc += PROCINCR;
1841352Sbill }
1851352Sbill #ifndef FLEXNAMES
1861352Sbill for(i=0; i<8; i++)
1871352Sbill procp->pname[i] = stentry.n_un.n_name[i];
1881352Sbill #else
1891352Sbill procp->pname = stentry.n_un.n_name;
1901352Sbill #endif
1911352Sbill procp->paddr = stentry.n_value;
1921352Sbill procp->st_offset = soffset;
1931352Sbill procp->sfptr = (class != N_TEXT) ? filep - 1 : badfile;
1941352Sbill procp->lineno = (class != N_TEXT) ? stentry.n_desc : 0;
1951352Sbill procp->entrypt = (class & STABMASK) == N_ENTRY;
1961352Sbill procp++;
1971352Sbill break;
1981352Sbill }
1991352Sbill if (stentry.n_type & N_EXT) {
2001352Sbill if (!extstart)
2011352Sbill extstart = soffset;
2021352Sbill if (stentry.n_type == N_DATA | N_EXT ||
2031352Sbill stentry.n_type == N_BSS | N_EXT ||
2041352Sbill stentry.n_value < firstdata)
2051352Sbill firstdata = stentry.n_value;
2061352Sbill }
2071352Sbill soffset += sizeof stentry;
2081352Sbill }
2091352Sbill qsort(procs, procp-procs, sizeof procs[0], compar);
2101352Sbill badproc->st_offset = badfile->stf_offset = soffset;
2111352Sbill badproc->sfptr = procp->sfptr = badfile;
2121352Sbill #ifndef FLEXNAMES
2131352Sbill badproc->pname[0] = badfile->sfilename[0]=
2141352Sbill procp->pname[0] = filep->sfilename[0] = '\0';
2151352Sbill #else
2161352Sbill badproc->pname = badfile->sfilename=
2171352Sbill procp->pname = filep->sfilename = nullname;
2181352Sbill #endif
2191352Sbill
2201352Sbill if (!gflag)
2211352Sbill printf("Warning: `%s' not compiled with -g\n", symfil);
2221352Sbill setcur(1);
2231352Sbill }
2241352Sbill
2251352Sbill /* returns current procedure from state (curfile, fline) */
2261352Sbill struct proct *
curproc()2271352Sbill curproc() {
2281352Sbill register ADDR addr;
2291352Sbill
2303946Sroot addr = getaddr("", fline ? fline : 1);
2311352Sbill if (addr == -1) return(badproc);
2321352Sbill return(adrtoprocp(addr));
2331352Sbill
2341352Sbill }
2351352Sbill
2361352Sbill /* returns procedure s, uses curproc() if s == NULL */
2371352Sbill
2381352Sbill struct proct *
findproc(s)2391352Sbill findproc(s)
2401352Sbill char *s; {
2411352Sbill register struct proct *p, *altproc;
2421352Sbill
2431352Sbill if (s[0] == '\0') return(curproc());
2441352Sbill altproc = badproc;
2451352Sbill
2461352Sbill for (p=procs; p->pname[0]; p++) {
2471352Sbill if (eqpat(s, p->pname)) return(p);
2481352Sbill if (p->pname[0] == '_' && eqpatr(s, p->pname+1, 1))
2491352Sbill altproc = p;
2501352Sbill }
2511352Sbill return(altproc);
2521352Sbill }
2531352Sbill
2541352Sbill /* returns file s containing filename */
2551352Sbill struct filet *
findfile(s)2561352Sbill findfile(s)
2571352Sbill char *s; {
2581352Sbill register struct filet *f;
2593946Sroot if (s == 0 || *s == 0)
2603946Sroot return(files); /* start at beginning if no cur file */
2611352Sbill for (f=files; f->sfilename[0]; f++) {
2621352Sbill if (eqpat(f->sfilename, s)) {
2631352Sbill for( ; f->lineflag; f--) ;
2641352Sbill if (f < files) error("Bad file array");
2651352Sbill return(f);
2661352Sbill }
2671352Sbill }
2681352Sbill return(f);
2691352Sbill }
2701352Sbill
2711352Sbill /*
2721352Sbill * slookup():
2731352Sbill * looks up variable matching pat starting at (offset + sizeof stentry)
2741352Sbill * in a.out, searching backwards,
2751352Sbill * ignoring nested blocks to beginning to procedure.
2761352Sbill * Returns its offset and symbol table entries decoded in sl_*
2771352Sbill *
2781352Sbill * If comblk == "*" then match both within and outside common blocks,
2791352Sbill * if comblk == "" then match only outside common blocks,
2801352Sbill * else match only within comblk.
2811352Sbill */
2821352Sbill
2831352Sbill long
slookup(pat,poffset,stelt)2841352Sbill slookup(pat, poffset, stelt)
2851352Sbill long poffset; char *pat; {
2861352Sbill slookinit();
2871352Sbill slooknext(pat, poffset, stelt, "*");
2881352Sbill }
2891352Sbill
2901352Sbill int clevel, level, fnameflag, comfound, incomm;
2911352Sbill
slookinit()2921352Sbill slookinit() {
2931352Sbill clevel = level = fnameflag = comfound = incomm = 0;
2941352Sbill }
2951352Sbill
2961352Sbill long
slooknext(pat,poffset,stelt,comblk)2971352Sbill slooknext(pat, poffset, stelt, comblk)
2981352Sbill long poffset; char *pat, *comblk; {
2991352Sbill register int i;
3001352Sbill register long offset;
301*7776Srrh char *q;
302*7776Srrh u_char class;
3031352Sbill struct nlist stentry;
3041352Sbill struct proct *procp, *p;
3051352Sbill
3061352Sbill offset = poffset + sizeof stentry;
3071352Sbill if (debug) printf("slookup(%s,%d)\n",pat,offset);
3081352Sbill blseek(&sbuf, offset, 0);
3091352Sbill
3101352Sbill for (;;) {
3111352Sbill offset -= sizeof stentry;
3121352Sbill if (offset < ststart) break;
3131352Sbill if (bread(&sbuf, &stentry+1, -sizeof stentry)
3141352Sbill < sizeof stentry) break;
3151352Sbill class = stentry.n_type & STABMASK;
3161352Sbill switch (class & STABMASK) {
3171352Sbill case 0:
3181352Sbill break;
3191352Sbill case N_FUN:
3201352Sbill return(-1);
3211352Sbill case N_RBRAC:
3221352Sbill level++;
3231352Sbill break;
3241352Sbill case N_LBRAC:
3251352Sbill level--;
3261352Sbill break;
3271352Sbill case N_ECOMM:
3283946Sroot i = 0;
3291352Sbill #ifndef FLEXNAMES
3301352Sbill for (q = &stentry.n_un.n_name[7]; q>=stentry.n_un.n_name; q--) {
3311352Sbill if (*q == '_') {
3321352Sbill *q = '\0';
3333946Sroot i++;
3341352Sbill break;
3351352Sbill }
3361352Sbill }
3371352Sbill #else
3381352Sbill for (q = stentry.n_un.n_name; *q; q++)
3391352Sbill continue;
3401352Sbill if (*--q == '_')
3413946Sroot *q = 0, i++;
3421352Sbill #endif
3431352Sbill if (eqpat(comblk, stentry.n_un.n_name))
3441352Sbill comfound = 1;
3453946Sroot if (i)
3463946Sroot *q = '_';
3471352Sbill incomm = 1;
3481352Sbill case N_ECOML:
3491352Sbill clevel++;
3501352Sbill break;
3511352Sbill case N_BCOMM:
3521352Sbill comfound = incomm = 0;
3531352Sbill clevel--;
3541352Sbill break;
3551352Sbill case N_FNAME:
3561352Sbill if (fnameflag)
3571352Sbill break;
3581352Sbill procp = findproc(stentry.n_un.n_name);
3591352Sbill for (p=procs; p->pname[0]; p++) {
3601352Sbill if (p->entrypt == 0 &&
3611352Sbill p->st_offset > procp->st_offset &&
3621352Sbill p->st_offset < offset)
3631352Sbill offset = p->st_offset;
3641352Sbill }
3651352Sbill clevel = level = 0;
3661352Sbill fnameflag++;
3671352Sbill blseek(&sbuf, offset, 0);
3681352Sbill break;
3691352Sbill default:
3701352Sbill if (level <= 0 && eqpat(pat, stentry.n_un.n_name) &&
3711352Sbill stentry.n_un.n_name[0] && class & STABTYPES &&
3721352Sbill (eqstr("*", comblk) ||
3731352Sbill (comblk[0] == '\0' && incomm == 0) ||
3741352Sbill comfound) &&
3751352Sbill (stelt == (class == N_SSYM))) {
3761352Sbill if (class == N_LENG) {
3771352Sbill sl_size = stentry.n_value;
3781352Sbill offset -= sizeof stentry;
3791352Sbill bread(&sbuf, &stentry+1,
3801352Sbill -sizeof stentry);
3811352Sbill if (stentry.n_type&~N_EXT == N_BSS) {
3821352Sbill bread(&sbuf, &stentry+1,
3831352Sbill -sizeof stentry);
3841352Sbill offset -= sizeof stentry;
3851352Sbill }
3861352Sbill }
3871352Sbill else sl_size = 0;
3881352Sbill sl_class = stentry.n_type & STABMASK;
3891352Sbill sl_type = stentry.n_desc;
3901352Sbill sl_addr = stentry.n_value;
3911352Sbill #ifndef FLEXNAMES
3921352Sbill for (i=0; i<8; i++) sl_name[i] =
3931352Sbill stentry.n_un.n_name[i];
3941352Sbill #else
3951352Sbill sl_name = stentry.n_un.n_name;
3961352Sbill #endif
3971352Sbill if (clevel != 0) docomm(offset);
3981352Sbill return(offset - sizeof stentry);
3991352Sbill }
4001352Sbill }
4011352Sbill }
4021352Sbill return(-1);
4031352Sbill }
4041352Sbill
4051352Sbill /*
4061352Sbill * Look up global variable matching pat starting at (filestart+sizeof stentry)
4071352Sbill * Return its offset and symbol table entries decoded in sl_*
4081352Sbill */
4091352Sbill long
globallookup(pat,filestart,stelt)4101352Sbill globallookup(pat, filestart, stelt)
4111352Sbill char *pat; long filestart; {
4121352Sbill register int offset, i;
4131352Sbill struct nlist stentry;
414*7776Srrh int clevel;
415*7776Srrh u_char class;
4161352Sbill
4171352Sbill if (debug) printf("globallookup(%s,%d)\n", pat,filestart);
4181352Sbill blseek(&sbuf, filestart, 0);
4191352Sbill offset = filestart - sizeof stentry;
4201352Sbill clevel = 0;
4211352Sbill do {
4221352Sbill if (bread(&sbuf, &stentry, sizeof stentry) <
4231352Sbill sizeof stentry) return(-1);
4241352Sbill offset += sizeof stentry;
4251352Sbill } while ((stentry.n_type & STABMASK) == N_SO);
4261352Sbill for (;;) {
4271352Sbill class = stentry.n_type & STABMASK;
4281352Sbill switch (class & STABMASK) {
4291352Sbill case N_SO:
4301352Sbill return(-1);
4311352Sbill case N_ECOMM:
4321352Sbill clevel--;
4331352Sbill break;
4341352Sbill case N_BCOMM:
4351352Sbill clevel++;
4361352Sbill break;
4371352Sbill default:
4381352Sbill if (eqpat(pat, stentry.n_un.n_name)
4391352Sbill && stentry.n_un.n_name[0] && class & STABTYPES) {
4401352Sbill sl_class = stentry.n_type & STABMASK;
4411352Sbill if (sl_class != N_GSYM && sl_class != N_SSYM &&
4421352Sbill sl_class != N_STSYM && sl_class != N_LCSYM) goto g1;
4431352Sbill if (stelt != (sl_class == N_SSYM)) goto g1;
4441352Sbill sl_size = 0;
4451352Sbill sl_type = stentry.n_desc;
4461352Sbill sl_addr = stentry.n_value;
4471352Sbill #ifndef FLEXNAMES
4481352Sbill for (i=0; i<8; i++) sl_name[i] = stentry.n_un.n_name[i];
4491352Sbill #else
4501352Sbill sl_name = stentry.n_un.n_name;
4511352Sbill #endif
4521352Sbill if (clevel != 0) docomm(offset);
4531352Sbill goto g2;
4541352Sbill }
4551352Sbill }
4561352Sbill g1: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
4571352Sbill return(-1);
4581352Sbill offset += sizeof stentry;
4591352Sbill }
4601352Sbill g2: bread(&sbuf, &stentry, sizeof stentry);
4611352Sbill if (stentry.n_type&~N_EXT==N_BSS) {
4621352Sbill bread(&sbuf, &stentry, sizeof stentry);
4631352Sbill offset += sizeof stentry;
4641352Sbill }
4651352Sbill if (((stentry.n_type & STABMASK) == N_LENG) &&
4661352Sbill (eqpat(sl_name, stentry.n_un.n_name)))
4671352Sbill sl_size = stentry.n_value;
4681352Sbill
4691352Sbill if (sl_class == N_GSYM && (clevel == 0)) {
4701352Sbill blseek(&sbuf, extstart, 0);
4711352Sbill for(;;) {
4721352Sbill if (bread(&sbuf, &stentry, sizeof stentry)
4731352Sbill < sizeof stentry)
4741352Sbill return(-1);
4751352Sbill if (stentry.n_un.n_name[0] != '_') continue;
4761352Sbill if (eqpatr(sl_name, stentry.n_un.n_name+1, 1)) {
4771352Sbill sl_addr = stentry.n_value;
4781352Sbill break;
4791352Sbill }
4801352Sbill }
4811352Sbill }
4821352Sbill return(offset + sizeof stentry);
4831352Sbill }
4841352Sbill
4851352Sbill /* core address to procedure (pointer to proc array) */
4861352Sbill struct proct *
adrtoprocp(addr)4871352Sbill adrtoprocp(addr)
4881352Sbill ADDR addr; {
4891352Sbill register struct proct *procp, *lastproc;
4901352Sbill lastproc = badproc;
4911352Sbill for (procp=procs; procp->pname[0]; procp++) {
4921352Sbill if (procp->paddr > addr) break;
4931352Sbill if (procp->entrypt == 0)
4941352Sbill lastproc = procp;
4951352Sbill }
4961352Sbill return (lastproc);
4971352Sbill }
4981352Sbill
4991352Sbill
5001352Sbill /* core address to file (pointer to file array) */
5011352Sbill struct filet *
adrtofilep(addr)5021352Sbill adrtofilep(addr)
5031352Sbill ADDR addr; {
5041352Sbill register struct filet *filep;
5051352Sbill for (filep=files; filep->sfilename[0]; filep++) {
5061352Sbill if (filep->faddr > addr) break;
5071352Sbill }
5081352Sbill return (filep != files ? filep-1 : badfile);
5091352Sbill }
5101352Sbill
5111352Sbill /*
5121352Sbill * core address to linenumber
5131352Sbill * Sets external exactaddr to addr if addr is NOT the first instruction
5141352Sbill * of a line, set to -1 otherwise.
5151352Sbill * Sets external lnfaddr to address of first statement in line.
5161352Sbill */
5171352Sbill long lastoffset;
5181352Sbill
adrtolineno(addr)5191352Sbill adrtolineno(addr)
5201352Sbill ADDR addr; {
5211352Sbill register int lineno;
5221352Sbill long offset;
5231352Sbill struct nlist stentry;
5241352Sbill
5251352Sbill exactaddr = addr;
5261352Sbill lineno = lastoffset = -1;
5271352Sbill offset = adrtoprocp(addr)->st_offset;
5281352Sbill blseek(&sbuf, offset, 0);
5291352Sbill for (;;) {
5301352Sbill if (bread(&sbuf, &stentry, sizeof stentry)
5311352Sbill < sizeof stentry) break;
5321352Sbill if (stentry.n_type == N_SO)
5331352Sbill break;
5341352Sbill if (stentry.n_type == N_SLINE) {
5351352Sbill if (stentry.n_value > addr)
5361352Sbill break;
5371352Sbill lastoffset = offset;
5381352Sbill lineno = stentry.n_desc;
5391352Sbill lnfaddr = stentry.n_value;
5401352Sbill if (stentry.n_value == addr)
5411352Sbill exactaddr = -1;
5421352Sbill }
5431352Sbill offset += sizeof stentry;
5441352Sbill }
5451352Sbill return (lineno);
5461352Sbill }
5471352Sbill
5481352Sbill
5491352Sbill /* address to a.out offset */
5501352Sbill long
adrtostoffset(addr)5511352Sbill adrtostoffset(addr)
5521352Sbill ADDR addr; {
5531352Sbill adrtolineno(addr);
5541352Sbill return(lastoffset);
5551352Sbill }
5561352Sbill
5571352Sbill
5581352Sbill /*
5591352Sbill * Set (curfile, lineno) from core image.
5601352Sbill * Returns 1 if there is a core image, 0 otherwise.
5611352Sbill *
5621352Sbill * Print the current line iff verbose is set.
5631352Sbill */
setcur(verbose)5641352Sbill setcur(verbose) {
5651352Sbill register struct proct *procp;
5661352Sbill
5671352Sbill dot = *(ADDR *) (((ADDR) &u) + PC);
5681352Sbill
5691352Sbill if (dot == 0) {
5701352Sbill printf("No core image\n");
5711352Sbill goto setmain;
5721352Sbill }
5731352Sbill procp = adrtoprocp(dot);
5741352Sbill if ((procp->sfptr) != badfile) {
5751352Sbill finit(adrtofilep(procp->paddr)->sfilename);
5761352Sbill ffind(adrtolineno(dot));
5771352Sbill if (verbose) {
5781352Sbill if (exactaddr != -1)
5791352Sbill printf("0x%x in ", exactaddr);
5801352Sbill #ifndef FLEXNAMES
5811352Sbill printf("%.8s:", procp->pname);
5821352Sbill #else
5831352Sbill printf("%s:", procp->pname);
5841352Sbill #endif
5851352Sbill fprint();
5861352Sbill }
5871352Sbill return(1);
5881352Sbill }
5891352Sbill if (verbose) {
5901352Sbill if (procp->pname[0] == '_')
5911352Sbill #ifndef FLEXNAMES
5921352Sbill printf("%.7s: address 0x%x\n", procp->pname+1, dot);
5931352Sbill #else
5941352Sbill printf("%s: address 0x%x\n", procp->pname+1, dot);
5951352Sbill #endif
5961352Sbill else
5971352Sbill #ifndef FLEXNAMES
5981352Sbill printf("%.8s: address %d\n", procp->pname, dot);
5991352Sbill #else
6001352Sbill printf("%s: address %d\n", procp->pname, dot);
6011352Sbill #endif
6021352Sbill }
6031352Sbill
6041352Sbill setmain:
6051352Sbill procp = findproc("MAIN_");
6061352Sbill if ((procp->pname[0] != 'M') || (procp->sfptr == badfile)) {
6071352Sbill procp = findproc("main");
6081352Sbill if ((procp->pname[0] != 'm') || (procp->sfptr == badfile)) {
6091352Sbill /* printf("main not compiled with debug flag\n"); */
6101352Sbill return(0);
6111352Sbill }
6121352Sbill }
6131352Sbill finit(procp->sfptr->sfilename);
6141352Sbill ffind(procp->lineno);
6151352Sbill return(0);
6161352Sbill }
6171352Sbill
6181352Sbill compar(a, b)
6191352Sbill struct proct *a, *b; {
6201352Sbill if (a->paddr == b->paddr) {
6211352Sbill if (a->pname[0] == '_') return(-1);
6221352Sbill if (b->pname[0] == '_') return(1);
6231352Sbill return(0);
6241352Sbill }
6251352Sbill return(a->paddr < b->paddr ? -1 : 1);
6261352Sbill }
6271352Sbill
6281352Sbill /* gets offset of file or procedure named s */
nametooffset(s)6291352Sbill nametooffset(s)
6301352Sbill char *s; {
6311352Sbill register struct filet *f;
6321352Sbill register struct proct *p;
6331352Sbill
6341352Sbill if (*s == '\0')
6351352Sbill return(-1);
6361352Sbill if (eqany('.', s)) {
6371352Sbill f = findfile(s);
6381352Sbill return(f->sfilename[0] ? f->stf_offset : -1);
6391352Sbill }
6401352Sbill p = findproc(s);
6411352Sbill return(p->pname[0] ? p->st_offset : -1);
6421352Sbill }
6431352Sbill
6441352Sbill /* returns s if its a filename, its file otherwise */
6451352Sbill char *
nametofile(s)6461352Sbill nametofile(s)
6471352Sbill char *s; {
6481352Sbill register struct proct *p;
6491352Sbill
6501352Sbill if (eqany('.', s)) {
6511352Sbill return(s);
6521352Sbill }
6531352Sbill p = findproc(s);
6541352Sbill return(adrtofilep(p->paddr)->sfilename);
6551352Sbill }
6561352Sbill
6571352Sbill
6581352Sbill /* line number to address, starting at offset in a.out */
6591352Sbill /* assumes that offset is within file */
lntoaddr(lineno,offset,file)6601352Sbill lntoaddr(lineno, offset, file)
6611352Sbill long offset; char *file; {
6621352Sbill struct nlist stentry;
6631352Sbill register int i, ignore = 0;
6641352Sbill register int bestln=BIGNUM;
6651352Sbill ADDR bestaddr;
6661352Sbill char *p;
6671352Sbill
6681352Sbill blseek(&sbuf, offset, 0);
6691352Sbill
6701352Sbill do {
6711352Sbill if (bread(&sbuf, &stentry, sizeof stentry) <
6721352Sbill sizeof stentry) return(-1);
6731352Sbill } while ((stentry.n_type & STABMASK) == N_SO);
6741352Sbill for (;;) {
6751352Sbill switch(stentry.n_type & STABMASK) {
6761352Sbill case N_SLINE:
6771352Sbill if (!ignore) {
6781352Sbill if (stentry.n_desc == lineno)
6791352Sbill return(stentry.n_value);
6801352Sbill if (stentry.n_desc > lineno &&
6811352Sbill stentry.n_desc < bestln) {
6821352Sbill bestln = stentry.n_desc;
6831352Sbill bestaddr = stentry.n_value;
6841352Sbill }
6851352Sbill }
6861352Sbill break;
6871352Sbill
6881352Sbill case N_SO:
6891352Sbill goto ret;
6901352Sbill
6911352Sbill case N_SOL:
6921352Sbill p = file;
6931352Sbill #ifndef FLEXNAMES
6941352Sbill for (;;) {
6951352Sbill for (i=0; i<8; i++) {
6961352Sbill if (*p != stentry.n_un.n_name[i]) goto neq;
6971352Sbill if (*p++ == '\0') break;
6981352Sbill }
6991352Sbill if (stentry.n_un.n_name[7] == '\0')
7001352Sbill break;
7011352Sbill if (bread(&sbuf, &stentry, sizeof stentry)
7021352Sbill < sizeof stentry)
7031352Sbill error("Bad N_SO entry (1)");
704*7776Srrh if ((stentry.n_type & STABMASK) != (u_char)N_SOL)
7051352Sbill error("Bad N_SO entry (2)");
7061352Sbill }
7071352Sbill #else
7081352Sbill if (strcmp(file, stentry.n_un.n_name))
7091352Sbill goto neq;
7101352Sbill #endif
7111352Sbill ignore = 0;
7121352Sbill break;
7131352Sbill
7141352Sbill neq: ignore++;
7151352Sbill break;
7161352Sbill }
7171352Sbill if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
7181352Sbill break;
7191352Sbill }
7201352Sbill ret: return(bestln == BIGNUM ? -1 : bestaddr);
7211352Sbill }
7221352Sbill
7231352Sbill /* gets address of proc:number */
getaddr(proc,integ)7241352Sbill getaddr(proc,integ)
7251352Sbill char *proc; {
7261352Sbill register long offset;
7271352Sbill register char *s, *f;
7281352Sbill ADDR addr;
7291352Sbill
7301352Sbill s = proc[0] ? proc : curfile;
7311352Sbill if (*s == '\0')
7321352Sbill return(-1);
7331352Sbill offset = nametooffset(s);
7341352Sbill f = nametofile(s);
7351352Sbill if (debug) printf("getaddr() computed offset %d", offset);
7361352Sbill if (offset == -1) {
7371352Sbill addr = extaddr(proc);
7381352Sbill if (addr != -1) addr += 2; /* MACHINE DEPENDENT */
7391352Sbill if (debug) printf(" extaddr computed %d\n", addr);
7401352Sbill return(addr);
7411352Sbill }
7421352Sbill if (integ)
7431352Sbill addr = lntoaddr(integ, offset, s);
7441352Sbill else {
7451352Sbill ADDR oldaddr;
7461352Sbill oldaddr = findproc(proc)->paddr + 2; /* MACHINE DEPENDENT */
7471352Sbill addr = lntoaddr(adrtolineno(addr)+1, offset, f);
7481352Sbill if (addr == -1)
7491352Sbill addr = oldaddr;
7501352Sbill }
7511352Sbill if (debug) printf(" and addr %d\n", addr);
7521352Sbill if (addr == -1) return(-1);
7531352Sbill return(addr);
7541352Sbill }
7551352Sbill
7561352Sbill /* returns address of external */
7571352Sbill ADDR
extaddr(name)7581352Sbill extaddr(name)
7591352Sbill char *name; {
7601352Sbill struct nlist stentry;
7611352Sbill blseek(&sbuf, extstart, 0);
7621352Sbill
7631352Sbill for (;;) {
7641352Sbill if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
7651352Sbill return(-1);
7661352Sbill if (stentry.n_un.n_name[0] == '_' &&
7671352Sbill eqpatr(name, stentry.n_un.n_name+1, 1))
7681352Sbill return(stentry.n_value);
7691352Sbill }
7701352Sbill }
7711352Sbill
7721352Sbill
7731352Sbill /*
7741352Sbill * Look up external data symbol matching pat starting at
7751352Sbill * (filestart+sizeof stentry)
7761352Sbill * Return its address in sl_addr and name in sl_name.
7771352Sbill */
7781352Sbill long
extlookup(pat,filestart)7791352Sbill extlookup(pat, filestart)
7801352Sbill char *pat; long filestart; {
7811352Sbill register int offset, i;
7821352Sbill struct nlist stentry;
7831352Sbill
7841352Sbill blseek(&sbuf, filestart, 0);
7851352Sbill offset = filestart - sizeof stentry;
7861352Sbill do {
7871352Sbill if (bread(&sbuf, &stentry, sizeof stentry) <
7881352Sbill sizeof stentry) return(-1);
7891352Sbill offset += sizeof stentry;
7901352Sbill } while ((stentry.n_type & STABMASK) == N_SO);
7911352Sbill for (;;) {
7921352Sbill if (stentry.n_un.n_name[0] == '_' &&
7931352Sbill stentry.n_type == (N_DATA | N_EXT) &&
7941352Sbill eqpatr(pat, stentry.n_un.n_name+1, 1)) {
7951352Sbill sl_addr = stentry.n_value;
7961352Sbill #ifndef FLEXNAMES
7971352Sbill for (i=0; i<7; i++) sl_name[i] = stentry.n_un.n_name[i+1];
7981352Sbill #else
7991352Sbill sl_name = stentry.n_un.n_name;
8001352Sbill #endif
8011352Sbill return(offset + sizeof stentry);
8021352Sbill }
8031352Sbill g1: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
8041352Sbill return(-1);
8051352Sbill offset += sizeof stentry;
8061352Sbill }
8071352Sbill }
8081352Sbill
8091352Sbill /* find enclosing common blocks and fix up addresses */
docomm(offset)8101352Sbill docomm(offset)
8111352Sbill long offset; {
8121352Sbill struct nlist stentry;
8133946Sroot ADDR addr;
8141352Sbill
8151352Sbill for (;;) {
8161352Sbill if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) {
8171352Sbill error("Bad common block");
8181352Sbill return;
8191352Sbill }
8201352Sbill sl_class = N_GSYM;
8211352Sbill if ((stentry.n_type & STABMASK) == N_ECOMM) {
8223946Sroot addr = extaddr(stentry.n_un.n_name);
8233946Sroot if (addr == -1)
8243946Sroot error("Lost common block");
8253946Sroot sl_addr +=addr;
8261352Sbill blseek(&sbuf, offset, 0);
8271352Sbill return;
8281352Sbill }
8291352Sbill if ((stentry.n_type & STABMASK) == N_ECOML) {
8301352Sbill sl_addr += stentry.n_value;
8311352Sbill blseek(&sbuf, offset, 0);
8321352Sbill return;
8331352Sbill }
8341352Sbill }
8351352Sbill }
8361352Sbill
8371352Sbill /* determine if class is that of a variable */
8381352Sbill char pctypes[] = {N_GSYM, N_STSYM, N_LCSYM, N_RSYM, N_SSYM, N_LSYM,
8391352Sbill N_PSYM, 0};
varclass(class)8401352Sbill varclass(class)
841*7776Srrh u_char class; {
8421352Sbill char *p;
8431352Sbill
8441352Sbill for (p=pctypes; *p; p++) {
8451352Sbill if (class == *p)
8461352Sbill return(1);
8471352Sbill }
8481352Sbill return(0);
8491352Sbill }
8501352Sbill
8511352Sbill /*
8521352Sbill * address to external name
8531352Sbill * returns difference between addr and address of external
8541352Sbill * name returned in sl_name
8551352Sbill */
adrtoext(addr)8561352Sbill adrtoext(addr)
8571352Sbill ADDR addr; {
8581352Sbill struct nlist stentry;
8591352Sbill register int i, prevdiff = MAXPOS, diff;
8601352Sbill
8611352Sbill blseek(&sbuf, extstart, 0);
8621352Sbill for (;;) {
8631352Sbill if (bread(&sbuf, &stentry, sizeof stentry)
8641352Sbill < sizeof stentry)
8651352Sbill return (prevdiff!=MAXPOS ? prevdiff : -1);
8661352Sbill if (stentry.n_type == (N_DATA | N_EXT) ||
8671352Sbill stentry.n_type == (N_BSS | N_EXT)) {
8681352Sbill diff = addr - stentry.n_value;
8691352Sbill if (diff >= 0 && diff < prevdiff) {
8701352Sbill #ifndef FLEXNAMES
8711352Sbill for (i=0; i<7; i++)
8721352Sbill sl_name[i] = stentry.n_un.n_name[i+1];
8731352Sbill #else
8741352Sbill sl_name = stentry.n_un.n_name;
8751352Sbill #endif
8761352Sbill if (diff == 0)
8771352Sbill return(0);
8781352Sbill prevdiff = diff;
8791352Sbill }
8801352Sbill }
8811352Sbill }
8821352Sbill }
8831352Sbill
8841352Sbill /*
8851352Sbill * address to local name in procp
8861352Sbill * returns difference between addr and address of local
8871352Sbill * returned in sl_name
8881352Sbill */
adrtolocal(addr,procp)8891352Sbill adrtolocal(addr, procp)
8901352Sbill ADDR addr; struct proct *procp; {
8911352Sbill struct nlist stentry;
8921352Sbill register int i, prevdiff = MAXPOS, diff;
8931352Sbill
8941352Sbill blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
8951352Sbill for (;;) {
8961352Sbill if (bread(&sbuf, &stentry, sizeof stentry)
8971352Sbill < sizeof stentry)
8981352Sbill return(prevdiff!=MAXPOS ? prevdiff : -1);
8991352Sbill if (stentry.n_type == N_FUN)
9001352Sbill return(prevdiff!=MAXPOS ? prevdiff : -1);
9011352Sbill if (stentry.n_type == N_LSYM) {
9021352Sbill diff = addr - stentry.n_value;
9031352Sbill if (diff >= 0 && diff < prevdiff) {
9041352Sbill #ifndef FLEXNAMES
9051352Sbill for (i=0; i<8; i++)
9061352Sbill sl_name[i] = stentry.n_un.n_name[i];
9071352Sbill #else
9081352Sbill sl_name = stentry.n_un.n_name;
9091352Sbill #endif
9101352Sbill if (diff == 0)
9111352Sbill return(0);
9121352Sbill prevdiff = diff;
9131352Sbill }
9141352Sbill }
9151352Sbill }
9161352Sbill }
9171352Sbill
9181352Sbill /*
9191352Sbill * address to parameter name in procp
9201352Sbill * returns difference between addr and address of local
9211352Sbill * returned in sl_name
9221352Sbill */
adrtoparam(addr,procp)9231352Sbill adrtoparam(addr, procp)
9241352Sbill ADDR addr; struct proct *procp; {
9251352Sbill struct nlist stentry;
9261352Sbill register int i, prevdiff = MAXPOS, diff;
9271352Sbill
9281352Sbill blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
9291352Sbill for (;;) {
9301352Sbill if (bread(&sbuf, &stentry, sizeof stentry)
9311352Sbill < sizeof stentry)
9321352Sbill return(prevdiff!=MAXPOS ? prevdiff : -1);
9331352Sbill if (stentry.n_type == N_FUN)
9341352Sbill return(prevdiff!=MAXPOS ? prevdiff : -1);
9351352Sbill if (stentry.n_type == N_PSYM) {
9361352Sbill diff = addr - stentry.n_value;
9371352Sbill if (diff >= 0 && diff < prevdiff) {
9381352Sbill #ifndef FLEXNAMES
9391352Sbill for (i=0; i<8; i++)
9401352Sbill sl_name[i] = stentry.n_un.n_name[i];
9411352Sbill #else
9421352Sbill sl_name = stentry.n_un.n_name;
9431352Sbill #endif
9441352Sbill if (diff == 0)
9451352Sbill return(0);
9461352Sbill prevdiff = diff;
9471352Sbill }
9481352Sbill }
9491352Sbill }
9501352Sbill }
9511352Sbill
9521352Sbill /*
9531352Sbill * register number to register variable name in procp
9541352Sbill * returned in sl_name
9551352Sbill */
adrtoregvar(regno,procp)9561352Sbill adrtoregvar(regno, procp)
9571352Sbill ADDR regno; struct proct *procp; {
9581352Sbill struct nlist stentry;
9591352Sbill register int i;
9601352Sbill
9611352Sbill blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
9621352Sbill for (;;) {
9631352Sbill if (bread(&sbuf, &stentry, sizeof stentry)
9641352Sbill < sizeof stentry) return(-1);
9651352Sbill if (stentry.n_type == N_FUN)
9661352Sbill return(-1);
9671352Sbill if (stentry.n_type == N_RSYM) {
9681352Sbill if (stentry.n_value == regno) {
9691352Sbill #ifndef FLEXNAMES
9701352Sbill for (i=0; i<8; i++)
9711352Sbill sl_name[i] = stentry.n_un.n_name[i];
9721352Sbill #else
9731352Sbill sl_name = stentry.n_un.n_name;
9741352Sbill #endif
9751352Sbill return(0);
9761352Sbill }
9771352Sbill }
9781352Sbill }
9791352Sbill }
9801352Sbill
9811352Sbill /* sets file map for M command */
setmap(s)9821352Sbill setmap(s)
9831352Sbill char *s; {
9841352Sbill union {
9851352Sbill MAP *m;
9861352Sbill L_INT *mp;
9871352Sbill } amap;
9881352Sbill int starflag = 0;
9891352Sbill
9901352Sbill amap.mp = 0;
9911352Sbill for (; *s; s++) {
9921352Sbill switch (*s) {
9931352Sbill case '/':
9941352Sbill amap.m = &datmap;
9951352Sbill break;
9961352Sbill case '?':
9971352Sbill amap.m = &txtmap;
9981352Sbill break;
9991352Sbill case '*':
10001352Sbill starflag++;
10011352Sbill break;
10021352Sbill default:
10031352Sbill goto sout;
10041352Sbill }
10051352Sbill }
10061352Sbill
10071352Sbill sout: if (amap.mp == 0) {
10081352Sbill error("Map `?' or `/' must be specified");
10091352Sbill return;
10101352Sbill }
10111352Sbill if (starflag)
10121352Sbill amap.mp += 3;
10131352Sbill for (; *s; s++) {
10141352Sbill if (*s >= '0' && *s <= '9')
10151352Sbill *(amap.mp)++ = readint(&s);
10161352Sbill }
10171352Sbill }
1018