Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
6 int machdebug = 0;
8 Fhdr *fhdrlist;
9 static Fhdr *last;
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 }
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 }
35 void
36 _delhdr(Fhdr *h)
37 {
38 Fhdr *p;
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 }
54 Fhdr*
55 findhdr(char *name)
56 {
57 int len, plen;
58 Fhdr *p;
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 }
71 int
72 pc2file(u64int pc, char *file, uint nfile, ulong *line)
73 {
74 Fhdr *p;
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 }
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 }
90 int
91 file2pc(char *file, ulong line, u64int *addr)
92 {
93 Fhdr *p;
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;
104 int
105 line2pc(u64int basepc, ulong line, u64int *pc)
107 Fhdr *p;
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;
114 werrstr("no instructions on line %lud", line);
115 return -1;
118 int
119 fnbound(u64int pc, u64int *bounds)
121 Fhdr *p;
122 Loc l;
123 Symbol *s;
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;
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;
137 bounds[1] = s->hiloc.addr + p->base;
138 return 0;
141 werrstr("no function contains 0x%lux", pc);
142 return -1;
145 int
146 fileline(u64int pc, char *a, uint n)
148 ulong line;
150 if(pc2file(pc, a, n, &line) < 0)
151 return -1;
152 seprint(a+strlen(a), a+n, ":%lud", line);
153 return 0;
156 Symbol*
157 flookupsym(Fhdr *fhdr, char *name)
159 Symbol **a, *t;
160 uint n, m;
161 int i;
163 a = fhdr->byname;
164 n = fhdr->nsym;
165 if(a == nil)
166 return nil;
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];
187 return nil;
190 Symbol*
191 flookupsymx(Fhdr *fhdr, char *name)
193 Symbol **a, *t;
194 uint n, m;
195 int i;
197 a = fhdr->byxname;
198 n = fhdr->nsym;
199 if(a == nil)
200 return nil;
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];
221 return nil;
224 int
225 lookupsym(char *fn, char *var, Symbol *s)
227 Symbol *t, s1;
228 Fhdr *p;
229 char *nam;
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;
242 if(t == nil)
243 goto err;
244 if(fn && var)
245 return lookuplsym(&s1, var, s);
246 *s = s1;
247 return 0;
249 err:
250 werrstr("unknown symbol %s%s%s", fn ? fn : "",
251 fn && var ? ":" : "", var ? var : "");
252 return -1;
255 int
256 findexsym(Fhdr *fp, uint i, Symbol *s)
258 if(i >= fp->nsym)
259 return -1;
260 relocsym(s, &fp->sym[i], fp->base);
261 return 0;
264 int
265 indexsym(uint ndx, Symbol *s)
267 uint t;
268 Fhdr *p;
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;
279 return -1;
282 Symbol*
283 ffindsym(Fhdr *fhdr, Loc loc, uint class)
285 Symbol *a, *t;
286 int n, i, hi, lo;
287 int cmp;
289 a = fhdr->sym;
290 n = fhdr->nsym;
291 if(a == nil || n <= 0)
292 return nil;
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;
314 /* found position where value would go, but not there -- go back one */
315 if(lo == 0)
316 return nil;
317 i = lo-1;
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--;
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;
335 int
336 findsym(Loc loc, uint class, Symbol *s)
338 Fhdr *p, *bestp;
339 Symbol *t, *best;
340 long bestd, d;
341 Loc l;
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;
360 if(best){
361 if(class != CANY && class != best->class)
362 goto err;
363 relocsym(s, best, bestp->base);
364 return 0;
366 err:
367 werrstr("could not find symbol at %L", loc);
368 return -1;
371 int
372 lookuplsym(Symbol *s1, char *name, Symbol *s2)
374 Fhdr *p;
376 p = s1->fhdr;
377 if(p->lookuplsym && p->lookuplsym(p, s1, name, s2) >= 0){
378 relocsym(s2, s2, p->base);
379 return 0;
381 return -1;
384 int
385 indexlsym(Symbol *s1, uint ndx, Symbol *s2)
387 Fhdr *p;
389 p = s1->fhdr;
390 if(p->indexlsym && p->indexlsym(p, s1, ndx, s2) >= 0){
391 relocsym(s2, s2, p->base);
392 return 0;
394 return -1;
397 int
398 findlsym(Symbol *s1, Loc loc, Symbol *s2)
400 Fhdr *p;
402 p = s1->fhdr;
403 if(p->findlsym && p->findlsym(p, s1, loc, s2) >= 0){
404 relocsym(s2, s2, p->base);
405 return 0;
407 return -1;
410 int
411 unwindframe(Map *map, Regs *regs, u64int *next, Symbol *sym)
413 Fhdr *p;
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;
423 int
424 symoff(char *a, uint n, u64int addr, uint class)
426 Loc l;
427 Symbol s;
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;
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;
442 /* location, class, name */
443 static int
444 byloccmp(const void *va, const void *vb)
446 int i;
447 Symbol *a, *b;
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);
460 /* name, location, class */
461 static int
462 byxnamecmp(const void *va, const void *vb)
464 int i;
465 Symbol *a, *b;
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;
481 /* name, location, class */
482 static int
483 bynamecmp(const void *va, const void *vb)
485 int i;
486 Symbol *a, *b;
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;
499 int
500 symopen(Fhdr *hdr)
502 int i;
503 Symbol *r, *w, *es;
505 if(hdr->syminit == 0){
506 werrstr("no debugging symbols");
507 return -1;
509 if(hdr->syminit(hdr) < 0)
510 return -1;
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;
522 hdr->nsym = w - hdr->sym;
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);
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);
541 return 0;
544 void
545 symclose(Fhdr *hdr)
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;
557 Symbol*
558 _addsym(Fhdr *fp, Symbol *sym)
560 char *t;
561 static char buf[65536];
562 Symbol *s;
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;
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;
579 sym->xname = t;
580 s = &fp->sym[fp->nsym++];
581 *s = *sym;
582 return s;