174a4d8c2SCharles.Forsyth #include <lib9.h>
274a4d8c2SCharles.Forsyth #include <bio.h>
374a4d8c2SCharles.Forsyth #include "mach.h"
474a4d8c2SCharles.Forsyth
574a4d8c2SCharles.Forsyth #define HUGEINT 0x7fffffff
674a4d8c2SCharles.Forsyth #define NNAME 20 /* a relic of the past */
774a4d8c2SCharles.Forsyth
874a4d8c2SCharles.Forsyth typedef struct txtsym Txtsym;
974a4d8c2SCharles.Forsyth typedef struct file File;
1074a4d8c2SCharles.Forsyth typedef struct hist Hist;
1174a4d8c2SCharles.Forsyth
1274a4d8c2SCharles.Forsyth struct txtsym { /* Text Symbol table */
1374a4d8c2SCharles.Forsyth int n; /* number of local vars */
1474a4d8c2SCharles.Forsyth Sym **locals; /* array of ptrs to autos */
1574a4d8c2SCharles.Forsyth Sym *sym; /* function symbol entry */
1674a4d8c2SCharles.Forsyth };
1774a4d8c2SCharles.Forsyth
1874a4d8c2SCharles.Forsyth struct hist { /* Stack of include files & #line directives */
1974a4d8c2SCharles.Forsyth char *name; /* Assumes names Null terminated in file */
2074a4d8c2SCharles.Forsyth long line; /* line # where it was included */
2174a4d8c2SCharles.Forsyth long offset; /* line # of #line directive */
2274a4d8c2SCharles.Forsyth };
2374a4d8c2SCharles.Forsyth
2474a4d8c2SCharles.Forsyth struct file { /* Per input file header to history stack */
25*d67b7dadSforsyth uvlong addr; /* address of first text sym */
26*d67b7dadSforsyth /* union { */
27*d67b7dadSforsyth Txtsym *txt; /* first text symbol */
28*d67b7dadSforsyth Sym *sym; /* only during initilization */
29*d67b7dadSforsyth /* }; */
3074a4d8c2SCharles.Forsyth int n; /* size of history stack */
3174a4d8c2SCharles.Forsyth Hist *hist; /* history stack */
3274a4d8c2SCharles.Forsyth };
3374a4d8c2SCharles.Forsyth
3474a4d8c2SCharles.Forsyth static int debug = 0;
3574a4d8c2SCharles.Forsyth
3674a4d8c2SCharles.Forsyth static Sym **autos; /* Base of auto variables */
3774a4d8c2SCharles.Forsyth static File *files; /* Base of file arena */
38fb67f84dSCharles.Forsyth static int fpmax; /* largest file path index */
3974a4d8c2SCharles.Forsyth static Sym **fnames; /* file names path component table */
4074a4d8c2SCharles.Forsyth static Sym **globals; /* globals by addr table */
4174a4d8c2SCharles.Forsyth static Hist *hist; /* base of history stack */
4274a4d8c2SCharles.Forsyth static int isbuilt; /* internal table init flag */
4374a4d8c2SCharles.Forsyth static long nauto; /* number of automatics */
4474a4d8c2SCharles.Forsyth static long nfiles; /* number of files */
4574a4d8c2SCharles.Forsyth static long nglob; /* number of globals */
4674a4d8c2SCharles.Forsyth static long nhist; /* number of history stack entries */
4774a4d8c2SCharles.Forsyth static long nsym; /* number of symbols */
48*d67b7dadSforsyth static int ntxt; /* number of text symbols */
4974a4d8c2SCharles.Forsyth static uchar *pcline; /* start of pc-line state table */
5074a4d8c2SCharles.Forsyth static uchar *pclineend; /* end of pc-line table */
5174a4d8c2SCharles.Forsyth static uchar *spoff; /* start of pc-sp state table */
5274a4d8c2SCharles.Forsyth static uchar *spoffend; /* end of pc-sp offset table */
5374a4d8c2SCharles.Forsyth static Sym *symbols; /* symbol table */
5474a4d8c2SCharles.Forsyth static Txtsym *txt; /* Base of text symbol table */
55*d67b7dadSforsyth static uvlong txtstart; /* start of text segment */
56*d67b7dadSforsyth static uvlong txtend; /* end of text segment */
5774a4d8c2SCharles.Forsyth
5874a4d8c2SCharles.Forsyth static void cleansyms(void);
59*d67b7dadSforsyth static long decodename(Biobuf*, Sym*);
6074a4d8c2SCharles.Forsyth static short *encfname(char*);
6174a4d8c2SCharles.Forsyth static int fline(char*, int, long, Hist*, Hist**);
6274a4d8c2SCharles.Forsyth static void fillsym(Sym*, Symbol*);
6374a4d8c2SCharles.Forsyth static int findglobal(char*, Symbol*);
6474a4d8c2SCharles.Forsyth static int findlocvar(Symbol*, char *, Symbol*);
6574a4d8c2SCharles.Forsyth static int findtext(char*, Symbol*);
6674a4d8c2SCharles.Forsyth static int hcomp(Hist*, short*);
67*d67b7dadSforsyth static int hline(File*, short*, long*);
6874a4d8c2SCharles.Forsyth static void printhist(char*, Hist*, int);
6974a4d8c2SCharles.Forsyth static int buildtbls(void);
7074a4d8c2SCharles.Forsyth static int symcomp(void*, void*);
7174a4d8c2SCharles.Forsyth static int symerrmsg(int, char*);
7274a4d8c2SCharles.Forsyth static int txtcomp(void*, void*);
7374a4d8c2SCharles.Forsyth static int filecomp(void*, void*);
7474a4d8c2SCharles.Forsyth
7574a4d8c2SCharles.Forsyth /*
7674a4d8c2SCharles.Forsyth * initialize the symbol tables
7774a4d8c2SCharles.Forsyth */
7874a4d8c2SCharles.Forsyth int
syminit(int fd,Fhdr * fp)7974a4d8c2SCharles.Forsyth syminit(int fd, Fhdr *fp)
8074a4d8c2SCharles.Forsyth {
8174a4d8c2SCharles.Forsyth Sym *p;
82*d67b7dadSforsyth long i, l, size;
83*d67b7dadSforsyth vlong vl;
8474a4d8c2SCharles.Forsyth Biobuf b;
85*d67b7dadSforsyth int svalsz;
8674a4d8c2SCharles.Forsyth
8774a4d8c2SCharles.Forsyth if(fp->symsz == 0)
8874a4d8c2SCharles.Forsyth return 0;
8974a4d8c2SCharles.Forsyth if(fp->type == FNONE)
9074a4d8c2SCharles.Forsyth return 0;
9174a4d8c2SCharles.Forsyth
9274a4d8c2SCharles.Forsyth cleansyms();
9374a4d8c2SCharles.Forsyth textseg(fp->txtaddr, fp);
9474a4d8c2SCharles.Forsyth /* minimum symbol record size = 4+1+2 bytes */
9574a4d8c2SCharles.Forsyth symbols = malloc((fp->symsz/(4+1+2)+1)*sizeof(Sym));
9674a4d8c2SCharles.Forsyth if(symbols == 0) {
9774a4d8c2SCharles.Forsyth werrstr("can't malloc %ld bytes", fp->symsz);
9874a4d8c2SCharles.Forsyth return -1;
9974a4d8c2SCharles.Forsyth }
10074a4d8c2SCharles.Forsyth Binit(&b, fd, OREAD);
10174a4d8c2SCharles.Forsyth Bseek(&b, fp->symoff, 0);
10274a4d8c2SCharles.Forsyth nsym = 0;
10374a4d8c2SCharles.Forsyth size = 0;
10474a4d8c2SCharles.Forsyth for(p = symbols; size < fp->symsz; p++, nsym++) {
105*d67b7dadSforsyth if(fp->_magic && (fp->magic & HDR_MAGIC)){
106*d67b7dadSforsyth svalsz = 8;
107*d67b7dadSforsyth if(Bread(&b, &vl, 8) != 8)
108*d67b7dadSforsyth return symerrmsg(8, "symbol");
109*d67b7dadSforsyth p->value = beswav(vl);
110*d67b7dadSforsyth }
111*d67b7dadSforsyth else{
112*d67b7dadSforsyth svalsz = 4;
113*d67b7dadSforsyth if(Bread(&b, &l, 4) != 4)
114*d67b7dadSforsyth return symerrmsg(4, "symbol");
115*d67b7dadSforsyth p->value = (u32int)beswal(l);
116*d67b7dadSforsyth }
11774a4d8c2SCharles.Forsyth if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type))
11874a4d8c2SCharles.Forsyth return symerrmsg(sizeof(p->value), "symbol");
11974a4d8c2SCharles.Forsyth
12074a4d8c2SCharles.Forsyth i = decodename(&b, p);
12174a4d8c2SCharles.Forsyth if(i < 0)
12274a4d8c2SCharles.Forsyth return -1;
123*d67b7dadSforsyth size += i+svalsz+sizeof(p->type);
12474a4d8c2SCharles.Forsyth
12574a4d8c2SCharles.Forsyth /* count global & auto vars, text symbols, and file names */
12674a4d8c2SCharles.Forsyth switch (p->type) {
12774a4d8c2SCharles.Forsyth case 'l':
12874a4d8c2SCharles.Forsyth case 'L':
12974a4d8c2SCharles.Forsyth case 't':
13074a4d8c2SCharles.Forsyth case 'T':
13174a4d8c2SCharles.Forsyth ntxt++;
13274a4d8c2SCharles.Forsyth break;
13374a4d8c2SCharles.Forsyth case 'd':
13474a4d8c2SCharles.Forsyth case 'D':
13574a4d8c2SCharles.Forsyth case 'b':
13674a4d8c2SCharles.Forsyth case 'B':
13774a4d8c2SCharles.Forsyth nglob++;
13874a4d8c2SCharles.Forsyth break;
13974a4d8c2SCharles.Forsyth case 'f':
14074a4d8c2SCharles.Forsyth if(strcmp(p->name, ".frame") == 0) {
14174a4d8c2SCharles.Forsyth p->type = 'm';
14274a4d8c2SCharles.Forsyth nauto++;
14374a4d8c2SCharles.Forsyth }
144fb67f84dSCharles.Forsyth else if(p->value > fpmax)
145fb67f84dSCharles.Forsyth fpmax = p->value; /* highest path index */
14674a4d8c2SCharles.Forsyth break;
14774a4d8c2SCharles.Forsyth case 'a':
14874a4d8c2SCharles.Forsyth case 'p':
14974a4d8c2SCharles.Forsyth case 'm':
15074a4d8c2SCharles.Forsyth nauto++;
15174a4d8c2SCharles.Forsyth break;
15274a4d8c2SCharles.Forsyth case 'z':
15374a4d8c2SCharles.Forsyth if(p->value == 1) { /* one extra per file */
15474a4d8c2SCharles.Forsyth nhist++;
15574a4d8c2SCharles.Forsyth nfiles++;
15674a4d8c2SCharles.Forsyth }
15774a4d8c2SCharles.Forsyth nhist++;
15874a4d8c2SCharles.Forsyth break;
15974a4d8c2SCharles.Forsyth default:
16074a4d8c2SCharles.Forsyth break;
16174a4d8c2SCharles.Forsyth }
16274a4d8c2SCharles.Forsyth }
16374a4d8c2SCharles.Forsyth if (debug)
164*d67b7dadSforsyth print("NG: %ld NT: %d NF: %d\n", nglob, ntxt, fpmax);
16574a4d8c2SCharles.Forsyth if (fp->sppcsz) { /* pc-sp offset table */
16674a4d8c2SCharles.Forsyth spoff = (uchar *)malloc(fp->sppcsz);
16774a4d8c2SCharles.Forsyth if(spoff == 0) {
16874a4d8c2SCharles.Forsyth werrstr("can't malloc %ld bytes", fp->sppcsz);
16974a4d8c2SCharles.Forsyth return -1;
17074a4d8c2SCharles.Forsyth }
17174a4d8c2SCharles.Forsyth Bseek(&b, fp->sppcoff, 0);
172*d67b7dadSforsyth if(Bread(&b, spoff, fp->sppcsz) != fp->sppcsz){
17374a4d8c2SCharles.Forsyth spoff = 0;
17474a4d8c2SCharles.Forsyth return symerrmsg(fp->sppcsz, "sp-pc");
17574a4d8c2SCharles.Forsyth }
17674a4d8c2SCharles.Forsyth spoffend = spoff+fp->sppcsz;
17774a4d8c2SCharles.Forsyth }
17874a4d8c2SCharles.Forsyth if (fp->lnpcsz) { /* pc-line number table */
17974a4d8c2SCharles.Forsyth pcline = (uchar *)malloc(fp->lnpcsz);
18074a4d8c2SCharles.Forsyth if(pcline == 0) {
18174a4d8c2SCharles.Forsyth werrstr("can't malloc %ld bytes", fp->lnpcsz);
18274a4d8c2SCharles.Forsyth return -1;
18374a4d8c2SCharles.Forsyth }
18474a4d8c2SCharles.Forsyth Bseek(&b, fp->lnpcoff, 0);
185*d67b7dadSforsyth if(Bread(&b, pcline, fp->lnpcsz) != fp->lnpcsz){
18674a4d8c2SCharles.Forsyth pcline = 0;
18774a4d8c2SCharles.Forsyth return symerrmsg(fp->lnpcsz, "pc-line");
18874a4d8c2SCharles.Forsyth }
18974a4d8c2SCharles.Forsyth pclineend = pcline+fp->lnpcsz;
19074a4d8c2SCharles.Forsyth }
19174a4d8c2SCharles.Forsyth return nsym;
19274a4d8c2SCharles.Forsyth }
19374a4d8c2SCharles.Forsyth
19474a4d8c2SCharles.Forsyth static int
symerrmsg(int n,char * table)19574a4d8c2SCharles.Forsyth symerrmsg(int n, char *table)
19674a4d8c2SCharles.Forsyth {
19774a4d8c2SCharles.Forsyth werrstr("can't read %d bytes of %s table", n, table);
19874a4d8c2SCharles.Forsyth return -1;
19974a4d8c2SCharles.Forsyth }
20074a4d8c2SCharles.Forsyth
201*d67b7dadSforsyth static long
decodename(Biobuf * bp,Sym * p)20274a4d8c2SCharles.Forsyth decodename(Biobuf *bp, Sym *p)
20374a4d8c2SCharles.Forsyth {
20474a4d8c2SCharles.Forsyth char *cp;
20574a4d8c2SCharles.Forsyth int c1, c2;
206*d67b7dadSforsyth long n;
207*d67b7dadSforsyth vlong o;
20874a4d8c2SCharles.Forsyth
20974a4d8c2SCharles.Forsyth if((p->type & 0x80) == 0) { /* old-style, fixed length names */
21074a4d8c2SCharles.Forsyth p->name = malloc(NNAME);
21174a4d8c2SCharles.Forsyth if(p->name == 0) {
21274a4d8c2SCharles.Forsyth werrstr("can't malloc %d bytes", NNAME);
21374a4d8c2SCharles.Forsyth return -1;
21474a4d8c2SCharles.Forsyth }
21574a4d8c2SCharles.Forsyth if(Bread(bp, p->name, NNAME) != NNAME)
21674a4d8c2SCharles.Forsyth return symerrmsg(NNAME, "symbol");
21774a4d8c2SCharles.Forsyth Bseek(bp, 3, 1);
21874a4d8c2SCharles.Forsyth return NNAME+3;
21974a4d8c2SCharles.Forsyth }
22074a4d8c2SCharles.Forsyth
22174a4d8c2SCharles.Forsyth p->type &= ~0x80;
22274a4d8c2SCharles.Forsyth if(p->type == 'z' || p->type == 'Z') {
223*d67b7dadSforsyth o = Bseek(bp, 0, 1);
22474a4d8c2SCharles.Forsyth if(Bgetc(bp) < 0) {
22574a4d8c2SCharles.Forsyth werrstr("can't read symbol name");
22674a4d8c2SCharles.Forsyth return -1;
22774a4d8c2SCharles.Forsyth }
22874a4d8c2SCharles.Forsyth for(;;) {
22974a4d8c2SCharles.Forsyth c1 = Bgetc(bp);
23074a4d8c2SCharles.Forsyth c2 = Bgetc(bp);
23174a4d8c2SCharles.Forsyth if(c1 < 0 || c2 < 0) {
23274a4d8c2SCharles.Forsyth werrstr("can't read symbol name");
23374a4d8c2SCharles.Forsyth return -1;
23474a4d8c2SCharles.Forsyth }
23574a4d8c2SCharles.Forsyth if(c1 == 0 && c2 == 0)
23674a4d8c2SCharles.Forsyth break;
23774a4d8c2SCharles.Forsyth }
238*d67b7dadSforsyth n = Bseek(bp, 0, 1)-o;
23974a4d8c2SCharles.Forsyth p->name = malloc(n);
24074a4d8c2SCharles.Forsyth if(p->name == 0) {
241*d67b7dadSforsyth werrstr("can't malloc %ld bytes", n);
24274a4d8c2SCharles.Forsyth return -1;
24374a4d8c2SCharles.Forsyth }
24474a4d8c2SCharles.Forsyth Bseek(bp, -n, 1);
24574a4d8c2SCharles.Forsyth if(Bread(bp, p->name, n) != n) {
246*d67b7dadSforsyth werrstr("can't read %ld bytes of symbol name", n);
24774a4d8c2SCharles.Forsyth return -1;
24874a4d8c2SCharles.Forsyth }
24974a4d8c2SCharles.Forsyth } else {
25074a4d8c2SCharles.Forsyth cp = Brdline(bp, '\0');
25174a4d8c2SCharles.Forsyth if(cp == 0) {
25274a4d8c2SCharles.Forsyth werrstr("can't read symbol name");
25374a4d8c2SCharles.Forsyth return -1;
25474a4d8c2SCharles.Forsyth }
25574a4d8c2SCharles.Forsyth n = Blinelen(bp);
25674a4d8c2SCharles.Forsyth p->name = malloc(n);
25774a4d8c2SCharles.Forsyth if(p->name == 0) {
258*d67b7dadSforsyth werrstr("can't malloc %ld bytes", n);
25974a4d8c2SCharles.Forsyth return -1;
26074a4d8c2SCharles.Forsyth }
26174a4d8c2SCharles.Forsyth strcpy(p->name, cp);
26274a4d8c2SCharles.Forsyth }
26374a4d8c2SCharles.Forsyth return n;
26474a4d8c2SCharles.Forsyth }
265*d67b7dadSforsyth
26674a4d8c2SCharles.Forsyth /*
26774a4d8c2SCharles.Forsyth * free any previously loaded symbol tables
26874a4d8c2SCharles.Forsyth */
26974a4d8c2SCharles.Forsyth static void
cleansyms(void)27074a4d8c2SCharles.Forsyth cleansyms(void)
27174a4d8c2SCharles.Forsyth {
27274a4d8c2SCharles.Forsyth if(globals)
27374a4d8c2SCharles.Forsyth free(globals);
27474a4d8c2SCharles.Forsyth globals = 0;
27574a4d8c2SCharles.Forsyth nglob = 0;
27674a4d8c2SCharles.Forsyth if(txt)
27774a4d8c2SCharles.Forsyth free(txt);
27874a4d8c2SCharles.Forsyth txt = 0;
27974a4d8c2SCharles.Forsyth ntxt = 0;
28074a4d8c2SCharles.Forsyth if(fnames)
28174a4d8c2SCharles.Forsyth free(fnames);
28274a4d8c2SCharles.Forsyth fnames = 0;
283fb67f84dSCharles.Forsyth fpmax = 0;
28474a4d8c2SCharles.Forsyth
28574a4d8c2SCharles.Forsyth if(files)
28674a4d8c2SCharles.Forsyth free(files);
28774a4d8c2SCharles.Forsyth files = 0;
28874a4d8c2SCharles.Forsyth nfiles = 0;
28974a4d8c2SCharles.Forsyth if(hist)
29074a4d8c2SCharles.Forsyth free(hist);
29174a4d8c2SCharles.Forsyth hist = 0;
29274a4d8c2SCharles.Forsyth nhist = 0;
29374a4d8c2SCharles.Forsyth if(autos)
29474a4d8c2SCharles.Forsyth free(autos);
29574a4d8c2SCharles.Forsyth autos = 0;
29674a4d8c2SCharles.Forsyth nauto = 0;
29774a4d8c2SCharles.Forsyth isbuilt = 0;
29874a4d8c2SCharles.Forsyth if(symbols)
29974a4d8c2SCharles.Forsyth free(symbols);
30074a4d8c2SCharles.Forsyth symbols = 0;
30174a4d8c2SCharles.Forsyth nsym = 0;
30274a4d8c2SCharles.Forsyth if(spoff)
30374a4d8c2SCharles.Forsyth free(spoff);
30474a4d8c2SCharles.Forsyth spoff = 0;
30574a4d8c2SCharles.Forsyth if(pcline)
30674a4d8c2SCharles.Forsyth free(pcline);
30774a4d8c2SCharles.Forsyth pcline = 0;
30874a4d8c2SCharles.Forsyth }
309*d67b7dadSforsyth
31074a4d8c2SCharles.Forsyth /*
31174a4d8c2SCharles.Forsyth * delimit the text segment
31274a4d8c2SCharles.Forsyth */
31374a4d8c2SCharles.Forsyth void
textseg(uvlong base,Fhdr * fp)314*d67b7dadSforsyth textseg(uvlong base, Fhdr *fp)
31574a4d8c2SCharles.Forsyth {
31674a4d8c2SCharles.Forsyth txtstart = base;
31774a4d8c2SCharles.Forsyth txtend = base+fp->txtsz;
31874a4d8c2SCharles.Forsyth }
319*d67b7dadSforsyth
32074a4d8c2SCharles.Forsyth /*
32174a4d8c2SCharles.Forsyth * symbase: return base and size of raw symbol table
32274a4d8c2SCharles.Forsyth * (special hack for high access rate operations)
32374a4d8c2SCharles.Forsyth */
32474a4d8c2SCharles.Forsyth Sym *
symbase(long * n)32574a4d8c2SCharles.Forsyth symbase(long *n)
32674a4d8c2SCharles.Forsyth {
32774a4d8c2SCharles.Forsyth *n = nsym;
32874a4d8c2SCharles.Forsyth return symbols;
32974a4d8c2SCharles.Forsyth }
330*d67b7dadSforsyth
33174a4d8c2SCharles.Forsyth /*
33274a4d8c2SCharles.Forsyth * Get the ith symbol table entry
33374a4d8c2SCharles.Forsyth */
33474a4d8c2SCharles.Forsyth Sym *
getsym(int index)33574a4d8c2SCharles.Forsyth getsym(int index)
33674a4d8c2SCharles.Forsyth {
337*d67b7dadSforsyth if(index >= 0 && index < nsym)
33874a4d8c2SCharles.Forsyth return &symbols[index];
33974a4d8c2SCharles.Forsyth return 0;
34074a4d8c2SCharles.Forsyth }
34174a4d8c2SCharles.Forsyth
34274a4d8c2SCharles.Forsyth /*
34374a4d8c2SCharles.Forsyth * initialize internal symbol tables
34474a4d8c2SCharles.Forsyth */
34574a4d8c2SCharles.Forsyth static int
buildtbls(void)34674a4d8c2SCharles.Forsyth buildtbls(void)
34774a4d8c2SCharles.Forsyth {
348*d67b7dadSforsyth long i;
349*d67b7dadSforsyth int j, nh, ng, nt;
35074a4d8c2SCharles.Forsyth File *f;
35174a4d8c2SCharles.Forsyth Txtsym *tp;
35274a4d8c2SCharles.Forsyth Hist *hp;
35374a4d8c2SCharles.Forsyth Sym *p, **ap;
35474a4d8c2SCharles.Forsyth
35574a4d8c2SCharles.Forsyth if(isbuilt)
35674a4d8c2SCharles.Forsyth return 1;
35774a4d8c2SCharles.Forsyth isbuilt = 1;
35874a4d8c2SCharles.Forsyth /* allocate the tables */
35974a4d8c2SCharles.Forsyth if(nglob) {
36074a4d8c2SCharles.Forsyth globals = malloc(nglob*sizeof(*globals));
36174a4d8c2SCharles.Forsyth if(!globals) {
36274a4d8c2SCharles.Forsyth werrstr("can't malloc global symbol table");
36374a4d8c2SCharles.Forsyth return 0;
36474a4d8c2SCharles.Forsyth }
36574a4d8c2SCharles.Forsyth }
36674a4d8c2SCharles.Forsyth if(ntxt) {
36774a4d8c2SCharles.Forsyth txt = malloc(ntxt*sizeof(*txt));
36874a4d8c2SCharles.Forsyth if (!txt) {
36974a4d8c2SCharles.Forsyth werrstr("can't malloc text symbol table");
37074a4d8c2SCharles.Forsyth return 0;
37174a4d8c2SCharles.Forsyth }
37274a4d8c2SCharles.Forsyth }
373*d67b7dadSforsyth fnames = malloc((fpmax+1)*sizeof(*fnames));
37474a4d8c2SCharles.Forsyth if (!fnames) {
37574a4d8c2SCharles.Forsyth werrstr("can't malloc file name table");
37674a4d8c2SCharles.Forsyth return 0;
37774a4d8c2SCharles.Forsyth }
378*d67b7dadSforsyth memset(fnames, 0, (fpmax+1)*sizeof(*fnames));
37974a4d8c2SCharles.Forsyth files = malloc(nfiles*sizeof(*files));
38074a4d8c2SCharles.Forsyth if(!files) {
38174a4d8c2SCharles.Forsyth werrstr("can't malloc file table");
38274a4d8c2SCharles.Forsyth return 0;
38374a4d8c2SCharles.Forsyth }
38474a4d8c2SCharles.Forsyth hist = malloc(nhist*sizeof(Hist));
38574a4d8c2SCharles.Forsyth if(hist == 0) {
38674a4d8c2SCharles.Forsyth werrstr("can't malloc history stack");
38774a4d8c2SCharles.Forsyth return 0;
38874a4d8c2SCharles.Forsyth }
38974a4d8c2SCharles.Forsyth autos = malloc(nauto*sizeof(Sym*));
39074a4d8c2SCharles.Forsyth if(autos == 0) {
39174a4d8c2SCharles.Forsyth werrstr("can't malloc auto symbol table");
39274a4d8c2SCharles.Forsyth return 0;
39374a4d8c2SCharles.Forsyth }
39474a4d8c2SCharles.Forsyth /* load the tables */
39574a4d8c2SCharles.Forsyth ng = nt = nh = 0;
39674a4d8c2SCharles.Forsyth f = 0;
39774a4d8c2SCharles.Forsyth tp = 0;
39874a4d8c2SCharles.Forsyth i = nsym;
39974a4d8c2SCharles.Forsyth hp = hist;
40074a4d8c2SCharles.Forsyth ap = autos;
40174a4d8c2SCharles.Forsyth for(p = symbols; i-- > 0; p++) {
40274a4d8c2SCharles.Forsyth switch(p->type) {
40374a4d8c2SCharles.Forsyth case 'D':
40474a4d8c2SCharles.Forsyth case 'd':
40574a4d8c2SCharles.Forsyth case 'B':
40674a4d8c2SCharles.Forsyth case 'b':
40774a4d8c2SCharles.Forsyth if(debug)
408*d67b7dadSforsyth print("Global: %s %llux\n", p->name, p->value);
40974a4d8c2SCharles.Forsyth globals[ng++] = p;
41074a4d8c2SCharles.Forsyth break;
41174a4d8c2SCharles.Forsyth case 'z':
41274a4d8c2SCharles.Forsyth if(p->value == 1) { /* New file */
41374a4d8c2SCharles.Forsyth if(f) {
41474a4d8c2SCharles.Forsyth f->n = nh;
41574a4d8c2SCharles.Forsyth f->hist[nh].name = 0; /* one extra */
41674a4d8c2SCharles.Forsyth hp += nh+1;
41774a4d8c2SCharles.Forsyth f++;
41874a4d8c2SCharles.Forsyth }
419*d67b7dadSforsyth else
420*d67b7dadSforsyth f = files;
42174a4d8c2SCharles.Forsyth f->hist = hp;
422*d67b7dadSforsyth f->sym = 0;
42374a4d8c2SCharles.Forsyth f->addr = 0;
42474a4d8c2SCharles.Forsyth nh = 0;
42574a4d8c2SCharles.Forsyth }
42674a4d8c2SCharles.Forsyth /* alloc one slot extra as terminator */
42774a4d8c2SCharles.Forsyth f->hist[nh].name = p->name;
42874a4d8c2SCharles.Forsyth f->hist[nh].line = p->value;
42974a4d8c2SCharles.Forsyth f->hist[nh].offset = 0;
43074a4d8c2SCharles.Forsyth if(debug)
43174a4d8c2SCharles.Forsyth printhist("-> ", &f->hist[nh], 1);
43274a4d8c2SCharles.Forsyth nh++;
43374a4d8c2SCharles.Forsyth break;
43474a4d8c2SCharles.Forsyth case 'Z':
43574a4d8c2SCharles.Forsyth if(f && nh > 0)
43674a4d8c2SCharles.Forsyth f->hist[nh-1].offset = p->value;
43774a4d8c2SCharles.Forsyth break;
43874a4d8c2SCharles.Forsyth case 'T':
43974a4d8c2SCharles.Forsyth case 't': /* Text: terminate history if first in file */
44074a4d8c2SCharles.Forsyth case 'L':
44174a4d8c2SCharles.Forsyth case 'l':
44274a4d8c2SCharles.Forsyth tp = &txt[nt++];
44374a4d8c2SCharles.Forsyth tp->n = 0;
44474a4d8c2SCharles.Forsyth tp->sym = p;
44574a4d8c2SCharles.Forsyth tp->locals = ap;
44674a4d8c2SCharles.Forsyth if(debug)
447*d67b7dadSforsyth print("TEXT: %s at %llux\n", p->name, p->value);
448*d67b7dadSforsyth if(f && !f->sym) { /* first */
449*d67b7dadSforsyth f->sym = p;
45074a4d8c2SCharles.Forsyth f->addr = p->value;
45174a4d8c2SCharles.Forsyth }
45274a4d8c2SCharles.Forsyth break;
45374a4d8c2SCharles.Forsyth case 'a':
45474a4d8c2SCharles.Forsyth case 'p':
45574a4d8c2SCharles.Forsyth case 'm': /* Local Vars */
45674a4d8c2SCharles.Forsyth if(!tp)
457*d67b7dadSforsyth print("Warning: Free floating local var: %s\n",
458*d67b7dadSforsyth p->name);
45974a4d8c2SCharles.Forsyth else {
46074a4d8c2SCharles.Forsyth if(debug)
461*d67b7dadSforsyth print("Local: %s %llux\n", p->name, p->value);
46274a4d8c2SCharles.Forsyth tp->locals[tp->n] = p;
46374a4d8c2SCharles.Forsyth tp->n++;
46474a4d8c2SCharles.Forsyth ap++;
46574a4d8c2SCharles.Forsyth }
46674a4d8c2SCharles.Forsyth break;
46774a4d8c2SCharles.Forsyth case 'f': /* File names */
46874a4d8c2SCharles.Forsyth if(debug)
469*d67b7dadSforsyth print("Fname: %s\n", p->name);
47074a4d8c2SCharles.Forsyth fnames[p->value] = p;
47174a4d8c2SCharles.Forsyth break;
47274a4d8c2SCharles.Forsyth default:
47374a4d8c2SCharles.Forsyth break;
47474a4d8c2SCharles.Forsyth }
47574a4d8c2SCharles.Forsyth }
47674a4d8c2SCharles.Forsyth /* sort global and text tables into ascending address order */
47774a4d8c2SCharles.Forsyth qsort(globals, nglob, sizeof(Sym*), symcomp);
47874a4d8c2SCharles.Forsyth qsort(txt, ntxt, sizeof(Txtsym), txtcomp);
47974a4d8c2SCharles.Forsyth qsort(files, nfiles, sizeof(File), filecomp);
48074a4d8c2SCharles.Forsyth tp = txt;
48174a4d8c2SCharles.Forsyth for(i = 0, f = files; i < nfiles; i++, f++) {
48274a4d8c2SCharles.Forsyth for(j = 0; j < ntxt; j++) {
483*d67b7dadSforsyth if(f->sym == tp->sym) {
48474a4d8c2SCharles.Forsyth if(debug) {
485*d67b7dadSforsyth print("LINK: %s to at %llux", f->sym->name, f->addr);
48674a4d8c2SCharles.Forsyth printhist("... ", f->hist, 1);
48774a4d8c2SCharles.Forsyth }
488*d67b7dadSforsyth f->txt = tp++;
48974a4d8c2SCharles.Forsyth break;
49074a4d8c2SCharles.Forsyth }
49174a4d8c2SCharles.Forsyth if(++tp >= txt+ntxt) /* wrap around */
49274a4d8c2SCharles.Forsyth tp = txt;
49374a4d8c2SCharles.Forsyth }
49474a4d8c2SCharles.Forsyth }
49574a4d8c2SCharles.Forsyth return 1;
49674a4d8c2SCharles.Forsyth }
49774a4d8c2SCharles.Forsyth
49874a4d8c2SCharles.Forsyth /*
49974a4d8c2SCharles.Forsyth * find symbol function.var by name.
50074a4d8c2SCharles.Forsyth * fn != 0 && var != 0 => look for fn in text, var in data
50174a4d8c2SCharles.Forsyth * fn != 0 && var == 0 => look for fn in text
50274a4d8c2SCharles.Forsyth * fn == 0 && var != 0 => look for var first in text then in data space.
50374a4d8c2SCharles.Forsyth */
50474a4d8c2SCharles.Forsyth int
lookup(char * fn,char * var,Symbol * s)50574a4d8c2SCharles.Forsyth lookup(char *fn, char *var, Symbol *s)
50674a4d8c2SCharles.Forsyth {
50774a4d8c2SCharles.Forsyth int found;
50874a4d8c2SCharles.Forsyth
50974a4d8c2SCharles.Forsyth if(buildtbls() == 0)
51074a4d8c2SCharles.Forsyth return 0;
51174a4d8c2SCharles.Forsyth if(fn) {
51274a4d8c2SCharles.Forsyth found = findtext(fn, s);
51374a4d8c2SCharles.Forsyth if(var == 0) /* case 2: fn not in text */
51474a4d8c2SCharles.Forsyth return found;
51574a4d8c2SCharles.Forsyth else if(!found) /* case 1: fn not found */
51674a4d8c2SCharles.Forsyth return 0;
51774a4d8c2SCharles.Forsyth } else if(var) {
51874a4d8c2SCharles.Forsyth found = findtext(var, s);
51974a4d8c2SCharles.Forsyth if(found)
52074a4d8c2SCharles.Forsyth return 1; /* case 3: var found in text */
52174a4d8c2SCharles.Forsyth } else return 0; /* case 4: fn & var == zero */
52274a4d8c2SCharles.Forsyth
52374a4d8c2SCharles.Forsyth if(found)
52474a4d8c2SCharles.Forsyth return findlocal(s, var, s); /* case 1: fn found */
52574a4d8c2SCharles.Forsyth return findglobal(var, s); /* case 3: var not found */
52674a4d8c2SCharles.Forsyth
52774a4d8c2SCharles.Forsyth }
528*d67b7dadSforsyth
52974a4d8c2SCharles.Forsyth /*
53074a4d8c2SCharles.Forsyth * find a function by name
53174a4d8c2SCharles.Forsyth */
53274a4d8c2SCharles.Forsyth static int
findtext(char * name,Symbol * s)53374a4d8c2SCharles.Forsyth findtext(char *name, Symbol *s)
53474a4d8c2SCharles.Forsyth {
53574a4d8c2SCharles.Forsyth int i;
53674a4d8c2SCharles.Forsyth
53774a4d8c2SCharles.Forsyth for(i = 0; i < ntxt; i++) {
53874a4d8c2SCharles.Forsyth if(strcmp(txt[i].sym->name, name) == 0) {
53974a4d8c2SCharles.Forsyth fillsym(txt[i].sym, s);
54074a4d8c2SCharles.Forsyth s->handle = (void *) &txt[i];
541*d67b7dadSforsyth s->index = i;
54274a4d8c2SCharles.Forsyth return 1;
54374a4d8c2SCharles.Forsyth }
54474a4d8c2SCharles.Forsyth }
54574a4d8c2SCharles.Forsyth return 0;
54674a4d8c2SCharles.Forsyth }
54774a4d8c2SCharles.Forsyth /*
54874a4d8c2SCharles.Forsyth * find global variable by name
54974a4d8c2SCharles.Forsyth */
55074a4d8c2SCharles.Forsyth static int
findglobal(char * name,Symbol * s)55174a4d8c2SCharles.Forsyth findglobal(char *name, Symbol *s)
55274a4d8c2SCharles.Forsyth {
553*d67b7dadSforsyth long i;
55474a4d8c2SCharles.Forsyth
55574a4d8c2SCharles.Forsyth for(i = 0; i < nglob; i++) {
55674a4d8c2SCharles.Forsyth if(strcmp(globals[i]->name, name) == 0) {
55774a4d8c2SCharles.Forsyth fillsym(globals[i], s);
558*d67b7dadSforsyth s->index = i;
55974a4d8c2SCharles.Forsyth return 1;
56074a4d8c2SCharles.Forsyth }
56174a4d8c2SCharles.Forsyth }
56274a4d8c2SCharles.Forsyth return 0;
56374a4d8c2SCharles.Forsyth }
564*d67b7dadSforsyth
56574a4d8c2SCharles.Forsyth /*
56674a4d8c2SCharles.Forsyth * find the local variable by name within a given function
56774a4d8c2SCharles.Forsyth */
56874a4d8c2SCharles.Forsyth int
findlocal(Symbol * s1,char * name,Symbol * s2)56974a4d8c2SCharles.Forsyth findlocal(Symbol *s1, char *name, Symbol *s2)
57074a4d8c2SCharles.Forsyth {
57174a4d8c2SCharles.Forsyth if(s1 == 0)
57274a4d8c2SCharles.Forsyth return 0;
57374a4d8c2SCharles.Forsyth if(buildtbls() == 0)
57474a4d8c2SCharles.Forsyth return 0;
57574a4d8c2SCharles.Forsyth return findlocvar(s1, name, s2);
57674a4d8c2SCharles.Forsyth }
577*d67b7dadSforsyth
57874a4d8c2SCharles.Forsyth /*
57974a4d8c2SCharles.Forsyth * find the local variable by name within a given function
58074a4d8c2SCharles.Forsyth * (internal function - does no parameter validation)
58174a4d8c2SCharles.Forsyth */
58274a4d8c2SCharles.Forsyth static int
findlocvar(Symbol * s1,char * name,Symbol * s2)58374a4d8c2SCharles.Forsyth findlocvar(Symbol *s1, char *name, Symbol *s2)
58474a4d8c2SCharles.Forsyth {
58574a4d8c2SCharles.Forsyth Txtsym *tp;
58674a4d8c2SCharles.Forsyth int i;
58774a4d8c2SCharles.Forsyth
58874a4d8c2SCharles.Forsyth tp = (Txtsym *)s1->handle;
58974a4d8c2SCharles.Forsyth if(tp && tp->locals) {
59074a4d8c2SCharles.Forsyth for(i = 0; i < tp->n; i++)
59174a4d8c2SCharles.Forsyth if (strcmp(tp->locals[i]->name, name) == 0) {
59274a4d8c2SCharles.Forsyth fillsym(tp->locals[i], s2);
59374a4d8c2SCharles.Forsyth s2->handle = (void *)tp;
594*d67b7dadSforsyth s2->index = tp->n-1 - i;
59574a4d8c2SCharles.Forsyth return 1;
59674a4d8c2SCharles.Forsyth }
59774a4d8c2SCharles.Forsyth }
59874a4d8c2SCharles.Forsyth return 0;
59974a4d8c2SCharles.Forsyth }
600*d67b7dadSforsyth
60174a4d8c2SCharles.Forsyth /*
60274a4d8c2SCharles.Forsyth * Get ith text symbol
60374a4d8c2SCharles.Forsyth */
60474a4d8c2SCharles.Forsyth int
textsym(Symbol * s,int index)60574a4d8c2SCharles.Forsyth textsym(Symbol *s, int index)
60674a4d8c2SCharles.Forsyth {
60774a4d8c2SCharles.Forsyth
60874a4d8c2SCharles.Forsyth if(buildtbls() == 0)
60974a4d8c2SCharles.Forsyth return 0;
610*d67b7dadSforsyth if(index < 0 || index >= ntxt)
61174a4d8c2SCharles.Forsyth return 0;
61274a4d8c2SCharles.Forsyth fillsym(txt[index].sym, s);
61374a4d8c2SCharles.Forsyth s->handle = (void *)&txt[index];
614*d67b7dadSforsyth s->index = index;
61574a4d8c2SCharles.Forsyth return 1;
61674a4d8c2SCharles.Forsyth }
617*d67b7dadSforsyth
61874a4d8c2SCharles.Forsyth /*
61974a4d8c2SCharles.Forsyth * Get ith file name
62074a4d8c2SCharles.Forsyth */
62174a4d8c2SCharles.Forsyth int
filesym(int index,char * buf,int n)62274a4d8c2SCharles.Forsyth filesym(int index, char *buf, int n)
62374a4d8c2SCharles.Forsyth {
62474a4d8c2SCharles.Forsyth Hist *hp;
62574a4d8c2SCharles.Forsyth
62674a4d8c2SCharles.Forsyth if(buildtbls() == 0)
62774a4d8c2SCharles.Forsyth return 0;
628*d67b7dadSforsyth if(index < 0 || index >= nfiles)
62974a4d8c2SCharles.Forsyth return 0;
63074a4d8c2SCharles.Forsyth hp = files[index].hist;
63174a4d8c2SCharles.Forsyth if(!hp || !hp->name)
63274a4d8c2SCharles.Forsyth return 0;
63374a4d8c2SCharles.Forsyth return fileelem(fnames, (uchar*)hp->name, buf, n);
63474a4d8c2SCharles.Forsyth }
635*d67b7dadSforsyth
63674a4d8c2SCharles.Forsyth /*
63774a4d8c2SCharles.Forsyth * Lookup name of local variable located at an offset into the frame.
63874a4d8c2SCharles.Forsyth * The type selects either a parameter or automatic.
63974a4d8c2SCharles.Forsyth */
64074a4d8c2SCharles.Forsyth int
getauto(Symbol * s1,int off,int type,Symbol * s2)64174a4d8c2SCharles.Forsyth getauto(Symbol *s1, int off, int type, Symbol *s2)
64274a4d8c2SCharles.Forsyth {
64374a4d8c2SCharles.Forsyth Txtsym *tp;
64474a4d8c2SCharles.Forsyth Sym *p;
64574a4d8c2SCharles.Forsyth int i, t;
64674a4d8c2SCharles.Forsyth
64774a4d8c2SCharles.Forsyth if(s1 == 0)
64874a4d8c2SCharles.Forsyth return 0;
64974a4d8c2SCharles.Forsyth if(type == CPARAM)
65074a4d8c2SCharles.Forsyth t = 'p';
65174a4d8c2SCharles.Forsyth else if(type == CAUTO)
65274a4d8c2SCharles.Forsyth t = 'a';
65374a4d8c2SCharles.Forsyth else
65474a4d8c2SCharles.Forsyth return 0;
65574a4d8c2SCharles.Forsyth if(buildtbls() == 0)
65674a4d8c2SCharles.Forsyth return 0;
65774a4d8c2SCharles.Forsyth tp = (Txtsym *)s1->handle;
65874a4d8c2SCharles.Forsyth if(tp == 0)
65974a4d8c2SCharles.Forsyth return 0;
66074a4d8c2SCharles.Forsyth for(i = 0; i < tp->n; i++) {
66174a4d8c2SCharles.Forsyth p = tp->locals[i];
66274a4d8c2SCharles.Forsyth if(p->type == t && p->value == off) {
66374a4d8c2SCharles.Forsyth fillsym(p, s2);
66474a4d8c2SCharles.Forsyth s2->handle = s1->handle;
665*d67b7dadSforsyth s2->index = tp->n-1 - i;
66674a4d8c2SCharles.Forsyth return 1;
66774a4d8c2SCharles.Forsyth }
66874a4d8c2SCharles.Forsyth }
66974a4d8c2SCharles.Forsyth return 0;
67074a4d8c2SCharles.Forsyth }
67174a4d8c2SCharles.Forsyth
67274a4d8c2SCharles.Forsyth /*
67374a4d8c2SCharles.Forsyth * Find text symbol containing addr; binary search assumes text array is sorted by addr
67474a4d8c2SCharles.Forsyth */
67574a4d8c2SCharles.Forsyth static int
srchtext(uvlong addr)676*d67b7dadSforsyth srchtext(uvlong addr)
67774a4d8c2SCharles.Forsyth {
678*d67b7dadSforsyth uvlong val;
67974a4d8c2SCharles.Forsyth int top, bot, mid;
68074a4d8c2SCharles.Forsyth Sym *sp;
68174a4d8c2SCharles.Forsyth
68274a4d8c2SCharles.Forsyth val = addr;
68374a4d8c2SCharles.Forsyth bot = 0;
68474a4d8c2SCharles.Forsyth top = ntxt;
68574a4d8c2SCharles.Forsyth for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
68674a4d8c2SCharles.Forsyth sp = txt[mid].sym;
687*d67b7dadSforsyth if(val < sp->value)
68874a4d8c2SCharles.Forsyth top = mid;
689*d67b7dadSforsyth else if(mid != ntxt-1 && val >= txt[mid+1].sym->value)
69074a4d8c2SCharles.Forsyth bot = mid;
69174a4d8c2SCharles.Forsyth else
69274a4d8c2SCharles.Forsyth return mid;
69374a4d8c2SCharles.Forsyth }
69474a4d8c2SCharles.Forsyth return -1;
69574a4d8c2SCharles.Forsyth }
69674a4d8c2SCharles.Forsyth
69774a4d8c2SCharles.Forsyth /*
69874a4d8c2SCharles.Forsyth * Find data symbol containing addr; binary search assumes data array is sorted by addr
69974a4d8c2SCharles.Forsyth */
700*d67b7dadSforsyth static int
srchdata(uvlong addr)701*d67b7dadSforsyth srchdata(uvlong addr)
70274a4d8c2SCharles.Forsyth {
703*d67b7dadSforsyth uvlong val;
70474a4d8c2SCharles.Forsyth int top, bot, mid;
70574a4d8c2SCharles.Forsyth Sym *sp;
70674a4d8c2SCharles.Forsyth
70774a4d8c2SCharles.Forsyth bot = 0;
70874a4d8c2SCharles.Forsyth top = nglob;
70974a4d8c2SCharles.Forsyth val = addr;
71074a4d8c2SCharles.Forsyth for(mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
71174a4d8c2SCharles.Forsyth sp = globals[mid];
712*d67b7dadSforsyth if(val < sp->value)
71374a4d8c2SCharles.Forsyth top = mid;
714*d67b7dadSforsyth else if(mid < nglob-1 && val >= globals[mid+1]->value)
71574a4d8c2SCharles.Forsyth bot = mid;
71674a4d8c2SCharles.Forsyth else
71774a4d8c2SCharles.Forsyth return mid;
71874a4d8c2SCharles.Forsyth }
71974a4d8c2SCharles.Forsyth return -1;
72074a4d8c2SCharles.Forsyth }
721*d67b7dadSforsyth
72274a4d8c2SCharles.Forsyth /*
72374a4d8c2SCharles.Forsyth * Find symbol containing val in specified search space
72474a4d8c2SCharles.Forsyth * There is a special case when a value falls beyond the end
72574a4d8c2SCharles.Forsyth * of the text segment; if the search space is CTEXT, that value
72674a4d8c2SCharles.Forsyth * (usually etext) is returned. If the search space is CANY, symbols in the
72774a4d8c2SCharles.Forsyth * data space are searched for a match.
72874a4d8c2SCharles.Forsyth */
72974a4d8c2SCharles.Forsyth int
findsym(uvlong val,int type,Symbol * s)730*d67b7dadSforsyth findsym(uvlong val, int type, Symbol *s)
73174a4d8c2SCharles.Forsyth {
73274a4d8c2SCharles.Forsyth int i;
73374a4d8c2SCharles.Forsyth
73474a4d8c2SCharles.Forsyth if(buildtbls() == 0)
73574a4d8c2SCharles.Forsyth return 0;
73674a4d8c2SCharles.Forsyth
73774a4d8c2SCharles.Forsyth if(type == CTEXT || type == CANY) {
738*d67b7dadSforsyth i = srchtext(val);
73974a4d8c2SCharles.Forsyth if(i >= 0) {
74074a4d8c2SCharles.Forsyth if(type == CTEXT || i != ntxt-1) {
74174a4d8c2SCharles.Forsyth fillsym(txt[i].sym, s);
74274a4d8c2SCharles.Forsyth s->handle = (void *) &txt[i];
743*d67b7dadSforsyth s->index = i;
74474a4d8c2SCharles.Forsyth return 1;
74574a4d8c2SCharles.Forsyth }
74674a4d8c2SCharles.Forsyth }
74774a4d8c2SCharles.Forsyth }
74874a4d8c2SCharles.Forsyth if(type == CDATA || type == CANY) {
749*d67b7dadSforsyth i = srchdata(val);
75074a4d8c2SCharles.Forsyth if(i >= 0) {
75174a4d8c2SCharles.Forsyth fillsym(globals[i], s);
752*d67b7dadSforsyth s->index = i;
75374a4d8c2SCharles.Forsyth return 1;
75474a4d8c2SCharles.Forsyth }
75574a4d8c2SCharles.Forsyth }
75674a4d8c2SCharles.Forsyth return 0;
75774a4d8c2SCharles.Forsyth }
75874a4d8c2SCharles.Forsyth
75974a4d8c2SCharles.Forsyth /*
76074a4d8c2SCharles.Forsyth * Find the start and end address of the function containing addr
76174a4d8c2SCharles.Forsyth */
76274a4d8c2SCharles.Forsyth int
fnbound(uvlong addr,uvlong * bounds)763*d67b7dadSforsyth fnbound(uvlong addr, uvlong *bounds)
76474a4d8c2SCharles.Forsyth {
76574a4d8c2SCharles.Forsyth int i;
76674a4d8c2SCharles.Forsyth
76774a4d8c2SCharles.Forsyth if(buildtbls() == 0)
76874a4d8c2SCharles.Forsyth return 0;
76974a4d8c2SCharles.Forsyth
77074a4d8c2SCharles.Forsyth i = srchtext(addr);
77174a4d8c2SCharles.Forsyth if(0 <= i && i < ntxt-1) {
77274a4d8c2SCharles.Forsyth bounds[0] = txt[i].sym->value;
77374a4d8c2SCharles.Forsyth bounds[1] = txt[i+1].sym->value;
77474a4d8c2SCharles.Forsyth return 1;
77574a4d8c2SCharles.Forsyth }
77674a4d8c2SCharles.Forsyth return 0;
77774a4d8c2SCharles.Forsyth }
77874a4d8c2SCharles.Forsyth
77974a4d8c2SCharles.Forsyth /*
78074a4d8c2SCharles.Forsyth * get the ith local symbol for a function
78174a4d8c2SCharles.Forsyth * the input symbol table is reverse ordered, so we reverse
78274a4d8c2SCharles.Forsyth * accesses here to maintain approx. parameter ordering in a stack trace.
78374a4d8c2SCharles.Forsyth */
78474a4d8c2SCharles.Forsyth int
localsym(Symbol * s,int index)78574a4d8c2SCharles.Forsyth localsym(Symbol *s, int index)
78674a4d8c2SCharles.Forsyth {
78774a4d8c2SCharles.Forsyth Txtsym *tp;
78874a4d8c2SCharles.Forsyth
789*d67b7dadSforsyth if(s == 0 || index < 0)
79074a4d8c2SCharles.Forsyth return 0;
79174a4d8c2SCharles.Forsyth if(buildtbls() == 0)
79274a4d8c2SCharles.Forsyth return 0;
79374a4d8c2SCharles.Forsyth
79474a4d8c2SCharles.Forsyth tp = (Txtsym *)s->handle;
79574a4d8c2SCharles.Forsyth if(tp && tp->locals && index < tp->n) {
79674a4d8c2SCharles.Forsyth fillsym(tp->locals[tp->n-index-1], s); /* reverse */
79774a4d8c2SCharles.Forsyth s->handle = (void *)tp;
798*d67b7dadSforsyth s->index = index;
79974a4d8c2SCharles.Forsyth return 1;
80074a4d8c2SCharles.Forsyth }
80174a4d8c2SCharles.Forsyth return 0;
80274a4d8c2SCharles.Forsyth }
803*d67b7dadSforsyth
80474a4d8c2SCharles.Forsyth /*
80574a4d8c2SCharles.Forsyth * get the ith global symbol
80674a4d8c2SCharles.Forsyth */
80774a4d8c2SCharles.Forsyth int
globalsym(Symbol * s,int index)80874a4d8c2SCharles.Forsyth globalsym(Symbol *s, int index)
80974a4d8c2SCharles.Forsyth {
81074a4d8c2SCharles.Forsyth if(s == 0)
81174a4d8c2SCharles.Forsyth return 0;
81274a4d8c2SCharles.Forsyth if(buildtbls() == 0)
81374a4d8c2SCharles.Forsyth return 0;
81474a4d8c2SCharles.Forsyth
815*d67b7dadSforsyth if(index >=0 && index < nglob) {
81674a4d8c2SCharles.Forsyth fillsym(globals[index], s);
817*d67b7dadSforsyth s->index = index;
81874a4d8c2SCharles.Forsyth return 1;
81974a4d8c2SCharles.Forsyth }
82074a4d8c2SCharles.Forsyth return 0;
82174a4d8c2SCharles.Forsyth }
822*d67b7dadSforsyth
82374a4d8c2SCharles.Forsyth /*
82474a4d8c2SCharles.Forsyth * find the pc given a file name and line offset into it.
82574a4d8c2SCharles.Forsyth */
826*d67b7dadSforsyth uvlong
file2pc(char * file,long line)827*d67b7dadSforsyth file2pc(char *file, long line)
82874a4d8c2SCharles.Forsyth {
82974a4d8c2SCharles.Forsyth File *fp;
830*d67b7dadSforsyth long i;
831*d67b7dadSforsyth uvlong pc, start, end;
83274a4d8c2SCharles.Forsyth short *name;
83374a4d8c2SCharles.Forsyth
83474a4d8c2SCharles.Forsyth if(buildtbls() == 0 || files == 0)
835*d67b7dadSforsyth return ~0;
83674a4d8c2SCharles.Forsyth name = encfname(file);
83774a4d8c2SCharles.Forsyth if(name == 0) { /* encode the file name */
83874a4d8c2SCharles.Forsyth werrstr("file %s not found", file);
839*d67b7dadSforsyth return ~0;
84074a4d8c2SCharles.Forsyth }
84174a4d8c2SCharles.Forsyth /* find this history stack */
84274a4d8c2SCharles.Forsyth for(i = 0, fp = files; i < nfiles; i++, fp++)
84374a4d8c2SCharles.Forsyth if (hline(fp, name, &line))
84474a4d8c2SCharles.Forsyth break;
84574a4d8c2SCharles.Forsyth free(name);
84674a4d8c2SCharles.Forsyth if(i >= nfiles) {
84774a4d8c2SCharles.Forsyth werrstr("line %ld in file %s not found", line, file);
848*d67b7dadSforsyth return ~0;
84974a4d8c2SCharles.Forsyth }
85074a4d8c2SCharles.Forsyth start = fp->addr; /* first text addr this file */
85174a4d8c2SCharles.Forsyth if(i < nfiles-1)
85274a4d8c2SCharles.Forsyth end = (fp+1)->addr; /* first text addr next file */
85374a4d8c2SCharles.Forsyth else
85474a4d8c2SCharles.Forsyth end = 0; /* last file in load module */
85574a4d8c2SCharles.Forsyth /*
85674a4d8c2SCharles.Forsyth * At this point, line contains the offset into the file.
85774a4d8c2SCharles.Forsyth * run the state machine to locate the pc closest to that value.
85874a4d8c2SCharles.Forsyth */
85974a4d8c2SCharles.Forsyth if(debug)
860*d67b7dadSforsyth print("find pc for %ld - between: %llux and %llux\n", line, start, end);
86174a4d8c2SCharles.Forsyth pc = line2addr(line, start, end);
862*d67b7dadSforsyth if(pc == ~0) {
86374a4d8c2SCharles.Forsyth werrstr("line %ld not in file %s", line, file);
864*d67b7dadSforsyth return ~0;
86574a4d8c2SCharles.Forsyth }
86674a4d8c2SCharles.Forsyth return pc;
86774a4d8c2SCharles.Forsyth }
868*d67b7dadSforsyth
86974a4d8c2SCharles.Forsyth /*
87074a4d8c2SCharles.Forsyth * search for a path component index
87174a4d8c2SCharles.Forsyth */
87274a4d8c2SCharles.Forsyth static int
pathcomp(char * s,int n)87374a4d8c2SCharles.Forsyth pathcomp(char *s, int n)
87474a4d8c2SCharles.Forsyth {
87574a4d8c2SCharles.Forsyth int i;
87674a4d8c2SCharles.Forsyth
877fb67f84dSCharles.Forsyth for(i = 0; i <= fpmax; i++)
878*d67b7dadSforsyth if(fnames[i] && strncmp(s, fnames[i]->name, n) == 0)
87974a4d8c2SCharles.Forsyth return i;
88074a4d8c2SCharles.Forsyth return -1;
88174a4d8c2SCharles.Forsyth }
882*d67b7dadSforsyth
88374a4d8c2SCharles.Forsyth /*
88474a4d8c2SCharles.Forsyth * Encode a char file name as a sequence of short indices
88574a4d8c2SCharles.Forsyth * into the file name dictionary.
88674a4d8c2SCharles.Forsyth */
88774a4d8c2SCharles.Forsyth static short*
encfname(char * file)88874a4d8c2SCharles.Forsyth encfname(char *file)
88974a4d8c2SCharles.Forsyth {
89074a4d8c2SCharles.Forsyth int i, j;
89174a4d8c2SCharles.Forsyth char *cp, *cp2;
89274a4d8c2SCharles.Forsyth short *dest;
89374a4d8c2SCharles.Forsyth
89474a4d8c2SCharles.Forsyth if(*file == '/') /* always check first '/' */
89574a4d8c2SCharles.Forsyth cp2 = file+1;
89674a4d8c2SCharles.Forsyth else {
89774a4d8c2SCharles.Forsyth cp2 = strchr(file, '/');
89874a4d8c2SCharles.Forsyth if(!cp2)
89974a4d8c2SCharles.Forsyth cp2 = strchr(file, 0);
90074a4d8c2SCharles.Forsyth }
90174a4d8c2SCharles.Forsyth cp = file;
90274a4d8c2SCharles.Forsyth dest = 0;
90374a4d8c2SCharles.Forsyth for(i = 0; *cp; i++) {
90474a4d8c2SCharles.Forsyth j = pathcomp(cp, cp2-cp);
90574a4d8c2SCharles.Forsyth if(j < 0)
90674a4d8c2SCharles.Forsyth return 0; /* not found */
90774a4d8c2SCharles.Forsyth dest = realloc(dest, (i+1)*sizeof(short));
90874a4d8c2SCharles.Forsyth dest[i] = j;
90974a4d8c2SCharles.Forsyth cp = cp2;
91074a4d8c2SCharles.Forsyth while(*cp == '/') /* skip embedded '/'s */
91174a4d8c2SCharles.Forsyth cp++;
91274a4d8c2SCharles.Forsyth cp2 = strchr(cp, '/');
91374a4d8c2SCharles.Forsyth if(!cp2)
91474a4d8c2SCharles.Forsyth cp2 = strchr(cp, 0);
91574a4d8c2SCharles.Forsyth }
91674a4d8c2SCharles.Forsyth dest = realloc(dest, (i+1)*sizeof(short));
91774a4d8c2SCharles.Forsyth dest[i] = 0;
91874a4d8c2SCharles.Forsyth return dest;
91974a4d8c2SCharles.Forsyth }
920*d67b7dadSforsyth
92174a4d8c2SCharles.Forsyth /*
92274a4d8c2SCharles.Forsyth * Search a history stack for a matching file name accumulating
92374a4d8c2SCharles.Forsyth * the size of intervening files in the stack.
92474a4d8c2SCharles.Forsyth */
92574a4d8c2SCharles.Forsyth static int
hline(File * fp,short * name,long * line)926*d67b7dadSforsyth hline(File *fp, short *name, long *line)
92774a4d8c2SCharles.Forsyth {
92874a4d8c2SCharles.Forsyth Hist *hp;
92974a4d8c2SCharles.Forsyth int offset, depth;
93074a4d8c2SCharles.Forsyth long ln;
93174a4d8c2SCharles.Forsyth
93274a4d8c2SCharles.Forsyth for(hp = fp->hist; hp->name; hp++) /* find name in stack */
93374a4d8c2SCharles.Forsyth if(hp->name[1] || hp->name[2]) {
93474a4d8c2SCharles.Forsyth if(hcomp(hp, name))
93574a4d8c2SCharles.Forsyth break;
93674a4d8c2SCharles.Forsyth }
93774a4d8c2SCharles.Forsyth if(!hp->name) /* match not found */
93874a4d8c2SCharles.Forsyth return 0;
93974a4d8c2SCharles.Forsyth if(debug)
94074a4d8c2SCharles.Forsyth printhist("hline found ... ", hp, 1);
94174a4d8c2SCharles.Forsyth /*
94274a4d8c2SCharles.Forsyth * unwind the stack until empty or we hit an entry beyond our line
94374a4d8c2SCharles.Forsyth */
94474a4d8c2SCharles.Forsyth ln = *line;
94574a4d8c2SCharles.Forsyth offset = hp->line-1;
94674a4d8c2SCharles.Forsyth depth = 1;
94774a4d8c2SCharles.Forsyth for(hp++; depth && hp->name; hp++) {
94874a4d8c2SCharles.Forsyth if(debug)
94974a4d8c2SCharles.Forsyth printhist("hline inspect ... ", hp, 1);
95074a4d8c2SCharles.Forsyth if(hp->name[1] || hp->name[2]) {
95174a4d8c2SCharles.Forsyth if(hp->offset){ /* Z record */
95274a4d8c2SCharles.Forsyth offset = 0;
95374a4d8c2SCharles.Forsyth if(hcomp(hp, name)) {
95474a4d8c2SCharles.Forsyth if(*line <= hp->offset)
95574a4d8c2SCharles.Forsyth break;
95674a4d8c2SCharles.Forsyth ln = *line+hp->line-hp->offset;
95774a4d8c2SCharles.Forsyth depth = 1; /* implicit pop */
95874a4d8c2SCharles.Forsyth } else
95974a4d8c2SCharles.Forsyth depth = 2; /* implicit push */
96074a4d8c2SCharles.Forsyth } else if(depth == 1 && ln < hp->line-offset)
96174a4d8c2SCharles.Forsyth break; /* Beyond our line */
96274a4d8c2SCharles.Forsyth else if(depth++ == 1) /* push */
96374a4d8c2SCharles.Forsyth offset -= hp->line;
96474a4d8c2SCharles.Forsyth } else if(--depth == 1) /* pop */
96574a4d8c2SCharles.Forsyth offset += hp->line;
96674a4d8c2SCharles.Forsyth }
96774a4d8c2SCharles.Forsyth *line = ln+offset;
96874a4d8c2SCharles.Forsyth return 1;
96974a4d8c2SCharles.Forsyth }
970*d67b7dadSforsyth
97174a4d8c2SCharles.Forsyth /*
97274a4d8c2SCharles.Forsyth * compare two encoded file names
97374a4d8c2SCharles.Forsyth */
97474a4d8c2SCharles.Forsyth static int
hcomp(Hist * hp,short * sp)97574a4d8c2SCharles.Forsyth hcomp(Hist *hp, short *sp)
97674a4d8c2SCharles.Forsyth {
97774a4d8c2SCharles.Forsyth uchar *cp;
97874a4d8c2SCharles.Forsyth int i, j;
97974a4d8c2SCharles.Forsyth short *s;
98074a4d8c2SCharles.Forsyth
98174a4d8c2SCharles.Forsyth cp = (uchar *)hp->name;
98274a4d8c2SCharles.Forsyth s = sp;
98374a4d8c2SCharles.Forsyth if (*s == 0)
98474a4d8c2SCharles.Forsyth return 0;
98574a4d8c2SCharles.Forsyth for (i = 1; j = (cp[i]<<8)|cp[i+1]; i += 2) {
98674a4d8c2SCharles.Forsyth if(j == 0)
98774a4d8c2SCharles.Forsyth break;
98874a4d8c2SCharles.Forsyth if(*s == j)
98974a4d8c2SCharles.Forsyth s++;
99074a4d8c2SCharles.Forsyth else
99174a4d8c2SCharles.Forsyth s = sp;
99274a4d8c2SCharles.Forsyth }
99374a4d8c2SCharles.Forsyth return *s == 0;
99474a4d8c2SCharles.Forsyth }
995*d67b7dadSforsyth
99674a4d8c2SCharles.Forsyth /*
99774a4d8c2SCharles.Forsyth * Convert a pc to a "file:line {file:line}" string.
99874a4d8c2SCharles.Forsyth */
999*d67b7dadSforsyth long
fileline(char * str,int n,uvlong dot)1000*d67b7dadSforsyth fileline(char *str, int n, uvlong dot)
100174a4d8c2SCharles.Forsyth {
1002*d67b7dadSforsyth long line, top, bot, mid;
100374a4d8c2SCharles.Forsyth File *f;
100474a4d8c2SCharles.Forsyth
100574a4d8c2SCharles.Forsyth *str = 0;
100674a4d8c2SCharles.Forsyth if(buildtbls() == 0)
100774a4d8c2SCharles.Forsyth return 0;
100874a4d8c2SCharles.Forsyth /* binary search assumes file list is sorted by addr */
100974a4d8c2SCharles.Forsyth bot = 0;
101074a4d8c2SCharles.Forsyth top = nfiles;
101174a4d8c2SCharles.Forsyth for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
101274a4d8c2SCharles.Forsyth f = &files[mid];
101374a4d8c2SCharles.Forsyth if(dot < f->addr)
101474a4d8c2SCharles.Forsyth top = mid;
101574a4d8c2SCharles.Forsyth else if(mid < nfiles-1 && dot >= (f+1)->addr)
101674a4d8c2SCharles.Forsyth bot = mid;
1017*d67b7dadSforsyth else {
1018*d67b7dadSforsyth line = pc2line(dot);
1019*d67b7dadSforsyth if(line > 0 && fline(str, n, line, f->hist, 0) >= 0)
1020*d67b7dadSforsyth return 1;
1021*d67b7dadSforsyth break;
102274a4d8c2SCharles.Forsyth }
1023*d67b7dadSforsyth }
1024*d67b7dadSforsyth return 0;
102574a4d8c2SCharles.Forsyth }
102674a4d8c2SCharles.Forsyth
102774a4d8c2SCharles.Forsyth /*
102874a4d8c2SCharles.Forsyth * Convert a line number within a composite file to relative line
102974a4d8c2SCharles.Forsyth * number in a source file. A composite file is the source
103074a4d8c2SCharles.Forsyth * file with included files inserted in line.
103174a4d8c2SCharles.Forsyth */
103274a4d8c2SCharles.Forsyth static int
fline(char * str,int n,long line,Hist * base,Hist ** ret)103374a4d8c2SCharles.Forsyth fline(char *str, int n, long line, Hist *base, Hist **ret)
103474a4d8c2SCharles.Forsyth {
103574a4d8c2SCharles.Forsyth Hist *start; /* start of current level */
103674a4d8c2SCharles.Forsyth Hist *h; /* current entry */
1037*d67b7dadSforsyth long delta; /* sum of size of files this level */
103874a4d8c2SCharles.Forsyth int k;
103974a4d8c2SCharles.Forsyth
104074a4d8c2SCharles.Forsyth start = base;
104174a4d8c2SCharles.Forsyth h = base;
104274a4d8c2SCharles.Forsyth delta = h->line;
104374a4d8c2SCharles.Forsyth while(h && h->name && line > h->line) {
104474a4d8c2SCharles.Forsyth if(h->name[1] || h->name[2]) {
104574a4d8c2SCharles.Forsyth if(h->offset != 0) { /* #line Directive */
104674a4d8c2SCharles.Forsyth delta = h->line-h->offset+1;
104774a4d8c2SCharles.Forsyth start = h;
104874a4d8c2SCharles.Forsyth base = h++;
104974a4d8c2SCharles.Forsyth } else { /* beginning of File */
105074a4d8c2SCharles.Forsyth if(start == base)
105174a4d8c2SCharles.Forsyth start = h++;
105274a4d8c2SCharles.Forsyth else {
105374a4d8c2SCharles.Forsyth k = fline(str, n, line, start, &h);
105474a4d8c2SCharles.Forsyth if(k <= 0)
105574a4d8c2SCharles.Forsyth return k;
105674a4d8c2SCharles.Forsyth }
105774a4d8c2SCharles.Forsyth }
105874a4d8c2SCharles.Forsyth } else {
1059*d67b7dadSforsyth if(start == base && ret) { /* end of recursion level */
106074a4d8c2SCharles.Forsyth *ret = h;
106174a4d8c2SCharles.Forsyth return 1;
106274a4d8c2SCharles.Forsyth } else { /* end of included file */
106374a4d8c2SCharles.Forsyth delta += h->line-start->line;
106474a4d8c2SCharles.Forsyth h++;
106574a4d8c2SCharles.Forsyth start = base;
106674a4d8c2SCharles.Forsyth }
106774a4d8c2SCharles.Forsyth }
106874a4d8c2SCharles.Forsyth }
106974a4d8c2SCharles.Forsyth if(!h)
107074a4d8c2SCharles.Forsyth return -1;
107174a4d8c2SCharles.Forsyth if(start != base)
107274a4d8c2SCharles.Forsyth line = line-start->line+1;
107374a4d8c2SCharles.Forsyth else
107474a4d8c2SCharles.Forsyth line = line-delta+1;
107574a4d8c2SCharles.Forsyth if(!h->name)
107674a4d8c2SCharles.Forsyth strncpy(str, "<eof>", n);
107774a4d8c2SCharles.Forsyth else {
107874a4d8c2SCharles.Forsyth k = fileelem(fnames, (uchar*)start->name, str, n);
107974a4d8c2SCharles.Forsyth if(k+8 < n)
108074a4d8c2SCharles.Forsyth sprint(str+k, ":%ld", line);
108174a4d8c2SCharles.Forsyth }
108274a4d8c2SCharles.Forsyth /**********Remove comments for complete back-trace of include sequence
108374a4d8c2SCharles.Forsyth * if(start != base) {
108474a4d8c2SCharles.Forsyth * k = strlen(str);
108574a4d8c2SCharles.Forsyth * if(k+2 < n) {
108674a4d8c2SCharles.Forsyth * str[k++] = ' ';
108774a4d8c2SCharles.Forsyth * str[k++] = '{';
108874a4d8c2SCharles.Forsyth * }
108974a4d8c2SCharles.Forsyth * k += fileelem(fnames, (uchar*) base->name, str+k, n-k);
109074a4d8c2SCharles.Forsyth * if(k+10 < n)
109174a4d8c2SCharles.Forsyth * sprint(str+k, ":%ld}", start->line-delta);
109274a4d8c2SCharles.Forsyth * }
109374a4d8c2SCharles.Forsyth ********************/
109474a4d8c2SCharles.Forsyth return 0;
109574a4d8c2SCharles.Forsyth }
1096*d67b7dadSforsyth
109774a4d8c2SCharles.Forsyth /*
109874a4d8c2SCharles.Forsyth * convert an encoded file name to a string.
109974a4d8c2SCharles.Forsyth */
110074a4d8c2SCharles.Forsyth int
fileelem(Sym ** fp,uchar * cp,char * buf,int n)110174a4d8c2SCharles.Forsyth fileelem(Sym **fp, uchar *cp, char *buf, int n)
110274a4d8c2SCharles.Forsyth {
110374a4d8c2SCharles.Forsyth int i, j;
110474a4d8c2SCharles.Forsyth char *c, *bp, *end;
110574a4d8c2SCharles.Forsyth
110674a4d8c2SCharles.Forsyth bp = buf;
110774a4d8c2SCharles.Forsyth end = buf+n-1;
110874a4d8c2SCharles.Forsyth for(i = 1; j = (cp[i]<<8)|cp[i+1]; i+=2){
110974a4d8c2SCharles.Forsyth c = fp[j]->name;
111074a4d8c2SCharles.Forsyth if(bp != buf && bp[-1] != '/' && bp < end)
111174a4d8c2SCharles.Forsyth *bp++ = '/';
111274a4d8c2SCharles.Forsyth while(bp < end && *c)
111374a4d8c2SCharles.Forsyth *bp++ = *c++;
111474a4d8c2SCharles.Forsyth }
111574a4d8c2SCharles.Forsyth *bp = 0;
1116*d67b7dadSforsyth i = bp-buf;
1117*d67b7dadSforsyth if(i > 1) {
1118*d67b7dadSforsyth cleanname(buf);
1119*d67b7dadSforsyth i = strlen(buf);
112074a4d8c2SCharles.Forsyth }
1121*d67b7dadSforsyth return i;
1122*d67b7dadSforsyth }
1123*d67b7dadSforsyth
112474a4d8c2SCharles.Forsyth /*
112574a4d8c2SCharles.Forsyth * compare the values of two symbol table entries.
112674a4d8c2SCharles.Forsyth */
112774a4d8c2SCharles.Forsyth static int
symcomp(void * a,void * b)112874a4d8c2SCharles.Forsyth symcomp(void *a, void *b)
112974a4d8c2SCharles.Forsyth {
1130*d67b7dadSforsyth int i;
1131*d67b7dadSforsyth
1132*d67b7dadSforsyth i = (*(Sym**)a)->value - (*(Sym**)b)->value;
1133*d67b7dadSforsyth if (i)
1134*d67b7dadSforsyth return i;
1135*d67b7dadSforsyth return strcmp((*(Sym**)a)->name, (*(Sym**)b)->name);
113674a4d8c2SCharles.Forsyth }
1137*d67b7dadSforsyth
113874a4d8c2SCharles.Forsyth /*
113974a4d8c2SCharles.Forsyth * compare the values of the symbols referenced by two text table entries
114074a4d8c2SCharles.Forsyth */
114174a4d8c2SCharles.Forsyth static int
txtcomp(void * a,void * b)114274a4d8c2SCharles.Forsyth txtcomp(void *a, void *b)
114374a4d8c2SCharles.Forsyth {
114474a4d8c2SCharles.Forsyth return ((Txtsym*)a)->sym->value - ((Txtsym*)b)->sym->value;
114574a4d8c2SCharles.Forsyth }
1146*d67b7dadSforsyth
114774a4d8c2SCharles.Forsyth /*
114874a4d8c2SCharles.Forsyth * compare the values of the symbols referenced by two file table entries
114974a4d8c2SCharles.Forsyth */
115074a4d8c2SCharles.Forsyth static int
filecomp(void * a,void * b)115174a4d8c2SCharles.Forsyth filecomp(void *a, void *b)
115274a4d8c2SCharles.Forsyth {
115374a4d8c2SCharles.Forsyth return ((File*)a)->addr - ((File*)b)->addr;
115474a4d8c2SCharles.Forsyth }
1155*d67b7dadSforsyth
115674a4d8c2SCharles.Forsyth /*
115774a4d8c2SCharles.Forsyth * fill an interface Symbol structure from a symbol table entry
115874a4d8c2SCharles.Forsyth */
115974a4d8c2SCharles.Forsyth static void
fillsym(Sym * sp,Symbol * s)116074a4d8c2SCharles.Forsyth fillsym(Sym *sp, Symbol *s)
116174a4d8c2SCharles.Forsyth {
116274a4d8c2SCharles.Forsyth s->type = sp->type;
116374a4d8c2SCharles.Forsyth s->value = sp->value;
116474a4d8c2SCharles.Forsyth s->name = sp->name;
1165*d67b7dadSforsyth s->index = 0;
116674a4d8c2SCharles.Forsyth switch(sp->type) {
116774a4d8c2SCharles.Forsyth case 'b':
116874a4d8c2SCharles.Forsyth case 'B':
116974a4d8c2SCharles.Forsyth case 'D':
117074a4d8c2SCharles.Forsyth case 'd':
117174a4d8c2SCharles.Forsyth s->class = CDATA;
117274a4d8c2SCharles.Forsyth break;
117374a4d8c2SCharles.Forsyth case 't':
117474a4d8c2SCharles.Forsyth case 'T':
117574a4d8c2SCharles.Forsyth case 'l':
117674a4d8c2SCharles.Forsyth case 'L':
117774a4d8c2SCharles.Forsyth s->class = CTEXT;
117874a4d8c2SCharles.Forsyth break;
117974a4d8c2SCharles.Forsyth case 'a':
118074a4d8c2SCharles.Forsyth s->class = CAUTO;
118174a4d8c2SCharles.Forsyth break;
118274a4d8c2SCharles.Forsyth case 'p':
118374a4d8c2SCharles.Forsyth s->class = CPARAM;
118474a4d8c2SCharles.Forsyth break;
118574a4d8c2SCharles.Forsyth case 'm':
118674a4d8c2SCharles.Forsyth s->class = CSTAB;
118774a4d8c2SCharles.Forsyth break;
118874a4d8c2SCharles.Forsyth default:
118974a4d8c2SCharles.Forsyth s->class = CNONE;
119074a4d8c2SCharles.Forsyth break;
119174a4d8c2SCharles.Forsyth }
119274a4d8c2SCharles.Forsyth s->handle = 0;
119374a4d8c2SCharles.Forsyth }
1194*d67b7dadSforsyth
119574a4d8c2SCharles.Forsyth /*
119674a4d8c2SCharles.Forsyth * find the stack frame, given the pc
119774a4d8c2SCharles.Forsyth */
1198*d67b7dadSforsyth uvlong
pc2sp(uvlong pc)1199*d67b7dadSforsyth pc2sp(uvlong pc)
120074a4d8c2SCharles.Forsyth {
1201*d67b7dadSforsyth uchar *c, u;
1202*d67b7dadSforsyth uvlong currpc, currsp;
120374a4d8c2SCharles.Forsyth
120474a4d8c2SCharles.Forsyth if(spoff == 0)
1205*d67b7dadSforsyth return ~0;
120674a4d8c2SCharles.Forsyth currsp = 0;
120774a4d8c2SCharles.Forsyth currpc = txtstart - mach->pcquant;
120874a4d8c2SCharles.Forsyth
120974a4d8c2SCharles.Forsyth if(pc<currpc || pc>txtend)
1210*d67b7dadSforsyth return ~0;
121174a4d8c2SCharles.Forsyth for(c = spoff; c < spoffend; c++) {
121274a4d8c2SCharles.Forsyth if (currpc >= pc)
121374a4d8c2SCharles.Forsyth return currsp;
121474a4d8c2SCharles.Forsyth u = *c;
121574a4d8c2SCharles.Forsyth if (u == 0) {
121674a4d8c2SCharles.Forsyth currsp += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4];
121774a4d8c2SCharles.Forsyth c += 4;
121874a4d8c2SCharles.Forsyth }
121974a4d8c2SCharles.Forsyth else if (u < 65)
122074a4d8c2SCharles.Forsyth currsp += 4*u;
122174a4d8c2SCharles.Forsyth else if (u < 129)
122274a4d8c2SCharles.Forsyth currsp -= 4*(u-64);
122374a4d8c2SCharles.Forsyth else
122474a4d8c2SCharles.Forsyth currpc += mach->pcquant*(u-129);
122574a4d8c2SCharles.Forsyth currpc += mach->pcquant;
122674a4d8c2SCharles.Forsyth }
1227*d67b7dadSforsyth return ~0;
122874a4d8c2SCharles.Forsyth }
1229*d67b7dadSforsyth
123074a4d8c2SCharles.Forsyth /*
123174a4d8c2SCharles.Forsyth * find the source file line number for a given value of the pc
123274a4d8c2SCharles.Forsyth */
123374a4d8c2SCharles.Forsyth long
pc2line(uvlong pc)1234*d67b7dadSforsyth pc2line(uvlong pc)
123574a4d8c2SCharles.Forsyth {
1236*d67b7dadSforsyth uchar *c, u;
1237*d67b7dadSforsyth uvlong currpc;
123874a4d8c2SCharles.Forsyth long currline;
123974a4d8c2SCharles.Forsyth
1240*d67b7dadSforsyth if(pcline == 0)
124174a4d8c2SCharles.Forsyth return -1;
1242*d67b7dadSforsyth currline = 0;
1243*d67b7dadSforsyth currpc = txtstart-mach->pcquant;
124474a4d8c2SCharles.Forsyth if(pc<currpc || pc>txtend)
1245*d67b7dadSforsyth return ~0;
1246*d67b7dadSforsyth
1247*d67b7dadSforsyth for(c = pcline; c < pclineend; c++) {
1248*d67b7dadSforsyth if(currpc >= pc)
124974a4d8c2SCharles.Forsyth return currline;
125074a4d8c2SCharles.Forsyth u = *c;
125174a4d8c2SCharles.Forsyth if(u == 0) {
125274a4d8c2SCharles.Forsyth currline += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4];
125374a4d8c2SCharles.Forsyth c += 4;
125474a4d8c2SCharles.Forsyth }
125574a4d8c2SCharles.Forsyth else if(u < 65)
125674a4d8c2SCharles.Forsyth currline += u;
125774a4d8c2SCharles.Forsyth else if(u < 129)
125874a4d8c2SCharles.Forsyth currline -= (u-64);
125974a4d8c2SCharles.Forsyth else
126074a4d8c2SCharles.Forsyth currpc += mach->pcquant*(u-129);
126174a4d8c2SCharles.Forsyth currpc += mach->pcquant;
126274a4d8c2SCharles.Forsyth }
1263*d67b7dadSforsyth return ~0;
126474a4d8c2SCharles.Forsyth }
1265*d67b7dadSforsyth
126674a4d8c2SCharles.Forsyth /*
126774a4d8c2SCharles.Forsyth * find the pc associated with a line number
126874a4d8c2SCharles.Forsyth * basepc and endpc are text addresses bounding the search.
126974a4d8c2SCharles.Forsyth * if endpc == 0, the end of the table is used (i.e., no upper bound).
127074a4d8c2SCharles.Forsyth * usually, basepc and endpc contain the first text address in
127174a4d8c2SCharles.Forsyth * a file and the first text address in the following file, respectively.
127274a4d8c2SCharles.Forsyth */
1273*d67b7dadSforsyth uvlong
line2addr(long line,uvlong basepc,uvlong endpc)1274*d67b7dadSforsyth line2addr(long line, uvlong basepc, uvlong endpc)
127574a4d8c2SCharles.Forsyth {
1276*d67b7dadSforsyth uchar *c, u;
1277*d67b7dadSforsyth uvlong currpc, pc;
127874a4d8c2SCharles.Forsyth long currline;
127974a4d8c2SCharles.Forsyth long delta, d;
1280*d67b7dadSforsyth int found;
128174a4d8c2SCharles.Forsyth
128274a4d8c2SCharles.Forsyth if(pcline == 0 || line == 0)
1283*d67b7dadSforsyth return ~0;
128474a4d8c2SCharles.Forsyth
128574a4d8c2SCharles.Forsyth currline = 0;
128674a4d8c2SCharles.Forsyth currpc = txtstart-mach->pcquant;
1287*d67b7dadSforsyth pc = ~0;
128874a4d8c2SCharles.Forsyth found = 0;
128974a4d8c2SCharles.Forsyth delta = HUGEINT;
129074a4d8c2SCharles.Forsyth
129174a4d8c2SCharles.Forsyth for(c = pcline; c < pclineend; c++) {
129274a4d8c2SCharles.Forsyth if(endpc && currpc >= endpc) /* end of file of interest */
129374a4d8c2SCharles.Forsyth break;
129474a4d8c2SCharles.Forsyth if(currpc >= basepc) { /* proper file */
129574a4d8c2SCharles.Forsyth if(currline >= line) {
129674a4d8c2SCharles.Forsyth d = currline-line;
129774a4d8c2SCharles.Forsyth found = 1;
129874a4d8c2SCharles.Forsyth } else
129974a4d8c2SCharles.Forsyth d = line-currline;
130074a4d8c2SCharles.Forsyth if(d < delta) {
130174a4d8c2SCharles.Forsyth delta = d;
130274a4d8c2SCharles.Forsyth pc = currpc;
130374a4d8c2SCharles.Forsyth }
130474a4d8c2SCharles.Forsyth }
130574a4d8c2SCharles.Forsyth u = *c;
130674a4d8c2SCharles.Forsyth if(u == 0) {
130774a4d8c2SCharles.Forsyth currline += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4];
130874a4d8c2SCharles.Forsyth c += 4;
130974a4d8c2SCharles.Forsyth }
131074a4d8c2SCharles.Forsyth else if(u < 65)
131174a4d8c2SCharles.Forsyth currline += u;
131274a4d8c2SCharles.Forsyth else if(u < 129)
131374a4d8c2SCharles.Forsyth currline -= (u-64);
131474a4d8c2SCharles.Forsyth else
131574a4d8c2SCharles.Forsyth currpc += mach->pcquant*(u-129);
131674a4d8c2SCharles.Forsyth currpc += mach->pcquant;
131774a4d8c2SCharles.Forsyth }
131874a4d8c2SCharles.Forsyth if(found)
131974a4d8c2SCharles.Forsyth return pc;
1320*d67b7dadSforsyth return ~0;
132174a4d8c2SCharles.Forsyth }
1322*d67b7dadSforsyth
132374a4d8c2SCharles.Forsyth /*
132474a4d8c2SCharles.Forsyth * Print a history stack (debug). if count is 0, prints the whole stack
132574a4d8c2SCharles.Forsyth */
132674a4d8c2SCharles.Forsyth static void
printhist(char * msg,Hist * hp,int count)132774a4d8c2SCharles.Forsyth printhist(char *msg, Hist *hp, int count)
132874a4d8c2SCharles.Forsyth {
132974a4d8c2SCharles.Forsyth int i;
133074a4d8c2SCharles.Forsyth uchar *cp;
133174a4d8c2SCharles.Forsyth char buf[128];
133274a4d8c2SCharles.Forsyth
133374a4d8c2SCharles.Forsyth i = 0;
133474a4d8c2SCharles.Forsyth while(hp->name) {
133574a4d8c2SCharles.Forsyth if(count && ++i > count)
133674a4d8c2SCharles.Forsyth break;
1337*d67b7dadSforsyth print("%s Line: %lx (%ld) Offset: %lx (%ld) Name: ", msg,
133874a4d8c2SCharles.Forsyth hp->line, hp->line, hp->offset, hp->offset);
133974a4d8c2SCharles.Forsyth for(cp = (uchar *)hp->name+1; (*cp<<8)|cp[1]; cp += 2) {
134074a4d8c2SCharles.Forsyth if (cp != (uchar *)hp->name+1)
1341*d67b7dadSforsyth print("/");
1342*d67b7dadSforsyth print("%x", (*cp<<8)|cp[1]);
134374a4d8c2SCharles.Forsyth }
134474a4d8c2SCharles.Forsyth fileelem(fnames, (uchar *) hp->name, buf, sizeof(buf));
1345*d67b7dadSforsyth print(" (%s)\n", buf);
134674a4d8c2SCharles.Forsyth hp++;
134774a4d8c2SCharles.Forsyth }
134874a4d8c2SCharles.Forsyth }
134974a4d8c2SCharles.Forsyth
135074a4d8c2SCharles.Forsyth #ifdef DEBUG
135174a4d8c2SCharles.Forsyth /*
135274a4d8c2SCharles.Forsyth * print the history stack for a file. (debug only)
135374a4d8c2SCharles.Forsyth * if (name == 0) => print all history stacks.
135474a4d8c2SCharles.Forsyth */
135574a4d8c2SCharles.Forsyth void
dumphist(char * name)135674a4d8c2SCharles.Forsyth dumphist(char *name)
135774a4d8c2SCharles.Forsyth {
135874a4d8c2SCharles.Forsyth int i;
135974a4d8c2SCharles.Forsyth File *f;
136074a4d8c2SCharles.Forsyth short *fname;
136174a4d8c2SCharles.Forsyth
136274a4d8c2SCharles.Forsyth if(buildtbls() == 0)
136374a4d8c2SCharles.Forsyth return;
136474a4d8c2SCharles.Forsyth if(name)
136574a4d8c2SCharles.Forsyth fname = encfname(name);
136674a4d8c2SCharles.Forsyth for(i = 0, f = files; i < nfiles; i++, f++)
136774a4d8c2SCharles.Forsyth if(fname == 0 || hcomp(f->hist, fname))
136874a4d8c2SCharles.Forsyth printhist("> ", f->hist, f->n);
136974a4d8c2SCharles.Forsyth
137074a4d8c2SCharles.Forsyth if(fname)
137174a4d8c2SCharles.Forsyth free(fname);
137274a4d8c2SCharles.Forsyth }
137374a4d8c2SCharles.Forsyth #endif
1374