8 static void dwarfsymclose(Fhdr*);
9 static int dwarfpc2file(Fhdr*, ulong, char*, uint, ulong*);
10 static int dwarfline2pc(Fhdr*, ulong, ulong, ulong*);
11 static int dwarflookuplsym(Fhdr*, Symbol*, char*, Symbol*);
12 static int dwarfindexlsym(Fhdr*, Symbol*, uint, Symbol*);
13 static int dwarffindlsym(Fhdr*, Symbol*, Loc, Symbol*);
14 static void dwarfsyminit(Fhdr*);
15 static int dwarftosym(Fhdr*, Dwarf*, DwarfSym*, Symbol*, int);
16 static int _dwarfunwind(Fhdr *fhdr, Map *map, Regs *regs, ulong *next, Symbol*);
21 if(hdr->dwarf == nil){
22 werrstr("no dwarf debugging symbols");
26 hdr->symclose = dwarfsymclose;
27 hdr->pc2file = dwarfpc2file;
28 hdr->line2pc = dwarfline2pc;
29 hdr->lookuplsym = dwarflookuplsym;
30 hdr->indexlsym = dwarfindexlsym;
31 hdr->findlsym = dwarffindlsym;
32 hdr->unwind = _dwarfunwind;
39 dwarfsymclose(Fhdr *hdr)
41 dwarfclose(hdr->dwarf);
46 dwarfpc2file(Fhdr *fhdr, ulong pc, char *buf, uint nbuf, ulong *line)
48 char *cdir, *dir, *file;
50 if(dwarfpctoline(fhdr->dwarf, pc, &cdir, &dir, &file, line, nil, nil) < 0)
53 if(file[0] == '/' || (dir==nil && cdir==nil))
54 strecpy(buf, buf+nbuf, file);
55 else if((dir && dir[0] == '/') || cdir==nil)
56 snprint(buf, nbuf, "%s/%s", dir, file);
58 snprint(buf, nbuf, "%s/%s/%s", cdir, dir ? dir : "", file);
64 dwarfline2pc(Fhdr *fhdr, ulong basepc, ulong line, ulong *pc)
66 werrstr("dwarf line2pc not implemented");
71 typesize(Dwarf *dwarf, ulong unit, ulong tref, char *name)
76 if(dwarfseeksym(dwarf, unit, tref-unit, &ds) < 0){
78 fprint(2, "warning: cannot compute size of parameter %s (%lud %lud: %r)\n",
83 if(ds.attrs.have.bytesize)
84 return ds.attrs.bytesize;
90 if(ds.attrs.have.type != TReference)
100 roundup(int s, int n)
102 return (s+n-1)&~(n-1);
106 dwarflenum(Fhdr *fhdr, Symbol *p, char *name, uint j, Loc l, Symbol *s)
115 if(p->u.dwarf.unit == 0 && p->u.dwarf.uoff == 0)
118 if(dwarfseeksym(fhdr->dwarf, p->u.dwarf.unit, p->u.dwarf.uoff, &ds) < 0)
125 while(dwarfnextsym(fhdr->dwarf, &ds) == 1 && depth < ds.depth){
126 if(ds.attrs.tag != TagVariable){
127 if(ds.attrs.tag != TagFormalParameter
128 && ds.attrs.tag != TagUnspecifiedParameters)
130 if(ds.depth != depth+1)
133 if(dwarftosym(fhdr, fhdr->dwarf, &ds, &s1, 1) < 0)
135 /* XXX move this out once there is another architecture */
137 * gcc tells us the registers where the parameters might be
138 * held for an instruction or two. use the parameter list to
139 * recompute the actual stack locations.
141 if(fhdr->mtype == M386)
142 if(ds.attrs.tag==TagFormalParameter || ds.attrs.tag==TagUnspecifiedParameters){
143 if(s1.loc.type==LOFFSET
144 && strcmp(s1.loc.reg, "BP")==0
145 && s1.loc.offset >= 8)
146 bpoff = s1.loc.offset;
148 s1.loc.type = LOFFSET;
150 s1.loc.offset = bpoff;
152 if(ds.attrs.tag == TagFormalParameter){
153 if(ds.attrs.have.type)
154 bpoff += roundup(typesize(fhdr->dwarf, p->u.dwarf.unit, ds.attrs.type, s1.name), 4);
156 fprint(2, "warning: cannot compute size of parameter %s\n", s1.name);
160 if(strcmp(ds.attrs.name, name) != 0)
163 if(loccmp(&s1.loc, &l) != 0)
178 dwarflookuplsym(Fhdr *fhdr, Symbol *p, char *name, Symbol *s)
180 return dwarflenum(fhdr, p, name, 0, zl, s);
184 dwarfindexlsym(Fhdr *fhdr, Symbol *p, uint i, Symbol *s)
186 return dwarflenum(fhdr, p, nil, i, zl, s);
190 dwarffindlsym(Fhdr *fhdr, Symbol *p, Loc l, Symbol *s)
192 return dwarflenum(fhdr, p, nil, 0, l, s);
196 dwarfsyminit(Fhdr *fp)
203 if(dwarfenum(d, &s) < 0)
206 while(dwarfnextsymat(d, &s, 0) == 1)
207 while(dwarfnextsymat(d, &s, 1) == 1){
208 if(s.attrs.name == nil)
213 if(dwarftosym(fp, d, &s, &sym, 0) < 0)
221 regname(Dwarf *d, int i)
223 if(i < 0 || i >= d->nreg)
229 dwarftosym(Fhdr *fp, Dwarf *d, DwarfSym *ds, Symbol *s, int infn)
234 memset(s, 0, sizeof *s);
235 s->u.dwarf.uoff = ds->uoff;
236 s->u.dwarf.unit = ds->unit;
237 switch(ds->attrs.tag){
240 case TagUnspecifiedParameters:
241 ds->attrs.name = "...";
244 case TagFormalParameter:
261 s->name = ds->attrs.name;
262 if(ds->attrs.have.lowpc){
264 s->loc.addr = ds->attrs.lowpc;
265 if(ds->attrs.have.highpc){
266 s->hiloc.type = LADDR;
267 s->hiloc.addr = ds->attrs.highpc;
269 }else if(ds->attrs.have.location == TConstant){
271 s->loc.addr = ds->attrs.location.c;
272 }else if(ds->attrs.have.location == TBlock){
273 b = ds->attrs.location.b;
277 buf.ep = b.data+b.len;
280 if(b.data[0]==OpAddr){
284 s->loc.addr = dwarfgetaddr(&buf);
285 }else if(OpReg0 <= b.data[0] && b.data[0] < OpReg0+0x20){
286 if(b.len != 1 || (s->loc.reg = regname(d, b.data[0]-OpReg0)) == nil)
289 }else if(OpBreg0 <= b.data[0] && b.data[0] < OpBreg0+0x20){
290 s->loc.type = LOFFSET;
291 s->loc.reg = regname(d, b.data[0]-0x70);
292 s->loc.offset = dwarfget128s(&buf);
293 if(s->loc.reg == nil)
295 }else if(b.data[0] == OpRegx){
297 s->loc.reg = regname(d, dwarfget128(&buf));
298 if(s->loc.reg == nil)
300 }else if(b.data[0] == OpFbreg){
301 s->loc.type = LOFFSET;
302 s->loc.reg = mach->fp;
303 s->loc.offset = dwarfget128s(&buf);
304 }else if(b.data[0] == OpBregx){
305 s->loc.type = LOFFSET;
306 s->loc.reg = regname(d, dwarfget128(&buf));
307 s->loc.offset = dwarfget128s(&buf);
308 if(s->loc.reg == nil)
316 if(ds->attrs.isexternal)
317 s->type += 'A' - 'a';
318 if(ds->attrs.tag==TagVariable && s->loc.type==LADDR && s->loc.addr>=fp->dataddr+fp->datsz)
319 s->type += 'b' - 'd';
326 dwarfeval(Dwarf *d, Map *map, Regs *regs, ulong cfa, int rno, DwarfExpr e, ulong *u)
338 werrstr("pc cannot be `same'");
341 return rget(regs, regname(d, rno), u);
343 if((i = windindex(regname(d, e.reg))) < 0)
345 return rget(regs, regname(d, i), u);
348 werrstr("unknown cfa");
351 if(get4(map, cfa + e.offset, &u4) < 0)
356 if(rget(regs, regname(d, e.reg), &uu) < 0)
358 if(get4(map, uu+e.offset, &u4) < 0)
363 werrstr("not evaluating dwarf loc expressions");
366 werrstr("not reached in dwarfeval");
372 dwarfexprfmt(Fmt *fmt)
376 if((e = va_arg(fmt->args, DwarfExpr*)) == nil)
377 return fmtstrcpy(fmt, "<nil>");
381 return fmtstrcpy(fmt, "undef");
383 return fmtstrcpy(fmt, "same");
385 return fmtprint(fmt, "%ld(cfa)", e->offset);
387 return fmtprint(fmt, "r%ld", e->reg);
389 return fmtprint(fmt, "%ld(r%ld)", e->offset, e->reg);
391 return fmtprint(fmt, "l.%.*H", e->loc.len, e->loc.data);
393 return fmtprint(fmt, "?%d", e->type);
399 _dwarfunwind(Fhdr *fhdr, Map *map, Regs *regs, ulong *next, Symbol *sym)
405 DwarfExpr *e, epc, ecfa;
409 * Use dwarfunwind to tell us what to do.
412 e = malloc(d->nreg*sizeof(e[0]));
415 if(rget(regs, mach->pc, &pc) < 0)
417 if(dwarfunwind(d, pc, &ecfa, &epc, e, d->nreg) < 0)
425 werrstr("invalid call-frame-address in _dwarfunwind");
430 if((name = regname(d, ecfa.reg)) == nil){
431 werrstr("invalid call-frame-address register %d", (int)ecfa.reg);
434 if(rget(regs, name, &cfa) < 0){
435 werrstr("fetching %s for call-frame-address: %r", name);
444 for(i=0; i<d->nreg; i++){
445 j = windindex(d->reg[i]);
448 if(dwarfeval(d, map, regs, cfa, i, e[i], &u) < 0)
456 if(dwarfeval(d, map, regs, cfa, -1, epc, &u) < 0){
457 werrstr("computing caller %s: %r", mach->pc);
460 next[windindex(mach->pc)] = u;