aboutsummaryrefslogtreecommitdiff
path: root/src/libmach/dwarfdump.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-04-19 19:29:25 +0000
committerrsc <devnull@localhost>2004-04-19 19:29:25 +0000
commita84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46 (patch)
tree59a0e921597e5aa53e83d487c16727a7bf01547a /src/libmach/dwarfdump.c
parent0e3cc9f456ea49919459bf1164d0c8309a6134fa (diff)
downloadplan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.tar.gz
plan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.tar.bz2
plan9port-a84cbb2a17c9d0b88c561d5b7cb50d79a19e7c46.zip
libmach
Diffstat (limited to 'src/libmach/dwarfdump.c')
-rw-r--r--src/libmach/dwarfdump.c138
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);
+ }
+}