13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3bd389b36SDavid du Colombier #include <bio.h> 43e12c5d1SDavid du Colombier #include <mach.h> 53e12c5d1SDavid du Colombier 6bd389b36SDavid du Colombier #define HUGEINT 0x7fffffff 7*219b2ee8SDavid du Colombier #define NNAME 20 /* a relic of the past */ 8bd389b36SDavid du Colombier 9*219b2ee8SDavid du Colombier typedef struct txtsym Txtsym; 10*219b2ee8SDavid du Colombier typedef struct file File; 11*219b2ee8SDavid du Colombier typedef struct hist Hist; 123e12c5d1SDavid du Colombier 13*219b2ee8SDavid du Colombier struct txtsym { /* Text Symbol table */ 14*219b2ee8SDavid du Colombier int n; /* number of local vars */ 15*219b2ee8SDavid du Colombier Sym **locals; /* array of ptrs to autos */ 16*219b2ee8SDavid du Colombier Sym *sym; /* function symbol entry */ 17*219b2ee8SDavid du Colombier }; 18*219b2ee8SDavid du Colombier 19*219b2ee8SDavid du Colombier struct hist { /* Stack of include files & #line directives */ 20*219b2ee8SDavid du Colombier char *name; /* Assumes names Null terminated in file */ 21*219b2ee8SDavid du Colombier long line; /* line # where it was included */ 22*219b2ee8SDavid du Colombier long offset; /* line # of #line directive */ 23*219b2ee8SDavid du Colombier }; 24*219b2ee8SDavid du Colombier 25*219b2ee8SDavid du Colombier struct file { /* Per input file header to history stack */ 26*219b2ee8SDavid du Colombier long addr; /* address of first text sym */ 27*219b2ee8SDavid du Colombier union { 28*219b2ee8SDavid du Colombier Txtsym *txt; /* first text symbol */ 29*219b2ee8SDavid du Colombier Sym *sym; /* only during initilization */ 30*219b2ee8SDavid du Colombier }; 31*219b2ee8SDavid du Colombier int n; /* size of history stack */ 32*219b2ee8SDavid du Colombier Hist *hist; /* history stack */ 33*219b2ee8SDavid du Colombier }; 34*219b2ee8SDavid du Colombier 35*219b2ee8SDavid du Colombier static int debug = 0; 36*219b2ee8SDavid du Colombier 37*219b2ee8SDavid du Colombier static Sym **autos; /* Base of auto variables */ 38*219b2ee8SDavid du Colombier static File *files; /* Base of file arena */ 39*219b2ee8SDavid du Colombier static int fmax; /* largest file path index */ 40*219b2ee8SDavid du Colombier static Sym **fnames; /* file names path component table */ 41*219b2ee8SDavid du Colombier static Sym **globals; /* globals by addr table */ 42*219b2ee8SDavid du Colombier static Hist *hist; /* base of history stack */ 43*219b2ee8SDavid du Colombier static int isbuilt; /* internal table init flag */ 44*219b2ee8SDavid du Colombier static long nauto; /* number of automatics */ 45*219b2ee8SDavid du Colombier static long nfiles; /* number of files */ 46*219b2ee8SDavid du Colombier static long nglob; /* number of globals */ 47*219b2ee8SDavid du Colombier static long nhist; /* number of history stack entries */ 483e12c5d1SDavid du Colombier static long nsym; /* number of symbols */ 49*219b2ee8SDavid du Colombier static int ntxt; /* number of text symbols */ 50*219b2ee8SDavid du Colombier static uchar *pcline; /* start of pc-line state table */ 513e12c5d1SDavid du Colombier static uchar *pclineend; /* end of pc-line table */ 52*219b2ee8SDavid du Colombier static uchar *spoff; /* start of pc-sp state table */ 53*219b2ee8SDavid du Colombier static uchar *spoffend; /* end of pc-sp offset table */ 54*219b2ee8SDavid du Colombier static Sym *symbols; /* symbol table */ 55*219b2ee8SDavid du Colombier static Txtsym *txt; /* Base of text symbol table */ 56*219b2ee8SDavid du Colombier static long txtstart; /* start of text segment */ 573e12c5d1SDavid du Colombier static long txtend; /* end of text segment */ 583e12c5d1SDavid du Colombier 59*219b2ee8SDavid du Colombier static void cleansyms(void); 60*219b2ee8SDavid du Colombier static int decodename(Biobuf*, Sym*); 61*219b2ee8SDavid du Colombier static short *encfname(char *); 62*219b2ee8SDavid du Colombier static Hist *fline(char *, int, long, Hist *); 63*219b2ee8SDavid du Colombier static void fillsym(Sym *, Symbol *); 64*219b2ee8SDavid du Colombier static int findglobal(char *, Symbol *); 65*219b2ee8SDavid du Colombier static int findlocvar(Symbol *, char *, Symbol *); 66*219b2ee8SDavid du Colombier static int findtext(char *, Symbol *); 67*219b2ee8SDavid du Colombier static int hcomp(Hist *, short *); 68*219b2ee8SDavid du Colombier static int hline(File *, short *, ulong *); 69*219b2ee8SDavid du Colombier static void printhist(char *, Hist *, int); 70*219b2ee8SDavid du Colombier static int buildtbls(void); 71*219b2ee8SDavid du Colombier static int symcomp(void *, void *); 72*219b2ee8SDavid du Colombier static int symerrmsg(int, char*); 73*219b2ee8SDavid du Colombier static int txtcomp(void *, void *); 74*219b2ee8SDavid du Colombier static int filecomp(void *, void *); 75*219b2ee8SDavid du Colombier 763e12c5d1SDavid du Colombier /* 773e12c5d1SDavid du Colombier * initialize the symbol tables 783e12c5d1SDavid du Colombier */ 793e12c5d1SDavid du Colombier int 803e12c5d1SDavid du Colombier syminit(int fd, Fhdr *fp) 813e12c5d1SDavid du Colombier { 82*219b2ee8SDavid du Colombier Sym *p; 83*219b2ee8SDavid du Colombier int i, size; 84*219b2ee8SDavid du Colombier Biobuf b; 853e12c5d1SDavid du Colombier 863e12c5d1SDavid du Colombier if(fp->symsz == 0) 873e12c5d1SDavid du Colombier return 0; 88*219b2ee8SDavid du Colombier if(fp->type == FNONE) 89*219b2ee8SDavid du Colombier return 0; 903e12c5d1SDavid du Colombier 91*219b2ee8SDavid du Colombier cleansyms(); 92*219b2ee8SDavid du Colombier textseg(fp->txtaddr, fp); 93*219b2ee8SDavid du Colombier /* minimum symbol record size = 4+1+2 bytes */ 94*219b2ee8SDavid du Colombier symbols = malloc((fp->symsz/(4+1+2)+1)*sizeof(Sym)); 953e12c5d1SDavid du Colombier if(symbols == 0) { 96*219b2ee8SDavid du Colombier werrstr("can't malloc %d bytes", fp->symsz); 973e12c5d1SDavid du Colombier return -1; 983e12c5d1SDavid du Colombier } 99*219b2ee8SDavid du Colombier 100*219b2ee8SDavid du Colombier Binit(&b, fd, OREAD); 101*219b2ee8SDavid du Colombier Bseek(&b, fp->symoff, 0); 102*219b2ee8SDavid du Colombier nsym = 0; 103*219b2ee8SDavid du Colombier size = 0; 104*219b2ee8SDavid du Colombier for(p = symbols; size < fp->symsz; p++, nsym++) { 105*219b2ee8SDavid du Colombier if(Bread(&b, &p->value, sizeof(p->value)) != sizeof(p->value)) 106*219b2ee8SDavid du Colombier return symerrmsg(sizeof(p->value), "symbol"); 107*219b2ee8SDavid du Colombier p->value = beswal(p->value); 108*219b2ee8SDavid du Colombier if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type)) 109*219b2ee8SDavid du Colombier return symerrmsg(sizeof(p->value), "symbol"); 110*219b2ee8SDavid du Colombier 111*219b2ee8SDavid du Colombier i = decodename(&b, p); 112*219b2ee8SDavid du Colombier if(i < 0) 1133e12c5d1SDavid du Colombier return -1; 114*219b2ee8SDavid du Colombier size += i+sizeof(p->value)+sizeof(p->type); 115*219b2ee8SDavid du Colombier 116*219b2ee8SDavid du Colombier /* count global & auto vars, text symbols, and file names */ 117*219b2ee8SDavid du Colombier switch (p->type) { 118*219b2ee8SDavid du Colombier case 'l': 119*219b2ee8SDavid du Colombier case 'L': 120*219b2ee8SDavid du Colombier case 't': 121*219b2ee8SDavid du Colombier case 'T': 122*219b2ee8SDavid du Colombier ntxt++; 123*219b2ee8SDavid du Colombier break; 124*219b2ee8SDavid du Colombier case 'd': 125*219b2ee8SDavid du Colombier case 'D': 126*219b2ee8SDavid du Colombier case 'b': 127*219b2ee8SDavid du Colombier case 'B': 128*219b2ee8SDavid du Colombier nglob++; 129*219b2ee8SDavid du Colombier break; 130*219b2ee8SDavid du Colombier case 'f': 131*219b2ee8SDavid du Colombier if(strcmp(p->name, ".frame") == 0) { 132*219b2ee8SDavid du Colombier p->type = 'm'; 133*219b2ee8SDavid du Colombier nauto++; 1343e12c5d1SDavid du Colombier } 135*219b2ee8SDavid du Colombier else if(p->value > fmax) 136*219b2ee8SDavid du Colombier fmax = p->value; /* highest path index */ 137*219b2ee8SDavid du Colombier break; 138*219b2ee8SDavid du Colombier case 'a': 139*219b2ee8SDavid du Colombier case 'p': 140*219b2ee8SDavid du Colombier case 'm': 141*219b2ee8SDavid du Colombier nauto++; 142*219b2ee8SDavid du Colombier break; 143*219b2ee8SDavid du Colombier case 'z': 144*219b2ee8SDavid du Colombier if(p->value == 1) { /* one extra per file */ 145*219b2ee8SDavid du Colombier nhist++; 146*219b2ee8SDavid du Colombier nfiles++; 1473e12c5d1SDavid du Colombier } 148*219b2ee8SDavid du Colombier nhist++; 149*219b2ee8SDavid du Colombier break; 150*219b2ee8SDavid du Colombier default: 151*219b2ee8SDavid du Colombier break; 152*219b2ee8SDavid du Colombier } 153*219b2ee8SDavid du Colombier } 154*219b2ee8SDavid du Colombier if (debug) 155*219b2ee8SDavid du Colombier print("NG: %d NT: %d NF: %d\n", nglob, ntxt, fmax); 1563e12c5d1SDavid du Colombier if (fp->sppcsz) { /* pc-sp offset table */ 1573e12c5d1SDavid du Colombier spoff = (uchar *)malloc(fp->sppcsz); 1583e12c5d1SDavid du Colombier if(spoff == 0) { 159*219b2ee8SDavid du Colombier werrstr("can't malloc %d bytes", fp->sppcsz); 1603e12c5d1SDavid du Colombier return -1; 1613e12c5d1SDavid du Colombier } 162*219b2ee8SDavid du Colombier Bseek(&b, fp->sppcoff, 0); 163*219b2ee8SDavid du Colombier i = Bread(&b, spoff, fp->sppcsz); 1643e12c5d1SDavid du Colombier if(i != fp->sppcsz){ 1653e12c5d1SDavid du Colombier spoff = 0; 166*219b2ee8SDavid du Colombier return symerrmsg(fp->sppcsz, "sp-pc"); 1673e12c5d1SDavid du Colombier } 1683e12c5d1SDavid du Colombier spoffend = spoff+fp->sppcsz; 1693e12c5d1SDavid du Colombier } 1703e12c5d1SDavid du Colombier if (fp->lnpcsz) { /* pc-line number table */ 1713e12c5d1SDavid du Colombier pcline = (uchar *)malloc(fp->lnpcsz); 1723e12c5d1SDavid du Colombier if(pcline == 0) { 173*219b2ee8SDavid du Colombier werrstr("can't malloc %d bytes", fp->lnpcsz); 1743e12c5d1SDavid du Colombier return -1; 1753e12c5d1SDavid du Colombier } 176*219b2ee8SDavid du Colombier Bseek(&b, fp->lnpcoff, 0); 177*219b2ee8SDavid du Colombier i = Bread(&b, pcline, fp->lnpcsz); 1783e12c5d1SDavid du Colombier if(i != fp->lnpcsz){ 1793e12c5d1SDavid du Colombier pcline = 0; 180*219b2ee8SDavid du Colombier return symerrmsg(fp->lnpcsz, "pc-line"); 1813e12c5d1SDavid du Colombier } 1823e12c5d1SDavid du Colombier pclineend = pcline+fp->lnpcsz; 1833e12c5d1SDavid du Colombier } 1843e12c5d1SDavid du Colombier return nsym; 1853e12c5d1SDavid du Colombier } 186*219b2ee8SDavid du Colombier 187*219b2ee8SDavid du Colombier static int 188*219b2ee8SDavid du Colombier symerrmsg(int n, char *table) 189*219b2ee8SDavid du Colombier { 190*219b2ee8SDavid du Colombier werrstr("can't read %d bytes of %s table", n, table); 191*219b2ee8SDavid du Colombier return -1; 192*219b2ee8SDavid du Colombier } 193*219b2ee8SDavid du Colombier 194*219b2ee8SDavid du Colombier static int 195*219b2ee8SDavid du Colombier decodename(Biobuf *bp, Sym *p) 196*219b2ee8SDavid du Colombier { 197*219b2ee8SDavid du Colombier char *cp; 198*219b2ee8SDavid du Colombier int c1, c2; 199*219b2ee8SDavid du Colombier int n; 200*219b2ee8SDavid du Colombier 201*219b2ee8SDavid du Colombier if((p->type & 0x80) == 0) { /* old-style, fixed length names */ 202*219b2ee8SDavid du Colombier p->name = malloc(NNAME); 203*219b2ee8SDavid du Colombier if(p->name == 0) { 204*219b2ee8SDavid du Colombier werrstr("can't malloc %d bytes", NNAME); 205*219b2ee8SDavid du Colombier return -1; 206*219b2ee8SDavid du Colombier } 207*219b2ee8SDavid du Colombier if(Bread(bp, p->name, NNAME) != NNAME) 208*219b2ee8SDavid du Colombier return symerrmsg(NNAME, "symbol"); 209*219b2ee8SDavid du Colombier Bseek(bp, 3, 1); 210*219b2ee8SDavid du Colombier return NNAME+3; 211*219b2ee8SDavid du Colombier } 212*219b2ee8SDavid du Colombier 213*219b2ee8SDavid du Colombier p->type &= ~0x80; 214*219b2ee8SDavid du Colombier if(p->type == 'z' || p->type == 'Z') { 215*219b2ee8SDavid du Colombier n = Bseek(bp, 0, 1); 216*219b2ee8SDavid du Colombier if(Bgetc(bp) < 0) { 217*219b2ee8SDavid du Colombier werrstr("can't read symbol name"); 218*219b2ee8SDavid du Colombier return -1; 219*219b2ee8SDavid du Colombier } 220*219b2ee8SDavid du Colombier for(;;) { 221*219b2ee8SDavid du Colombier c1 = Bgetc(bp); 222*219b2ee8SDavid du Colombier c2 = Bgetc(bp); 223*219b2ee8SDavid du Colombier if(c1 < 0 || c2 < 0) { 224*219b2ee8SDavid du Colombier werrstr("can't read symbol name"); 225*219b2ee8SDavid du Colombier return -1; 226*219b2ee8SDavid du Colombier } 227*219b2ee8SDavid du Colombier if(c1 == 0 && c2 == 0) 228*219b2ee8SDavid du Colombier break; 229*219b2ee8SDavid du Colombier } 230*219b2ee8SDavid du Colombier n = Bseek(bp, 0, 1)-n; 231*219b2ee8SDavid du Colombier p->name = malloc(n); 232*219b2ee8SDavid du Colombier if(p->name == 0) { 233*219b2ee8SDavid du Colombier werrstr("can't malloc %d bytes", n); 234*219b2ee8SDavid du Colombier return -1; 235*219b2ee8SDavid du Colombier } 236*219b2ee8SDavid du Colombier Bseek(bp, -n, 1); 237*219b2ee8SDavid du Colombier if(Bread(bp, p->name, n) != n) { 238*219b2ee8SDavid du Colombier werrstr("can't read %d bytes of symbol name", n); 239*219b2ee8SDavid du Colombier return -1; 240*219b2ee8SDavid du Colombier } 241*219b2ee8SDavid du Colombier } else { 242*219b2ee8SDavid du Colombier cp = Brdline(bp, '\0'); 243*219b2ee8SDavid du Colombier if(cp == 0) { 244*219b2ee8SDavid du Colombier werrstr("can't read symbol name"); 245*219b2ee8SDavid du Colombier return -1; 246*219b2ee8SDavid du Colombier } 247*219b2ee8SDavid du Colombier n = Blinelen(bp); 248*219b2ee8SDavid du Colombier p->name = malloc(n); 249*219b2ee8SDavid du Colombier if(p->name == 0) { 250*219b2ee8SDavid du Colombier werrstr("can't malloc %d bytes", n); 251*219b2ee8SDavid du Colombier return -1; 252*219b2ee8SDavid du Colombier } 253*219b2ee8SDavid du Colombier strcpy(p->name, cp); 254*219b2ee8SDavid du Colombier } 255*219b2ee8SDavid du Colombier return n; 256*219b2ee8SDavid du Colombier } 257*219b2ee8SDavid du Colombier /* 258*219b2ee8SDavid du Colombier * free any previously loaded symbol tables 259*219b2ee8SDavid du Colombier */ 260*219b2ee8SDavid du Colombier static void 261*219b2ee8SDavid du Colombier cleansyms(void) 262*219b2ee8SDavid du Colombier { 263*219b2ee8SDavid du Colombier if(globals) 264*219b2ee8SDavid du Colombier free(globals); 265*219b2ee8SDavid du Colombier globals = 0; 266*219b2ee8SDavid du Colombier nglob = 0; 267*219b2ee8SDavid du Colombier if(txt) 268*219b2ee8SDavid du Colombier free(txt); 269*219b2ee8SDavid du Colombier txt = 0; 270*219b2ee8SDavid du Colombier ntxt = 0; 271*219b2ee8SDavid du Colombier if(fnames) 272*219b2ee8SDavid du Colombier free(fnames); 273*219b2ee8SDavid du Colombier fnames = 0; 274*219b2ee8SDavid du Colombier fmax = 0; 275*219b2ee8SDavid du Colombier 276*219b2ee8SDavid du Colombier if(files) 277*219b2ee8SDavid du Colombier free(files); 278*219b2ee8SDavid du Colombier files = 0; 279*219b2ee8SDavid du Colombier nfiles = 0; 280*219b2ee8SDavid du Colombier if(hist) 281*219b2ee8SDavid du Colombier free(hist); 282*219b2ee8SDavid du Colombier hist = 0; 283*219b2ee8SDavid du Colombier nhist = 0; 284*219b2ee8SDavid du Colombier if(autos) 285*219b2ee8SDavid du Colombier free(autos); 286*219b2ee8SDavid du Colombier autos = 0; 287*219b2ee8SDavid du Colombier nauto = 0; 288*219b2ee8SDavid du Colombier isbuilt = 0; 289*219b2ee8SDavid du Colombier if(symbols) 290*219b2ee8SDavid du Colombier free(symbols); 291*219b2ee8SDavid du Colombier symbols = 0; 292*219b2ee8SDavid du Colombier nsym = 0; 293*219b2ee8SDavid du Colombier if(spoff) 294*219b2ee8SDavid du Colombier free(spoff); 295*219b2ee8SDavid du Colombier spoff = 0; 296*219b2ee8SDavid du Colombier if(pcline) 297*219b2ee8SDavid du Colombier free(pcline); 298*219b2ee8SDavid du Colombier pcline = 0; 299*219b2ee8SDavid du Colombier } 300*219b2ee8SDavid du Colombier /* 301*219b2ee8SDavid du Colombier * delimit the text segment 302*219b2ee8SDavid du Colombier */ 303*219b2ee8SDavid du Colombier void 304*219b2ee8SDavid du Colombier textseg(ulong base, Fhdr *fp) 305*219b2ee8SDavid du Colombier { 306*219b2ee8SDavid du Colombier txtstart = base; 307*219b2ee8SDavid du Colombier txtend = base+fp->txtsz; 308*219b2ee8SDavid du Colombier } 3093e12c5d1SDavid du Colombier /* 3103e12c5d1SDavid du Colombier * symbase: return base and size of raw symbol table 3113e12c5d1SDavid du Colombier * (special hack for high access rate operations) 3123e12c5d1SDavid du Colombier */ 3133e12c5d1SDavid du Colombier Sym * 3143e12c5d1SDavid du Colombier symbase(long *n) 3153e12c5d1SDavid du Colombier { 3163e12c5d1SDavid du Colombier *n = nsym; 3173e12c5d1SDavid du Colombier return symbols; 3183e12c5d1SDavid du Colombier } 3193e12c5d1SDavid du Colombier /* 3203e12c5d1SDavid du Colombier * Get the ith symbol table entry 3213e12c5d1SDavid du Colombier */ 3223e12c5d1SDavid du Colombier Sym * 3233e12c5d1SDavid du Colombier getsym(int index) 3243e12c5d1SDavid du Colombier { 3253e12c5d1SDavid du Colombier if(index < nsym) 3263e12c5d1SDavid du Colombier return &symbols[index]; 3273e12c5d1SDavid du Colombier return 0; 3283e12c5d1SDavid du Colombier } 329*219b2ee8SDavid du Colombier 330*219b2ee8SDavid du Colombier /* 331*219b2ee8SDavid du Colombier * initialize internal symbol tables 332*219b2ee8SDavid du Colombier */ 333*219b2ee8SDavid du Colombier static int 334*219b2ee8SDavid du Colombier buildtbls(void) 335*219b2ee8SDavid du Colombier { 336*219b2ee8SDavid du Colombier int i, j, nh, ng, nt; 337*219b2ee8SDavid du Colombier File *f; 338*219b2ee8SDavid du Colombier Txtsym *tp; 339*219b2ee8SDavid du Colombier Hist *hp; 340*219b2ee8SDavid du Colombier Sym *p, **ap; 341*219b2ee8SDavid du Colombier 342*219b2ee8SDavid du Colombier if(isbuilt) 343*219b2ee8SDavid du Colombier return 1; 344*219b2ee8SDavid du Colombier isbuilt = 1; 345*219b2ee8SDavid du Colombier /* allocate the tables */ 346*219b2ee8SDavid du Colombier if(nglob) { 347*219b2ee8SDavid du Colombier globals = malloc(nglob*sizeof(*globals)); 348*219b2ee8SDavid du Colombier if(!globals) { 349*219b2ee8SDavid du Colombier werrstr("can't malloc global symbol table"); 350*219b2ee8SDavid du Colombier return 0; 351*219b2ee8SDavid du Colombier } 352*219b2ee8SDavid du Colombier } 353*219b2ee8SDavid du Colombier if(ntxt) { 354*219b2ee8SDavid du Colombier txt = malloc(ntxt*sizeof(*txt)); 355*219b2ee8SDavid du Colombier if (!txt) { 356*219b2ee8SDavid du Colombier werrstr("can't malloc text symbol table"); 357*219b2ee8SDavid du Colombier return 0; 358*219b2ee8SDavid du Colombier } 359*219b2ee8SDavid du Colombier } 360*219b2ee8SDavid du Colombier fmax++; 361*219b2ee8SDavid du Colombier fnames = malloc(fmax*sizeof(*fnames)); 362*219b2ee8SDavid du Colombier if (!fnames) { 363*219b2ee8SDavid du Colombier werrstr("can't malloc file name table"); 364*219b2ee8SDavid du Colombier return 0; 365*219b2ee8SDavid du Colombier } 366*219b2ee8SDavid du Colombier memset(fnames, 0, fmax*sizeof(*fnames)); 367*219b2ee8SDavid du Colombier files = malloc(nfiles*sizeof(*files)); 368*219b2ee8SDavid du Colombier if(!files) { 369*219b2ee8SDavid du Colombier werrstr("can't malloc file table"); 370*219b2ee8SDavid du Colombier return 0; 371*219b2ee8SDavid du Colombier } 372*219b2ee8SDavid du Colombier hist = malloc(nhist*sizeof(Hist)); 373*219b2ee8SDavid du Colombier if(hist == 0) { 374*219b2ee8SDavid du Colombier werrstr("can't malloc history stack"); 375*219b2ee8SDavid du Colombier return 0; 376*219b2ee8SDavid du Colombier } 377*219b2ee8SDavid du Colombier autos = malloc(nauto*sizeof(Sym*)); 378*219b2ee8SDavid du Colombier if(autos == 0) { 379*219b2ee8SDavid du Colombier werrstr("can't malloc auto symbol table"); 380*219b2ee8SDavid du Colombier return 0; 381*219b2ee8SDavid du Colombier } 382*219b2ee8SDavid du Colombier /* load the tables */ 383*219b2ee8SDavid du Colombier ng = nt = nh = 0; 384*219b2ee8SDavid du Colombier f = 0; 385*219b2ee8SDavid du Colombier tp = 0; 386*219b2ee8SDavid du Colombier i = nsym; 387*219b2ee8SDavid du Colombier hp = hist; 388*219b2ee8SDavid du Colombier ap = autos; 389*219b2ee8SDavid du Colombier for(p = symbols; i-- > 0; p++) { 390*219b2ee8SDavid du Colombier switch(p->type) { 391*219b2ee8SDavid du Colombier case 'D': 392*219b2ee8SDavid du Colombier case 'd': 393*219b2ee8SDavid du Colombier case 'B': 394*219b2ee8SDavid du Colombier case 'b': 395*219b2ee8SDavid du Colombier if(debug) 396*219b2ee8SDavid du Colombier print("Global: %s %lux\n", p->name, p->value); 397*219b2ee8SDavid du Colombier globals[ng++] = p; 398*219b2ee8SDavid du Colombier break; 399*219b2ee8SDavid du Colombier case 'z': 400*219b2ee8SDavid du Colombier if(p->value == 1) { /* New file */ 401*219b2ee8SDavid du Colombier if(f) { 402*219b2ee8SDavid du Colombier f->n = nh; 403*219b2ee8SDavid du Colombier f->hist[nh].name = 0; /* one extra */ 404*219b2ee8SDavid du Colombier hp += nh+1; 405*219b2ee8SDavid du Colombier f++; 406*219b2ee8SDavid du Colombier } 407*219b2ee8SDavid du Colombier else f = files; 408*219b2ee8SDavid du Colombier f->hist = hp; 409*219b2ee8SDavid du Colombier f->sym = 0; 410*219b2ee8SDavid du Colombier f->addr = 0; 411*219b2ee8SDavid du Colombier nh = 0; 412*219b2ee8SDavid du Colombier } 413*219b2ee8SDavid du Colombier /* alloc one slot extra as terminator */ 414*219b2ee8SDavid du Colombier f->hist[nh].name = p->name; 415*219b2ee8SDavid du Colombier f->hist[nh].line = p->value; 416*219b2ee8SDavid du Colombier f->hist[nh].offset = 0; 417*219b2ee8SDavid du Colombier if(debug) 418*219b2ee8SDavid du Colombier printhist("-> ", &f->hist[nh], 1); 419*219b2ee8SDavid du Colombier nh++; 420*219b2ee8SDavid du Colombier break; 421*219b2ee8SDavid du Colombier case 'Z': 422*219b2ee8SDavid du Colombier if(f && nh > 0) 423*219b2ee8SDavid du Colombier f->hist[nh-1].offset = p->value; 424*219b2ee8SDavid du Colombier break; 425*219b2ee8SDavid du Colombier case 'T': 426*219b2ee8SDavid du Colombier case 't': /* Text: terminate history if first in file */ 427*219b2ee8SDavid du Colombier case 'L': 428*219b2ee8SDavid du Colombier case 'l': 429*219b2ee8SDavid du Colombier tp = &txt[nt++]; 430*219b2ee8SDavid du Colombier tp->n = 0; 431*219b2ee8SDavid du Colombier tp->sym = p; 432*219b2ee8SDavid du Colombier tp->locals = ap; 433*219b2ee8SDavid du Colombier if(debug) 434*219b2ee8SDavid du Colombier print("TEXT: %s at %lux\n", p->name, p->value); 435*219b2ee8SDavid du Colombier if(f && !f->sym) { /* first */ 436*219b2ee8SDavid du Colombier f->sym = p; 437*219b2ee8SDavid du Colombier f->addr = p->value; 438*219b2ee8SDavid du Colombier } 439*219b2ee8SDavid du Colombier break; 440*219b2ee8SDavid du Colombier case 'a': 441*219b2ee8SDavid du Colombier case 'p': 442*219b2ee8SDavid du Colombier case 'm': /* Local Vars */ 443*219b2ee8SDavid du Colombier if(!tp) 444*219b2ee8SDavid du Colombier print("Warning: Free floating local var"); 445*219b2ee8SDavid du Colombier else { 446*219b2ee8SDavid du Colombier if(debug) 447*219b2ee8SDavid du Colombier print("Local: %s %lux\n", p->name, p->value); 448*219b2ee8SDavid du Colombier tp->locals[tp->n] = p; 449*219b2ee8SDavid du Colombier tp->n++; 450*219b2ee8SDavid du Colombier ap++; 451*219b2ee8SDavid du Colombier } 452*219b2ee8SDavid du Colombier break; 453*219b2ee8SDavid du Colombier case 'f': /* File names */ 454*219b2ee8SDavid du Colombier if(debug) 455*219b2ee8SDavid du Colombier print("Fname: %s\n", p->name); 456*219b2ee8SDavid du Colombier fnames[p->value] = p; 457*219b2ee8SDavid du Colombier break; 458*219b2ee8SDavid du Colombier default: 459*219b2ee8SDavid du Colombier break; 460*219b2ee8SDavid du Colombier } 461*219b2ee8SDavid du Colombier } 462*219b2ee8SDavid du Colombier /* sort global and text tables into ascending address order */ 463*219b2ee8SDavid du Colombier qsort(globals, nglob, sizeof(Sym*), symcomp); 464*219b2ee8SDavid du Colombier qsort(txt, ntxt, sizeof(Txtsym), txtcomp); 465*219b2ee8SDavid du Colombier qsort(files, nfiles, sizeof(File), filecomp); 466*219b2ee8SDavid du Colombier tp = txt; 467*219b2ee8SDavid du Colombier for(i = 0, f = files; i < nfiles; i++, f++) { 468*219b2ee8SDavid du Colombier for(j = 0; j < ntxt; j++) { 469*219b2ee8SDavid du Colombier if(f->sym == tp->sym) { 470*219b2ee8SDavid du Colombier if(debug) { 471*219b2ee8SDavid du Colombier print("LINK: %s to", f->sym->name); 472*219b2ee8SDavid du Colombier printhist("... ", f->hist, 1); 473*219b2ee8SDavid du Colombier } 474*219b2ee8SDavid du Colombier f->txt = tp++; 475*219b2ee8SDavid du Colombier break; 476*219b2ee8SDavid du Colombier } 477*219b2ee8SDavid du Colombier if(++tp >= txt+ntxt) /* wrap around */ 478*219b2ee8SDavid du Colombier tp = txt; 479*219b2ee8SDavid du Colombier } 480*219b2ee8SDavid du Colombier } 481*219b2ee8SDavid du Colombier return 1; 482*219b2ee8SDavid du Colombier } 483*219b2ee8SDavid du Colombier 484*219b2ee8SDavid du Colombier /* 485*219b2ee8SDavid du Colombier * find symbol function.var by name. 486*219b2ee8SDavid du Colombier * fn != 0 && var != 0 => look for fn in text, var in data 487*219b2ee8SDavid du Colombier * fn != 0 && var == 0 => look for fn in text 488*219b2ee8SDavid du Colombier * fn == 0 && var != 0 => look for var first in text then in data space. 489*219b2ee8SDavid du Colombier */ 490*219b2ee8SDavid du Colombier int 491*219b2ee8SDavid du Colombier lookup(char *fn, char *var, Symbol *s) 492*219b2ee8SDavid du Colombier { 493*219b2ee8SDavid du Colombier int found; 494*219b2ee8SDavid du Colombier 495*219b2ee8SDavid du Colombier if(buildtbls() == 0) 496*219b2ee8SDavid du Colombier return 0; 497*219b2ee8SDavid du Colombier if(fn) { 498*219b2ee8SDavid du Colombier found = findtext(fn, s); 499*219b2ee8SDavid du Colombier if(var == 0) /* case 2: fn not in text */ 500*219b2ee8SDavid du Colombier return found; 501*219b2ee8SDavid du Colombier else if(!found) /* case 1: fn not found */ 502*219b2ee8SDavid du Colombier return 0; 503*219b2ee8SDavid du Colombier } else if(var) { 504*219b2ee8SDavid du Colombier found = findtext(var, s); 505*219b2ee8SDavid du Colombier if(found) 506*219b2ee8SDavid du Colombier return 1; /* case 3: var found in text */ 507*219b2ee8SDavid du Colombier } else return 0; /* case 4: fn & var == zero */ 508*219b2ee8SDavid du Colombier 509*219b2ee8SDavid du Colombier if(found) 510*219b2ee8SDavid du Colombier return findlocal(s, var, s); /* case 1: fn found */ 511*219b2ee8SDavid du Colombier return findglobal(var, s); /* case 3: var not found */ 512*219b2ee8SDavid du Colombier 513*219b2ee8SDavid du Colombier } 514*219b2ee8SDavid du Colombier /* 515*219b2ee8SDavid du Colombier * find a function by name 516*219b2ee8SDavid du Colombier */ 517*219b2ee8SDavid du Colombier static int 518*219b2ee8SDavid du Colombier findtext(char *name, Symbol *s) 519*219b2ee8SDavid du Colombier { 520*219b2ee8SDavid du Colombier int i; 521*219b2ee8SDavid du Colombier 522*219b2ee8SDavid du Colombier for(i = 0; i < ntxt; i++) { 523*219b2ee8SDavid du Colombier if(strcmp(txt[i].sym->name, name) == 0) { 524*219b2ee8SDavid du Colombier fillsym(txt[i].sym, s); 525*219b2ee8SDavid du Colombier s->handle = (void *) &txt[i]; 526*219b2ee8SDavid du Colombier return 1; 527*219b2ee8SDavid du Colombier } 528*219b2ee8SDavid du Colombier } 529*219b2ee8SDavid du Colombier return 0; 530*219b2ee8SDavid du Colombier } 531*219b2ee8SDavid du Colombier /* 532*219b2ee8SDavid du Colombier * find global variable by name 533*219b2ee8SDavid du Colombier */ 534*219b2ee8SDavid du Colombier static int 535*219b2ee8SDavid du Colombier findglobal(char *name, Symbol *s) 536*219b2ee8SDavid du Colombier { 537*219b2ee8SDavid du Colombier int i; 538*219b2ee8SDavid du Colombier 539*219b2ee8SDavid du Colombier for(i = 0; i < nglob; i++) { 540*219b2ee8SDavid du Colombier if(strcmp(globals[i]->name, name) == 0) { 541*219b2ee8SDavid du Colombier fillsym(globals[i], s); 542*219b2ee8SDavid du Colombier return 1; 543*219b2ee8SDavid du Colombier } 544*219b2ee8SDavid du Colombier } 545*219b2ee8SDavid du Colombier return 0; 546*219b2ee8SDavid du Colombier } 547*219b2ee8SDavid du Colombier /* 548*219b2ee8SDavid du Colombier * find the local variable by name within a given function 549*219b2ee8SDavid du Colombier */ 550*219b2ee8SDavid du Colombier int 551*219b2ee8SDavid du Colombier findlocal(Symbol *s1, char *name, Symbol *s2) 552*219b2ee8SDavid du Colombier { 553*219b2ee8SDavid du Colombier if(s1 == 0) 554*219b2ee8SDavid du Colombier return 0; 555*219b2ee8SDavid du Colombier if(buildtbls() == 0) 556*219b2ee8SDavid du Colombier return 0; 557*219b2ee8SDavid du Colombier return findlocvar(s1, name, s2); 558*219b2ee8SDavid du Colombier } 559*219b2ee8SDavid du Colombier /* 560*219b2ee8SDavid du Colombier * find the local variable by name within a given function 561*219b2ee8SDavid du Colombier * (internal function - does no parameter validation) 562*219b2ee8SDavid du Colombier */ 563*219b2ee8SDavid du Colombier static int 564*219b2ee8SDavid du Colombier findlocvar(Symbol *s1, char *name, Symbol *s2) 565*219b2ee8SDavid du Colombier { 566*219b2ee8SDavid du Colombier Txtsym *tp; 567*219b2ee8SDavid du Colombier int i; 568*219b2ee8SDavid du Colombier 569*219b2ee8SDavid du Colombier tp = (Txtsym *)s1->handle; 570*219b2ee8SDavid du Colombier if(tp && tp->locals) { 571*219b2ee8SDavid du Colombier for(i = 0; i < tp->n; i++) 572*219b2ee8SDavid du Colombier if (strcmp(tp->locals[i]->name, name) == 0) { 573*219b2ee8SDavid du Colombier fillsym(tp->locals[i], s2); 574*219b2ee8SDavid du Colombier s2->handle = (void *)tp; 575*219b2ee8SDavid du Colombier return 1; 576*219b2ee8SDavid du Colombier } 577*219b2ee8SDavid du Colombier } 578*219b2ee8SDavid du Colombier return 0; 579*219b2ee8SDavid du Colombier } 580*219b2ee8SDavid du Colombier /* 581*219b2ee8SDavid du Colombier * Get ith text symbol 582*219b2ee8SDavid du Colombier */ 583*219b2ee8SDavid du Colombier int 584*219b2ee8SDavid du Colombier textsym(Symbol *s, int index) 585*219b2ee8SDavid du Colombier { 586*219b2ee8SDavid du Colombier 587*219b2ee8SDavid du Colombier if(buildtbls() == 0) 588*219b2ee8SDavid du Colombier return 0; 589*219b2ee8SDavid du Colombier if(index >= ntxt) 590*219b2ee8SDavid du Colombier return 0; 591*219b2ee8SDavid du Colombier fillsym(txt[index].sym, s); 592*219b2ee8SDavid du Colombier s->handle = (void *)&txt[index]; 593*219b2ee8SDavid du Colombier return 1; 594*219b2ee8SDavid du Colombier } 595*219b2ee8SDavid du Colombier /* 596*219b2ee8SDavid du Colombier * Get ith file name 597*219b2ee8SDavid du Colombier */ 598*219b2ee8SDavid du Colombier int 599*219b2ee8SDavid du Colombier filesym(int index, char *buf, int n) 600*219b2ee8SDavid du Colombier { 601*219b2ee8SDavid du Colombier Hist *hp; 602*219b2ee8SDavid du Colombier 603*219b2ee8SDavid du Colombier if(buildtbls() == 0) 604*219b2ee8SDavid du Colombier return 0; 605*219b2ee8SDavid du Colombier if(index >= nfiles) 606*219b2ee8SDavid du Colombier return 0; 607*219b2ee8SDavid du Colombier hp = files[index].hist; 608*219b2ee8SDavid du Colombier if(!hp || !hp->name) 609*219b2ee8SDavid du Colombier return 0; 610*219b2ee8SDavid du Colombier return fileelem(fnames, (uchar*)hp->name, buf, n); 611*219b2ee8SDavid du Colombier } 612*219b2ee8SDavid du Colombier /* 613*219b2ee8SDavid du Colombier * Lookup name of local variable located at an offset into the frame. 614*219b2ee8SDavid du Colombier * The type selects either a parameter or automatic. 615*219b2ee8SDavid du Colombier */ 616*219b2ee8SDavid du Colombier int 617*219b2ee8SDavid du Colombier getauto(Symbol *s1, int off, int type, Symbol *s2) 618*219b2ee8SDavid du Colombier { 619*219b2ee8SDavid du Colombier Txtsym *tp; 620*219b2ee8SDavid du Colombier Sym *p; 621*219b2ee8SDavid du Colombier int i, t; 622*219b2ee8SDavid du Colombier 623*219b2ee8SDavid du Colombier if(s1 == 0) 624*219b2ee8SDavid du Colombier return 0; 625*219b2ee8SDavid du Colombier if(type == CPARAM) 626*219b2ee8SDavid du Colombier t = 'p'; 627*219b2ee8SDavid du Colombier else if(type == CAUTO) 628*219b2ee8SDavid du Colombier t = 'a'; 629*219b2ee8SDavid du Colombier else 630*219b2ee8SDavid du Colombier return 0; 631*219b2ee8SDavid du Colombier if(buildtbls() == 0) 632*219b2ee8SDavid du Colombier return 0; 633*219b2ee8SDavid du Colombier tp = (Txtsym *)s1->handle; 634*219b2ee8SDavid du Colombier if(tp == 0) 635*219b2ee8SDavid du Colombier return 0; 636*219b2ee8SDavid du Colombier for(i = 0; i < tp->n; i++) { 637*219b2ee8SDavid du Colombier p = tp->locals[i]; 638*219b2ee8SDavid du Colombier if(p->type == t && p->value == off) { 639*219b2ee8SDavid du Colombier fillsym(p, s2); 640*219b2ee8SDavid du Colombier s2->handle = s1->handle; 641*219b2ee8SDavid du Colombier return 1; 642*219b2ee8SDavid du Colombier } 643*219b2ee8SDavid du Colombier } 644*219b2ee8SDavid du Colombier return 0; 645*219b2ee8SDavid du Colombier } 646*219b2ee8SDavid du Colombier 647*219b2ee8SDavid du Colombier /* 648*219b2ee8SDavid du Colombier * Find text symbol containing addr; binary search assumes text array is sorted by addr 649*219b2ee8SDavid du Colombier */ 650*219b2ee8SDavid du Colombier static int 651*219b2ee8SDavid du Colombier srchtext(long addr) 652*219b2ee8SDavid du Colombier { 653*219b2ee8SDavid du Colombier ulong val; 654*219b2ee8SDavid du Colombier int top, bot, mid; 655*219b2ee8SDavid du Colombier Sym *sp; 656*219b2ee8SDavid du Colombier 657*219b2ee8SDavid du Colombier val = addr; 658*219b2ee8SDavid du Colombier bot = 0; 659*219b2ee8SDavid du Colombier top = ntxt; 660*219b2ee8SDavid du Colombier for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) { 661*219b2ee8SDavid du Colombier sp = txt[mid].sym; 662*219b2ee8SDavid du Colombier if(val < (ulong)sp->value) 663*219b2ee8SDavid du Colombier top = mid; 664*219b2ee8SDavid du Colombier else if(mid != ntxt-1 && val >= (ulong)txt[mid+1].sym->value) 665*219b2ee8SDavid du Colombier bot = mid; 666*219b2ee8SDavid du Colombier else 667*219b2ee8SDavid du Colombier return mid; 668*219b2ee8SDavid du Colombier } 669*219b2ee8SDavid du Colombier return -1; 670*219b2ee8SDavid du Colombier } 671*219b2ee8SDavid du Colombier 672*219b2ee8SDavid du Colombier /* 673*219b2ee8SDavid du Colombier * Find data symbol containing addr; binary search assumes data array is sorted by addr 674*219b2ee8SDavid du Colombier */ 675*219b2ee8SDavid du Colombier static 676*219b2ee8SDavid du Colombier int srchdata(long addr) 677*219b2ee8SDavid du Colombier { 678*219b2ee8SDavid du Colombier ulong val; 679*219b2ee8SDavid du Colombier int top, bot, mid; 680*219b2ee8SDavid du Colombier Sym *sp; 681*219b2ee8SDavid du Colombier 682*219b2ee8SDavid du Colombier bot = 0; 683*219b2ee8SDavid du Colombier top = nglob; 684*219b2ee8SDavid du Colombier val = addr; 685*219b2ee8SDavid du Colombier for(mid = (bot+top)/2; mid < top; mid = (bot+top)/2) { 686*219b2ee8SDavid du Colombier sp = globals[mid]; 687*219b2ee8SDavid du Colombier if(val < (ulong)sp->value) 688*219b2ee8SDavid du Colombier top = mid; 689*219b2ee8SDavid du Colombier else if(mid < nglob-1 && val >= (ulong)globals[mid+1]->value) 690*219b2ee8SDavid du Colombier bot = mid; 691*219b2ee8SDavid du Colombier else 692*219b2ee8SDavid du Colombier return mid; 693*219b2ee8SDavid du Colombier } 694*219b2ee8SDavid du Colombier return -1; 695*219b2ee8SDavid du Colombier } 696*219b2ee8SDavid du Colombier /* 697*219b2ee8SDavid du Colombier * Find symbol containing val in specified search space 698*219b2ee8SDavid du Colombier * There is a special case when a value falls beyond the end 699*219b2ee8SDavid du Colombier * of the text segment; if the search space is CTEXT, that value 700*219b2ee8SDavid du Colombier * (usually etext) is returned. If the search space is CANY, symbols in the 701*219b2ee8SDavid du Colombier * data space are searched for a match. 702*219b2ee8SDavid du Colombier */ 703*219b2ee8SDavid du Colombier int 704*219b2ee8SDavid du Colombier findsym(long w, int type, Symbol *s) 705*219b2ee8SDavid du Colombier { 706*219b2ee8SDavid du Colombier int i; 707*219b2ee8SDavid du Colombier 708*219b2ee8SDavid du Colombier if(buildtbls() == 0) 709*219b2ee8SDavid du Colombier return 0; 710*219b2ee8SDavid du Colombier 711*219b2ee8SDavid du Colombier if(type == CTEXT || type == CANY) { 712*219b2ee8SDavid du Colombier i = srchtext(w); 713*219b2ee8SDavid du Colombier if(i >= 0) { 714*219b2ee8SDavid du Colombier if(type == CTEXT || i != ntxt-1) { 715*219b2ee8SDavid du Colombier fillsym(txt[i].sym, s); 716*219b2ee8SDavid du Colombier s->handle = (void *) &txt[i]; 717*219b2ee8SDavid du Colombier return 1; 718*219b2ee8SDavid du Colombier } 719*219b2ee8SDavid du Colombier } 720*219b2ee8SDavid du Colombier } 721*219b2ee8SDavid du Colombier if(type == CDATA || type == CANY) { 722*219b2ee8SDavid du Colombier i = srchdata(w); 723*219b2ee8SDavid du Colombier if(i >= 0) { 724*219b2ee8SDavid du Colombier fillsym(globals[i], s); 725*219b2ee8SDavid du Colombier return 1; 726*219b2ee8SDavid du Colombier } 727*219b2ee8SDavid du Colombier } 728*219b2ee8SDavid du Colombier return 0; 729*219b2ee8SDavid du Colombier } 730*219b2ee8SDavid du Colombier 731*219b2ee8SDavid du Colombier /* 732*219b2ee8SDavid du Colombier * Find the start and end address of the function containing addr 733*219b2ee8SDavid du Colombier */ 734*219b2ee8SDavid du Colombier int 735*219b2ee8SDavid du Colombier fnbound(long addr, ulong *bounds) 736*219b2ee8SDavid du Colombier { 737*219b2ee8SDavid du Colombier int i; 738*219b2ee8SDavid du Colombier 739*219b2ee8SDavid du Colombier if(buildtbls() == 0) 740*219b2ee8SDavid du Colombier return 0; 741*219b2ee8SDavid du Colombier 742*219b2ee8SDavid du Colombier i = srchtext(addr); 743*219b2ee8SDavid du Colombier if(0 <= i && i < ntxt-1) { 744*219b2ee8SDavid du Colombier bounds[0] = txt[i].sym->value; 745*219b2ee8SDavid du Colombier bounds[1] = txt[i+1].sym->value; 746*219b2ee8SDavid du Colombier return 1; 747*219b2ee8SDavid du Colombier } 748*219b2ee8SDavid du Colombier return 0; 749*219b2ee8SDavid du Colombier } 750*219b2ee8SDavid du Colombier 751*219b2ee8SDavid du Colombier /* 752*219b2ee8SDavid du Colombier * get the ith local symbol for a function 753*219b2ee8SDavid du Colombier * the input symbol table is reverse ordered, so we reverse 754*219b2ee8SDavid du Colombier * accesses here to maintain approx. parameter ordering in a stack trace. 755*219b2ee8SDavid du Colombier */ 756*219b2ee8SDavid du Colombier int 757*219b2ee8SDavid du Colombier localsym(Symbol *s, int index) 758*219b2ee8SDavid du Colombier { 759*219b2ee8SDavid du Colombier Txtsym *tp; 760*219b2ee8SDavid du Colombier 761*219b2ee8SDavid du Colombier if(s == 0) 762*219b2ee8SDavid du Colombier return 0; 763*219b2ee8SDavid du Colombier if(buildtbls() == 0) 764*219b2ee8SDavid du Colombier return 0; 765*219b2ee8SDavid du Colombier 766*219b2ee8SDavid du Colombier tp = (Txtsym *)s->handle; 767*219b2ee8SDavid du Colombier if(tp && tp->locals && index < tp->n) { 768*219b2ee8SDavid du Colombier fillsym(tp->locals[tp->n-index-1], s); /* reverse */ 769*219b2ee8SDavid du Colombier s->handle = (void *)tp; 770*219b2ee8SDavid du Colombier return 1; 771*219b2ee8SDavid du Colombier } 772*219b2ee8SDavid du Colombier return 0; 773*219b2ee8SDavid du Colombier } 774*219b2ee8SDavid du Colombier /* 775*219b2ee8SDavid du Colombier * get the ith global symbol 776*219b2ee8SDavid du Colombier */ 777*219b2ee8SDavid du Colombier int 778*219b2ee8SDavid du Colombier globalsym(Symbol *s, int index) 779*219b2ee8SDavid du Colombier { 780*219b2ee8SDavid du Colombier if(s == 0) 781*219b2ee8SDavid du Colombier return 0; 782*219b2ee8SDavid du Colombier if(buildtbls() == 0) 783*219b2ee8SDavid du Colombier return 0; 784*219b2ee8SDavid du Colombier 785*219b2ee8SDavid du Colombier if(index < nglob) { 786*219b2ee8SDavid du Colombier fillsym(globals[index], s); 787*219b2ee8SDavid du Colombier return 1; 788*219b2ee8SDavid du Colombier } 789*219b2ee8SDavid du Colombier return 0; 790*219b2ee8SDavid du Colombier } 791*219b2ee8SDavid du Colombier /* 792*219b2ee8SDavid du Colombier * find the pc given a file name and line offset into it. 793*219b2ee8SDavid du Colombier */ 794*219b2ee8SDavid du Colombier long 795*219b2ee8SDavid du Colombier file2pc(char *file, ulong line) 796*219b2ee8SDavid du Colombier { 797*219b2ee8SDavid du Colombier File *fp; 798*219b2ee8SDavid du Colombier int i; 799*219b2ee8SDavid du Colombier long pc; 800*219b2ee8SDavid du Colombier ulong start, end; 801*219b2ee8SDavid du Colombier short *name; 802*219b2ee8SDavid du Colombier 803*219b2ee8SDavid du Colombier if(buildtbls() == 0 || files == 0) 804*219b2ee8SDavid du Colombier return -1; 805*219b2ee8SDavid du Colombier name = encfname(file); 806*219b2ee8SDavid du Colombier if(name == 0) { /* encode the file name */ 807*219b2ee8SDavid du Colombier werrstr("file %s not found", file); 808*219b2ee8SDavid du Colombier return -1; 809*219b2ee8SDavid du Colombier } 810*219b2ee8SDavid du Colombier /* find this history stack */ 811*219b2ee8SDavid du Colombier for(i = 0, fp = files; i < nfiles; i++, fp++) 812*219b2ee8SDavid du Colombier if (hline(fp, name, &line)) 813*219b2ee8SDavid du Colombier break; 814*219b2ee8SDavid du Colombier free(name); 815*219b2ee8SDavid du Colombier if(i >= nfiles) { 816*219b2ee8SDavid du Colombier werrstr("line %d in file %s not found", line, file); 817*219b2ee8SDavid du Colombier return -1; 818*219b2ee8SDavid du Colombier } 819*219b2ee8SDavid du Colombier start = fp->addr; /* first text addr this file */ 820*219b2ee8SDavid du Colombier if(i < nfiles-1) 821*219b2ee8SDavid du Colombier end = (fp+1)->addr; /* first text addr next file */ 822*219b2ee8SDavid du Colombier else 823*219b2ee8SDavid du Colombier end = 0; /* last file in load module */ 824*219b2ee8SDavid du Colombier /* 825*219b2ee8SDavid du Colombier * At this point, line contains the offset into the file. 826*219b2ee8SDavid du Colombier * run the state machine to locate the pc closest to that value. 827*219b2ee8SDavid du Colombier */ 828*219b2ee8SDavid du Colombier if(debug) 829*219b2ee8SDavid du Colombier print("find pc for %d - between: %lux and %lux\n", line, start, end); 830*219b2ee8SDavid du Colombier pc = line2addr(line, start, end); 831*219b2ee8SDavid du Colombier if(pc == -1) { 832*219b2ee8SDavid du Colombier werrstr("line %d not in file %s", line, file); 833*219b2ee8SDavid du Colombier return -1; 834*219b2ee8SDavid du Colombier } 835*219b2ee8SDavid du Colombier return pc; 836*219b2ee8SDavid du Colombier } 837*219b2ee8SDavid du Colombier /* 838*219b2ee8SDavid du Colombier * search for a path component index 839*219b2ee8SDavid du Colombier */ 840*219b2ee8SDavid du Colombier static int 841*219b2ee8SDavid du Colombier pathcomp(char *s, int n) 842*219b2ee8SDavid du Colombier { 843*219b2ee8SDavid du Colombier int i; 844*219b2ee8SDavid du Colombier 845*219b2ee8SDavid du Colombier for(i = 0; i <= fmax; i++) 846*219b2ee8SDavid du Colombier if(fnames[i] && strncmp(s, fnames[i]->name, n) == 0) 847*219b2ee8SDavid du Colombier return i; 848*219b2ee8SDavid du Colombier return -1; 849*219b2ee8SDavid du Colombier } 850*219b2ee8SDavid du Colombier /* 851*219b2ee8SDavid du Colombier * Encode a char file name as a sequence of short indices 852*219b2ee8SDavid du Colombier * into the file name dictionary. 853*219b2ee8SDavid du Colombier */ 854*219b2ee8SDavid du Colombier static short* 855*219b2ee8SDavid du Colombier encfname(char *file) 856*219b2ee8SDavid du Colombier { 857*219b2ee8SDavid du Colombier int i, j; 858*219b2ee8SDavid du Colombier char *cp, *cp2; 859*219b2ee8SDavid du Colombier short *dest; 860*219b2ee8SDavid du Colombier 861*219b2ee8SDavid du Colombier if(*file == '/') /* always check first '/' */ 862*219b2ee8SDavid du Colombier cp2 = file+1; 863*219b2ee8SDavid du Colombier else { 864*219b2ee8SDavid du Colombier cp2 = strchr(file, '/'); 865*219b2ee8SDavid du Colombier if(!cp2) 866*219b2ee8SDavid du Colombier cp2 = strchr(file, 0); 867*219b2ee8SDavid du Colombier } 868*219b2ee8SDavid du Colombier cp = file; 869*219b2ee8SDavid du Colombier dest = 0; 870*219b2ee8SDavid du Colombier for(i = 0; *cp; i++) { 871*219b2ee8SDavid du Colombier j = pathcomp(cp, cp2-cp); 872*219b2ee8SDavid du Colombier if(j < 0) 873*219b2ee8SDavid du Colombier return 0; /* not found */ 874*219b2ee8SDavid du Colombier dest = realloc(dest, (i+1)*sizeof(short)); 875*219b2ee8SDavid du Colombier dest[i] = j; 876*219b2ee8SDavid du Colombier cp = cp2; 877*219b2ee8SDavid du Colombier while(*cp == '/') /* skip embedded '/'s */ 878*219b2ee8SDavid du Colombier cp++; 879*219b2ee8SDavid du Colombier cp2 = strchr(cp, '/'); 880*219b2ee8SDavid du Colombier if(!cp2) 881*219b2ee8SDavid du Colombier cp2 = strchr(cp, 0); 882*219b2ee8SDavid du Colombier } 883*219b2ee8SDavid du Colombier dest = realloc(dest, (i+1)*sizeof(short)); 884*219b2ee8SDavid du Colombier dest[i] = 0; 885*219b2ee8SDavid du Colombier return dest; 886*219b2ee8SDavid du Colombier } 887*219b2ee8SDavid du Colombier /* 888*219b2ee8SDavid du Colombier * Search a history stack for a matching file name accumulating 889*219b2ee8SDavid du Colombier * the size of intervening files in the stack. 890*219b2ee8SDavid du Colombier */ 891*219b2ee8SDavid du Colombier static int 892*219b2ee8SDavid du Colombier hline(File *fp, short *name, ulong *line) 893*219b2ee8SDavid du Colombier { 894*219b2ee8SDavid du Colombier Hist *hp; 895*219b2ee8SDavid du Colombier int offset, depth; 896*219b2ee8SDavid du Colombier long ln; 897*219b2ee8SDavid du Colombier 898*219b2ee8SDavid du Colombier for(hp = fp->hist; hp->name; hp++) /* find name in stack */ 899*219b2ee8SDavid du Colombier if(hp->name[1] || hp->name[2]) { 900*219b2ee8SDavid du Colombier if(hcomp(hp, name)) 901*219b2ee8SDavid du Colombier break; 902*219b2ee8SDavid du Colombier } 903*219b2ee8SDavid du Colombier if(!hp->name) /* match not found */ 904*219b2ee8SDavid du Colombier return 0; 905*219b2ee8SDavid du Colombier if(debug) 906*219b2ee8SDavid du Colombier printhist("hline found ... ", hp, 1); 907*219b2ee8SDavid du Colombier /* 908*219b2ee8SDavid du Colombier * unwind the stack until empty or we hit an entry beyond our line 909*219b2ee8SDavid du Colombier */ 910*219b2ee8SDavid du Colombier ln = *line; 911*219b2ee8SDavid du Colombier offset = hp->line-1; 912*219b2ee8SDavid du Colombier depth = 1; 913*219b2ee8SDavid du Colombier for(hp++; depth && hp->name; hp++) { 914*219b2ee8SDavid du Colombier if(debug) 915*219b2ee8SDavid du Colombier printhist("hline inspect ... ", hp, 1); 916*219b2ee8SDavid du Colombier if(hp->name[1] || hp->name[2]) { 917*219b2ee8SDavid du Colombier if(hp->offset){ /* Z record */ 918*219b2ee8SDavid du Colombier offset = 0; 919*219b2ee8SDavid du Colombier if(hcomp(hp, name)) { 920*219b2ee8SDavid du Colombier if(*line <= hp->offset) 921*219b2ee8SDavid du Colombier break; 922*219b2ee8SDavid du Colombier ln = *line+hp->line-hp->offset; 923*219b2ee8SDavid du Colombier depth = 1; /* implicit pop */ 924*219b2ee8SDavid du Colombier } else 925*219b2ee8SDavid du Colombier depth = 2; /* implicit push */ 926*219b2ee8SDavid du Colombier } else if(depth == 1 && ln < hp->line-offset) 927*219b2ee8SDavid du Colombier break; /* Beyond our line */ 928*219b2ee8SDavid du Colombier else if(depth++ == 1) /* push */ 929*219b2ee8SDavid du Colombier offset -= hp->line; 930*219b2ee8SDavid du Colombier } else if(--depth == 1) /* pop */ 931*219b2ee8SDavid du Colombier offset += hp->line; 932*219b2ee8SDavid du Colombier } 933*219b2ee8SDavid du Colombier *line = ln+offset; 934*219b2ee8SDavid du Colombier return 1; 935*219b2ee8SDavid du Colombier } 936*219b2ee8SDavid du Colombier /* 937*219b2ee8SDavid du Colombier * compare two encoded file names 938*219b2ee8SDavid du Colombier */ 939*219b2ee8SDavid du Colombier static int 940*219b2ee8SDavid du Colombier hcomp(Hist *hp, short *sp) 941*219b2ee8SDavid du Colombier { 942*219b2ee8SDavid du Colombier uchar *cp; 943*219b2ee8SDavid du Colombier int i, j; 944*219b2ee8SDavid du Colombier short *s; 945*219b2ee8SDavid du Colombier 946*219b2ee8SDavid du Colombier cp = (uchar *)hp->name; 947*219b2ee8SDavid du Colombier s = sp; 948*219b2ee8SDavid du Colombier if (*s == 0) 949*219b2ee8SDavid du Colombier return 0; 950*219b2ee8SDavid du Colombier for (i = 1; j = (cp[i]<<8)|cp[i+1]; i += 2) { 951*219b2ee8SDavid du Colombier if(j == 0) 952*219b2ee8SDavid du Colombier break; 953*219b2ee8SDavid du Colombier if(*s == j) 954*219b2ee8SDavid du Colombier s++; 955*219b2ee8SDavid du Colombier else 956*219b2ee8SDavid du Colombier s = sp; 957*219b2ee8SDavid du Colombier } 958*219b2ee8SDavid du Colombier return *s == 0; 959*219b2ee8SDavid du Colombier } 960*219b2ee8SDavid du Colombier /* 961*219b2ee8SDavid du Colombier * Convert a pc to a "file:line {file:line}" string. 962*219b2ee8SDavid du Colombier */ 963*219b2ee8SDavid du Colombier int 964*219b2ee8SDavid du Colombier fileline(char *str, int n, ulong dot) 965*219b2ee8SDavid du Colombier { 966*219b2ee8SDavid du Colombier long line; 967*219b2ee8SDavid du Colombier int top, bot, mid; 968*219b2ee8SDavid du Colombier File *f; 969*219b2ee8SDavid du Colombier 970*219b2ee8SDavid du Colombier *str = 0; 971*219b2ee8SDavid du Colombier if(buildtbls() == 0) 972*219b2ee8SDavid du Colombier return 0; 973*219b2ee8SDavid du Colombier 974*219b2ee8SDavid du Colombier /* binary search assumes file list is sorted by addr */ 975*219b2ee8SDavid du Colombier bot = 0; 976*219b2ee8SDavid du Colombier top = nfiles; 977*219b2ee8SDavid du Colombier for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) { 978*219b2ee8SDavid du Colombier f = &files[mid]; 979*219b2ee8SDavid du Colombier if(dot < f->addr) 980*219b2ee8SDavid du Colombier top = mid; 981*219b2ee8SDavid du Colombier else if(mid < nfiles-1 && dot >= (f+1)->addr) 982*219b2ee8SDavid du Colombier bot = mid; 983*219b2ee8SDavid du Colombier else { 984*219b2ee8SDavid du Colombier line = pc2line(dot); 985*219b2ee8SDavid du Colombier if(line > 0 && fline(str, n, line, f->hist)) 986*219b2ee8SDavid du Colombier return 1; 987*219b2ee8SDavid du Colombier break; 988*219b2ee8SDavid du Colombier } 989*219b2ee8SDavid du Colombier } 990*219b2ee8SDavid du Colombier return 0; 991*219b2ee8SDavid du Colombier } 992*219b2ee8SDavid du Colombier 993*219b2ee8SDavid du Colombier /* 994*219b2ee8SDavid du Colombier * Convert a line number within a composite file to relative line 995*219b2ee8SDavid du Colombier * number in a source file. A composite file is the source 996*219b2ee8SDavid du Colombier * file with included files inserted in line. 997*219b2ee8SDavid du Colombier */ 998*219b2ee8SDavid du Colombier static Hist * 999*219b2ee8SDavid du Colombier fline(char *str, int n, long line, Hist *base) 1000*219b2ee8SDavid du Colombier { 1001*219b2ee8SDavid du Colombier Hist *start; /* start of current level */ 1002*219b2ee8SDavid du Colombier Hist *h; /* current entry */ 1003*219b2ee8SDavid du Colombier int delta; /* sum of size of files this level */ 1004*219b2ee8SDavid du Colombier int k; 1005*219b2ee8SDavid du Colombier 1006*219b2ee8SDavid du Colombier start = base; 1007*219b2ee8SDavid du Colombier h = base; 1008*219b2ee8SDavid du Colombier delta = h->line; 1009*219b2ee8SDavid du Colombier while(h && h->name && line > h->line) { 1010*219b2ee8SDavid du Colombier if(h->name[1] || h->name[2]) { 1011*219b2ee8SDavid du Colombier if(h->offset != 0) { /* #line Directive */ 1012*219b2ee8SDavid du Colombier delta = h->line-h->offset+1; 1013*219b2ee8SDavid du Colombier start = h; 1014*219b2ee8SDavid du Colombier base = h++; 1015*219b2ee8SDavid du Colombier } else { /* beginning of File */ 1016*219b2ee8SDavid du Colombier if(start == base) 1017*219b2ee8SDavid du Colombier start = h++; 1018*219b2ee8SDavid du Colombier else { 1019*219b2ee8SDavid du Colombier h = fline(str, n, line, start); 1020*219b2ee8SDavid du Colombier if(!h) 1021*219b2ee8SDavid du Colombier break; 1022*219b2ee8SDavid du Colombier } 1023*219b2ee8SDavid du Colombier } 1024*219b2ee8SDavid du Colombier } else { 1025*219b2ee8SDavid du Colombier if(start == base) /* end of recursion level */ 1026*219b2ee8SDavid du Colombier return h; 1027*219b2ee8SDavid du Colombier else { /* end of included file */ 1028*219b2ee8SDavid du Colombier delta += h->line-start->line; 1029*219b2ee8SDavid du Colombier h++; 1030*219b2ee8SDavid du Colombier start = base; 1031*219b2ee8SDavid du Colombier } 1032*219b2ee8SDavid du Colombier } 1033*219b2ee8SDavid du Colombier } 1034*219b2ee8SDavid du Colombier if(!h) 1035*219b2ee8SDavid du Colombier return 0; 1036*219b2ee8SDavid du Colombier if(start != base) 1037*219b2ee8SDavid du Colombier line = line-start->line+1; 1038*219b2ee8SDavid du Colombier else 1039*219b2ee8SDavid du Colombier line = line-delta+1; 1040*219b2ee8SDavid du Colombier if(!h->name) 1041*219b2ee8SDavid du Colombier strncpy(str, "<eof>", n); 1042*219b2ee8SDavid du Colombier else { 1043*219b2ee8SDavid du Colombier k = fileelem(fnames, (uchar*)start->name, str, n); 1044*219b2ee8SDavid du Colombier if(k+8 < n) 1045*219b2ee8SDavid du Colombier sprint(str+k, ":%ld", line); 1046*219b2ee8SDavid du Colombier } 1047*219b2ee8SDavid du Colombier /**********Remove comments for complete back-trace of include sequence 1048*219b2ee8SDavid du Colombier * if(start != base) { 1049*219b2ee8SDavid du Colombier * k = strlen(str); 1050*219b2ee8SDavid du Colombier * if(k+2 < n) { 1051*219b2ee8SDavid du Colombier * str[k++] = ' '; 1052*219b2ee8SDavid du Colombier * str[k++] = '{'; 1053*219b2ee8SDavid du Colombier * } 1054*219b2ee8SDavid du Colombier * k += fileelem(fnames, (uchar*) base->name, str+k, n-k); 1055*219b2ee8SDavid du Colombier * if(k+10 < n) 1056*219b2ee8SDavid du Colombier * sprint(str+k, ":%ld}", start->line-delta); 1057*219b2ee8SDavid du Colombier * } 1058*219b2ee8SDavid du Colombier ********************/ 1059*219b2ee8SDavid du Colombier return h; 1060*219b2ee8SDavid du Colombier } 1061*219b2ee8SDavid du Colombier /* 1062*219b2ee8SDavid du Colombier * convert an encoded file name to a string. 1063*219b2ee8SDavid du Colombier */ 1064*219b2ee8SDavid du Colombier int 1065*219b2ee8SDavid du Colombier fileelem(Sym **fp, uchar *cp, char *buf, int n) 1066*219b2ee8SDavid du Colombier { 1067*219b2ee8SDavid du Colombier int i, j; 1068*219b2ee8SDavid du Colombier char *c, *bp, *end; 1069*219b2ee8SDavid du Colombier 1070*219b2ee8SDavid du Colombier bp = buf; 1071*219b2ee8SDavid du Colombier end = buf+n-1; 1072*219b2ee8SDavid du Colombier for(i = 1; j = (cp[i]<<8)|cp[i+1]; i+=2){ 1073*219b2ee8SDavid du Colombier c = fp[j]->name; 1074*219b2ee8SDavid du Colombier if(bp != buf && bp[-1] != '/' && bp < end) 1075*219b2ee8SDavid du Colombier *bp++ = '/'; 1076*219b2ee8SDavid du Colombier while(bp < end && *c) 1077*219b2ee8SDavid du Colombier *bp++ = *c++; 1078*219b2ee8SDavid du Colombier } 1079*219b2ee8SDavid du Colombier *bp = 0; 1080*219b2ee8SDavid du Colombier return bp-buf; 1081*219b2ee8SDavid du Colombier } 1082*219b2ee8SDavid du Colombier /* 1083*219b2ee8SDavid du Colombier * compare the values of two symbol table entries. 1084*219b2ee8SDavid du Colombier */ 1085*219b2ee8SDavid du Colombier static int 1086*219b2ee8SDavid du Colombier symcomp(void *a, void *b) 1087*219b2ee8SDavid du Colombier { 1088*219b2ee8SDavid du Colombier return (*(Sym**)a)->value - (*(Sym**)b)->value; 1089*219b2ee8SDavid du Colombier } 1090*219b2ee8SDavid du Colombier /* 1091*219b2ee8SDavid du Colombier * compare the values of the symbols referenced by two text table entries 1092*219b2ee8SDavid du Colombier */ 1093*219b2ee8SDavid du Colombier static int 1094*219b2ee8SDavid du Colombier txtcomp(void *a, void *b) 1095*219b2ee8SDavid du Colombier { 1096*219b2ee8SDavid du Colombier return ((Txtsym*)a)->sym->value - ((Txtsym*)b)->sym->value; 1097*219b2ee8SDavid du Colombier } 1098*219b2ee8SDavid du Colombier /* 1099*219b2ee8SDavid du Colombier * compare the values of the symbols referenced by two file table entries 1100*219b2ee8SDavid du Colombier */ 1101*219b2ee8SDavid du Colombier static int 1102*219b2ee8SDavid du Colombier filecomp(void *a, void *b) 1103*219b2ee8SDavid du Colombier { 1104*219b2ee8SDavid du Colombier return ((File*)a)->addr - ((File*)b)->addr; 1105*219b2ee8SDavid du Colombier } 1106*219b2ee8SDavid du Colombier /* 1107*219b2ee8SDavid du Colombier * fill an interface Symbol structure from a symbol table entry 1108*219b2ee8SDavid du Colombier */ 1109*219b2ee8SDavid du Colombier static void 1110*219b2ee8SDavid du Colombier fillsym(Sym *sp, Symbol *s) 1111*219b2ee8SDavid du Colombier { 1112*219b2ee8SDavid du Colombier s->type = sp->type; 1113*219b2ee8SDavid du Colombier s->value = sp->value; 1114*219b2ee8SDavid du Colombier s->name = sp->name; 1115*219b2ee8SDavid du Colombier switch(sp->type) { 1116*219b2ee8SDavid du Colombier case 'b': 1117*219b2ee8SDavid du Colombier case 'B': 1118*219b2ee8SDavid du Colombier case 'D': 1119*219b2ee8SDavid du Colombier case 'd': 1120*219b2ee8SDavid du Colombier s->class = CDATA; 1121*219b2ee8SDavid du Colombier break; 1122*219b2ee8SDavid du Colombier case 't': 1123*219b2ee8SDavid du Colombier case 'T': 1124*219b2ee8SDavid du Colombier case 'l': 1125*219b2ee8SDavid du Colombier case 'L': 1126*219b2ee8SDavid du Colombier s->class = CTEXT; 1127*219b2ee8SDavid du Colombier break; 1128*219b2ee8SDavid du Colombier case 'a': 1129*219b2ee8SDavid du Colombier s->class = CAUTO; 1130*219b2ee8SDavid du Colombier break; 1131*219b2ee8SDavid du Colombier case 'p': 1132*219b2ee8SDavid du Colombier s->class = CPARAM; 1133*219b2ee8SDavid du Colombier break; 1134*219b2ee8SDavid du Colombier case 'm': 1135*219b2ee8SDavid du Colombier s->class = CSTAB; 1136*219b2ee8SDavid du Colombier break; 1137*219b2ee8SDavid du Colombier default: 1138*219b2ee8SDavid du Colombier s->class = CNONE; 1139*219b2ee8SDavid du Colombier break; 1140*219b2ee8SDavid du Colombier } 1141*219b2ee8SDavid du Colombier s->handle = 0; 1142*219b2ee8SDavid du Colombier } 11433e12c5d1SDavid du Colombier /* 11443e12c5d1SDavid du Colombier * find the stack frame, given the pc 11453e12c5d1SDavid du Colombier */ 11463e12c5d1SDavid du Colombier long 11473e12c5d1SDavid du Colombier pc2sp(ulong pc) 11483e12c5d1SDavid du Colombier { 11493e12c5d1SDavid du Colombier uchar *c; 11503e12c5d1SDavid du Colombier uchar u; 11513e12c5d1SDavid du Colombier ulong currpc; 11523e12c5d1SDavid du Colombier long currsp; 11533e12c5d1SDavid du Colombier 11543e12c5d1SDavid du Colombier if(spoff == 0) 11553e12c5d1SDavid du Colombier return -1; 11563e12c5d1SDavid du Colombier currsp = 0; 11573e12c5d1SDavid du Colombier currpc = txtstart - mach->pcquant; 11583e12c5d1SDavid du Colombier 11593e12c5d1SDavid du Colombier if(pc<currpc || pc>txtend) 11603e12c5d1SDavid du Colombier return -1; 11613e12c5d1SDavid du Colombier for(c = spoff; c < spoffend; c++) { 11623e12c5d1SDavid du Colombier if (currpc >= pc) 11633e12c5d1SDavid du Colombier return currsp; 11643e12c5d1SDavid du Colombier u = *c; 11653e12c5d1SDavid du Colombier if (u == 0) { 11663e12c5d1SDavid du Colombier currsp += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4]; 11673e12c5d1SDavid du Colombier c += 4; 1168*219b2ee8SDavid du Colombier } 1169*219b2ee8SDavid du Colombier else if (u < 65) 11703e12c5d1SDavid du Colombier currsp += 4*u; 11713e12c5d1SDavid du Colombier else if (u < 129) 11723e12c5d1SDavid du Colombier currsp -= 4*(u-64); 11733e12c5d1SDavid du Colombier else 11743e12c5d1SDavid du Colombier currpc += mach->pcquant*(u-129); 11753e12c5d1SDavid du Colombier currpc += mach->pcquant; 11763e12c5d1SDavid du Colombier } 11773e12c5d1SDavid du Colombier return -1; 11783e12c5d1SDavid du Colombier } 11793e12c5d1SDavid du Colombier /* 11803e12c5d1SDavid du Colombier * find the source file line number for a given value of the pc 11813e12c5d1SDavid du Colombier */ 11823e12c5d1SDavid du Colombier long 11833e12c5d1SDavid du Colombier pc2line(ulong pc) 11843e12c5d1SDavid du Colombier { 11853e12c5d1SDavid du Colombier uchar *c; 11863e12c5d1SDavid du Colombier uchar u; 11873e12c5d1SDavid du Colombier ulong currpc; 11883e12c5d1SDavid du Colombier long currline; 11893e12c5d1SDavid du Colombier 11903e12c5d1SDavid du Colombier if(pcline == 0) 11913e12c5d1SDavid du Colombier return -1; 11923e12c5d1SDavid du Colombier currline = 0; 11933e12c5d1SDavid du Colombier currpc = txtstart-mach->pcquant; 11943e12c5d1SDavid du Colombier if(pc<currpc || pc>txtend) 11953e12c5d1SDavid du Colombier return -1; 1196*219b2ee8SDavid du Colombier 11973e12c5d1SDavid du Colombier for(c = pcline; c < pclineend; c++) { 11983e12c5d1SDavid du Colombier if(currpc >= pc) 11993e12c5d1SDavid du Colombier return currline; 12003e12c5d1SDavid du Colombier u = *c; 12013e12c5d1SDavid du Colombier if(u == 0) { 12023e12c5d1SDavid du Colombier currline += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4]; 12033e12c5d1SDavid du Colombier c += 4; 1204*219b2ee8SDavid du Colombier } 1205*219b2ee8SDavid du Colombier else if(u < 65) 12063e12c5d1SDavid du Colombier currline += u; 12073e12c5d1SDavid du Colombier else if(u < 129) 12083e12c5d1SDavid du Colombier currline -= (u-64); 12093e12c5d1SDavid du Colombier else 12103e12c5d1SDavid du Colombier currpc += mach->pcquant*(u-129); 12113e12c5d1SDavid du Colombier currpc += mach->pcquant; 12123e12c5d1SDavid du Colombier } 12133e12c5d1SDavid du Colombier return -1; 12143e12c5d1SDavid du Colombier } 12153e12c5d1SDavid du Colombier /* 1216bd389b36SDavid du Colombier * find the pc associated with a line number 1217bd389b36SDavid du Colombier * basepc and endpc are text addresses bounding the search. 1218bd389b36SDavid du Colombier * if endpc == 0, the end of the table is used (i.e., no upper bound). 1219bd389b36SDavid du Colombier * usually, basepc and endpc contain the first text address in 1220bd389b36SDavid du Colombier * a file and the first text address in the following file, respectively. 12213e12c5d1SDavid du Colombier */ 12223e12c5d1SDavid du Colombier long 1223bd389b36SDavid du Colombier line2addr(ulong line, ulong basepc, ulong endpc) 12243e12c5d1SDavid du Colombier { 12253e12c5d1SDavid du Colombier uchar *c; 12263e12c5d1SDavid du Colombier uchar u; 1227bd389b36SDavid du Colombier ulong currpc; 1228bd389b36SDavid du Colombier long currline; 1229bd389b36SDavid du Colombier long delta, d; 1230bd389b36SDavid du Colombier long pc, found; 12313e12c5d1SDavid du Colombier 12323e12c5d1SDavid du Colombier if(pcline == 0 || line == 0) 12333e12c5d1SDavid du Colombier return -1; 1234*219b2ee8SDavid du Colombier 1235bd389b36SDavid du Colombier currline = 0; 1236bd389b36SDavid du Colombier currpc = txtstart-mach->pcquant; 1237bd389b36SDavid du Colombier pc = -1; 1238bd389b36SDavid du Colombier found = 0; 1239bd389b36SDavid du Colombier delta = HUGEINT; 12403e12c5d1SDavid du Colombier 12413e12c5d1SDavid du Colombier for(c = pcline; c < pclineend; c++) { 1242bd389b36SDavid du Colombier if(endpc && currpc >= endpc) /* end of file of interest */ 1243bd389b36SDavid du Colombier break; 1244bd389b36SDavid du Colombier if(currpc >= basepc) { /* proper file */ 1245bd389b36SDavid du Colombier if(currline >= line) { 1246bd389b36SDavid du Colombier d = currline-line; 1247bd389b36SDavid du Colombier found = 1; 1248bd389b36SDavid du Colombier } else 1249bd389b36SDavid du Colombier d = line-currline; 1250bd389b36SDavid du Colombier if(d < delta) { 1251bd389b36SDavid du Colombier delta = d; 1252bd389b36SDavid du Colombier pc = currpc; 12533e12c5d1SDavid du Colombier } 1254bd389b36SDavid du Colombier } 12553e12c5d1SDavid du Colombier u = *c; 12563e12c5d1SDavid du Colombier if(u == 0) { 12573e12c5d1SDavid du Colombier currline += (c[1]<<24)|(c[2]<<16)|(c[3]<<8)|c[4]; 12583e12c5d1SDavid du Colombier c += 4; 1259*219b2ee8SDavid du Colombier } 1260*219b2ee8SDavid du Colombier else if(u < 65) 12613e12c5d1SDavid du Colombier currline += u; 12623e12c5d1SDavid du Colombier else if(u < 129) 12633e12c5d1SDavid du Colombier currline -= (u-64); 12643e12c5d1SDavid du Colombier else 12653e12c5d1SDavid du Colombier currpc += mach->pcquant*(u-129); 12663e12c5d1SDavid du Colombier currpc += mach->pcquant; 12673e12c5d1SDavid du Colombier } 1268bd389b36SDavid du Colombier if(found) 1269bd389b36SDavid du Colombier return pc; 12703e12c5d1SDavid du Colombier return -1; 12713e12c5d1SDavid du Colombier } 12723e12c5d1SDavid du Colombier /* 1273*219b2ee8SDavid du Colombier * Print a history stack (debug). if count is 0, prints the whole stack 12743e12c5d1SDavid du Colombier */ 1275*219b2ee8SDavid du Colombier void 1276*219b2ee8SDavid du Colombier printhist(char *msg, Hist *hp, int count) 12773e12c5d1SDavid du Colombier { 1278*219b2ee8SDavid du Colombier int i; 1279*219b2ee8SDavid du Colombier uchar *cp; 1280*219b2ee8SDavid du Colombier char buf[128]; 12813e12c5d1SDavid du Colombier 1282*219b2ee8SDavid du Colombier i = 0; 1283*219b2ee8SDavid du Colombier while(hp->name) { 1284*219b2ee8SDavid du Colombier if(count && ++i > count) 12853e12c5d1SDavid du Colombier break; 1286*219b2ee8SDavid du Colombier print("%s Line: %x (%d) Offset: %x (%d) Name: ", msg, 1287*219b2ee8SDavid du Colombier hp->line, hp->line, hp->offset, hp->offset); 1288*219b2ee8SDavid du Colombier for(cp = (uchar *)hp->name+1; (*cp<<8)|cp[1]; cp += 2) { 1289*219b2ee8SDavid du Colombier if (cp != (uchar *)hp->name+1) 1290*219b2ee8SDavid du Colombier print("/"); 1291*219b2ee8SDavid du Colombier print("%x", (*cp<<8)|cp[1]); 12923e12c5d1SDavid du Colombier } 1293*219b2ee8SDavid du Colombier fileelem(fnames, (uchar *) hp->name, buf, sizeof(buf)); 1294*219b2ee8SDavid du Colombier print(" (%s)\n", buf); 1295*219b2ee8SDavid du Colombier hp++; 12963e12c5d1SDavid du Colombier } 1297*219b2ee8SDavid du Colombier } 1298*219b2ee8SDavid du Colombier 1299*219b2ee8SDavid du Colombier #ifdef DEBUG 1300*219b2ee8SDavid du Colombier /* 1301*219b2ee8SDavid du Colombier * print the history stack for a file. (debug only) 1302*219b2ee8SDavid du Colombier * if (name == 0) => print all history stacks. 1303*219b2ee8SDavid du Colombier */ 1304*219b2ee8SDavid du Colombier void 1305*219b2ee8SDavid du Colombier dumphist(char *name) 1306*219b2ee8SDavid du Colombier { 1307*219b2ee8SDavid du Colombier int i; 1308*219b2ee8SDavid du Colombier File *f; 1309*219b2ee8SDavid du Colombier short *fname; 1310*219b2ee8SDavid du Colombier 1311*219b2ee8SDavid du Colombier if(buildtbls() == 0) 1312*219b2ee8SDavid du Colombier return; 1313*219b2ee8SDavid du Colombier if(name) 1314*219b2ee8SDavid du Colombier fname = encfname(name); 1315*219b2ee8SDavid du Colombier for(i = 0, f = files; i < nfiles; i++, f++) 1316*219b2ee8SDavid du Colombier if(fname == 0 || hcomp(f->hist, fname)) 1317*219b2ee8SDavid du Colombier printhist("> ", f->hist, f->n); 1318*219b2ee8SDavid du Colombier 1319*219b2ee8SDavid du Colombier if(fname) 1320*219b2ee8SDavid du Colombier free(fname); 1321*219b2ee8SDavid du Colombier } 1322*219b2ee8SDavid du Colombier #endif 1323