plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }