BSD 4 release
[unix-history] / usr / src / cmd / sdb / symt.c
index a7d46ca..ff4082f 100644 (file)
@@ -1,11 +1,54 @@
+static char sccsid[] = "@(#)symt.c 4.1 10/9/80";
 #include "head.h"
 #include <a.out.h>
 #include "head.h"
 #include <a.out.h>
+#include <stab.h>
+
+#ifndef STABTYPES
+#define        STABTYPES N_STAB
+#endif
 #include <sys/stat.h>
 
 struct user u;
 int compar();
 char *symfil;
 
 #include <sys/stat.h>
 
 struct user u;
 int compar();
 char *symfil;
 
+#ifdef FLEXNAMES
+
+struct nlist *symtab;
+char   nullname[] = {0,0,0,0,0,0,0,0,0};       /* a few 0 bytes */
+off_t  stoff;
+
+stread(buff, nbytes)
+struct nlist *buff;
+int nbytes;
+{
+       register int from = stoff;
+
+       stoff += nbytes;
+       if (stoff >= gstart)
+               return (-1);
+       if (nbytes < 0) {
+               from = stoff;
+               buff--;
+       }
+       from = (from - ststart);
+       *buff = symtab[from/sizeof (struct nlist)];
+       return (sizeof (struct nlist));
+}
+
+stseek(off, rel)
+long off;
+{
+
+       if (rel == 1)
+               stoff += off;
+       else
+               stoff = off;
+}
+#define        bread(a,b,c)    stread(b,c)
+#define        blseek(a,b,c)   stseek(b,c)
+#endif
+
 /* initialize file and procedure tables */
 initfp() {
        struct nlist stentry;
 /* initialize file and procedure tables */
 initfp() {
        struct nlist stentry;
@@ -14,11 +57,56 @@ initfp() {
        struct stat stbuf;
 
        long soffset;
        struct stat stbuf;
 
        long soffset;
-       int i;
+       int i, gflag = 0;
        char class;
        register char *p, *q;
        
        char class;
        register char *p, *q;
        
+#ifdef FLEXNAMES
+       register struct nlist *sp;
+       int malformed = 0;
+       lseek(txtmap.ufd, gstart, 0);
+       if (read(txtmap.ufd, &ssiz, sizeof(ssiz)) != sizeof (ssiz)) {
+               printf("%s: no string table (old format?)\n", symfil);
+               exit(1);
+       }
+       strtab = (char *)malloc(ssiz);
+       if (strtab == 0) {
+               printf("no room for %d bytes of string table\n", ssiz);
+               exit(1);
+       }
+       ssiz -= sizeof (ssiz);
+       if (read(txtmap.ufd, strtab+sizeof (ssiz), ssiz) != ssiz) {
+               printf("%s: error reading string table\n", symfil);
+               exit(1);
+       }
+       i = gstart - ststart;
+       symtab = (struct nlist *)malloc(i);
+       if (symtab == 0) {
+               printf("no room for %d bytes of symbol table\n", i);
+               exit(1);
+       }
+       lseek(txtmap.ufd, ststart, 0);
+       if (read(txtmap.ufd, symtab, i) != i) {
+               printf("%s: error reading symbol table\n", symfil);
+               exit(1);
+       }
+       for (sp = &symtab[i/sizeof (struct nlist)]; --sp >= symtab; )
+       if (sp->n_un.n_strx != 0) {
+               if (sp->n_un.n_strx < sizeof (ssiz) || sp->n_un.n_strx >= ssiz) {
+                       if (malformed == 0) {
+                               printf("danger: mangled symbol table\n");
+                               malformed = 1;
+                       }
+                       sp->n_un.n_name = nullname;
+               } else
+                       sp->n_un.n_name = strtab + sp->n_un.n_strx;
+       } else
+               sp->n_un.n_name = nullname;
+#endif
+#ifndef VMUNIX
        sbuf.fd = txtmap.ufd;
        sbuf.fd = txtmap.ufd;
+#endif
+       firstdata = MAXPOS;
        soffset = ststart;
        blseek(&sbuf,ststart,0);
        filep = files = badfile = (struct filet *) sbrk(sizeof filep[0]);
        soffset = ststart;
        blseek(&sbuf,ststart,0);
        filep = files = badfile = (struct filet *) sbrk(sizeof filep[0]);
@@ -31,6 +119,7 @@ initfp() {
                switch (class & STABMASK) {
                case N_SO:
                case N_SOL:
                switch (class & STABMASK) {
                case N_SO:
                case N_SOL:
+                       gflag++;
                        if (filep == badfile) {
                                p = sbrk(FILEINCR*sizeof filep[0]);
                                if (p < 0) {
                        if (filep == badfile) {
                                p = sbrk(FILEINCR*sizeof filep[0]);
                                if (p < 0) {
@@ -54,9 +143,10 @@ initfp() {
                        filep->faddr = stentry.n_value;
                        filep->lineflag = (class == N_SOL);
                        filep->stf_offset = soffset;
                        filep->faddr = stentry.n_value;
                        filep->lineflag = (class == N_SOL);
                        filep->stf_offset = soffset;
+#ifndef FLEXNAMES
                        p = filep->sfilename;
                        for (;;) {
                        p = filep->sfilename;
                        for (;;) {
-                               for (i=0; i<8; i++) *p++ = stentry.n_name[i];
+                               for (i=0; i<8; i++) *p++ = stentry.n_un.n_name[i];
                                if (*(p-1) == '\0') break;
                                if (bread(&sbuf, &stentry, sizeof stentry) 
                                                < sizeof stentry)
                                if (*(p-1) == '\0') break;
                                if (bread(&sbuf, &stentry, sizeof stentry) 
                                                < sizeof stentry)
@@ -66,6 +156,9 @@ initfp() {
                                        error("Bad N_SO entry (2)");
                                soffset += sizeof stentry;
                        }
                                        error("Bad N_SO entry (2)");
                                soffset += sizeof stentry;
                        }
+#else
+                       filep->sfilename = stentry.n_un.n_name;
+#endif
                        q = filep->sfilename;
                        for (p=fp; *q; *p++ = *q++) ;
                        *p = 0;
                        q = filep->sfilename;
                        for (p=fp; *q; *p++ = *q++) ;
                        *p = 0;
@@ -80,7 +173,7 @@ initfp() {
                        break;
                        
                case N_TEXT:
                        break;
                        
                case N_TEXT:
-                       if (stentry.n_name[0] != '_') break;
+                       if (stentry.n_un.n_name[0] != '_') break;
                case N_FUN:
                case N_ENTRY:
                        if (procp == badproc) {
                case N_FUN:
                case N_ENTRY:
                        if (procp == badproc) {
@@ -90,8 +183,12 @@ initfp() {
                                }
                                badproc += PROCINCR;
                        }
                                }
                                badproc += PROCINCR;
                        }
+#ifndef FLEXNAMES
                        for(i=0; i<8; i++)
                        for(i=0; i<8; i++)
-                               procp->pname[i] = stentry.n_name[i];
+                               procp->pname[i] = stentry.n_un.n_name[i];
+#else
+                       procp->pname = stentry.n_un.n_name;
+#endif
                        procp->paddr = stentry.n_value;
                        procp->st_offset = soffset;
                        procp->sfptr = (class != N_TEXT) ? filep - 1 : badfile;
                        procp->paddr = stentry.n_value;
                        procp->st_offset = soffset;
                        procp->sfptr = (class != N_TEXT) ? filep - 1 : badfile;
@@ -100,17 +197,29 @@ initfp() {
                        procp++;
                        break;
                }
                        procp++;
                        break;
                }
-               if (stentry.n_type & N_EXT  &&  !extstart) {
-                       extstart = soffset;
+               if (stentry.n_type & N_EXT) {
+                       if (!extstart)
+                               extstart = soffset;
+                       if (stentry.n_type == N_DATA | N_EXT ||
+                                       stentry.n_type == N_BSS | N_EXT ||
+                                       stentry.n_value < firstdata)
+                               firstdata = stentry.n_value;
                }
                soffset += sizeof stentry;
        }
        qsort(procs, procp-procs, sizeof procs[0], compar);
                }
                soffset += sizeof stentry;
        }
        qsort(procs, procp-procs, sizeof procs[0], compar);
-       badproc->st_offset = soffset;
+       badproc->st_offset = badfile->stf_offset = soffset;
        badproc->sfptr = procp->sfptr = badfile;
        badproc->sfptr = procp->sfptr = badfile;
+#ifndef FLEXNAMES
        badproc->pname[0] = badfile->sfilename[0]=
                procp->pname[0] = filep->sfilename[0] = '\0';
        badproc->pname[0] = badfile->sfilename[0]=
                procp->pname[0] = filep->sfilename[0] = '\0';
+#else
+       badproc->pname = badfile->sfilename=
+               procp->pname = filep->sfilename = nullname;
+#endif
 
 
+       if (!gflag)
+               printf("Warning: `%s' not compiled with -g\n", symfil);
        setcur(1);
 }
 
        setcur(1);
 }
 
@@ -130,15 +239,17 @@ curproc() {
 struct proct *
 findproc(s)
 char *s; {
 struct proct *
 findproc(s)
 char *s; {
-       register struct proct *p;
+       register struct proct *p, *altproc;
        
        if (s[0] == '\0') return(curproc());
        
        if (s[0] == '\0') return(curproc());
+       altproc = badproc;
        
        
-       for(p=procs; p->pname[0]; p++)
-               if (eqstr(p->pname, s)) return(p);
-               
-       if (debug) printf("%s(): unknown name\n", s);
-       return(badproc);
+       for (p=procs; p->pname[0]; p++) {
+               if (eqpat(s, p->pname)) return(p);
+               if (p->pname[0] == '_' && eqpatr(s, p->pname+1, 1))
+                       altproc = p;
+       }
+       return(altproc);
 }
 
 /* returns file s containing filename */
 }
 
 /* returns file s containing filename */
@@ -147,7 +258,7 @@ findfile(s)
 char *s; {
        register struct filet *f;
        for (f=files; f->sfilename[0]; f++) {
 char *s; {
        register struct filet *f;
        for (f=files; f->sfilename[0]; f++) {
-               if (eqstr(f->sfilename, s)) { 
+               if (eqpat(f->sfilename, s)) { 
                        for( ; f->lineflag; f--) ;
                        if (f < files) error("Bad file array");
                        return(f);
                        for( ; f->lineflag; f--) ;
                        if (f < files) error("Bad file array");
                        return(f);
@@ -158,8 +269,9 @@ char *s; {
 
 /*
  * slookup():
 
 /*
  * slookup():
- * looks up variable matching pat starting at offset in a.out, searching
- * backwards, ignoring nested blocks to beginning to procedure.
+ * looks up variable matching pat starting at (offset + sizeof stentry)
+ * in a.out, searching backwards,
+ * ignoring nested blocks to beginning to procedure.
  * Returns its offset and symbol table entries decoded in sl_*
  *
  * If comblk == "*" then match both within and outside common blocks,
  * Returns its offset and symbol table entries decoded in sl_*
  *
  * If comblk == "*" then match both within and outside common blocks,
@@ -211,13 +323,20 @@ long poffset; char *pat, *comblk; {
                        level--;
                        break;
                case N_ECOMM:
                        level--;
                        break;
                case N_ECOMM:
-                       for (q = &stentry.n_name[7]; q>=stentry.n_name; q--) {
+#ifndef FLEXNAMES
+                       for (q = &stentry.n_un.n_name[7]; q>=stentry.n_un.n_name; q--) {
                                if (*q == '_') {
                                        *q = '\0';
                                        break;
                                }
                        }
                                if (*q == '_') {
                                        *q = '\0';
                                        break;
                                }
                        }
-                       if (eqpat(comblk, stentry.n_name))
+#else
+                       for (q = stentry.n_un.n_name; *q; q++)
+                               continue;
+                       if (*--q == '_')
+                               *q = 0;
+#endif
+                       if (eqpat(comblk, stentry.n_un.n_name))
                                comfound = 1;
                        incomm = 1;
                case N_ECOML:
                                comfound = 1;
                        incomm = 1;
                case N_ECOML:
@@ -230,7 +349,7 @@ long poffset; char *pat, *comblk; {
                case N_FNAME:
                        if (fnameflag)
                                break;
                case N_FNAME:
                        if (fnameflag)
                                break;
-                       procp = findproc(stentry.n_name);
+                       procp = findproc(stentry.n_un.n_name);
                        for (p=procs; p->pname[0]; p++) {
                                if (p->entrypt == 0 &&
                                        p->st_offset > procp->st_offset &&
                        for (p=procs; p->pname[0]; p++) {
                                if (p->entrypt == 0 &&
                                        p->st_offset > procp->st_offset &&
@@ -242,8 +361,8 @@ long poffset; char *pat, *comblk; {
                        blseek(&sbuf, offset, 0);
                        break;
                default:
                        blseek(&sbuf, offset, 0);
                        break;
                default:
-                       if (level <= 0  &&  eqpat(pat, stentry.n_name) &&
-                               stentry.n_name[0] && class & STABTYPES &&
+                       if (level <= 0  &&  eqpat(pat, stentry.n_un.n_name) &&
+                               stentry.n_un.n_name[0] && class & STABTYPES &&
                                (eqstr("*", comblk) ||
                                 (comblk[0] == '\0' && incomm == 0) ||
                                 comfound) &&
                                (eqstr("*", comblk) ||
                                 (comblk[0] == '\0' && incomm == 0) ||
                                 comfound) &&
@@ -253,13 +372,22 @@ long poffset; char *pat, *comblk; {
                                        offset -= sizeof stentry;
                                        bread(&sbuf, &stentry+1,
                                                        -sizeof stentry);
                                        offset -= sizeof stentry;
                                        bread(&sbuf, &stentry+1,
                                                        -sizeof stentry);
+                                       if (stentry.n_type&~N_EXT == N_BSS) {
+                                               bread(&sbuf, &stentry+1,
+                                                   -sizeof stentry);
+                                               offset -= sizeof stentry;
+                                       }
                                }
                                else sl_size = 0;
                                sl_class = stentry.n_type & STABMASK;
                                sl_type = stentry.n_desc;
                                sl_addr = stentry.n_value;
                                }
                                else sl_size = 0;
                                sl_class = stentry.n_type & STABMASK;
                                sl_type = stentry.n_desc;
                                sl_addr = stentry.n_value;
+#ifndef FLEXNAMES
                                for (i=0; i<8; i++) sl_name[i] =
                                for (i=0; i<8; i++) sl_name[i] =
-                                               stentry.n_name[i];
+                                               stentry.n_un.n_name[i];
+#else
+                               sl_name = stentry.n_un.n_name;
+#endif
                                if (clevel != 0) docomm(offset);
                                return(offset - sizeof stentry);
                        }
                                if (clevel != 0) docomm(offset);
                                return(offset - sizeof stentry);
                        }
@@ -269,7 +397,7 @@ long poffset; char *pat, *comblk; {
 }
 
 /* 
 }
 
 /* 
- * Look up global variable matching pat
+ * Look up global variable matching pat starting at (filestart+sizeof stentry)
  * Return its offset and symbol table entries decoded in sl_*
  */
 long
  * Return its offset and symbol table entries decoded in sl_*
  */
 long
@@ -300,16 +428,20 @@ char *pat; long filestart; {
                        clevel++;
                        break;
                default:
                        clevel++;
                        break;
                default:
-               if (eqpat(pat, stentry.n_name) 
-                               && stentry.n_name[0] && class & STABTYPES) {
+               if (eqpat(pat, stentry.n_un.n_name) 
+                               && stentry.n_un.n_name[0] && class & STABTYPES) {
                        sl_class = stentry.n_type & STABMASK;
                        if (sl_class != N_GSYM && sl_class != N_SSYM && 
                        sl_class = stentry.n_type & STABMASK;
                        if (sl_class != N_GSYM && sl_class != N_SSYM && 
-                               sl_class != N_STSYM) goto g1;
+                               sl_class != N_STSYM && sl_class != N_LCSYM) goto g1;
                        if (stelt != (sl_class == N_SSYM)) goto g1;
                        sl_size = 0;
                        sl_type = stentry.n_desc;
                        sl_addr = stentry.n_value;
                        if (stelt != (sl_class == N_SSYM)) goto g1;
                        sl_size = 0;
                        sl_type = stentry.n_desc;
                        sl_addr = stentry.n_value;
-                       for (i=0; i<8; i++) sl_name[i] = stentry.n_name[i];
+#ifndef FLEXNAMES
+                       for (i=0; i<8; i++) sl_name[i] = stentry.n_un.n_name[i];
+#else
+                       sl_name = stentry.n_un.n_name;
+#endif
                        if (clevel != 0) docomm(offset);
                        goto g2;
                }
                        if (clevel != 0) docomm(offset);
                        goto g2;
                }
@@ -319,8 +451,12 @@ g1:                if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
                offset += sizeof stentry;
        }
 g2:    bread(&sbuf, &stentry, sizeof stentry);
                offset += sizeof stentry;
        }
 g2:    bread(&sbuf, &stentry, sizeof stentry);
+       if (stentry.n_type&~N_EXT==N_BSS) {
+               bread(&sbuf, &stentry, sizeof stentry);
+               offset += sizeof stentry;
+       }
        if (((stentry.n_type & STABMASK) == N_LENG) &&
        if (((stentry.n_type & STABMASK) == N_LENG) &&
-                       (eqpat(sl_name, stentry.n_name)))
+                       (eqpat(sl_name, stentry.n_un.n_name)))
                sl_size = stentry.n_value;
 
        if (sl_class == N_GSYM && (clevel == 0)) {
                sl_size = stentry.n_value;
 
        if (sl_class == N_GSYM && (clevel == 0)) {
@@ -329,8 +465,8 @@ g2: bread(&sbuf, &stentry, sizeof stentry);
                        if (bread(&sbuf, &stentry, sizeof stentry) 
                                        < sizeof stentry)
                                return(-1);
                        if (bread(&sbuf, &stentry, sizeof stentry) 
                                        < sizeof stentry)
                                return(-1);
-                       if (stentry.n_name[0] != '_') continue;
-                       if (eqpatr(sl_name, stentry.n_name+1, 1)) {
+                       if (stentry.n_un.n_name[0] != '_') continue;
+                       if (eqpatr(sl_name, stentry.n_un.n_name+1, 1)) {
                                sl_addr = stentry.n_value;
                                break;
                        }
                                sl_addr = stentry.n_value;
                                break;
                        }
@@ -365,7 +501,12 @@ ADDR addr; {
        return (filep != files ? filep-1 : badfile);
 }
  
        return (filep != files ? filep-1 : badfile);
 }
  
-/* core address to linenumber */
+/*
+ * core address to linenumber 
+ *  Sets external exactaddr to addr if addr is NOT the first instruction 
+ * of a line, set to -1 otherwise.
+ *  Sets external lnfaddr to address of first statement in line.
+ */
 long lastoffset;
 
 adrtolineno(addr) 
 long lastoffset;
 
 adrtolineno(addr) 
@@ -374,16 +515,23 @@ ADDR addr; {
        long offset; 
        struct nlist stentry;
        
        long offset; 
        struct nlist stentry;
        
+       exactaddr = addr;
        lineno = lastoffset = -1;
        lineno = lastoffset = -1;
-       offset = adrtoproc(addr)->st_offset;
+       offset = adrtoprocp(addr)->st_offset;
        blseek(&sbuf, offset, 0);
        for (;;) {
                if (bread(&sbuf, &stentry, sizeof stentry) 
                                < sizeof stentry) break;
        blseek(&sbuf, offset, 0);
        for (;;) {
                if (bread(&sbuf, &stentry, sizeof stentry) 
                                < sizeof stentry) break;
+               if (stentry.n_type == N_SO)
+                       break;
                if (stentry.n_type == N_SLINE) {
                if (stentry.n_type == N_SLINE) {
-                       if (stentry.n_value > addr) break;
+                       if (stentry.n_value > addr)
+                               break;
                        lastoffset = offset;
                        lineno = stentry.n_desc;
                        lastoffset = offset;
                        lineno = stentry.n_desc;
+                       lnfaddr = stentry.n_value;
+                       if (stentry.n_value == addr) 
+                               exactaddr = -1;
                }
                offset += sizeof stentry;
        }
                }
                offset += sizeof stentry;
        }
@@ -420,16 +568,30 @@ setcur(verbose) {
                finit(adrtofilep(procp->paddr)->sfilename);
                ffind(adrtolineno(dot));
                if (verbose) {
                finit(adrtofilep(procp->paddr)->sfilename);
                ffind(adrtolineno(dot));
                if (verbose) {
+                       if (exactaddr != -1)
+                               printf("0x%x in ", exactaddr);
+#ifndef FLEXNAMES
                        printf("%.8s:", procp->pname);
                        printf("%.8s:", procp->pname);
+#else
+                       printf("%s:", procp->pname);
+#endif
                        fprint();
                }
                return(1);
        }
        if (verbose) {
                if (procp->pname[0] == '_') 
                        fprint();
                }
                return(1);
        }
        if (verbose) {
                if (procp->pname[0] == '_') 
+#ifndef FLEXNAMES
                        printf("%.7s: address 0x%x\n", procp->pname+1, dot);
                        printf("%.7s: address 0x%x\n", procp->pname+1, dot);
+#else
+                       printf("%s: address 0x%x\n", procp->pname+1, dot);
+#endif
                else
                else
+#ifndef FLEXNAMES
                        printf("%.8s: address %d\n", procp->pname, dot);
                        printf("%.8s: address %d\n", procp->pname, dot);
+#else
+                       printf("%s: address %d\n", procp->pname, dot);
+#endif
        }
        
 setmain:
        }
        
 setmain:
@@ -437,8 +599,7 @@ setmain:
        if ((procp->pname[0] != 'M') || (procp->sfptr == badfile)) {
                procp = findproc("main");
                if ((procp->pname[0] != 'm') || (procp->sfptr == badfile)) {
        if ((procp->pname[0] != 'M') || (procp->sfptr == badfile)) {
                procp = findproc("main");
                if ((procp->pname[0] != 'm') || (procp->sfptr == badfile)) {
-                       nolines = 1;
-                       printf("main not compiled with debug flag\n");
+                       /* printf("main not compiled with debug flag\n"); */
                        return(0);
                }
        }
                        return(0);
                }
        }
@@ -472,6 +633,7 @@ char *s; {
        p = findproc(s);
        return(p->pname[0] ? p->st_offset : -1);
 }
        p = findproc(s);
        return(p->pname[0] ? p->st_offset : -1);
 }
+
 /* returns s if its a filename, its file otherwise */
 char *
 nametofile(s)
 /* returns s if its a filename, its file otherwise */
 char *
 nametofile(s)
@@ -521,12 +683,13 @@ long offset; char *file; {
 
                case N_SOL:
                        p = file;
 
                case N_SOL:
                        p = file;
+#ifndef FLEXNAMES
                        for (;;) {
                                for (i=0; i<8; i++) {
                        for (;;) {
                                for (i=0; i<8; i++) {
-                                       if (*p != stentry.n_name[i]) goto neq;
+                                       if (*p != stentry.n_un.n_name[i]) goto neq;
                                        if (*p++ == '\0') break;
                                }
                                        if (*p++ == '\0') break;
                                }
-                               if (stentry.n_name[7] == '\0')
+                               if (stentry.n_un.n_name[7] == '\0')
                                        break;
                                if (bread(&sbuf, &stentry, sizeof stentry) 
                                                < sizeof stentry)
                                        break;
                                if (bread(&sbuf, &stentry, sizeof stentry) 
                                                < sizeof stentry)
@@ -535,6 +698,10 @@ long offset; char *file; {
                                                (unsigned char) N_SOL)
                                        error("Bad N_SO entry (2)");
                        }
                                                (unsigned char) N_SOL)
                                        error("Bad N_SO entry (2)");
                        }
+#else
+                       if (strcmp(file, stentry.n_un.n_name))
+                               goto neq;
+#endif
                        ignore = 0;
                        break;
 
                        ignore = 0;
                        break;
 
@@ -569,8 +736,11 @@ char *proc; {
        if (integ)
                addr = lntoaddr(integ, offset, s);
        else {
        if (integ)
                addr = lntoaddr(integ, offset, s);
        else {
-               addr = findproc(proc)->paddr + 2;  /* MACHINE DEPENDENT */
+               ADDR oldaddr;
+               oldaddr = findproc(proc)->paddr + 2;  /* MACHINE DEPENDENT */
                addr = lntoaddr(adrtolineno(addr)+1, offset, f);
                addr = lntoaddr(adrtolineno(addr)+1, offset, f);
+               if (addr == -1)
+                       addr = oldaddr;
        }
        if (debug) printf(" and addr %d\n", addr);
        if (addr == -1) return(-1);
        }
        if (debug) printf(" and addr %d\n", addr);
        if (addr == -1) return(-1);
@@ -587,12 +757,49 @@ char *name; {
        for (;;) {
                if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
                        return(-1);
        for (;;) {
                if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
                        return(-1);
-               if (stentry.n_name[0] == '_' && 
-                           eqpatr(name, stentry.n_name+1, 1)) 
+               if (stentry.n_un.n_name[0] == '_' && 
+                           eqpatr(name, stentry.n_un.n_name+1, 1)) 
                        return(stentry.n_value);
        }
 }
 
                        return(stentry.n_value);
        }
 }
 
+
+/* 
+ * Look up external data symbol matching pat starting at 
+ *  (filestart+sizeof stentry)
+ * Return its address in sl_addr and name in sl_name.
+ */
+long
+extlookup(pat, filestart)
+char *pat; long filestart; {
+       register int offset, i;
+       struct nlist stentry;
+       
+       blseek(&sbuf, filestart, 0);
+       offset = filestart - sizeof stentry;
+       do {
+               if (bread(&sbuf, &stentry, sizeof stentry) <
+                               sizeof stentry) return(-1);
+               offset += sizeof stentry;
+       } while ((stentry.n_type & STABMASK) == N_SO);
+       for (;;) {
+               if (stentry.n_un.n_name[0] == '_' && 
+                           stentry.n_type == (N_DATA | N_EXT) &&
+                           eqpatr(pat, stentry.n_un.n_name+1, 1)) {
+                       sl_addr = stentry.n_value;
+#ifndef FLEXNAMES
+                       for (i=0; i<7; i++) sl_name[i] = stentry.n_un.n_name[i+1];
+#else
+                       sl_name = stentry.n_un.n_name;
+#endif
+                       return(offset + sizeof stentry);
+               }
+g1:            if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
+                       return(-1);
+               offset += sizeof stentry;
+       }
+}
+
 /* find enclosing common blocks and fix up addresses */
 docomm(offset)
 long offset; {
 /* find enclosing common blocks and fix up addresses */
 docomm(offset)
 long offset; {
@@ -605,7 +812,7 @@ long offset; {
                }
                sl_class = N_GSYM;
                if ((stentry.n_type & STABMASK) == N_ECOMM) {
                }
                sl_class = N_GSYM;
                if ((stentry.n_type & STABMASK) == N_ECOMM) {
-                       sl_addr += extaddr(stentry.n_name);
+                       sl_addr += extaddr(stentry.n_un.n_name);
                        blseek(&sbuf, offset, 0);
                        return;
                }
                        blseek(&sbuf, offset, 0);
                        return;
                }
@@ -630,3 +837,171 @@ char class; {
        }
        return(0);
 }
        }
        return(0);
 }
+
+/*
+ * address to external name 
+ * returns difference between addr and address of external
+ * name returned in sl_name
+ */
+adrtoext(addr) 
+ADDR addr; {
+       struct nlist stentry;
+       register int i, prevdiff = MAXPOS, diff;
+
+       blseek(&sbuf, extstart, 0);
+       for (;;) {
+               if (bread(&sbuf, &stentry, sizeof stentry) 
+                               < sizeof stentry)
+                       return (prevdiff!=MAXPOS ? prevdiff : -1);
+               if (stentry.n_type == (N_DATA | N_EXT) ||
+                   stentry.n_type == (N_BSS | N_EXT)) {
+                       diff = addr - stentry.n_value;
+                       if (diff >= 0 && diff < prevdiff) {
+#ifndef FLEXNAMES
+                               for (i=0; i<7; i++)
+                                       sl_name[i] = stentry.n_un.n_name[i+1];
+#else
+                               sl_name = stentry.n_un.n_name;
+#endif
+                               if (diff == 0)
+                                       return(0);
+                               prevdiff = diff;
+                       }
+               }
+       }
+}
+
+/*
+ * address to local name in procp
+ * returns difference between addr and address of local
+ * returned in sl_name
+ */
+adrtolocal(addr, procp) 
+ADDR addr; struct proct *procp; {
+       struct nlist stentry;
+       register int i, prevdiff = MAXPOS, diff;
+
+       blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
+       for (;;) {
+               if (bread(&sbuf, &stentry, sizeof stentry) 
+                               < sizeof stentry)
+                       return(prevdiff!=MAXPOS ? prevdiff : -1);
+               if (stentry.n_type == N_FUN)
+                       return(prevdiff!=MAXPOS ? prevdiff : -1);
+               if (stentry.n_type == N_LSYM) {
+                       diff = addr - stentry.n_value;
+                       if (diff >= 0 && diff < prevdiff) {
+#ifndef FLEXNAMES
+                               for (i=0; i<8; i++)
+                                       sl_name[i] = stentry.n_un.n_name[i];
+#else
+                               sl_name = stentry.n_un.n_name;
+#endif
+                               if (diff == 0)
+                                       return(0);
+                               prevdiff = diff;
+                       }
+               }
+       }
+}
+
+/*
+ * address to parameter name in procp
+ * returns difference between addr and address of local
+ * returned in sl_name
+ */
+adrtoparam(addr, procp) 
+ADDR addr; struct proct *procp; {
+       struct nlist stentry;
+       register int i, prevdiff = MAXPOS, diff;
+
+       blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
+       for (;;) {
+               if (bread(&sbuf, &stentry, sizeof stentry) 
+                               < sizeof stentry) 
+                       return(prevdiff!=MAXPOS ? prevdiff : -1);
+               if (stentry.n_type == N_FUN)
+                       return(prevdiff!=MAXPOS ? prevdiff : -1);
+               if (stentry.n_type == N_PSYM) {
+                       diff = addr - stentry.n_value;
+                       if (diff >= 0 && diff < prevdiff) {
+#ifndef FLEXNAMES
+                               for (i=0; i<8; i++)
+                                       sl_name[i] = stentry.n_un.n_name[i];
+#else
+                               sl_name = stentry.n_un.n_name;
+#endif
+                               if (diff == 0)
+                                       return(0);
+                               prevdiff = diff;
+                       }
+               }
+       }
+}
+
+/*
+ * register number to register variable name in procp
+ * returned in sl_name
+ */
+adrtoregvar(regno, procp) 
+ADDR regno; struct proct *procp; {
+       struct nlist stentry;
+       register int i;
+
+       blseek(&sbuf, procp->st_offset + sizeof stentry, 0);
+       for (;;) {
+               if (bread(&sbuf, &stentry, sizeof stentry) 
+                               < sizeof stentry) return(-1);
+               if (stentry.n_type == N_FUN)
+                       return(-1);
+               if (stentry.n_type == N_RSYM) {
+                       if (stentry.n_value == regno) {
+#ifndef FLEXNAMES
+                               for (i=0; i<8; i++)
+                                       sl_name[i] = stentry.n_un.n_name[i];
+#else
+                               sl_name = stentry.n_un.n_name;
+#endif
+                               return(0);
+                       }
+               }
+       }
+}
+
+/* sets file map for M command */
+setmap(s)
+char *s; {
+       union {
+               MAP *m;
+               L_INT *mp;
+       } amap;
+       int starflag = 0;
+
+       amap.mp = 0;
+       for (; *s; s++) {
+               switch (*s) {
+               case '/':
+                       amap.m = &datmap;
+                       break;
+               case '?':
+                       amap.m = &txtmap;
+                       break;
+               case '*':
+                       starflag++;
+                       break;
+               default:        
+                       goto sout;
+               }
+       }
+       
+sout:  if (amap.mp == 0) {
+               error("Map `?' or `/' must be specified");
+               return;
+       }
+       if (starflag)
+               amap.mp += 3;
+       for (; *s; s++) {
+               if (*s >= '0' && *s <= '9')
+                       *(amap.mp)++ = readint(&s);
+       }
+}