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 h->next = nil;
51 }
53 Fhdr*
54 findhdr(char *name)
55 {
56 int len, plen;
57 Fhdr *p;
59 len = strlen(name);
60 for(p=fhdrlist; p; p=p->next){
61 plen = strlen(p->filename);
62 if(plen >= len)
63 if(strcmp(p->filename+plen-len, name) == 0)
64 if(plen == len || p->filename[plen-len-1] == '/')
65 return p;
66 }
67 return nil;
68 }
70 int
71 pc2file(ulong pc, char *file, uint nfile, ulong *line)
72 {
73 Fhdr *p;
75 for(p=fhdrlist; p; p=p->next)
76 if(p->pc2file && p->pc2file(p, pc-p->base, file, nfile, line) >= 0)
77 return 0;
78 werrstr("no source file for 0x%lux", pc);
79 return -1;
80 }
82 int
83 pc2line(ulong pc, ulong *line)
84 {
85 char tmp[10]; /* just in case */
86 return pc2file(pc, tmp, sizeof tmp, line);
87 }
89 int
90 file2pc(char *file, ulong line, ulong *addr)
91 {
92 Fhdr *p;
94 for(p=fhdrlist; p; p=p->next)
95 if(p->file2pc && p->file2pc(p, file, line, addr) >= 0){
96 *addr += p->base;
97 return 0;
98 }
99 werrstr("no instructions at %s:%lud", file, line);
100 return -1;
103 int
104 line2pc(ulong basepc, ulong line, ulong *pc)
106 Fhdr *p;
108 for(p=fhdrlist; p; p=p->next)
109 if(p->line2pc && p->line2pc(p, basepc-p->base, line, pc) >= 0){
110 *pc += p->base;
111 return 0;
113 werrstr("no instructions on line %lud", line);
114 return -1;
117 int
118 fnbound(ulong pc, ulong *bounds)
120 Fhdr *p;
121 Loc l;
122 Symbol *s;
124 for(p=fhdrlist; p; p=p->next){
125 l = locaddr(pc - p->base);
126 if((s = ffindsym(p, l, CANY)) != nil){
127 if(s->loc.type != LADDR){
128 werrstr("function %s has weird location %L", s->name, s->loc);
129 return -1;
131 bounds[0] = s->loc.addr + p->base;
132 if(s->hiloc.type != LADDR){
133 werrstr("can't find upper bound for function %s", s->name);
134 return -1;
136 bounds[1] = s->hiloc.addr + p->base;
137 return 0;
140 werrstr("no function contains 0x%lux", pc);
141 return -1;
144 int
145 fileline(ulong pc, char *a, uint n)
147 ulong line;
149 if(pc2file(pc, a, n, &line) < 0)
150 return -1;
151 seprint(a+strlen(a), a+n, ":%lud", line);
152 return 0;
155 Symbol*
156 flookupsym(Fhdr *fhdr, char *name)
158 Symbol **a, *t;
159 uint n, m;
160 int i;
162 a = fhdr->byname;
163 n = fhdr->nsym;
164 if(a == nil)
165 return nil;
167 while(n > 0){
168 m = n/2;
169 t = a[m];
170 i = strcmp(name, t->name);
171 if(i < 0)
172 n = m;
173 else if(i > 0){
174 n -= m+1;
175 a += m+1;
176 }else{
177 /* found! */
178 m += a - fhdr->byname;
179 a = fhdr->byname;
180 assert(strcmp(name, a[m]->name) == 0);
181 while(m > 0 && strcmp(name, a[m-1]->name) == 0)
182 m--;
183 return a[m];
186 return nil;
189 int
190 lookupsym(char *fn, char *var, Symbol *s)
192 Symbol *t, s1;
193 Fhdr *p;
194 char *nam;
196 nam = fn ? fn : var;
197 if(nam == nil)
198 return -1;
199 t = nil;
200 for(p=fhdrlist; p; p=p->next)
201 if((t=flookupsym(p, nam)) != nil){
202 relocsym(&s1, t, p->base);
203 break;
205 if(t == nil)
206 goto err;
207 if(fn && var)
208 return lookuplsym(&s1, var, s);
209 *s = s1;
210 return 0;
212 err:
213 werrstr("unknown symbol %s%s%s", fn ? fn : "",
214 fn && var ? ":" : "", var ? var : "");
215 return -1;
218 int
219 findexsym(Fhdr *fp, uint i, Symbol *s)
221 if(i >= fp->nsym)
222 return -1;
223 relocsym(s, &fp->sym[i], fp->base);
224 return 0;
227 int
228 indexsym(uint ndx, Symbol *s)
230 uint t;
231 Fhdr *p;
233 for(p=fhdrlist; p; p=p->next){
234 t = p->nsym;
235 if(t < ndx)
236 ndx -= t;
237 else{
238 relocsym(s, &p->sym[ndx], p->base);
239 return 0;
242 return -1;
245 Symbol*
246 ffindsym(Fhdr *fhdr, Loc loc, uint class)
248 Symbol *a, *t;
249 int n, i, hi, lo;
250 int cmp;
252 a = fhdr->sym;
253 n = fhdr->nsym;
254 if(a == nil || n <= 0)
255 return nil;
257 /*
258 * We have a list of possibly duplicate locations in a.
259 * We want to find the largest index i such that
260 * a[i] <= loc. This cannot be done with a simple
261 * binary search. Instead we binary search to find
262 * where the location should be.
263 */
264 lo = 0;
265 hi = n;
266 while(lo < hi){
267 i = (lo+hi)/2;
268 cmp = loccmp(&loc, &a[i].loc);
269 if(cmp < 0) /* loc < a[i].loc */
270 hi = i;
271 if(cmp > 0) /* loc > a[i].loc */
272 lo = i+1;
273 if(cmp == 0)
274 goto found;
277 /* found position where value would go, but not there -- go back one */
278 if(lo == 0)
279 return nil;
280 i = lo-1;
282 found:
283 /*
284 * might be in a run of all-the-same -- go back to beginning of run.
285 * if runs were long, could binary search for a[i].loc instead.
286 */
287 while(i > 0 && loccmp(&a[i-1].loc, &a[i].loc) == 0)
288 i--;
290 t = &a[i];
291 if(t->hiloc.type && loccmp(&loc, &t->hiloc) >= 0)
292 return nil;
293 if(class != CANY && class != t->class)
294 return nil;
295 return t;
298 int
299 findsym(Loc loc, uint class, Symbol *s)
301 Fhdr *p, *bestp;
302 Symbol *t, *best;
303 long bestd, d;
304 Loc l;
306 l = loc;
307 best = nil;
308 bestp = nil;
309 bestd = 0;
310 for(p=fhdrlist; p; p=p->next){
311 if(l.type == LADDR)
312 l.addr = loc.addr - p->base;
313 if((t = ffindsym(p, l, CANY)) != nil){
314 d = l.addr - t->loc.addr;
315 if(0 <= d && d < 4096)
316 if(best == nil || d < bestd){
317 best = t;
318 bestp = p;
319 bestd = d;
323 if(best){
324 if(class != CANY && class != best->class)
325 goto err;
326 relocsym(s, best, bestp->base);
327 return 0;
329 err:
330 werrstr("could not find symbol at %L", loc);
331 return -1;
334 int
335 lookuplsym(Symbol *s1, char *name, Symbol *s2)
337 Fhdr *p;
339 p = s1->fhdr;
340 if(p->lookuplsym && p->lookuplsym(p, s1, name, s2) >= 0){
341 relocsym(s2, s2, p->base);
342 return 0;
344 return -1;
347 int
348 indexlsym(Symbol *s1, uint ndx, Symbol *s2)
350 Fhdr *p;
352 p = s1->fhdr;
353 if(p->indexlsym && p->indexlsym(p, s1, ndx, s2) >= 0){
354 relocsym(s2, s2, p->base);
355 return 0;
357 return -1;
360 int
361 findlsym(Symbol *s1, Loc loc, Symbol *s2)
363 Fhdr *p;
365 p = s1->fhdr;
366 if(p->findlsym && p->findlsym(p, s1, loc, s2) >= 0){
367 relocsym(s2, s2, p->base);
368 return 0;
370 return -1;
373 int
374 unwindframe(Map *map, Regs *regs, ulong *next, Symbol *sym)
376 Fhdr *p;
378 for(p=fhdrlist; p; p=p->next)
379 if(p->unwind && p->unwind(p, map, regs, next, sym) >= 0)
380 return 0;
381 if(mach->unwind && mach->unwind(map, regs, next, sym) >= 0)
382 return 0;
383 return -1;
386 int
387 symoff(char *a, uint n, ulong addr, uint class)
389 Loc l;
390 Symbol s;
392 l.type = LADDR;
393 l.addr = addr;
394 if(findsym(l, class, &s) < 0 || addr-s.loc.addr >= 4096){
395 snprint(a, n, "%lux", addr);
396 return -1;
398 if(addr != s.loc.addr)
399 snprint(a, n, "%s+%ld", s.name, addr-s.loc.addr);
400 else
401 snprint(a, n, "%s", s.name);
402 return 0;
405 /* location, class, name */
406 static int
407 byloccmp(const void *va, const void *vb)
409 int i;
410 Symbol *a, *b;
412 a = (Symbol*)va;
413 b = (Symbol*)vb;
414 i = loccmp(&a->loc, &b->loc);
415 if(i != 0)
416 return i;
417 i = a->class - b->class;
418 if(i != 0)
419 return i;
420 return strcmp(a->name, b->name);
423 /* name, location, class */
424 static int
425 bynamecmp(const void *va, const void *vb)
427 int i;
428 Symbol *a, *b;
430 a = *(Symbol**)va;
431 b = *(Symbol**)vb;
432 i = strcmp(a->name, b->name);
433 if(i != 0)
434 return i;
435 i = loccmp(&a->loc, &b->loc);
436 if(i != 0)
437 return i;
438 return a->class - b->class;
441 int
442 syminit(Fhdr *hdr)
444 int i;
445 Symbol *r, *w, *es;
447 if(hdr->syminit == 0){
448 werrstr("no debugging symbols");
449 return -1;
451 if(hdr->syminit(hdr) < 0)
452 return -1;
454 qsort(hdr->sym, hdr->nsym, sizeof(hdr->sym[0]), byloccmp);
455 es = hdr->sym+hdr->nsym;
456 for(r=w=hdr->sym; r<es; r++){
457 if(w > hdr->sym
458 && strcmp((w-1)->name, r->name) ==0
459 && loccmp(&(w-1)->loc, &r->loc) == 0){
460 /* skip it */
461 }else
462 *w++ = *r;
464 hdr->nsym = w - hdr->sym;
466 hdr->byname = malloc(hdr->nsym*sizeof(hdr->byname[0]));
467 if(hdr->byname == nil){
468 fprint(2, "could not allocate table to sort by location\n");
469 }else{
470 for(i=0; i<hdr->nsym; i++)
471 hdr->byname[i] = &hdr->sym[i];
472 qsort(hdr->byname, hdr->nsym, sizeof(hdr->byname[0]), bynamecmp);
474 return 0;
477 Symbol*
478 addsym(Fhdr *fp, Symbol *sym)
480 Symbol *s;
482 if(fp->nsym%128 == 0){
483 s = realloc(fp->sym, (fp->nsym+128)*sizeof(fp->sym[0]));
484 if(s == nil)
485 return nil;
486 fp->sym = s;
488 if(machdebug)
489 fprint(2, "sym %s %c %L\n", sym->name, sym->type, sym->loc);
490 sym->fhdr = fp;
491 s = &fp->sym[fp->nsym++];
492 *s = *sym;
493 return s;