URI:
       tsym.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tsym.c (9957B)
       ---
            1 #include <u.h>
            2 #include <libc.h>
            3 #include <bio.h>
            4 #include <mach.h>
            5 
            6 int machdebug = 0;
            7 
            8 Fhdr *fhdrlist;
            9 static Fhdr *last;
           10 
           11 static void
           12 relocsym(Symbol *dst, Symbol *src, ulong base)
           13 {
           14         if(dst != src)
           15                 *dst = *src;
           16         if(dst->loc.type == LADDR)
           17                 dst->loc.addr += base;
           18         if(dst->hiloc.type == LADDR)
           19                 dst->hiloc.addr += base;
           20 }
           21 
           22 void
           23 _addhdr(Fhdr *h)
           24 {
           25         h->next = nil;
           26         if(fhdrlist == nil){
           27                 fhdrlist = h;
           28                 last = h;
           29         }else{
           30                 last->next = h;
           31                 last = h;
           32         }
           33 }
           34 
           35 void
           36 _delhdr(Fhdr *h)
           37 {
           38         Fhdr *p;
           39 
           40         if(h == fhdrlist)
           41                 fhdrlist = h->next;
           42         else{
           43                 for(p=fhdrlist; p && p->next!=h; p=p->next)
           44                         ;
           45                 if(p){
           46                         p->next = h->next;
           47                         if(p->next == nil)
           48                                 last = p;
           49                 }
           50         }
           51         h->next = nil;
           52 }
           53 
           54 Fhdr*
           55 findhdr(char *name)
           56 {
           57         int len, plen;
           58         Fhdr *p;
           59 
           60         len = strlen(name);
           61         for(p=fhdrlist; p; p=p->next){
           62                 plen = strlen(p->filename);
           63                 if(plen >= len)
           64                 if(strcmp(p->filename+plen-len, name) == 0)
           65                 if(plen == len || p->filename[plen-len-1] == '/')
           66                         return p;
           67         }
           68         return nil;
           69 }
           70 
           71 int
           72 pc2file(u64int pc, char *file, uint nfile, ulong *line)
           73 {
           74         Fhdr *p;
           75 
           76         for(p=fhdrlist; p; p=p->next)
           77                 if(p->pc2file && p->pc2file(p, pc-p->base, file, nfile, line) >= 0)
           78                         return 0;
           79         werrstr("no source file for 0x%lux", pc);
           80         return -1;
           81 }
           82 
           83 int
           84 pc2line(u64int pc, ulong *line)
           85 {
           86         char tmp[10];        /* just in case */
           87         return pc2file(pc, tmp, sizeof tmp, line);
           88 }
           89 
           90 int
           91 file2pc(char *file, ulong line, u64int *addr)
           92 {
           93         Fhdr *p;
           94 
           95         for(p=fhdrlist; p; p=p->next)
           96                 if(p->file2pc && p->file2pc(p, file, line, addr) >= 0){
           97                         *addr += p->base;
           98                         return 0;
           99                 }
          100         werrstr("no instructions at %s:%lud", file, line);
          101         return -1;
          102 }
          103 
          104 int
          105 line2pc(u64int basepc, ulong line, u64int *pc)
          106 {
          107         Fhdr *p;
          108 
          109         for(p=fhdrlist; p; p=p->next)
          110                 if(p->line2pc && p->line2pc(p, basepc-p->base, line, pc) >= 0){
          111                         *pc += p->base;
          112                         return 0;
          113                 }
          114         werrstr("no instructions on line %lud", line);
          115         return -1;
          116 }
          117 
          118 int
          119 fnbound(u64int pc, u64int *bounds)
          120 {
          121         Fhdr *p;
          122         Loc l;
          123         Symbol *s;
          124 
          125         for(p=fhdrlist; p; p=p->next){
          126                 l = locaddr(pc - p->base);
          127                 if((s = ffindsym(p, l, CANY)) != nil){
          128                         if(s->loc.type != LADDR){
          129                                 werrstr("function %s has weird location %L", s->name, s->loc);
          130                                 return -1;
          131                         }
          132                         bounds[0] = s->loc.addr + p->base;
          133                         if(s->hiloc.type != LADDR){
          134                                 werrstr("can't find upper bound for function %s", s->name);
          135                                 return -1;
          136                         }
          137                         bounds[1] = s->hiloc.addr + p->base;
          138                         return 0;
          139                 }
          140         }
          141         werrstr("no function contains 0x%lux", pc);
          142         return -1;
          143 }
          144 
          145 int
          146 fileline(u64int pc, char *a, uint n)
          147 {
          148         ulong line;
          149 
          150         if(pc2file(pc, a, n, &line) < 0)
          151                 return -1;
          152         seprint(a+strlen(a), a+n, ":%lud", line);
          153         return 0;
          154 }
          155 
          156 Symbol*
          157 flookupsym(Fhdr *fhdr, char *name)
          158 {
          159         Symbol **a, *t;
          160         uint n, m;
          161         int i;
          162 
          163         a = fhdr->byname;
          164         n = fhdr->nsym;
          165         if(a == nil)
          166                 return nil;
          167 
          168         while(n > 0){
          169                 m = n/2;
          170                 t = a[m];
          171                 i = strcmp(name, t->name);
          172                 if(i < 0)
          173                         n = m;
          174                 else if(i > 0){
          175                         n -= m+1;
          176                         a += m+1;
          177                 }else{
          178                         /* found! */
          179                         m += a - fhdr->byname;
          180                         a = fhdr->byname;
          181                         assert(strcmp(name, a[m]->name) == 0);
          182                         while(m > 0 && strcmp(name, a[m-1]->name) == 0)
          183                                 m--;
          184                         return a[m];
          185                 }
          186         }
          187         return nil;
          188 }
          189 
          190 Symbol*
          191 flookupsymx(Fhdr *fhdr, char *name)
          192 {
          193         Symbol **a, *t;
          194         uint n, m;
          195         int i;
          196 
          197         a = fhdr->byxname;
          198         n = fhdr->nsym;
          199         if(a == nil)
          200                 return nil;
          201 
          202         while(n > 0){
          203                 m = n/2;
          204                 t = a[m];
          205                 i = strcmp(name, t->xname);
          206                 if(i < 0)
          207                         n = m;
          208                 else if(i > 0){
          209                         n -= m+1;
          210                         a += m+1;
          211                 }else{
          212                         /* found! */
          213                         m += a - fhdr->byxname;
          214                         a = fhdr->byxname;
          215                         assert(strcmp(name, a[m]->xname) == 0);
          216                         while(m > 0 && strcmp(name, a[m-1]->xname) == 0)
          217                                 m--;
          218                         return a[m];
          219                 }
          220         }
          221         return nil;
          222 }
          223 
          224 int
          225 lookupsym(char *fn, char *var, Symbol *s)
          226 {
          227         Symbol *t, s1;
          228         Fhdr *p;
          229         char *nam;
          230 
          231         nam = fn ? fn : var;
          232         if(nam == nil)
          233                 return -1;
          234         t = nil;
          235         for(p=fhdrlist; p; p=p->next)
          236                 if((t=flookupsym(p, nam)) != nil
          237                 || (t=flookupsymx(p, nam)) != nil){
          238                         relocsym(&s1, t, p->base);
          239                         break;
          240                 }
          241 
          242         if(t == nil)
          243                 goto err;
          244         if(fn && var)
          245                 return lookuplsym(&s1, var, s);
          246         *s = s1;
          247         return 0;
          248 
          249 err:
          250         werrstr("unknown symbol %s%s%s", fn ? fn : "",
          251                 fn && var ? ":" : "", var ? var : "");
          252         return -1;
          253 }
          254 
          255 int
          256 findexsym(Fhdr *fp, uint i, Symbol *s)
          257 {
          258         if(i >= fp->nsym)
          259                 return -1;
          260         relocsym(s, &fp->sym[i], fp->base);
          261         return 0;
          262 }
          263 
          264 int
          265 indexsym(uint ndx, Symbol *s)
          266 {
          267         uint t;
          268         Fhdr *p;
          269 
          270         for(p=fhdrlist; p; p=p->next){
          271                 t = p->nsym;
          272                 if(t < ndx)
          273                         ndx -= t;
          274                 else{
          275                         relocsym(s, &p->sym[ndx], p->base);
          276                         return 0;
          277                 }
          278         }
          279         return -1;
          280 }
          281 
          282 Symbol*
          283 ffindsym(Fhdr *fhdr, Loc loc, uint class)
          284 {
          285         Symbol *a, *t;
          286         int n, i, hi, lo;
          287         int cmp;
          288 
          289         a = fhdr->sym;
          290         n = fhdr->nsym;
          291         if(a == nil || n <= 0)
          292                 return nil;
          293 
          294         /*
          295          * We have a list of possibly duplicate locations in a.
          296          * We want to find the largest index i such that
          297          * a[i] <= loc.  This cannot be done with a simple
          298          * binary search.  Instead we binary search to find
          299          * where the location should be.
          300          */
          301         lo = 0;
          302         hi = n;
          303         while(lo < hi){
          304                 i = (lo+hi)/2;
          305                 cmp = loccmp(&loc, &a[i].loc);
          306                 if(cmp < 0)        /* loc < a[i].loc */
          307                         hi = i;
          308                 if(cmp > 0)        /* loc > a[i].loc */
          309                         lo = i+1;
          310                 if(cmp == 0)
          311                         goto found;
          312         }
          313 
          314         /* found position where value would go, but not there -- go back one */
          315         if(lo == 0)
          316                 return nil;
          317         i = lo-1;
          318 
          319 found:
          320         /*
          321          * might be in a run of all-the-same -- go back to beginning of run.
          322          * if runs were long, could binary search for a[i].loc instead.
          323          */
          324         while(i > 0 && loccmp(&a[i-1].loc, &a[i].loc) == 0)
          325                 i--;
          326 
          327         t = &a[i];
          328         if(t->hiloc.type && loccmp(&loc, &t->hiloc) >= 0)
          329                 return nil;
          330         if(class != CANY && class != t->class)
          331                 return nil;
          332         return t;
          333 }
          334 
          335 int
          336 findsym(Loc loc, uint class, Symbol *s)
          337 {
          338         Fhdr *p, *bestp;
          339         Symbol *t, *best;
          340         long bestd, d;
          341         Loc l;
          342 
          343         l = loc;
          344         best = nil;
          345         bestp = nil;
          346         bestd = 0;
          347         for(p=fhdrlist; p; p=p->next){
          348                 if(l.type == LADDR)
          349                         l.addr = loc.addr - p->base;
          350                 if((t = ffindsym(p, l, CANY)) != nil){
          351                         d = l.addr - t->loc.addr;
          352                         if(0 <= d && d < 4096)
          353                         if(best == nil || d < bestd){
          354                                 best = t;
          355                                 bestp = p;
          356                                 bestd = d;
          357                         }
          358                 }
          359         }
          360         if(best){
          361                 if(class != CANY && class != best->class)
          362                         goto err;
          363                 relocsym(s, best, bestp->base);
          364                 return 0;
          365         }
          366 err:
          367         werrstr("could not find symbol at %L", loc);
          368         return -1;
          369 }
          370 
          371 int
          372 lookuplsym(Symbol *s1, char *name, Symbol *s2)
          373 {
          374         Fhdr *p;
          375 
          376         p = s1->fhdr;
          377         if(p->lookuplsym && p->lookuplsym(p, s1, name, s2) >= 0){
          378                 relocsym(s2, s2, p->base);
          379                 return 0;
          380         }
          381         return -1;
          382 }
          383 
          384 int
          385 indexlsym(Symbol *s1, uint ndx, Symbol *s2)
          386 {
          387         Fhdr *p;
          388 
          389         p = s1->fhdr;
          390         if(p->indexlsym && p->indexlsym(p, s1, ndx, s2) >= 0){
          391                 relocsym(s2, s2, p->base);
          392                 return 0;
          393         }
          394         return -1;
          395 }
          396 
          397 int
          398 findlsym(Symbol *s1, Loc loc, Symbol *s2)
          399 {
          400         Fhdr *p;
          401 
          402         p = s1->fhdr;
          403         if(p->findlsym && p->findlsym(p, s1, loc, s2) >= 0){
          404                 relocsym(s2, s2, p->base);
          405                 return 0;
          406         }
          407         return -1;
          408 }
          409 
          410 int
          411 unwindframe(Map *map, Regs *regs, u64int *next, Symbol *sym)
          412 {
          413         Fhdr *p;
          414 
          415         for(p=fhdrlist; p; p=p->next)
          416                 if(p->unwind && p->unwind(p, map, regs, next, sym) >= 0)
          417                         return 0;
          418         if(mach->unwind && mach->unwind(map, regs, next, sym) >= 0)
          419                 return 0;
          420         return -1;
          421 }
          422 
          423 int
          424 symoff(char *a, uint n, u64int addr, uint class)
          425 {
          426         Loc l;
          427         Symbol s;
          428 
          429         l.type = LADDR;
          430         l.addr = addr;
          431         if(findsym(l, class, &s) < 0 || addr-s.loc.addr >= 4096){
          432                 snprint(a, n, "%#lux", addr);
          433                 return -1;
          434         }
          435         if(addr != s.loc.addr)
          436                 snprint(a, n, "%s+%#lx", s.name, addr-s.loc.addr);
          437         else
          438                 snprint(a, n, "%s", s.name);
          439         return 0;
          440 }
          441 
          442 /* location, class, name */
          443 static int
          444 byloccmp(const void *va, const void *vb)
          445 {
          446         int i;
          447         Symbol *a, *b;
          448 
          449         a = (Symbol*)va;
          450         b = (Symbol*)vb;
          451         i = loccmp(&a->loc, &b->loc);
          452         if(i != 0)
          453                 return i;
          454         i = a->class - b->class;
          455         if(i != 0)
          456                 return i;
          457         return strcmp(a->name, b->name);
          458 }
          459 
          460 /* name, location, class */
          461 static int
          462 byxnamecmp(const void *va, const void *vb)
          463 {
          464         int i;
          465         Symbol *a, *b;
          466 
          467         a = *(Symbol**)va;
          468         b = *(Symbol**)vb;
          469         i = strcmp(a->xname, b->xname);
          470         if(i != 0)
          471                 return i;
          472         i = strcmp(a->name, b->name);
          473         if(i != 0)
          474                 return i;
          475         i = loccmp(&a->loc, &b->loc);
          476         if(i != 0)
          477                 return i;
          478         return a->class - b->class;
          479 }
          480 
          481 /* name, location, class */
          482 static int
          483 bynamecmp(const void *va, const void *vb)
          484 {
          485         int i;
          486         Symbol *a, *b;
          487 
          488         a = *(Symbol**)va;
          489         b = *(Symbol**)vb;
          490         i = strcmp(a->name, b->name);
          491         if(i != 0)
          492                 return i;
          493         i = loccmp(&a->loc, &b->loc);
          494         if(i != 0)
          495                 return i;
          496         return a->class - b->class;
          497 }
          498 
          499 int
          500 symopen(Fhdr *hdr)
          501 {
          502         int i;
          503         Symbol *r, *w, *es;
          504 
          505         if(hdr->syminit == 0){
          506                 werrstr("no debugging symbols");
          507                 return -1;
          508         }
          509         if(hdr->syminit(hdr) < 0)
          510                 return -1;
          511 
          512         qsort(hdr->sym, hdr->nsym, sizeof(hdr->sym[0]), byloccmp);
          513         es = hdr->sym+hdr->nsym;
          514         for(r=w=hdr->sym; r<es; r++){
          515                 if(w > hdr->sym
          516                 && strcmp((w-1)->name, r->name) ==0
          517                 && loccmp(&(w-1)->loc, &r->loc) == 0){
          518                         /* skip it */
          519                 }else
          520                         *w++ = *r;
          521         }
          522         hdr->nsym = w - hdr->sym;
          523 
          524         hdr->byname = malloc(hdr->nsym*sizeof(hdr->byname[0]));
          525         if(hdr->byname == nil){
          526                 fprint(2, "could not allocate table to sort by name\n");
          527         }else{
          528                 for(i=0; i<hdr->nsym; i++)
          529                         hdr->byname[i] = &hdr->sym[i];
          530                 qsort(hdr->byname, hdr->nsym, sizeof(hdr->byname[0]), bynamecmp);
          531         }
          532 
          533         hdr->byxname = malloc(hdr->nsym*sizeof(hdr->byxname[0]));
          534         if(hdr->byxname == nil){
          535                 fprint(2, "could not allocate table to sort by xname\n");
          536         }else{
          537                 for(i=0; i<hdr->nsym; i++)
          538                         hdr->byxname[i] = &hdr->sym[i];
          539                 qsort(hdr->byxname, hdr->nsym, sizeof(hdr->byxname[0]), byxnamecmp);
          540         }
          541         return 0;
          542 }
          543 
          544 void
          545 symclose(Fhdr *hdr)
          546 {
          547         _delhdr(hdr);
          548         if(hdr->symclose)
          549                 hdr->symclose(hdr);
          550         free(hdr->byname);
          551         hdr->byname = nil;
          552         free(hdr->sym);
          553         hdr->sym = nil;
          554         hdr->nsym = 0;
          555 }
          556 
          557 Symbol*
          558 _addsym(Fhdr *fp, Symbol *sym)
          559 {
          560         char *t;
          561         static char buf[65536];
          562         Symbol *s;
          563 
          564         if(fp->nsym%128 == 0){
          565                 s = realloc(fp->sym, (fp->nsym+128)*sizeof(fp->sym[0]));
          566                 if(s == nil)
          567                         return nil;
          568                 fp->sym = s;
          569         }
          570         if(machdebug)
          571                 fprint(2, "sym %s %c %L\n", sym->name, sym->type, sym->loc);
          572         sym->fhdr = fp;
          573         t = demangle(sym->name, buf, 1);
          574         if(t != sym->name){
          575                 t = strdup(t);
          576                 if(t == nil)
          577                         return nil;
          578         }
          579         sym->xname = t;
          580         s = &fp->sym[fp->nsym++];
          581         *s = *sym;
          582         return s;
          583 }