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 int
54 pc2file(ulong pc, char *file, uint nfile, ulong *line)
55 {
56 Fhdr *p;
58 for(p=fhdrlist; p; p=p->next)
59 if(p->pc2file && p->pc2file(p, pc-p->base, file, nfile, line) >= 0)
60 return 0;
61 werrstr("no source file for 0x%lux", pc);
62 return -1;
63 }
65 int
66 pc2line(ulong pc, ulong *line)
67 {
68 char tmp[10]; /* just in case */
69 return pc2file(pc, tmp, sizeof tmp, line);
70 }
72 int
73 file2pc(char *file, ulong line, ulong *addr)
74 {
75 Fhdr *p;
77 for(p=fhdrlist; p; p=p->next)
78 if(p->file2pc && p->file2pc(p, file, line, addr) >= 0){
79 *addr += p->base;
80 return 0;
81 }
82 werrstr("no instructions at %s:%lud", file, line);
83 return -1;
84 }
86 int
87 line2pc(ulong basepc, ulong line, ulong *pc)
88 {
89 Fhdr *p;
91 for(p=fhdrlist; p; p=p->next)
92 if(p->line2pc && p->line2pc(p, basepc-p->base, line, pc) >= 0){
93 *pc += p->base;
94 return 0;
95 }
96 werrstr("no instructions on line %lud", line);
97 return -1;
98 }
100 int
101 fnbound(ulong pc, ulong *bounds)
103 Fhdr *p;
104 Loc l;
105 Symbol *s;
107 for(p=fhdrlist; p; p=p->next){
108 l = locaddr(pc - p->base);
109 if((s = ffindsym(p, l, CANY)) != nil){
110 if(s->loc.type != LADDR){
111 werrstr("function %s has weird location %L", s->name, s->loc);
112 return -1;
114 bounds[0] = s->loc.addr + p->base;
115 if(s->hiloc.type != LADDR){
116 werrstr("can't find upper bound for function %s", s->name);
117 return -1;
119 bounds[1] = s->hiloc.addr + p->base;
120 return 0;
123 werrstr("no function contains 0x%lux", pc);
124 return -1;
127 int
128 fileline(ulong pc, char *a, uint n)
130 ulong line;
132 if(pc2file(pc, a, n, &line) < 0)
133 return -1;
134 seprint(a+strlen(a), a+n, ":%lud", line);
135 return 0;
138 Symbol*
139 flookupsym(Fhdr *fhdr, char *name)
141 Symbol **a, *t;
142 uint n, m;
143 int i;
145 a = fhdr->byname;
146 n = fhdr->nsym;
147 if(a == nil)
148 return nil;
150 while(n > 0){
151 m = n/2;
152 t = a[m];
153 i = strcmp(name, t->name);
154 if(i < 0)
155 n = m;
156 else if(i > 0){
157 n -= m+1;
158 a += m+1;
159 }else{
160 /* found! */
161 m += a - fhdr->byname;
162 a = fhdr->byname;
163 assert(strcmp(name, a[m]->name) == 0);
164 while(m > 0 && strcmp(name, a[m-1]->name) == 0)
165 m--;
166 return a[m];
169 return nil;
172 int
173 lookupsym(char *fn, char *var, Symbol *s)
175 Symbol *t, s1;
176 Fhdr *p;
177 char *nam;
179 nam = fn ? fn : var;
180 if(nam == nil)
181 return -1;
182 t = nil;
183 for(p=fhdrlist; p; p=p->next)
184 if((t=flookupsym(p, nam)) != nil){
185 relocsym(&s1, t, p->base);
186 break;
188 if(t == nil)
189 goto err;
190 if(fn && var)
191 return lookuplsym(&s1, var, s);
192 *s = s1;
193 return 0;
195 err:
196 werrstr("unknown symbol %s%s%s", fn ? fn : "",
197 fn && var ? ":" : "", var ? var : "");
198 return -1;
201 int
202 findexsym(Fhdr *fp, uint i, Symbol *s)
204 if(i >= fp->nsym)
205 return -1;
206 relocsym(s, &fp->sym[i], fp->base);
207 return 0;
210 int
211 indexsym(uint ndx, Symbol *s)
213 uint t;
214 Fhdr *p;
216 for(p=fhdrlist; p; p=p->next){
217 t = p->nsym;
218 if(t < ndx)
219 ndx -= t;
220 else{
221 relocsym(s, &p->sym[ndx], p->base);
222 return 0;
225 return -1;
228 Symbol*
229 ffindsym(Fhdr *fhdr, Loc loc, uint class)
231 Symbol *a, *t;
232 int n, i, hi, lo;
233 int cmp;
235 a = fhdr->sym;
236 n = fhdr->nsym;
237 if(a == nil || n <= 0)
238 return nil;
240 /*
241 * We have a list of possibly duplicate locations in a.
242 * We want to find the largest index i such that
243 * a[i] <= loc. This cannot be done with a simple
244 * binary search. Instead we binary search to find
245 * where the location should be.
246 */
247 lo = 0;
248 hi = n;
249 while(lo < hi){
250 i = (lo+hi)/2;
251 cmp = loccmp(&loc, &a[i].loc);
252 if(cmp < 0) /* loc < a[i].loc */
253 hi = i;
254 if(cmp > 0) /* loc > a[i].loc */
255 lo = i+1;
256 if(cmp == 0)
257 goto found;
260 /* found position where value would go, but not there -- go back one */
261 if(lo == 0)
262 return nil;
263 i = lo-1;
265 found:
266 /*
267 * might be in a run of all-the-same -- go back to beginning of run.
268 * if runs were long, could binary search for a[i].loc instead.
269 */
270 while(i > 0 && loccmp(&a[i-1].loc, &a[i].loc) == 0)
271 i--;
273 t = &a[i];
274 if(t->hiloc.type && loccmp(&loc, &t->hiloc) >= 0)
275 return nil;
276 if(class != CANY && class != t->class)
277 return nil;
278 return t;
281 int
282 findsym(Loc loc, uint class, Symbol *s)
284 Fhdr *p, *bestp;
285 Symbol *t, *best;
286 long bestd, d;
287 Loc l;
289 l = loc;
290 best = nil;
291 bestp = nil;
292 bestd = 0;
293 for(p=fhdrlist; p; p=p->next){
294 if(l.type == LADDR)
295 l.addr = loc.addr - p->base;
296 if((t = ffindsym(p, l, CANY)) != nil){
297 d = l.addr - t->loc.addr;
298 if(d < 4096)
299 if(best == nil || d < bestd){
300 best = t;
301 bestp = p;
302 bestd = d;
306 if(best){
307 if(class != CANY && class != best->class)
308 goto err;
309 relocsym(s, best, bestp->base);
310 return 0;
312 err:
313 werrstr("could not find symbol at %L", loc);
314 return -1;
317 int
318 lookuplsym(Symbol *s1, char *name, Symbol *s2)
320 Fhdr *p;
322 p = s1->fhdr;
323 if(p->lookuplsym && p->lookuplsym(p, s1, name, s2) >= 0){
324 relocsym(s2, s2, p->base);
325 return 0;
327 return -1;
330 int
331 indexlsym(Symbol *s1, uint ndx, Symbol *s2)
333 Fhdr *p;
335 p = s1->fhdr;
336 if(p->indexlsym && p->indexlsym(p, s1, ndx, s2) >= 0){
337 relocsym(s2, s2, p->base);
338 return 0;
340 return -1;
343 int
344 findlsym(Symbol *s1, Loc loc, Symbol *s2)
346 Fhdr *p;
348 p = s1->fhdr;
349 if(p->findlsym && p->findlsym(p, s1, loc, s2) >= 0){
350 relocsym(s2, s2, p->base);
351 return 0;
353 return -1;
356 int
357 unwindframe(Map *map, Regs *regs, ulong *next)
359 Fhdr *p;
361 for(p=fhdrlist; p; p=p->next)
362 if(p->unwind && p->unwind(p, map, regs, next) >= 0)
363 return 0;
364 if(mach->unwind && mach->unwind(map, regs, next) >= 0)
365 return 0;
366 return -1;
369 int
370 symoff(char *a, uint n, ulong addr, uint class)
372 Loc l;
373 Symbol s;
375 l.type = LADDR;
376 l.addr = addr;
377 if(findsym(l, class, &s) < 0 || addr-s.loc.addr >= 4096){
378 snprint(a, n, "%lux", addr);
379 return -1;
381 if(addr != s.loc.addr)
382 snprint(a, n, "%s+%ld", s.name, addr-s.loc.addr);
383 else
384 snprint(a, n, "%s", s.name);
385 return 0;
388 /* location, class, name */
389 static int
390 byloccmp(const void *va, const void *vb)
392 int i;
393 Symbol *a, *b;
395 a = (Symbol*)va;
396 b = (Symbol*)vb;
397 i = loccmp(&a->loc, &b->loc);
398 if(i != 0)
399 return i;
400 i = a->class - b->class;
401 if(i != 0)
402 return i;
403 return strcmp(a->name, b->name);
406 /* name, location, class */
407 static int
408 bynamecmp(const void *va, const void *vb)
410 int i;
411 Symbol *a, *b;
413 a = *(Symbol**)va;
414 b = *(Symbol**)vb;
415 i = strcmp(a->name, b->name);
416 if(i != 0)
417 return i;
418 i = loccmp(&a->loc, &b->loc);
419 if(i != 0)
420 return i;
421 return a->class - b->class;
424 int
425 syminit(Fhdr *hdr)
427 int i;
428 Symbol *r, *w, *es;
430 if(hdr->syminit == nil){
431 werrstr("no debugging symbols");
432 return -1;
434 if(hdr->syminit(hdr) < 0)
435 return -1;
437 qsort(hdr->sym, hdr->nsym, sizeof(hdr->sym[0]), byloccmp);
438 es = hdr->sym+hdr->nsym;
439 for(r=w=hdr->sym; r<es; r++){
440 if(w > hdr->sym
441 && strcmp((w-1)->name, r->name) ==0
442 && loccmp(&(w-1)->loc, &r->loc) == 0){
443 /* skip it */
444 }else
445 *w++ = *r;
447 hdr->nsym = w - hdr->sym;
449 hdr->byname = malloc(hdr->nsym*sizeof(hdr->byname[0]));
450 if(hdr->byname == nil){
451 fprint(2, "could not allocate table to sort by location\n");
452 }else{
453 for(i=0; i<hdr->nsym; i++)
454 hdr->byname[i] = &hdr->sym[i];
455 qsort(hdr->byname, hdr->nsym, sizeof(hdr->byname[0]), bynamecmp);
457 return 0;
460 Symbol*
461 addsym(Fhdr *fp, Symbol *sym)
463 Symbol *s;
465 if(fp->nsym%128 == 0){
466 s = realloc(fp->sym, (fp->nsym+128)*sizeof(fp->sym[0]));
467 if(s == nil)
468 return nil;
469 fp->sym = s;
471 if(machdebug)
472 fprint(2, "sym %s %c %L\n", sym->name, sym->type, sym->loc);
473 sym->fhdr = fp;
474 s = &fp->sym[fp->nsym++];
475 *s = *sym;
476 return s;