diff options
author | rsc <devnull@localhost> | 2004-04-19 19:29:25 +0000 |
---|---|---|
committer | rsc <devnull@localhost> | 2004-04-19 19:29:25 +0000 |
commit | a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46 (patch) | |
tree | 59a0e921597e5aa53e83d487c16727a7bf01547a /src/libmach/dwarfdump.c | |
parent | 0e3cc9f456ea49919459bf1164d0c8309a6134fa (diff) | |
download | plan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.tar.gz plan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.tar.bz2 plan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.zip |
libmach
Diffstat (limited to 'src/libmach/dwarfdump.c')
-rw-r--r-- | src/libmach/dwarfdump.c | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/libmach/dwarfdump.c b/src/libmach/dwarfdump.c new file mode 100644 index 00000000..47c38c37 --- /dev/null +++ b/src/libmach/dwarfdump.c @@ -0,0 +1,138 @@ +#include <u.h> +#include <libc.h> +#include <bio.h> +#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) == 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 + 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; i<nelem(r); i++) + if(r[i].type != RuleSame) + print(" r%d=%R", i, &r[i]); + print("\n"); +} + +int +exprfmt(Fmt *fmt) +{ + DwarfExpr *e; + + if((e = va_arg(fmt->args, DwarfExpr*)) == nil) + return fmtstrcpy(fmt, "<nil>"); + + 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); + } +} |