/* initialize file and procedure tables */
register struct proct *procp;
register struct filet *filep;
filep = files = badfile = (struct filet *) sbrk(sizeof filep[0]);
procp = procs = badproc = (struct proct *) sbrk(sizeof procp[0]);
if (bread(&sbuf, &stentry, sizeof stentry) <
class = stentry.n_type & STABMASK;
switch (class & STABMASK) {
p = sbrk(FILEINCR*sizeof filep[0]);
q = p + FILEINCR*sizeof filep[0];
while (p > (char *) procs)
FILEINCR*sizeof filep[0]);
FILEINCR*sizeof filep[0]);
badproc = (struct proct *)
FILEINCR*sizeof filep[0]);
filep->faddr = stentry.n_value;
filep->lineflag = (class == N_SOL);
filep->stf_offset = soffset;
for (i=0; i<8; i++) *p++ = stentry.n_name[i];
if (*(p-1) == '\0') break;
if (bread(&sbuf, &stentry, sizeof stentry)
error("Bad N_SO entry (1)");
if ((stentry.n_type & STABMASK) !=
error("Bad N_SO entry (2)");
soffset += sizeof stentry;
if (stat(filep->sfilename, &stbuf) == -1)
printf("Warning: `%s' not found\n",
else if (stbuf.st_mtime > symtime)
printf("Warning: `%s' newer than `%s'\n",
if (stentry.n_name[0] != '_') break;
if (sbrk(PROCINCR*sizeof procp[0]) < 0) {
procp->pname[i] = stentry.n_name[i];
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;
if (stentry.n_type & N_EXT && !extstart) {
soffset += sizeof stentry;
qsort(procs, procp-procs, sizeof procs[0], compar);
badproc->st_offset = soffset;
badproc->sfptr = procp->sfptr = badfile;
badproc->pname[0] = badfile->sfilename[0]=
procp->pname[0] = filep->sfilename[0] = '\0';
/* returns current procedure from state (curfile, fline) */
addr = getaddr("", fline);
if (addr == -1) return(badproc);
return(adrtoprocp(addr));
/* returns procedure s, uses curproc() if s == NULL */
register struct proct *p;
if (s[0] == '\0') return(curproc());
for(p=procs; p->pname[0]; p++)
if (eqstr(p->pname, s)) return(p);
if (debug) printf("%s(): unknown name\n", s);
/* returns file s containing filename */
register struct filet *f;
for (f=files; f->sfilename[0]; f++) {
if (eqstr(f->sfilename, s)) {
for( ; f->lineflag; f--) ;
if (f < files) error("Bad file array");
* looks up variable matching pat starting at offset 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.
slookup(pat, poffset, stelt)
long poffset; char *pat; {
slooknext(pat, poffset, stelt, "*");
int clevel, level, fnameflag, comfound, incomm;
clevel = level = fnameflag = comfound = incomm = 0;
slooknext(pat, poffset, stelt, comblk)
long poffset; char *pat, *comblk; {
offset = poffset + sizeof stentry;
if (debug) printf("slookup(%s,%d)\n",pat,offset);
blseek(&sbuf, offset, 0);
offset -= sizeof stentry;
if (offset < ststart) break;
if (bread(&sbuf, &stentry+1, -sizeof stentry)
class = stentry.n_type & STABMASK;
switch (class & STABMASK) {
for (q = &stentry.n_name[7]; q>=stentry.n_name; q--) {
if (eqpat(comblk, stentry.n_name))
procp = findproc(stentry.n_name);
for (p=procs; p->pname[0]; p++) {
p->st_offset > procp->st_offset &&
blseek(&sbuf, offset, 0);
if (level <= 0 && eqpat(pat, stentry.n_name) &&
stentry.n_name[0] && class & STABTYPES &&
(comblk[0] == '\0' && incomm == 0) ||
(stelt == (class == N_SSYM))) {
sl_size = stentry.n_value;
offset -= sizeof stentry;
sl_class = stentry.n_type & STABMASK;
sl_type = stentry.n_desc;
sl_addr = stentry.n_value;
for (i=0; i<8; i++) sl_name[i] =
if (clevel != 0) docomm(offset);
return(offset - sizeof stentry);
* Look up global variable matching pat
* Return its offset and symbol table entries decoded in sl_*
globallookup(pat, filestart, stelt)
char *pat; long filestart; {
if (debug) printf("globallookup(%s,%d)\n", pat,filestart);
blseek(&sbuf, filestart, 0);
offset = filestart - sizeof stentry;
if (bread(&sbuf, &stentry, sizeof stentry) <
sizeof stentry) return(-1);
offset += sizeof stentry;
} while ((stentry.n_type & STABMASK) == N_SO);
class = stentry.n_type & STABMASK;
switch (class & STABMASK) {
if (eqpat(pat, stentry.n_name)
&& stentry.n_name[0] && class & STABTYPES) {
sl_class = stentry.n_type & STABMASK;
if (sl_class != N_GSYM && sl_class != N_SSYM &&
sl_class != N_STSYM) goto g1;
if (stelt != (sl_class == N_SSYM)) goto g1;
sl_type = stentry.n_desc;
sl_addr = stentry.n_value;
for (i=0; i<8; i++) sl_name[i] = stentry.n_name[i];
if (clevel != 0) docomm(offset);
g1: if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
offset += sizeof stentry;
g2: bread(&sbuf, &stentry, sizeof stentry);
if (((stentry.n_type & STABMASK) == N_LENG) &&
(eqpat(sl_name, stentry.n_name)))
sl_size = stentry.n_value;
if (sl_class == N_GSYM && (clevel == 0)) {
blseek(&sbuf, extstart, 0);
if (bread(&sbuf, &stentry, sizeof stentry)
if (stentry.n_name[0] != '_') continue;
if (eqpatr(sl_name, stentry.n_name+1, 1)) {
sl_addr = stentry.n_value;
return(offset + sizeof stentry);
/* core address to procedure (pointer to proc array) */
register struct proct *procp, *lastproc;
for (procp=procs; procp->pname[0]; procp++) {
if (procp->paddr > addr) break;
/* core address to file (pointer to file array) */
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 */
lineno = lastoffset = -1;
offset = adrtoproc(addr)->st_offset;
blseek(&sbuf, offset, 0);
if (bread(&sbuf, &stentry, sizeof stentry)
if (stentry.n_type == N_SLINE) {
if (stentry.n_value > addr) break;
offset += sizeof stentry;
/* address to a.out offset */
* Set (curfile, lineno) from core image.
* Returns 1 if there is a core image, 0 otherwise.
* Print the current line iff verbose is set.
register struct proct *procp;
dot = *(ADDR *) (((ADDR) &u) + PC);
printf("No core image\n");
if ((procp->sfptr) != badfile) {
finit(adrtofilep(dot)->sfilename);
printf("%.8s:", procp->pname);
if (procp->pname[0] == '_')
printf("%.7s: address 0x%x\n", procp->pname+1, dot);
printf("%.8s: address %d\n", procp->pname, dot);
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");
finit(procp->sfptr->sfilename);
if (a->paddr == b->paddr) {
if (a->pname[0] == '_') return(-1);
if (b->pname[0] == '_') return(1);
return(a->paddr < b->paddr ? -1 : 1);
/* gets offset of file or procedure named s */
register struct filet *f;
register struct proct *p;
return(f->sfilename[0] ? f->stf_offset : -1);
return(p->pname[0] ? p->st_offset : -1);
/* returns s if its a filename, its file otherwise */
register struct proct *p;
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; {
register int i, ignore = 0;
register int bestln=BIGNUM;
blseek(&sbuf, offset, 0);
if (bread(&sbuf, &stentry, sizeof stentry) <
sizeof stentry) return(-1);
} while ((stentry.n_type & STABMASK) == N_SO);
switch(stentry.n_type & STABMASK) {
if (stentry.n_desc == lineno)
if (stentry.n_desc > lineno &&
stentry.n_desc < bestln) {
bestaddr = stentry.n_value;
if (*p != stentry.n_name[i]) goto neq;
if (stentry.n_name[7] == '\0')
if (bread(&sbuf, &stentry, sizeof stentry)
error("Bad N_SO entry (1)");
if ((stentry.n_type & STABMASK) !=
error("Bad N_SO entry (2)");
if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
ret: return(bestln == BIGNUM ? -1 : bestaddr);
/* gets address of proc:number */
s = proc[0] ? proc : curfile;
offset = nametooffset(s);
if (debug) printf("getaddr() computed offset %d", offset);
if (addr != -1) addr += 2; /* MACHINE DEPENDENT */
if (debug) printf(" extaddr computed %d\n", addr);
addr = lntoaddr(integ, offset, s);
addr = findproc(proc)->paddr + 2; /* MACHINE DEPENDENT */
addr = lntoaddr(adrtolineno(addr)+1, offset, f);
if (debug) printf(" and addr %d\n", addr);
if (addr == -1) return(-1);
/* returns address of external */
blseek(&sbuf, extstart, 0);
if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry)
if (stentry.n_name[0] == '_' &&
eqpatr(name, stentry.n_name+1, 1))
/* find enclosing common blocks and fix up addresses */
if (bread(&sbuf, &stentry, sizeof stentry) < sizeof stentry) {
error("Bad common block");
if ((stentry.n_type & STABMASK) == N_ECOMM) {
sl_addr += extaddr(stentry.n_name);
blseek(&sbuf, offset, 0);
if ((stentry.n_type & STABMASK) == N_ECOML) {
sl_addr += stentry.n_value;
blseek(&sbuf, offset, 0);
/* determine if class is that of a variable */
char pctypes[] = {N_GSYM, N_STSYM, N_LCSYM, N_RSYM, N_SSYM, N_LSYM,
for (p=pctypes; *p; p++) {