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