sym.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 }