BSD 4 development
[unix-history] / .ref-5cb41021d721f4e0ac572d592613f963e495d1ff / usr / src / old / sdb / symt.c
static char sccsid[] = "@(#)symt.c 4.1 %G%";
#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;
#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;
register struct proct *procp;
register struct filet *filep;
struct stat stbuf;
long soffset;
int i, gflag = 0;
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;
#endif
firstdata = MAXPOS;
soffset = ststart;
blseek(&sbuf,ststart,0);
filep = files = badfile = (struct filet *) sbrk(sizeof filep[0]);
procp = procs = badproc = (struct proct *) sbrk(sizeof procp[0]);
for(;;) {
if (bread(&sbuf, &stentry, sizeof stentry) <
sizeof stentry) break;
class = stentry.n_type & STABMASK;
switch (class & STABMASK) {
case N_SO:
case N_SOL:
gflag++;
if (filep == badfile) {
p = sbrk(FILEINCR*sizeof filep[0]);
if (p < 0) {
perror("sdb");
exit(4);
}
q = p + FILEINCR*sizeof filep[0];
while (p > (char *) procs)
*--q = *--p;
badfile += FILEINCR;
procp = (struct proct *)
((char *) procp +
FILEINCR*sizeof filep[0]);
procs = (struct proct *)
((char *) procs +
FILEINCR*sizeof filep[0]);
badproc = (struct proct *)
((char *)badproc +
FILEINCR*sizeof filep[0]);
}
filep->faddr = stentry.n_value;
filep->lineflag = (class == N_SOL);
filep->stf_offset = soffset;
#ifndef FLEXNAMES
p = filep->sfilename;
for (;;) {
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)
error("Bad N_SO entry (1)");
if ((stentry.n_type & STABMASK) !=
(unsigned char) class)
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;
if (stat(filework, &stbuf) == -1)
printf("Warning: `%s' not found\n",
filep->sfilename);
else if (stbuf.st_mtime > symtime)
printf("Warning: `%s' newer than `%s'\n",
filep->sfilename,
symfil);
filep++;
break;
case N_TEXT:
if (stentry.n_un.n_name[0] != '_') break;
case N_FUN:
case N_ENTRY:
if (procp == badproc) {
if (sbrk(PROCINCR*sizeof procp[0]) < 0) {
perror("sdb");
exit(4);
}
badproc += PROCINCR;
}
#ifndef FLEXNAMES
for(i=0; i<8; 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->lineno = (class != N_TEXT) ? stentry.n_desc : 0;
procp->entrypt = (class & STABMASK) == N_ENTRY;
procp++;
break;
}
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);
badproc->st_offset = badfile->stf_offset = soffset;
badproc->sfptr = procp->sfptr = badfile;
#ifndef FLEXNAMES
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);
}
/* returns current procedure from state (curfile, fline) */
struct proct *
curproc() {
register ADDR addr;
addr = getaddr("", fline);
if (addr == -1) return(badproc);
return(adrtoprocp(addr));
}
/* returns procedure s, uses curproc() if s == NULL */
struct proct *
findproc(s)
char *s; {
register struct proct *p, *altproc;
if (s[0] == '\0') return(curproc());
altproc = 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 */
struct filet *
findfile(s)
char *s; {
register struct filet *f;
for (f=files; f->sfilename[0]; f++) {
if (eqpat(f->sfilename, s)) {
for( ; f->lineflag; f--) ;
if (f < files) error("Bad file array");
return(f);
}
}
return(f);
}
/*
* slookup():
* 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,
* if comblk == "" then match only outside common blocks,
* else match only within comblk.
*/
long
slookup(pat, poffset, stelt)
long poffset; char *pat; {
slookinit();
slooknext(pat, poffset, stelt, "*");
}
int clevel, level, fnameflag, comfound, incomm;
slookinit() {
clevel = level = fnameflag = comfound = incomm = 0;
}
long
slooknext(pat, poffset, stelt, comblk)
long poffset; char *pat, *comblk; {
register int i;
register long offset;
char class, *q;
struct nlist stentry;
struct proct *procp, *p;
offset = poffset + sizeof stentry;
if (debug) printf("slookup(%s,%d)\n",pat,offset);
blseek(&sbuf, offset, 0);
for (;;) {
offset -= sizeof stentry;
if (offset < ststart) break;
if (bread(&sbuf, &stentry+1, -sizeof stentry)
< sizeof stentry) break;
class = stentry.n_type & STABMASK;
switch (class & STABMASK) {
case 0:
break;
case N_FUN:
return(-1);
case N_RBRAC:
level++;
break;
case N_LBRAC:
level--;
break;
case N_ECOMM:
#ifndef FLEXNAMES
for (q = &stentry.n_un.n_name[7]; q>=stentry.n_un.n_name; q--) {
if (*q == '_') {
*q = '\0';
break;
}
}
#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:
clevel++;
break;
case N_BCOMM:
comfound = incomm = 0;
clevel--;
break;
case N_FNAME:
if (fnameflag)
break;
procp = findproc(stentry.n_un.n_name);
for (p=procs; p->pname[0]; p++) {
if (p->entrypt == 0 &&
p->st_offset > procp->st_offset &&
p->st_offset < offset)
offset = p->st_offset;
}
clevel = level = 0;
fnameflag++;
blseek(&sbuf, offset, 0);
break;
default:
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) &&
(stelt == (class == N_SSYM))) {
if (class == N_LENG) {
sl_size = stentry.n_value;
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;
#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);
return(offset - sizeof stentry);
}
}
}
return(-1);
}
/*
* Look up global variable matching pat starting at (filestart+sizeof stentry)
* Return its offset and symbol table entries decoded in sl_*
*/
long
globallookup(pat, filestart, stelt)
char *pat; long filestart; {
register int offset, i;
struct nlist stentry;
int class, clevel;
if (debug) printf("globallookup(%s,%d)\n", pat,filestart);
blseek(&sbuf, filestart, 0);
offset = filestart - sizeof stentry;
clevel = 0;
do {
if (bread(&sbuf, &stentry, sizeof stentry) <
sizeof stentry) return(-1);
offset += sizeof stentry;
} while ((stentry.n_type & STABMASK) == N_SO);
for (;;) {
class = stentry.n_type & STABMASK;
switch (class & STABMASK) {
case N_SO:
return(-1);
case N_ECOMM:
clevel--;
break;
case N_BCOMM:
clevel++;
break;
default:
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 != 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;
#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;
}
}
g1: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
return(-1);
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) &&
(eqpat(sl_name, stentry.n_un.n_name)))
sl_size = stentry.n_value;
if (sl_class == N_GSYM && (clevel == 0)) {
blseek(&sbuf, extstart, 0);
for(;;) {
if (bread(&sbuf, &stentry, sizeof stentry)
< sizeof stentry)
return(-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;
}
}
}
return(offset + sizeof stentry);
}
/* core address to procedure (pointer to proc array) */
struct proct *
adrtoprocp(addr)
ADDR addr; {
register struct proct *procp, *lastproc;
lastproc = badproc;
for (procp=procs; procp->pname[0]; procp++) {
if (procp->paddr > addr) break;
if (procp->entrypt == 0)
lastproc = procp;
}
return (lastproc);
}
/* core address to file (pointer to file array) */
struct filet *
adrtofilep(addr)
ADDR addr; {
register struct filet *filep;
for (filep=files; filep->sfilename[0]; filep++) {
if (filep->faddr > addr) break;
}
return (filep != files ? filep-1 : badfile);
}
/*
* 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)
ADDR addr; {
register int lineno;
long offset;
struct nlist stentry;
exactaddr = addr;
lineno = lastoffset = -1;
offset = adrtoprocp(addr)->st_offset;
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_value > addr)
break;
lastoffset = offset;
lineno = stentry.n_desc;
lnfaddr = stentry.n_value;
if (stentry.n_value == addr)
exactaddr = -1;
}
offset += sizeof stentry;
}
return (lineno);
}
/* address to a.out offset */
long
adrtostoffset(addr)
ADDR addr; {
adrtolineno(addr);
return(lastoffset);
}
/*
* Set (curfile, lineno) from core image.
* Returns 1 if there is a core image, 0 otherwise.
*
* Print the current line iff verbose is set.
*/
setcur(verbose) {
register struct proct *procp;
dot = *(ADDR *) (((ADDR) &u) + PC);
if (dot == 0) {
printf("No core image\n");
goto setmain;
}
procp = adrtoprocp(dot);
if ((procp->sfptr) != badfile) {
finit(adrtofilep(procp->paddr)->sfilename);
ffind(adrtolineno(dot));
if (verbose) {
if (exactaddr != -1)
printf("0x%x in ", exactaddr);
#ifndef FLEXNAMES
printf("%.8s:", procp->pname);
#else
printf("%s:", procp->pname);
#endif
fprint();
}
return(1);
}
if (verbose) {
if (procp->pname[0] == '_')
#ifndef FLEXNAMES
printf("%.7s: address 0x%x\n", procp->pname+1, dot);
#else
printf("%s: address 0x%x\n", procp->pname+1, dot);
#endif
else
#ifndef FLEXNAMES
printf("%.8s: address %d\n", procp->pname, dot);
#else
printf("%s: address %d\n", procp->pname, dot);
#endif
}
setmain:
procp = findproc("MAIN_");
if ((procp->pname[0] != 'M') || (procp->sfptr == badfile)) {
procp = findproc("main");
if ((procp->pname[0] != 'm') || (procp->sfptr == badfile)) {
/* printf("main not compiled with debug flag\n"); */
return(0);
}
}
finit(procp->sfptr->sfilename);
ffind(procp->lineno);
return(0);
}
compar(a, b)
struct proct *a, *b; {
if (a->paddr == b->paddr) {
if (a->pname[0] == '_') return(-1);
if (b->pname[0] == '_') return(1);
return(0);
}
return(a->paddr < b->paddr ? -1 : 1);
}
/* gets offset of file or procedure named s */
nametooffset(s)
char *s; {
register struct filet *f;
register struct proct *p;
if (*s == '\0')
return(-1);
if (eqany('.', s)) {
f = findfile(s);
return(f->sfilename[0] ? f->stf_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)
char *s; {
register struct proct *p;
if (eqany('.', s)) {
return(s);
}
p = findproc(s);
return(adrtofilep(p->paddr)->sfilename);
}
/* line number to address, starting at offset in a.out */
/* assumes that offset is within file */
lntoaddr(lineno, offset, file)
long offset; char *file; {
struct nlist stentry;
register int i, ignore = 0;
register int bestln=BIGNUM;
ADDR bestaddr;
char *p;
blseek(&sbuf, offset, 0);
do {
if (bread(&sbuf, &stentry, sizeof stentry) <
sizeof stentry) return(-1);
} while ((stentry.n_type & STABMASK) == N_SO);
for (;;) {
switch(stentry.n_type & STABMASK) {
case N_SLINE:
if (!ignore) {
if (stentry.n_desc == lineno)
return(stentry.n_value);
if (stentry.n_desc > lineno &&
stentry.n_desc < bestln) {
bestln = stentry.n_desc;
bestaddr = stentry.n_value;
}
}
break;
case N_SO:
goto ret;
case N_SOL:
p = file;
#ifndef FLEXNAMES
for (;;) {
for (i=0; i<8; i++) {
if (*p != stentry.n_un.n_name[i]) goto neq;
if (*p++ == '\0') break;
}
if (stentry.n_un.n_name[7] == '\0')
break;
if (bread(&sbuf, &stentry, sizeof stentry)
< sizeof stentry)
error("Bad N_SO entry (1)");
if ((stentry.n_type & STABMASK) !=
(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;
neq: ignore++;
break;
}
if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
break;
}
ret: return(bestln == BIGNUM ? -1 : bestaddr);
}
/* gets address of proc:number */
getaddr(proc,integ)
char *proc; {
register long offset;
register char *s, *f;
ADDR addr;
s = proc[0] ? proc : curfile;
if (*s == '\0')
return(-1);
offset = nametooffset(s);
f = nametofile(s);
if (debug) printf("getaddr() computed offset %d", offset);
if (offset == -1) {
addr = extaddr(proc);
if (addr != -1) addr += 2; /* MACHINE DEPENDENT */
if (debug) printf(" extaddr computed %d\n", addr);
return(addr);
}
if (integ)
addr = lntoaddr(integ, offset, s);
else {
ADDR oldaddr;
oldaddr = findproc(proc)->paddr + 2; /* MACHINE DEPENDENT */
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);
return(addr);
}
/* returns address of external */
ADDR
extaddr(name)
char *name; {
struct nlist stentry;
blseek(&sbuf, extstart, 0);
for (;;) {
if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
return(-1);
if (stentry.n_un.n_name[0] == '_' &&
eqpatr(name, stentry.n_un.n_name+1, 1))
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; {
struct nlist stentry;
for (;;) {
if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) {
error("Bad common block");
return;
}
sl_class = N_GSYM;
if ((stentry.n_type & STABMASK) == N_ECOMM) {
sl_addr += extaddr(stentry.n_un.n_name);
blseek(&sbuf, offset, 0);
return;
}
if ((stentry.n_type & STABMASK) == N_ECOML) {
sl_addr += stentry.n_value;
blseek(&sbuf, offset, 0);
return;
}
}
}
/* determine if class is that of a variable */
char pctypes[] = {N_GSYM, N_STSYM, N_LCSYM, N_RSYM, N_SSYM, N_LSYM,
N_PSYM, 0};
varclass(class)
char class; {
char *p;
for (p=pctypes; *p; p++) {
if (class == *p)
return(1);
}
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);
}
}