blob: 4730fdc19773ffa887e62e39b600894352ccec1b [file] [log] [blame]
rsca84cbb22004-04-19 19:29:25 +00001#include <u.h>
2#include <libc.h>
3#include <bio.h>
4#include <mach.h>
5
6int machdebug = 0;
7
8Fhdr *fhdrlist;
9static Fhdr *last;
10
11static void
12relocsym(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
22void
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
35void
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 ;
rscdd944ec2005-01-23 22:33:04 +000045 if(p){
rsca84cbb22004-04-19 19:29:25 +000046 p->next = h->next;
rscdd944ec2005-01-23 22:33:04 +000047 if(p->next == nil)
48 last = p;
49 }
rsca84cbb22004-04-19 19:29:25 +000050 }
51 h->next = nil;
52}
53
rsc1cc215a2004-12-25 22:03:28 +000054Fhdr*
55findhdr(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
rsca84cbb22004-04-19 19:29:25 +000071int
72pc2file(ulong 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
83int
84pc2line(ulong pc, ulong *line)
85{
86 char tmp[10]; /* just in case */
87 return pc2file(pc, tmp, sizeof tmp, line);
88}
89
90int
91file2pc(char *file, ulong line, ulong *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
104int
105line2pc(ulong basepc, ulong line, ulong *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
118int
119fnbound(ulong pc, ulong *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
145int
146fileline(ulong 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
156Symbol*
157flookupsym(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
190int
191lookupsym(char *fn, char *var, Symbol *s)
192{
193 Symbol *t, s1;
194 Fhdr *p;
195 char *nam;
196
197 nam = fn ? fn : var;
198 if(nam == nil)
199 return -1;
200 t = nil;
201 for(p=fhdrlist; p; p=p->next)
202 if((t=flookupsym(p, nam)) != nil){
203 relocsym(&s1, t, p->base);
204 break;
205 }
206 if(t == nil)
207 goto err;
208 if(fn && var)
209 return lookuplsym(&s1, var, s);
210 *s = s1;
211 return 0;
212
213err:
214 werrstr("unknown symbol %s%s%s", fn ? fn : "",
215 fn && var ? ":" : "", var ? var : "");
216 return -1;
217}
218
219int
220findexsym(Fhdr *fp, uint i, Symbol *s)
221{
222 if(i >= fp->nsym)
223 return -1;
224 relocsym(s, &fp->sym[i], fp->base);
225 return 0;
226}
227
228int
229indexsym(uint ndx, Symbol *s)
230{
231 uint t;
232 Fhdr *p;
233
234 for(p=fhdrlist; p; p=p->next){
235 t = p->nsym;
236 if(t < ndx)
237 ndx -= t;
238 else{
239 relocsym(s, &p->sym[ndx], p->base);
240 return 0;
241 }
242 }
243 return -1;
244}
245
246Symbol*
247ffindsym(Fhdr *fhdr, Loc loc, uint class)
248{
249 Symbol *a, *t;
250 int n, i, hi, lo;
251 int cmp;
252
253 a = fhdr->sym;
254 n = fhdr->nsym;
255 if(a == nil || n <= 0)
256 return nil;
257
258 /*
259 * We have a list of possibly duplicate locations in a.
260 * We want to find the largest index i such that
261 * a[i] <= loc. This cannot be done with a simple
262 * binary search. Instead we binary search to find
263 * where the location should be.
264 */
265 lo = 0;
266 hi = n;
267 while(lo < hi){
268 i = (lo+hi)/2;
269 cmp = loccmp(&loc, &a[i].loc);
270 if(cmp < 0) /* loc < a[i].loc */
271 hi = i;
272 if(cmp > 0) /* loc > a[i].loc */
273 lo = i+1;
274 if(cmp == 0)
275 goto found;
276 }
277
278 /* found position where value would go, but not there -- go back one */
279 if(lo == 0)
280 return nil;
281 i = lo-1;
282
283found:
284 /*
285 * might be in a run of all-the-same -- go back to beginning of run.
286 * if runs were long, could binary search for a[i].loc instead.
287 */
288 while(i > 0 && loccmp(&a[i-1].loc, &a[i].loc) == 0)
289 i--;
290
291 t = &a[i];
292 if(t->hiloc.type && loccmp(&loc, &t->hiloc) >= 0)
293 return nil;
294 if(class != CANY && class != t->class)
295 return nil;
296 return t;
297}
298
299int
300findsym(Loc loc, uint class, Symbol *s)
301{
302 Fhdr *p, *bestp;
303 Symbol *t, *best;
304 long bestd, d;
305 Loc l;
306
307 l = loc;
308 best = nil;
309 bestp = nil;
310 bestd = 0;
311 for(p=fhdrlist; p; p=p->next){
312 if(l.type == LADDR)
313 l.addr = loc.addr - p->base;
314 if((t = ffindsym(p, l, CANY)) != nil){
315 d = l.addr - t->loc.addr;
rsc62c277e2004-04-20 04:33:53 +0000316 if(0 <= d && d < 4096)
rsca84cbb22004-04-19 19:29:25 +0000317 if(best == nil || d < bestd){
318 best = t;
319 bestp = p;
320 bestd = d;
321 }
322 }
323 }
324 if(best){
325 if(class != CANY && class != best->class)
326 goto err;
327 relocsym(s, best, bestp->base);
328 return 0;
329 }
330err:
331 werrstr("could not find symbol at %L", loc);
332 return -1;
333}
334
335int
336lookuplsym(Symbol *s1, char *name, Symbol *s2)
337{
338 Fhdr *p;
339
340 p = s1->fhdr;
341 if(p->lookuplsym && p->lookuplsym(p, s1, name, s2) >= 0){
342 relocsym(s2, s2, p->base);
343 return 0;
344 }
345 return -1;
346}
347
348int
349indexlsym(Symbol *s1, uint ndx, Symbol *s2)
350{
351 Fhdr *p;
352
353 p = s1->fhdr;
354 if(p->indexlsym && p->indexlsym(p, s1, ndx, s2) >= 0){
355 relocsym(s2, s2, p->base);
356 return 0;
357 }
358 return -1;
359}
360
361int
362findlsym(Symbol *s1, Loc loc, Symbol *s2)
363{
364 Fhdr *p;
365
366 p = s1->fhdr;
367 if(p->findlsym && p->findlsym(p, s1, loc, s2) >= 0){
368 relocsym(s2, s2, p->base);
369 return 0;
370 }
371 return -1;
372}
373
374int
rsc1cc215a2004-12-25 22:03:28 +0000375unwindframe(Map *map, Regs *regs, ulong *next, Symbol *sym)
rsca84cbb22004-04-19 19:29:25 +0000376{
377 Fhdr *p;
378
379 for(p=fhdrlist; p; p=p->next)
rsc1cc215a2004-12-25 22:03:28 +0000380 if(p->unwind && p->unwind(p, map, regs, next, sym) >= 0)
rsca84cbb22004-04-19 19:29:25 +0000381 return 0;
rsc1cc215a2004-12-25 22:03:28 +0000382 if(mach->unwind && mach->unwind(map, regs, next, sym) >= 0)
rsca84cbb22004-04-19 19:29:25 +0000383 return 0;
384 return -1;
385}
386
387int
388symoff(char *a, uint n, ulong addr, uint class)
389{
390 Loc l;
391 Symbol s;
392
393 l.type = LADDR;
394 l.addr = addr;
395 if(findsym(l, class, &s) < 0 || addr-s.loc.addr >= 4096){
rscfbca1e12005-02-11 17:01:25 +0000396 snprint(a, n, "%#lux", addr);
rsca84cbb22004-04-19 19:29:25 +0000397 return -1;
398 }
399 if(addr != s.loc.addr)
rscfbca1e12005-02-11 17:01:25 +0000400 snprint(a, n, "%s+%#lx", s.name, addr-s.loc.addr);
rsca84cbb22004-04-19 19:29:25 +0000401 else
402 snprint(a, n, "%s", s.name);
403 return 0;
404}
405
406/* location, class, name */
407static int
408byloccmp(const void *va, const void *vb)
409{
410 int i;
411 Symbol *a, *b;
412
413 a = (Symbol*)va;
414 b = (Symbol*)vb;
415 i = loccmp(&a->loc, &b->loc);
416 if(i != 0)
417 return i;
418 i = a->class - b->class;
419 if(i != 0)
420 return i;
421 return strcmp(a->name, b->name);
422}
423
424/* name, location, class */
425static int
426bynamecmp(const void *va, const void *vb)
427{
428 int i;
429 Symbol *a, *b;
430
431 a = *(Symbol**)va;
432 b = *(Symbol**)vb;
433 i = strcmp(a->name, b->name);
434 if(i != 0)
435 return i;
436 i = loccmp(&a->loc, &b->loc);
437 if(i != 0)
438 return i;
439 return a->class - b->class;
440}
441
442int
rsc39dbe6e2005-01-07 18:45:17 +0000443symopen(Fhdr *hdr)
rsca84cbb22004-04-19 19:29:25 +0000444{
445 int i;
446 Symbol *r, *w, *es;
447
wkja8763862004-07-09 01:54:06 +0000448 if(hdr->syminit == 0){
rsca84cbb22004-04-19 19:29:25 +0000449 werrstr("no debugging symbols");
450 return -1;
451 }
452 if(hdr->syminit(hdr) < 0)
453 return -1;
454
455 qsort(hdr->sym, hdr->nsym, sizeof(hdr->sym[0]), byloccmp);
456 es = hdr->sym+hdr->nsym;
457 for(r=w=hdr->sym; r<es; r++){
458 if(w > hdr->sym
459 && strcmp((w-1)->name, r->name) ==0
460 && loccmp(&(w-1)->loc, &r->loc) == 0){
461 /* skip it */
462 }else
463 *w++ = *r;
464 }
465 hdr->nsym = w - hdr->sym;
466
467 hdr->byname = malloc(hdr->nsym*sizeof(hdr->byname[0]));
468 if(hdr->byname == nil){
469 fprint(2, "could not allocate table to sort by location\n");
470 }else{
471 for(i=0; i<hdr->nsym; i++)
472 hdr->byname[i] = &hdr->sym[i];
473 qsort(hdr->byname, hdr->nsym, sizeof(hdr->byname[0]), bynamecmp);
474 }
475 return 0;
476}
477
rsc39dbe6e2005-01-07 18:45:17 +0000478void
479symclose(Fhdr *hdr)
480{
481 _delhdr(hdr);
482 if(hdr->symclose)
483 hdr->symclose(hdr);
484 free(hdr->byname);
485 hdr->byname = nil;
486 free(hdr->sym);
487 hdr->sym = nil;
488 hdr->nsym = 0;
489}
490
rsca84cbb22004-04-19 19:29:25 +0000491Symbol*
rsc39dbe6e2005-01-07 18:45:17 +0000492_addsym(Fhdr *fp, Symbol *sym)
rsca84cbb22004-04-19 19:29:25 +0000493{
494 Symbol *s;
495
496 if(fp->nsym%128 == 0){
497 s = realloc(fp->sym, (fp->nsym+128)*sizeof(fp->sym[0]));
498 if(s == nil)
499 return nil;
500 fp->sym = s;
501 }
502 if(machdebug)
503 fprint(2, "sym %s %c %L\n", sym->name, sym->type, sym->loc);
504 sym->fhdr = fp;
505 s = &fp->sym[fp->nsym++];
506 *s = *sym;
507 return s;
508}
509