#include <lib9.h>#include <bio.h>#include "mach.h" #define HUGEINT 0x7fffffff#define NNAME 20 /* a relic of the past */ typedef struct txtsym Txtsym;typedef struct file File;typedef struct hist Hist; struct txtsym { /* Text Symbol table */ int n; /* number of local vars */ Sym **locals; /* array of ptrs to autos */ Sym *sym; /* function symbol entry */}; struct hist { /* Stack of include files & #line directives */ char *name; /* Assumes names Null terminated in file */ long line; /* line # where it was included */ long offset; /* line # of #line directive */}; struct file { /* Per input file header to history stack */ uvlong addr; /* address of first text sym */ /* union { */ Txtsym *txt; /* first text symbol */ Sym *sym; /* only during initilization */ /* }; */ int n; /* size of history stack */ Hist *hist; /* history stack */}; static int debug = 0; static Sym **autos; /* Base of auto variables */static File *files; /* Base of file arena */static int fpmax; /* largest file path index */static Sym **fnames; /* file names path component table */static Sym **globals; /* globals by addr table */static Hist *hist; /* base of history stack */static int isbuilt; /* internal table init flag */static long nauto; /* number of automatics */static long nfiles; /* number of files */static long nglob; /* number of globals */static long nhist; /* number of history stack entries */static long nsym; /* number of symbols */static int ntxt; /* number of text symbols */static uchar *pcline; /* start of pc-line state table */static uchar *pclineend; /* end of pc-line table */static uchar *spoff; /* start of pc-sp state table */static uchar *spoffend; /* end of pc-sp offset table */static Sym *symbols; /* symbol table */static Txtsym *txt; /* Base of text symbol table */static uvlong txtstart; /* start of text segment */static uvlong txtend; /* end of text segment */ static void cleansyms(void);static long decodename(Biobuf*, Sym*);static short *encfname(char*);static int fline(char*, int, long, Hist*, Hist**);static void fillsym(Sym*, Symbol*);static int findglobal(char*, Symbol*);static int findlocvar(Symbol*, char *, Symbol*);static int findtext(char*, Symbol*);static int hcomp(Hist*, short*);static int hline(File*, short*, long*);static void printhist(char*, Hist*, int);static int buildtbls(void);static int symcomp(void*, void*);static int symerrmsg(int, char*);static int txtcomp(void*, void*);static int filecomp(void*, void*); /* * initialize the symbol tables */intsyminit(int fd, Fhdr *fp){ Sym *p; long i, l, size; vlong vl; Biobuf b; int svalsz; if(fp->symsz == 0) return 0; if(fp->type == FNONE) return 0; cleansyms(); textseg(fp->txtaddr, fp); /* minimum symbol record size = 4+1+2 bytes */ symbols = malloc((fp->symsz/(4+1+2)+1)*sizeof(Sym)); if(symbols == 0) { werrstr("can't malloc %ld bytes", fp->symsz); return -1; } Binit(&b, fd, OREAD); Bseek(&b, fp->symoff, 0); nsym = 0; size = 0; for(p = symbols; size < fp->symsz; p++, nsym++) { if(fp->_magic && (fp->magic & HDR_MAGIC)){ svalsz = 8; if(Bread(&b, &vl, 8) != 8) return symerrmsg(8, "symbol"); p->value = beswav(vl); } else{ svalsz = 4; if(Bread(&b, &l, 4) != 4) return symerrmsg(4, "symbol"); p->value = (u32int)beswal(l); } if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type)) return symerrmsg(sizeof(p->value), "symbol"); i = decodename(&b, p); if(i < 0) return -1; size += i+svalsz+sizeof(p->type); /* count global & auto vars, text symbols, and file names */ switch (p->type) { case 'l': case 'L': case 't': case 'T': ntxt++; break; case 'd': case 'D': case 'b': case 'B': nglob++; break; case 'f': if(strcmp(p->name, ".frame") == 0) { p->type = 'm'; nauto++; } else if(p->value > fpmax) fpmax = p->value; /* highest path index */ break; case 'a': case 'p': case 'm': nauto++; break; case 'z': if(p->value == 1) { /* one extra per file */ nhist++; nfiles++; } nhist++; break; default: break; } } if (debug) print("NG: %ld NT: %d NF: %d\n", nglob, ntxt, fpmax); if (fp->sppcsz) { /* pc-sp offset table */ spoff = (uchar *)malloc(fp->sppcsz); if(spoff == 0) { werrstr("can't malloc %ld bytes", fp->sppcsz); return -1; } Bseek(&b, fp->sppcoff, 0); if(Bread(&b, spoff, fp->sppcsz) != fp->sppcsz){ spoff = 0; return symerrmsg(fp->sppcsz, "sp-pc"); } spoffend = spoff+fp->sppcsz; } if (fp->lnpcsz) { /* pc-line number table */ pcline = (uchar *)malloc(fp->lnpcsz); if(pcline == 0) { werrstr("can't malloc %ld bytes", fp->lnpcsz); return -1; } Bseek(&b, fp->lnpcoff, 0); if(Bread(&b, pcline, fp->lnpcsz) != fp->lnpcsz){ pcline = 0; return symerrmsg(fp->lnpcsz, "pc-line"); } pclineend = pcline+fp->lnpcsz; } if(fp->type == FARM) /* thumb pc table */ thumbpctab(&b, fp); return nsym;} static intsymerrmsg(int n, char *table){ werrstr("can't read %d bytes of %s table", n, table); return -1;} static longdecodename(Biobuf *bp, Sym *p){ char *cp; int c1, c2; long n; vlong o; if((p->type & 0x80) == 0) { /* old-style, fixed length names */ p->name = malloc(NNAME); if(p->name == 0) { werrstr("can't malloc %d bytes", NNAME); return -1; } if(Bread(bp, p->name, NNAME) != NNAME) return symerrmsg(NNAME, "symbol"); Bseek(bp, 3, 1); return NNAME+3; } p->type &= ~0x80; if(p->type == 'z' || p->type == 'Z') { o = Bseek(bp, 0, 1); if(Bgetc(bp) < 0) { werrstr("can't read symbol name"); return -1; } for(;;) { c1 = Bgetc(bp); c2 = Bgetc(bp); if(c1 < 0 || c2 < 0) { werrstr("can't read symbol name"); return -1; } if(c1 == 0 && c2 == 0) break; } n = Bseek(bp, 0, 1)-o; p->name = malloc(n); if(p->name == 0) { werrstr("can't malloc %ld bytes", n); return -1; } Bseek(bp, -n, 1); if(Bread(bp, p->name, n) != n) { werrstr("can't read %ld bytes of symbol name", n); return -1; } } else { cp = Brdline(bp, '\0'); if(cp == 0) { werrstr("can't read symbol name"); return -1; } n = Blinelen(bp); p->name = malloc(n); if(p->name == 0) { werrstr("can't malloc %ld bytes", n); return -1; } strcpy(p->name, cp); } return n;} /* * free any previously loaded symbol tables */static voidcleansyms(void){ if(globals) free(globals); globals = 0; nglob = 0; if(txt) free(txt); txt = 0; ntxt = 0; if(fnames) free(fnames); fnames = 0; fpmax = 0; if(files) free(files); files = 0; nfiles = 0; if(hist) free(hist); hist = 0; nhist = 0; if(autos) free(autos); autos = 0; nauto = 0; isbuilt = 0; if(symbols) free(symbols); symbols = 0; nsym = 0; if(spoff) free(spoff); spoff = 0; if(pcline) free(pcline); pcline = 0;} /* * delimit the text segment */voidtextseg(uvlong base, Fhdr *fp){ txtstart = base; txtend = base+fp->txtsz;} /* * symbase: return base and size of raw symbol table * (special hack for high access rate operations) */Sym *symbase(long *n){ *n = nsym; return symbols;} /* * Get the ith symbol table entry */Sym *getsym(int index){ if(index >= 0 && index < nsym) return &symbols[index]; return 0;} /* * initialize internal symbol tables */static intbuildtbls(void){ long i; int j, nh, ng, nt; File *f; Txtsym *tp; Hist *hp; Sym *p, **ap; if(isbuilt) return 1; isbuilt = 1; /* allocate the tables */ if(nglob) { globals = malloc(nglob*sizeof(*globals)); if(!globals) { werrstr("can't malloc global symbol table"); return 0; } } if(ntxt) { txt = malloc(ntxt*sizeof(*txt)); if (!txt) { werrstr("can't malloc text symbol table"); return 0; } } fnames = malloc((fpmax+1)*sizeof(*fnames)); if (!fnames) { werrstr("can't malloc file name table"); return 0; } memset(fnames, 0, (fpmax+1)*sizeof(*fnames)); files = malloc(nfiles*sizeof(*files)); if(!files) { werrstr("can't malloc file table"); return 0; } hist = malloc(nhist*sizeof(Hist)); if(hist == 0) { werrstr("can't malloc history stack"); return 0; } autos = malloc(nauto*sizeof(Sym*)); if(autos == 0) { werrstr("can't malloc auto symbol table"); return 0; } /* load the tables */ ng = nt = nh = 0; f = 0; tp = 0; i = nsym; hp = hist; ap = autos; for(p = symbols; i-- > 0; p++) { switch(p->type) { case 'D': case 'd': case 'B': case 'b': if(debug) print("Global: %s %llux\n", p->name, p->value); globals[ng++] = p; break; case 'z': if(p->value == 1) { /* New file */ if(f) { f->n = nh; f->hist[nh].name = 0; /* one extra */ hp += nh+1; f++; } else f = files; f->hist = hp; f->sym = 0; f->addr = 0; nh = 0; } /* alloc one slot extra as terminator */ f->hist[nh].name = p->name; f->hist[nh].line = p->value; f->hist[nh].offset = 0; if(debug) printhist("-> ", &f->hist[nh], 1); nh++; break; case 'Z': if(f && nh > 0) f->hist[nh-1].offset = p->value; break; case 'T': case 't': /* Text: terminate history if first in file */ case 'L': case 'l': tp = &txt[nt++]; tp->n = 0; tp->sym = p; tp->locals = ap; if(debug) print("TEXT: %s at %llux\n", p->name, p->value); if(f && !f->sym) { /* first */ f->sym = p; f->addr = p->value; } break; case 'a': case 'p': case 'm': /* Local Vars */ if(!tp) print("Warning: Free floating local var: %s\n", p->name); else { if(debug) print("Local: %s %llux\n", p->name, p->value); tp->locals[tp->n] = p; tp->n++; ap++; } break; case 'f': /* File names */ if(debug) print("Fname: %s\n", p->name); fnames[p->value] = p; break; default: break; } } /* sort global and text tables into ascending address order */ qsort(globals, nglob, sizeof(Sym*), symcomp); qsort(txt, ntxt, sizeof(Txtsym), txtcomp); qsort(files, nfiles, sizeof(File), filecomp); tp = txt; for(i = 0, f = files; i < nfiles; i++, f++) { for(j = 0; j < ntxt; j++) { if(f->sym == tp->sym) { if(debug) { print("LINK: %s to at %llux", f->sym->name, f->addr); printhist("... ", f->hist, 1); } f->txt = tp++; break; } if(++tp >= txt+ntxt) /* wrap around */ tp = txt; } } return 1;} /*Lines 1–500 of 1375. Load more
#include <lib9.h> #include <bio.h> #include "mach.h" #define HUGEINT 0x7fffffff #define NNAME 20 /* a relic of the past */ typedef struct txtsym Txtsym; typedef struct file File; typedef struct hist Hist; struct txtsym { /* Text Symbol table */ int n; /* number of local vars */ Sym **locals; /* array of ptrs to autos */ Sym *sym; /* function symbol entry */ }; struct hist { /* Stack of include files & #line directives */ char *name; /* Assumes names Null terminated in file */ long line; /* line # where it was included */ long offset; /* line # of #line directive */ }; struct file { /* Per input file header to history stack */ uvlong addr; /* address of first text sym */ /* union { */ Txtsym *txt; /* first text symbol */ Sym *sym; /* only during initilization */ /* }; */ int n; /* size of history stack */ Hist *hist; /* history stack */ }; static int debug = 0; static Sym **autos; /* Base of auto variables */ static File *files; /* Base of file arena */ static int fpmax; /* largest file path index */ static Sym **fnames; /* file names path component table */ static Sym **globals; /* globals by addr table */ static Hist *hist; /* base of history stack */ static int isbuilt; /* internal table init flag */ static long nauto; /* number of automatics */ static long nfiles; /* number of files */ static long nglob; /* number of globals */ static long nhist; /* number of history stack entries */ static long nsym; /* number of symbols */ static int ntxt; /* number of text symbols */ static uchar *pcline; /* start of pc-line state table */ static uchar *pclineend; /* end of pc-line table */ static uchar *spoff; /* start of pc-sp state table */ static uchar *spoffend; /* end of pc-sp offset table */ static Sym *symbols; /* symbol table */ static Txtsym *txt; /* Base of text symbol table */ static uvlong txtstart; /* start of text segment */ static uvlong txtend; /* end of text segment */ static void cleansyms(void); static long decodename(Biobuf*, Sym*); static short *encfname(char*); static int fline(char*, int, long, Hist*, Hist**); static void fillsym(Sym*, Symbol*); static int findglobal(char*, Symbol*); static int findlocvar(Symbol*, char *, Symbol*); static int findtext(char*, Symbol*); static int hcomp(Hist*, short*); static int hline(File*, short*, long*); static void printhist(char*, Hist*, int); static int buildtbls(void); static int symcomp(void*, void*); static int symerrmsg(int, char*); static int txtcomp(void*, void*); static int filecomp(void*, void*); /* * initialize the symbol tables */ int syminit(int fd, Fhdr *fp) { Sym *p; long i, l, size; vlong vl; Biobuf b; int svalsz; if(fp->symsz == 0) return 0; if(fp->type == FNONE) return 0; cleansyms(); textseg(fp->txtaddr, fp); /* minimum symbol record size = 4+1+2 bytes */ symbols = malloc((fp->symsz/(4+1+2)+1)*sizeof(Sym)); if(symbols == 0) { werrstr("can't malloc %ld bytes", fp->symsz); return -1; } Binit(&b, fd, OREAD); Bseek(&b, fp->symoff, 0); nsym = 0; size = 0; for(p = symbols; size < fp->symsz; p++, nsym++) { if(fp->_magic && (fp->magic & HDR_MAGIC)){ svalsz = 8; if(Bread(&b, &vl, 8) != 8) return symerrmsg(8, "symbol"); p->value = beswav(vl); } else{ svalsz = 4; if(Bread(&b, &l, 4) != 4) return symerrmsg(4, "symbol"); p->value = (u32int)beswal(l); } if(Bread(&b, &p->type, sizeof(p->type)) != sizeof(p->type)) return symerrmsg(sizeof(p->value), "symbol"); i = decodename(&b, p); if(i < 0) return -1; size += i+svalsz+sizeof(p->type); /* count global & auto vars, text symbols, and file names */ switch (p->type) { case 'l': case 'L': case 't': case 'T': ntxt++; break; case 'd': case 'D': case 'b': case 'B': nglob++; break; case 'f': if(strcmp(p->name, ".frame") == 0) { p->type = 'm'; nauto++; } else if(p->value > fpmax) fpmax = p->value; /* highest path index */ break; case 'a': case 'p': case 'm': nauto++; break; case 'z': if(p->value == 1) { /* one extra per file */ nhist++; nfiles++; } nhist++; break; default: break; } } if (debug) print("NG: %ld NT: %d NF: %d\n", nglob, ntxt, fpmax); if (fp->sppcsz) { /* pc-sp offset table */ spoff = (uchar *)malloc(fp->sppcsz); if(spoff == 0) { werrstr("can't malloc %ld bytes", fp->sppcsz); return -1; } Bseek(&b, fp->sppcoff, 0); if(Bread(&b, spoff, fp->sppcsz) != fp->sppcsz){ spoff = 0; return symerrmsg(fp->sppcsz, "sp-pc"); } spoffend = spoff+fp->sppcsz; } if (fp->lnpcsz) { /* pc-line number table */ pcline = (uchar *)malloc(fp->lnpcsz); if(pcline == 0) { werrstr("can't malloc %ld bytes", fp->lnpcsz); return -1; } Bseek(&b, fp->lnpcoff, 0); if(Bread(&b, pcline, fp->lnpcsz) != fp->lnpcsz){ pcline = 0; return symerrmsg(fp->lnpcsz, "pc-line"); } pclineend = pcline+fp->lnpcsz; } if(fp->type == FARM) /* thumb pc table */ thumbpctab(&b, fp); return nsym; } static int symerrmsg(int n, char *table) { werrstr("can't read %d bytes of %s table", n, table); return -1; } static long decodename(Biobuf *bp, Sym *p) { char *cp; int c1, c2; long n; vlong o; if((p->type & 0x80) == 0) { /* old-style, fixed length names */ p->name = malloc(NNAME); if(p->name == 0) { werrstr("can't malloc %d bytes", NNAME); return -1; } if(Bread(bp, p->name, NNAME) != NNAME) return symerrmsg(NNAME, "symbol"); Bseek(bp, 3, 1); return NNAME+3; } p->type &= ~0x80; if(p->type == 'z' || p->type == 'Z') { o = Bseek(bp, 0, 1); if(Bgetc(bp) < 0) { werrstr("can't read symbol name"); return -1; } for(;;) { c1 = Bgetc(bp); c2 = Bgetc(bp); if(c1 < 0 || c2 < 0) { werrstr("can't read symbol name"); return -1; } if(c1 == 0 && c2 == 0) break; } n = Bseek(bp, 0, 1)-o; p->name = malloc(n); if(p->name == 0) { werrstr("can't malloc %ld bytes", n); return -1; } Bseek(bp, -n, 1); if(Bread(bp, p->name, n) != n) { werrstr("can't read %ld bytes of symbol name", n); return -1; } } else { cp = Brdline(bp, '\0'); if(cp == 0) { werrstr("can't read symbol name"); return -1; } n = Blinelen(bp); p->name = malloc(n); if(p->name == 0) { werrstr("can't malloc %ld bytes", n); return -1; } strcpy(p->name, cp); } return n; } /* * free any previously loaded symbol tables */ static void cleansyms(void) { if(globals) free(globals); globals = 0; nglob = 0; if(txt) free(txt); txt = 0; ntxt = 0; if(fnames) free(fnames); fnames = 0; fpmax = 0; if(files) free(files); files = 0; nfiles = 0; if(hist) free(hist); hist = 0; nhist = 0; if(autos) free(autos); autos = 0; nauto = 0; isbuilt = 0; if(symbols) free(symbols); symbols = 0; nsym = 0; if(spoff) free(spoff); spoff = 0; if(pcline) free(pcline); pcline = 0; } /* * delimit the text segment */ void textseg(uvlong base, Fhdr *fp) { txtstart = base; txtend = base+fp->txtsz; } /* * symbase: return base and size of raw symbol table * (special hack for high access rate operations) */ Sym * symbase(long *n) { *n = nsym; return symbols; } /* * Get the ith symbol table entry */ Sym * getsym(int index) { if(index >= 0 && index < nsym) return &symbols[index]; return 0; } /* * initialize internal symbol tables */ static int buildtbls(void) { long i; int j, nh, ng, nt; File *f; Txtsym *tp; Hist *hp; Sym *p, **ap; if(isbuilt) return 1; isbuilt = 1; /* allocate the tables */ if(nglob) { globals = malloc(nglob*sizeof(*globals)); if(!globals) { werrstr("can't malloc global symbol table"); return 0; } } if(ntxt) { txt = malloc(ntxt*sizeof(*txt)); if (!txt) { werrstr("can't malloc text symbol table"); return 0; } } fnames = malloc((fpmax+1)*sizeof(*fnames)); if (!fnames) { werrstr("can't malloc file name table"); return 0; } memset(fnames, 0, (fpmax+1)*sizeof(*fnames)); files = malloc(nfiles*sizeof(*files)); if(!files) { werrstr("can't malloc file table"); return 0; } hist = malloc(nhist*sizeof(Hist)); if(hist == 0) { werrstr("can't malloc history stack"); return 0; } autos = malloc(nauto*sizeof(Sym*)); if(autos == 0) { werrstr("can't malloc auto symbol table"); return 0; } /* load the tables */ ng = nt = nh = 0; f = 0; tp = 0; i = nsym; hp = hist; ap = autos; for(p = symbols; i-- > 0; p++) { switch(p->type) { case 'D': case 'd': case 'B': case 'b': if(debug) print("Global: %s %llux\n", p->name, p->value); globals[ng++] = p; break; case 'z': if(p->value == 1) { /* New file */ if(f) { f->n = nh; f->hist[nh].name = 0; /* one extra */ hp += nh+1; f++; } else f = files; f->hist = hp; f->sym = 0; f->addr = 0; nh = 0; } /* alloc one slot extra as terminator */ f->hist[nh].name = p->name; f->hist[nh].line = p->value; f->hist[nh].offset = 0; if(debug) printhist("-> ", &f->hist[nh], 1); nh++; break; case 'Z': if(f && nh > 0) f->hist[nh-1].offset = p->value; break; case 'T': case 't': /* Text: terminate history if first in file */ case 'L': case 'l': tp = &txt[nt++]; tp->n = 0; tp->sym = p; tp->locals = ap; if(debug) print("TEXT: %s at %llux\n", p->name, p->value); if(f && !f->sym) { /* first */ f->sym = p; f->addr = p->value; } break; case 'a': case 'p': case 'm': /* Local Vars */ if(!tp) print("Warning: Free floating local var: %s\n", p->name); else { if(debug) print("Local: %s %llux\n", p->name, p->value); tp->locals[tp->n] = p; tp->n++; ap++; } break; case 'f': /* File names */ if(debug) print("Fname: %s\n", p->name); fnames[p->value] = p; break; default: break; } } /* sort global and text tables into ascending address order */ qsort(globals, nglob, sizeof(Sym*), symcomp); qsort(txt, ntxt, sizeof(Txtsym), txtcomp); qsort(files, nfiles, sizeof(File), filecomp); tp = txt; for(i = 0, f = files; i < nfiles; i++, f++) { for(j = 0; j < ntxt; j++) { if(f->sym == tp->sym) { if(debug) { print("LINK: %s to at %llux", f->sym->name, f->addr); printhist("... ", f->hist, 1); } f->txt = tp++; break; } if(++tp >= txt+ntxt) /* wrap around */ tp = txt; } } return 1; } /*