static char sccsid
[] = "@(#)symt.c 4.1 %G%";
char nullname
[] = {0,0,0,0,0,0,0,0,0}; /* a few 0 bytes */
register int from
= stoff
;
*buff
= symtab
[from
/sizeof (struct nlist
)];
return (sizeof (struct nlist
));
#define bread(a,b,c) stread(b,c)
#define blseek(a,b,c) stseek(b,c)
/* initialize file and procedure tables */
register struct proct
*procp
;
register struct filet
*filep
;
register struct nlist
*sp
;
lseek(txtmap
.ufd
, gstart
, 0);
if (read(txtmap
.ufd
, &ssiz
, sizeof(ssiz
)) != sizeof (ssiz
)) {
printf("%s: no string table (old format?)\n", symfil
);
strtab
= (char *)malloc(ssiz
);
printf("no room for %d bytes of string table\n", ssiz
);
if (read(txtmap
.ufd
, strtab
+sizeof (ssiz
), ssiz
) != ssiz
) {
printf("%s: error reading string table\n", symfil
);
symtab
= (struct nlist
*)malloc(i
);
printf("no room for %d bytes of symbol table\n", i
);
lseek(txtmap
.ufd
, ststart
, 0);
if (read(txtmap
.ufd
, symtab
, i
) != i
) {
printf("%s: error reading symbol table\n", symfil
);
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
) {
printf("danger: mangled symbol table\n");
sp
->n_un
.n_name
= nullname
;
sp
->n_un
.n_name
= strtab
+ sp
->n_un
.n_strx
;
sp
->n_un
.n_name
= nullname
;
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_un
.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
;
filep
->sfilename
= stentry
.n_un
.n_name
;
for (p
=fp
; *q
; *p
++ = *q
++) ;
if (stat(filework
, &stbuf
) == -1)
printf("Warning: `%s' not found\n",
else if (stbuf
.st_mtime
> symtime
)
printf("Warning: `%s' newer than `%s'\n",
if (stentry
.n_un
.n_name
[0] != '_') break;
if (sbrk(PROCINCR
*sizeof procp
[0]) < 0) {
procp
->pname
[i
] = stentry
.n_un
.n_name
[i
];
procp
->pname
= stentry
.n_un
.n_name
;
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
) {
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
;
badproc
->pname
[0] = badfile
->sfilename
[0]=
procp
->pname
[0] = filep
->sfilename
[0] = '\0';
badproc
->pname
= badfile
->sfilename
=
procp
->pname
= filep
->sfilename
= nullname
;
printf("Warning: `%s' not compiled with -g\n", symfil
);
/* 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
, *altproc
;
if (s
[0] == '\0') return(curproc());
for (p
=procs
; p
->pname
[0]; p
++) {
if (eqpat(s
, p
->pname
)) return(p
);
if (p
->pname
[0] == '_' && eqpatr(s
, p
->pname
+1, 1))
/* returns file s containing filename */
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");
* 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.
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_un
.n_name
[7]; q
>=stentry
.n_un
.n_name
; q
--) {
for (q
= stentry
.n_un
.n_name
; *q
; q
++)
if (eqpat(comblk
, stentry
.n_un
.n_name
))
procp
= findproc(stentry
.n_un
.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_un
.n_name
) &&
stentry
.n_un
.n_name
[0] && class & STABTYPES
&&
(comblk
[0] == '\0' && incomm
== 0) ||
(stelt
== (class == N_SSYM
))) {
sl_size
= stentry
.n_value
;
offset
-= sizeof stentry
;
if (stentry
.n_type
&~N_EXT
== N_BSS
) {
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
] =
sl_name
= stentry
.n_un
.n_name
;
if (clevel
!= 0) docomm(offset
);
return(offset
- sizeof stentry
);
* Look up global variable matching pat starting at (filestart+sizeof stentry)
* 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_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_type
= stentry
.n_desc
;
sl_addr
= stentry
.n_value
;
for (i
=0; i
<8; i
++) sl_name
[i
] = stentry
.n_un
.n_name
[i
];
sl_name
= stentry
.n_un
.n_name
;
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
&~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);
if (bread(&sbuf
, &stentry
, sizeof stentry
)
if (stentry
.n_un
.n_name
[0] != '_') continue;
if (eqpatr(sl_name
, stentry
.n_un
.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
* 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.
lineno
= lastoffset
= -1;
offset
= adrtoprocp(addr
)->st_offset
;
blseek(&sbuf
, offset
, 0);
if (bread(&sbuf
, &stentry
, sizeof stentry
)
if (stentry
.n_type
== N_SO
)
if (stentry
.n_type
== N_SLINE
) {
if (stentry
.n_value
> addr
)
lnfaddr
= stentry
.n_value
;
if (stentry
.n_value
== addr
)
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(procp
->paddr
)->sfilename
);
printf("0x%x in ", exactaddr
);
printf("%.8s:", procp
->pname
);
printf("%s:", procp
->pname
);
if (procp
->pname
[0] == '_')
printf("%.7s: address 0x%x\n", procp
->pname
+1, dot
);
printf("%s: address 0x%x\n", procp
->pname
+1, dot
);
printf("%.8s: address %d\n", procp
->pname
, dot
);
printf("%s: 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_un
.n_name
[i
]) goto neq
;
if (stentry
.n_un
.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 (strcmp(file
, stentry
.n_un
.n_name
))
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
);
oldaddr
= 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_un
.n_name
[0] == '_' &&
eqpatr(name
, stentry
.n_un
.n_name
+1, 1))
* Look up external data symbol matching pat starting at
* (filestart+sizeof stentry)
* Return its address in sl_addr and name in sl_name.
extlookup(pat
, filestart
)
char *pat
; long 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
);
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
;
for (i
=0; i
<7; i
++) sl_name
[i
] = stentry
.n_un
.n_name
[i
+1];
sl_name
= stentry
.n_un
.n_name
;
return(offset
+ sizeof stentry
);
g1
: if (bread(&sbuf
, &stentry
, sizeof stentry
) < sizeof stentry
)
offset
+= sizeof stentry
;
/* 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_un
.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
++) {
* address to external name
* returns difference between addr and address of external
* name returned in sl_name
register int i
, prevdiff
= MAXPOS
, diff
;
blseek(&sbuf
, extstart
, 0);
if (bread(&sbuf
, &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
) {
sl_name
[i
] = stentry
.n_un
.n_name
[i
+1];
sl_name
= stentry
.n_un
.n_name
;
* address to local name in procp
* returns difference between addr and address of local
ADDR addr
; struct proct
*procp
; {
register int i
, prevdiff
= MAXPOS
, diff
;
blseek(&sbuf
, procp
->st_offset
+ sizeof stentry
, 0);
if (bread(&sbuf
, &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
) {
sl_name
[i
] = stentry
.n_un
.n_name
[i
];
sl_name
= stentry
.n_un
.n_name
;
* address to parameter name in procp
* returns difference between addr and address of local
ADDR addr
; struct proct
*procp
; {
register int i
, prevdiff
= MAXPOS
, diff
;
blseek(&sbuf
, procp
->st_offset
+ sizeof stentry
, 0);
if (bread(&sbuf
, &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
) {
sl_name
[i
] = stentry
.n_un
.n_name
[i
];
sl_name
= stentry
.n_un
.n_name
;
* register number to register variable name in procp
adrtoregvar(regno
, procp
)
ADDR regno
; struct proct
*procp
; {
blseek(&sbuf
, procp
->st_offset
+ sizeof stentry
, 0);
if (bread(&sbuf
, &stentry
, sizeof stentry
)
< sizeof stentry
) return(-1);
if (stentry
.n_type
== N_FUN
)
if (stentry
.n_type
== N_RSYM
) {
if (stentry
.n_value
== regno
) {
sl_name
[i
] = stentry
.n_un
.n_name
[i
];
sl_name
= stentry
.n_un
.n_name
;
/* sets file map for M command */
sout
: if (amap
.mp
== 0) {
error("Map `?' or `/' must be specified");
if (*s
>= '0' && *s
<= '9')
*(amap
.mp
)++ = readint(&s
);