#include #include #include #include "elf.h" #include "dwarf.h" void printrules(Dwarf *d, ulong pc); int exprfmt(Fmt*); void usage(void) { fprint(2, "usage: dwarfdump file\n"); exits("usage"); } void main(int argc, char **argv) { int c; Elf *elf; Dwarf *d; DwarfSym s; char *cdir, *dir, *file; ulong line, mtime, length; ARGBEGIN{ default: usage(); }ARGEND if(argc != 1) usage(); fmtinstall('R', exprfmt); fmtinstall('H', encodefmt); if((elf = elfopen(argv[0])) == nil) sysfatal("elfopen %s: %r", argv[0]); if((d=dwarfopen(elf)) == nil) sysfatal("dwarfopen: %r"); if(dwarfenum(d, &s) < 0) sysfatal("dwarfenumall: %r"); while(dwarfnextsym(d, &s) == 1){ switch(s.attrs.tag){ case TagCompileUnit: print("compileunit %s\n", s.attrs.name); break; case TagSubprogram: c = 't'; goto sym; case TagVariable: c = 'd'; goto sym; case TagConstant: c = 'c'; goto sym; case TagFormalParameter: if(!s.attrs.name) break; c = 'p'; sym: if(s.attrs.isexternal) c += 'A' - 'a'; print("%c %s", c, s.attrs.name); if(s.attrs.have.lowpc) print(" 0x%lux-0x%lux", s.attrs.lowpc, s.attrs.highpc); switch(s.attrs.have.location){ case TBlock: print(" @ %.*H", s.attrs.location.b.len, s.attrs.location.b.data); break; case TConstant: print(" @ 0x%lux", s.attrs.location.c); break; } if(s.attrs.have.ranges) print(" ranges@0x%lux", s.attrs.ranges); print("\n"); if(s.attrs.have.lowpc){ if(dwarfpctoline(d, s.attrs.lowpc, &cdir, &dir, &file, &line, &mtime, &length) < 0) print("\tcould not find source: %r\n"); else if(dir == nil) print("\t%s/%s:%lud mtime=%lud length=%lud\n", cdir, file, line, mtime, length); else print("\t%s/%s/%s:%lud mtime=%lud length=%lud\n", cdir, dir, file, line, mtime, length); if(0) printrules(d, s.attrs.lowpc); if(0) printrules(d, (s.attrs.lowpc+s.attrs.highpc)/2); } break; } } exits(0); } void printrules(Dwarf *d, ulong pc) { int i; DwarfExpr r[10]; DwarfExpr cfa, ra; if(dwarfunwind(d, pc, &cfa, &ra, r, nelem(r)) < 0) print("\tcannot unwind from pc 0x%lux: %r\n", pc); print("\tpc=0x%lux cfa=%R ra=%R", pc, &cfa, &ra); for(i=0; iargs, DwarfExpr*)) == nil) return fmtstrcpy(fmt, ""); switch(e->type){ case RuleUndef: return fmtstrcpy(fmt, "undef"); case RuleSame: return fmtstrcpy(fmt, "same"); case RuleCfaOffset: return fmtprint(fmt, "%ld(cfa)", e->offset); case RuleRegister: return fmtprint(fmt, "r%ld", e->reg); case RuleRegOff: return fmtprint(fmt, "%ld(r%ld)", e->offset, e->reg); case RuleLocation: return fmtprint(fmt, "l.%.*H", e->loc.len, e->loc.data); default: return fmtprint(fmt, "?%d", e->type); } }