[CMAKE]
authorAmine Khaldi <amine.khaldi@reactos.org>
Tue, 31 May 2011 18:22:20 +0000 (18:22 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Tue, 31 May 2011 18:22:20 +0000 (18:22 +0000)
* Several improvements to debug symbols handling.
* A new (killer/awesome/...etc) feature has been introduced to kdbg: argument values support. Now backtraces contain not only usermode and kernelmode addresses translated, but also the argument values passed to the functions along the trace.
* Brought to you by the Arty.

svn path=/branches/cmake-bringup/; revision=52027

22 files changed:
include/reactos/rossym.h
lib/rossym/CMakeLists.txt
lib/rossym/compat.h
lib/rossym/dwarf.h
lib/rossym/dwarfabbrev.c
lib/rossym/dwarfaranges.c
lib/rossym/dwarfcfa.c
lib/rossym/dwarfget.c
lib/rossym/dwarfinfo.c
lib/rossym/dwarfopen.c
lib/rossym/dwarfpc.c
lib/rossym/find.c
lib/rossym/fromfile.c
lib/rossym/initum.c
lib/rossym/pe.c
lib/rossym/pe.h
lib/rossym/rossympriv.h
ntoskrnl/include/internal/kd.h
ntoskrnl/kdbg/i386/i386-dis.c
ntoskrnl/kdbg/kdb_cli.c
ntoskrnl/kdbg/kdb_symbols.c
ntoskrnl/ke/bug.c

index d65f969..1f7bf2f 100644 (file)
@@ -17,33 +17,86 @@ typedef struct _ROSSYM_ENTRY {
   ULONG SourceLine;
 } ROSSYM_ENTRY, *PROSSYM_ENTRY;
 
+enum _ROSSYM_REGNAME {
+    ROSSYM_X86_EAX = 0,
+    ROSSYM_X86_ECX,
+    ROSSYM_X86_EDX,
+    ROSSYM_X86_EBX,
+    ROSSYM_X86_ESP,
+    ROSSYM_X86_EBP,
+    ROSSYM_X86_ESI,
+    ROSSYM_X86_EDI,
+
+       ROSSYM_X64_RAX = 0, 
+       ROSSYM_X64_RDX,
+       ROSSYM_X64_RCX,
+       ROSSYM_X64_RBX,
+       ROSSYM_X64_RSI,
+       ROSSYM_X64_RDI,
+       ROSSYM_X64_RBP,
+       ROSSYM_X64_RSP,
+       Rossym_X64_R8,
+       ROSSYM_X64_R9,
+       ROSSYM_X64_R10,
+       ROSSYM_X64_R11,
+       ROSSYM_X64_R12,
+       ROSSYM_X64_R13,
+       ROSSYM_X64_R14,
+       ROSSYM_X64_R15
+};
+
+typedef struct _ROSSYM_REGISTERS {
+  ULONGLONG Registers[32];
+} ROSSYM_REGISTERS, *PROSSYM_REGISTERS;
+
+typedef struct _ROSSYM_PARAMETER {
+  ULONGLONG Value;
+  char *ValueName;
+} ROSSYM_PARAMETER, *PROSSYM_PARAMETER;
+
+typedef enum _ROSSYM_LINEINFO_FLAGS {
+  ROSSYM_LINEINFO_HAS_REGISTERS = 1
+} ROSSYM_LINEINFO_FLAGS;
+
+typedef enum _ROSSYM_LINEINFO_TYPE {
+  ROSSYM_LINEINFO_UNKNOWN,
+  ROSSYM_LINEINFO_NARROW_STRING,
+  ROSSYM_LINEINFO_WIDE_STRING,
+  ROSSYM_LINEINFO_ANSI_STRING,
+  ROSSYM_LINEINFO_UNICODE_STRING,
+  ROSSYM_LINEINFO_HANDLE
+} ROSSYM_LINEINFO_STRINGTYPE;
+
+typedef struct _ROSSYM_LINEINFO {
+  ROSSYM_LINEINFO_FLAGS Flags;
+  ULONG LineNumber;
+  char *FileName;
+  char *FunctionName;
+  ROSSYM_REGISTERS Registers;
+  ULONG NumParams;
+  ROSSYM_PARAMETER Parameters[16];
+} ROSSYM_LINEINFO, *PROSSYM_LINEINFO;
+
 typedef struct _ROSSYM_CALLBACKS {
   PVOID (*AllocMemProc)(ULONG_PTR Size);
   VOID (*FreeMemProc)(PVOID Area);
   BOOLEAN (*ReadFileProc)(PVOID FileContext, PVOID Buffer, ULONG Size);
   BOOLEAN (*SeekFileProc)(PVOID FileContext, ULONG_PTR Position);
+  BOOLEAN (*MemGetProc)(PVOID FileContext, ULONG_PTR *Target, PVOID SourceMem, ULONG Size);
 } ROSSYM_CALLBACKS, *PROSSYM_CALLBACKS;
 
-typedef struct _ROSSYM_OWN_FILECONTEXT {
-  BOOLEAN (*ReadFileProc)(PVOID FileContext, PVOID Buffer, ULONG Size);
-  BOOLEAN (*SeekFileProc)(PVOID FileContext, ULONG_PTR Position);
-} ROSSYM_OWN_FILECONTEXT, *PROSSYM_OWN_FILECONTEXT;
-
 struct Dwarf;
 typedef struct Dwarf *PROSSYM_INFO;
 
 VOID RosSymInit(PROSSYM_CALLBACKS Callbacks);
-VOID RosSymInitKernelMode(VOID);
 VOID RosSymInitUserMode(VOID);
 
-BOOLEAN RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize,
-                            PROSSYM_INFO *RosSymInfo);
 BOOLEAN RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo);
-BOOLEAN RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
-                                    ULONG_PTR RelativeAddress,
                                   ULONG *LineNumber,
-                                    char *FileName,
-                                    char *FunctionName);
+BOOLEAN RosSymGetAddressInformation
+(PROSSYM_INFO RosSymInfo,
ULONG_PTR RelativeAddress,
+ PROSSYM_LINEINFO RosSymLineInfo);
+VOID RosSymFreeInfo(PROSSYM_LINEINFO RosSymLineInfo);
 VOID RosSymDelete(PROSSYM_INFO RosSymInfo);
 
 #endif /* REACTOS_ROSSYM_H_INCLUDED */
index 2b05860..7338794 100644 (file)
@@ -5,7 +5,6 @@ else()
 add_definitions(-D_NTSYSTEM_)
 list(APPEND SOURCE
     delete.c
-    dwarf386.c
     dwarfabbrev.c
     dwarfaranges.c
     dwarfcfa.c
@@ -16,9 +15,7 @@ list(APPEND SOURCE
     dwarfpubnames.c
     find.c
     fromfile.c
-    iofile.c
     init.c
-    initkm.c
     initum.c
     pe.c
     zwfile.c)
index 64dc549..375b498 100644 (file)
@@ -32,6 +32,8 @@ void *RosSymRealloc(void *mem, ulong newsize);
 void xfree(void *v);
 
 #define werrstr(str, ...) DPRINT(str "\n" ,##__VA_ARGS__)
+//#define werrstr(x, ...) printf("(%s:%d) " x "\n",__FILE__,__LINE__,##__VA_ARGS__)
+
 #define malloc(x) RosSymAllocMem(x)
 #define mallocz(x,y) RosSymAllocMemZero(x,y)
 #define free(x) xfree(x)
index 0468981..7308d7d 100644 (file)
@@ -6,6 +6,8 @@ typedef struct DwarfBlock DwarfBlock;
 typedef struct DwarfBuf DwarfBuf;
 typedef struct DwarfExpr DwarfExpr;
 typedef struct DwarfSym DwarfSym;
+typedef struct DwarfStack DwarfStack;
+typedef struct DwarfParam DwarfParam;
 typedef union DwarfVal DwarfVal;
 
 enum
@@ -203,6 +205,16 @@ struct DwarfBlock
        ulong len;
 };
 
+struct DwarfParam
+{
+       char *name;
+       ulong unit;
+       ulong type;
+    ulong loctype;
+       ulong fde, len;
+    ulong value;
+};
+
 /* not for consumer use */
 struct DwarfBuf
 {
@@ -372,19 +384,16 @@ struct DwarfExpr
 
 struct DwarfSym
 {
-       DwarfAttrs attrs;
-
+    DwarfAttrs attrs;
+    
 /* not for consumer use... */
-       DwarfBuf b;
-       ulong unit;
-       uint uoff;
-       ulong aoff;
-       int depth;
-       int allunits;
-       ulong nextunit;
+    uint num;
+    DwarfBuf b;
+    int depth;
+    ulong unit, childoff, nextunit;
+    ulong aoff;
 };
 
-
 struct _Pe;
 Dwarf *dwarfopen(struct _Pe *elf);
 void dwarfclose(Dwarf*);
@@ -398,9 +407,11 @@ int dwarfenumunit(Dwarf*, ulong, DwarfSym*);
 int dwarfseeksym(Dwarf*, ulong, ulong, DwarfSym*);
 int dwarfenum(Dwarf*, DwarfSym*);
 int dwarfnextsym(Dwarf*, DwarfSym*);
-int dwarfnextsymat(Dwarf*, DwarfSym*, int);
-int dwarfpctoline(Dwarf*, ulong, char**, char**, char**, char **, ulong*, ulong*, ulong*);
-int dwarfunwind(Dwarf*, ulong, DwarfExpr*, DwarfExpr*, DwarfExpr*, int);
+int dwarfnextsymat(Dwarf*, DwarfSym *parent, DwarfSym *child);
+int dwarfpctoline(Dwarf*, DwarfSym *proc, ulong, char**, char**, ulong *);
+int dwarfgetarg(Dwarf *d, const char *name, DwarfBuf *locbuf, ulong cfa, PROSSYM_REGISTERS registers, ulong *value);
+int dwarfgettype(Dwarf *d, DwarfSym *param, DwarfSym *type);
+
 ulong dwarfget1(DwarfBuf*);
 ulong dwarfget2(DwarfBuf*);
 ulong dwarfget4(DwarfBuf*);
@@ -411,7 +422,10 @@ ulong dwarfgetaddr(DwarfBuf*);
 int dwarfgetn(DwarfBuf*, uchar*, int);
 uchar *dwarfgetnref(DwarfBuf*, ulong);
 char *dwarfgetstring(DwarfBuf*);
-
+int dwarfcomputecfa(Dwarf *d, DwarfExpr *cfa, PROSSYM_REGISTERS registers, ulong *cfaLocation);
+int dwarfregunwind(Dwarf *d, ulong pc, ulong fde, DwarfExpr *cfa, PROSSYM_REGISTERS registers);
+int dwarfargvalue(Dwarf *d, DwarfSym *proc, ulong pc, ulong cfa, PROSSYM_REGISTERS registers, DwarfParam *parameters);
+int dwarfgetparams(Dwarf *d, DwarfSym *s, ulong pc, int pnum, DwarfParam *paramblocks);
 
 typedef struct DwarfAbbrev DwarfAbbrev;
 typedef struct DwarfAttr DwarfAttr;
@@ -449,6 +463,7 @@ struct Dwarf
        DwarfBlock pubtypes;
        DwarfBlock ranges;
        DwarfBlock str;
+       DwarfBlock loc;
 
        /* little cache */
        struct {
@@ -458,14 +473,15 @@ struct Dwarf
        } acache;
 };
 
+struct DwarfStack
+{
+    ulong storage[16]; // own storage
+    ulong *data;
+    ulong length, max;
+};
+
 DwarfAbbrev *dwarfgetabbrev(Dwarf*, ulong, ulong);
 
 int dwarfgetinfounit(Dwarf*, ulong, DwarfBlock*);
 
-extern int dwarf386nregs;
-extern char *dwarf386regs[];
-extern char *dwarf386fp;
-
-#define SYMBOL_SIZE 18
 #define MAXIMUM_DWARF_NAME_SIZE 64
-#define MAXIMUM_COFF_SYMBOL_LENGTH 256
index d21ca6a..365d442 100644 (file)
@@ -25,117 +25,119 @@ DwarfAbbrev *dwarfgetabbrev(Dwarf*, ulong, ulong);
 static int
 loadabbrevs(Dwarf *d, ulong off, DwarfAbbrev **aa)
 {
-       int nattr, nabbrev;
-       DwarfAbbrev *abbrev;
-       DwarfAttr *attr;
-
-       if(d->acache.off == off && d->acache.na){
-               *aa = d->acache.a;
-               return d->acache.na;
-       }
-
-       /* two passes - once to count, then allocate, then a second to copy */
-       if(parseabbrevs(d, off, nil, nil, &nabbrev, &nattr) < 0) {
-               return -1;
-       }
-
-       abbrev = malloc(nabbrev*sizeof(DwarfAbbrev) + nattr*sizeof(DwarfAttr));
-       attr = (DwarfAttr*)(abbrev+nabbrev);
-
-       if(parseabbrevs(d, off, abbrev, attr, nil, nil) < 0){
-               free(abbrev);
-               return -1;
-       }
-
-       free(d->acache.a);
-       d->acache.a = abbrev;
-       d->acache.na = nabbrev;
-       d->acache.off = off;
-
-       *aa = abbrev;
-       return nabbrev;
+    int nattr, nabbrev;
+    DwarfAbbrev *abbrev;
+    DwarfAttr *attr;
+
+    if(d->acache.off == off && d->acache.na){
+        *aa = d->acache.a;
+        return d->acache.na;
+    }
+
+    /* two passes - once to count, then allocate, then a second to copy */
+    if(parseabbrevs(d, off, nil, nil, &nabbrev, &nattr) < 0) {
+        return -1;
+    }
+
+    abbrev = malloc(nabbrev*sizeof(DwarfAbbrev) + nattr*sizeof(DwarfAttr));
+    attr = (DwarfAttr*)(abbrev+nabbrev);
+
+    if(parseabbrevs(d, off, abbrev, attr, nil, nil) < 0){
+        free(abbrev);
+        return -1;
+    }
+
+    free(d->acache.a);
+    d->acache.a = abbrev;
+    d->acache.na = nabbrev;
+    d->acache.off = off;
+
+    *aa = abbrev;
+    return nabbrev;
 }
 
 static int
 parseabbrevs(Dwarf *d, ulong off, DwarfAbbrev *abbrev, DwarfAttr *attr, int *pnabbrev, int *pnattr)
 {
-       int i, nabbrev, nattr, haskids;
-       ulong num, tag, name, form;
-       DwarfBuf b;
-
-       if(off >= d->abbrev.len){
-               werrstr("bad abbrev section offset 0x%lux >= 0x%lux\n", off, d->abbrev.len);
-               return -1;
-       }
-
-       memset(&b, 0, sizeof b);
-       b.p = d->abbrev.data + off;
-       b.ep = d->abbrev.data + d->abbrev.len;
-
-       nabbrev = 0;
-       nattr = 0;
-       for(;;){
-               if(b.p == nil){
-                       werrstr("malformed abbrev data");
-                       return -1;
-               }
-               num = dwarfget128(&b);
-               if(num == 0)
-                       break;
-               tag = dwarfget128(&b);
-               haskids = dwarfget1(&b);
-               for(i=0;; i++){
-                       name = dwarfget128(&b);
-                       form = dwarfget128(&b);
-                       if(name == 0 && form == 0)
-                               break;
-                       if(attr){
-                               attr[i].name = name;
-                               attr[i].form = form;
-                       }
-               }
-               if(abbrev){
-                       abbrev->num = num;
-                       abbrev->tag = tag;
-                       abbrev->haskids = haskids;
-                       abbrev->attr = attr;
-                       abbrev->nattr = i;
-                       abbrev++;
-                       attr += i;
-               }
-               nabbrev++;
-               nattr += i;
-       }
-       if(pnabbrev)
-               *pnabbrev = nabbrev;
-       if(pnattr)
-               *pnattr = nattr;
-       return 0;
+    int i, nabbrev, nattr, haskids;
+    ulong num, tag, name, form;
+    DwarfBuf b;
+
+    if(off >= d->abbrev.len){
+        werrstr("bad abbrev section offset 0x%lux >= 0x%lux", off, d->abbrev.len);
+        return -1;
+    }
+
+    memset(&b, 0, sizeof b);
+    b.p = d->abbrev.data + off;
+    b.ep = d->abbrev.data + d->abbrev.len;
+
+    nabbrev = 0;
+    nattr = 0;
+    for(;;){
+        if(b.p == nil){
+            werrstr("malformed abbrev data");
+            return -1;
+        }
+        num = dwarfget128(&b);
+        if(num == 0)
+            break;
+        tag = dwarfget128(&b);
+        DPRINT("num %d tag %x @ %x", num, tag, b.p - d->abbrev.data);
+        haskids = dwarfget1(&b);
+        for(i=0;; i++){
+            name = dwarfget128(&b);
+            form = dwarfget128(&b);
+            assert(form < 0x3000);
+            if(name == 0 && form == 0)
+                break;
+            if(attr){
+                attr[i].name = name;
+                attr[i].form = form;
+            }
+        }
+        if(abbrev){
+            abbrev->num = num;
+            abbrev->tag = tag;
+            abbrev->haskids = haskids;
+            abbrev->attr = attr;
+            abbrev->nattr = i;
+            abbrev++;
+            attr += i;
+        }
+        nabbrev++;
+        nattr += i;
+    }
+    if(pnabbrev)
+        *pnabbrev = nabbrev;
+    if(pnattr)
+        *pnattr = nattr;
+    return 0;
 }
 
 static DwarfAbbrev*
 findabbrev(DwarfAbbrev *a, int na, ulong num)
 {
-       int i;
-
-       for(i=0; i<na; i++)
-               if(a[i].num == num)
-                       return &a[i];
-       werrstr("abbrev not found");
-       return nil;
+    int i;
+
+    for(i=0; i<na; i++)
+        if(a[i].num == num)
+            return &a[i];
+    assert(0);
+    werrstr("abbrev not found");
+    return nil;
 }
 
 DwarfAbbrev*
 dwarfgetabbrev(Dwarf *d, ulong off, ulong num)
 {
-       DwarfAbbrev *a;
-       int na;
-
-       if((na = loadabbrevs(d, off, &a)) < 0){
-               werrstr("loadabbrevs: %r");
-               return nil;
-       }
-       return findabbrev(a, na, num);
+    DwarfAbbrev *a;
+    int na;
+
+    if((na = loadabbrevs(d, off, &a)) < 0){
+        werrstr("loadabbrevs: %r");
+        return nil;
+    }
+    return findabbrev(a, na, num);
 }
 
-
index e9e82c1..cda4cd6 100644 (file)
 int
 dwarfaddrtounit(Dwarf *d, ulong addr, ulong *unit)
 {
-       DwarfBuf b;
-       int segsize, i;
-       ulong len, id, off, base, size;
-       uchar *start, *end;
+    DwarfBuf b;
+    int segsize, i;
+    ulong len, id, off, base, size;
+    uchar *start, *end;
 
-       memset(&b, 0, sizeof b);
-       b.d = d;
-       b.p = d->aranges.data;
-       b.ep = b.p + d->aranges.len;
+    memset(&b, 0, sizeof b);
+    b.d = d;
+    b.p = d->aranges.data;
+    b.ep = b.p + d->aranges.len;
 
-       while(b.p < b.ep){
-               start = b.p;
-               len = dwarfget4(&b);
-               if (!len) { b.ep = b.p - 4; return -1; }
-               if((id = dwarfget2(&b)) != 2){
-                       if(b.p == nil){
-                       underflow:
-                               werrstr("buffer underflow reading address ranges header");
-                       }else
-                               werrstr("bad dwarf version 0x%x in address ranges header", id);
-                       return -1;
-               }
-               off = dwarfget4(&b);
-               b.addrsize = dwarfget1(&b);
-               if(d->addrsize == 0)
-                       d->addrsize = b.addrsize;
-               segsize = dwarfget1(&b);
-               USED(segsize);  /* what am i supposed to do with this? */
-               if(b.p == nil)
-                       goto underflow;
-               if((i = (b.p-start) % (2*b.addrsize)) != 0)
-                       b.p += 2*b.addrsize - i;
-               end = start+4+len;
-               while(b.p!=nil && b.p<end){
-                       base = dwarfgetaddr(&b);
-                       size = dwarfgetaddr(&b);
-                       if (!size) continue;
-                       if(b.p == nil)
-                               goto underflow;
-                       if(base <= addr && addr < base+size){
-                               *unit = off;
-                               return 0;
-                       }
-               }
-               if(b.p == nil)
-                       goto underflow;
-               b.p = end;
-       }
-       werrstr("address 0x%lux is not listed in dwarf debugging symbols", addr);
-       return -1;
+    while(b.p < b.ep){
+        start = b.p;
+        len = dwarfget4(&b);
+        if (!len) { b.ep = b.p - 4; return -1; }
+        if((id = dwarfget2(&b)) != 2){
+            if(b.p == nil){
+            underflow:
+                werrstr("buffer underflow reading address ranges header");
+            }else
+                werrstr("bad dwarf version 0x%x in address ranges header", id);
+            return -1;
+        }
+        off = dwarfget4(&b);
+        b.addrsize = dwarfget1(&b);
+        if(d->addrsize == 0)
+            d->addrsize = b.addrsize;
+        segsize = dwarfget1(&b);
+        USED(segsize); /* what am i supposed to do with this? */
+        if(b.p == nil)
+            goto underflow;
+        if((i = (b.p-start) % (2*b.addrsize)) != 0)
+            b.p += 2*b.addrsize - i;
+        end = start+4+len;
+        while(b.p!=nil && b.p<end){
+            base = dwarfgetaddr(&b);
+            size = dwarfgetaddr(&b);
+            if (!size) continue;
+            if(b.p == nil)
+                goto underflow;
+            if(base <= addr && addr < base+size){
+                *unit = off;
+                return 0;
+            }
+        }
+        if(b.p == nil)
+            goto underflow;
+        b.p = end;
+    }
+    werrstr("address 0x%lux is not listed in dwarf debugging symbols", addr);
+    return -1;
 }
-
-
index 4197058..3c0c349 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+#include "pe.h"
 #include "dwarf.h"
 
-#define trace 0
+#define trace 1
 
 typedef struct State State;
 struct State
@@ -71,7 +72,7 @@ dwarfunwind(Dwarf *d, ulong pc, DwarfExpr *cfa, DwarfExpr *ra, DwarfExpr *r, int
        memset(r, 0, nr*sizeof(r[0]));
        for(i=0; i<nr; i++)
                r[i].type = RuleSame;
-       if(trace) werrstr("s.init %p-%p, fde %p-%p\n", s.init.p, s.init.ep, fde.p, fde.ep);
+       if(trace) werrstr("s.init %p-%p, fde %p-%p", s.init.p, s.init.ep, fde.p, fde.ep);
        b = s.init;
        if(dexec(&b, &s, 0) < 0)
                goto err;
@@ -79,9 +80,9 @@ dwarfunwind(Dwarf *d, ulong pc, DwarfExpr *cfa, DwarfExpr *ra, DwarfExpr *r, int
        s.initr = initr;
        memmove(initr, r, nr*sizeof(initr[0]));
 
-       if(trace) werrstr("s.loc 0x%lux pc 0x%lux\n", s.loc, pc);
+       if(trace) werrstr("s.loc 0x%lx pc 0x%lx", s.loc, pc);
        while(s.loc < pc){
-               if(trace) werrstr("s.loc 0x%lux pc 0x%lux\n", s.loc, pc);
+               if(trace) werrstr("s.loc 0x%lx pc 0x%lx", s.loc, pc);
                if(dexec(&fde, &s, 1) < 0)
                        goto err;
        }
@@ -139,15 +140,16 @@ findfde(Dwarf *d, ulong pc, State *s, DwarfBuf *fde)
                id = dwarfget4(&b);
                if(id == 0xFFFFFFFF){   /* CIE */
                        vers = dwarfget1(&b);
+                       if (trace) werrstr("CIE len %x id %x vers %x", len, id, vers);
                        if(vers != 1 && vers != 2 && vers != 3){
                                if(++nbad == 1)
-                                       werrstr("unknown cie version %d (wanted 1-3)\n", vers);
+                                       werrstr("unknown cie version %d (wanted 1-3)", vers);
                                continue;
                        }
                        aug = dwarfgetstring(&b);
                        if(aug && *aug){
                                if(++nbad == 1)
-                                       werrstr("unknown augmentation: %s\n", aug);
+                                       werrstr("unknown augmentation: %s", aug);
                                continue;
                        }
                        s->iquantum = dwarfget128(&b);
@@ -163,6 +165,7 @@ findfde(Dwarf *d, ulong pc, State *s, DwarfBuf *fde)
                }else{  /* FDE */
                        base = dwarfgetaddr(&b);
                        size = dwarfgetaddr(&b);
+            if (trace) werrstr("FDE: base %x-%x (want pc %x)", base, base+size, pc);
                        fde->p = b.p;
                        fde->ep = next;
                        s->loc = base;
@@ -171,7 +174,7 @@ findfde(Dwarf *d, ulong pc, State *s, DwarfBuf *fde)
                                return 0;
                }
        }
-       werrstr("cannot find call frame information for pc 0x%lux", pc);
+       werrstr("cannot find call frame information for pc 0x%lx", pc);
        return -1;
 
 }
@@ -180,7 +183,7 @@ static int
 checkreg(State *s, long r)
 {
        if(r < 0 || r >= s->nr){
-               werrstr("bad register number 0x%lux", r);
+               werrstr("bad register number 0x%lx", r);
                return -1;
        }
        return 0;
@@ -197,20 +200,21 @@ dexec(DwarfBuf *b, State *s, int locstop)
                if(b->p == b->ep){
                        if(s->initr)
                                s->loc = s->endloc;
+            werrstr("end dexec");
                        return 0;
                }
                c = dwarfget1(b);
                if(b->p == nil){
                        werrstr("ran out of instructions during cfa program");
-                       if(trace) werrstr("%r\n");
+                       if(trace) werrstr("%r");
                        return -1;
                }
-               if(trace) werrstr("+ loc=0x%lux op 0x%ux ", s->loc, c);
+               if(trace) werrstr("+ loc=0x%x op 0x%x ", s->loc, c);
                switch(c>>6){
                case 1: /* advance location */
                        arg1 = c&0x3F;
                advance:
-                       if(trace) werrstr("loc += %ld\n", arg1*s->iquantum);
+                       if(trace) werrstr("loc += %ld", arg1*s->iquantum);
                        s->loc += arg1 * s->iquantum;
                        if(locstop)
                                return 0;
@@ -220,7 +224,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
                        arg1 = c&0x3F;
                        arg2 = dwarfget128(b);
                offset:
-                       if(trace) werrstr("r%ld += %ld\n", arg1, arg2*s->dquantum);
+                       if(trace) werrstr("r%ld += %ld", arg1, arg2*s->dquantum);
                        if(checkreg(s, arg1) < 0)
                                return -1;
                        s->r[arg1].type = RuleCfaOffset;
@@ -230,7 +234,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
                case 3: /* restore initial setting */
                        arg1 = c&0x3F;
                restore:
-                       if(trace) werrstr("r%ld = init\n", arg1);
+                       if(trace) werrstr("r%ld = init", arg1);
                        if(checkreg(s, arg1) < 0)
                                return -1;
                        s->r[arg1] = s->initr[arg1];
@@ -239,12 +243,12 @@ dexec(DwarfBuf *b, State *s, int locstop)
 
                switch(c){
                case 0: /* nop */
-                       if(trace) werrstr("nop\n");
+                       if(trace) werrstr("nop");
                        continue;
 
                case 0x01:      /* set location */
                        s->loc = dwarfgetaddr(b);
-                       if(trace) werrstr("loc = 0x%lux\n", s->loc);
+                       if(trace) werrstr("loc = 0x%lx", s->loc);
                        if(locstop)
                                return 0;
                        continue;
@@ -272,7 +276,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
 
                case 0x07:      /* undefined */
                        arg1 = dwarfget128(b);
-                       if(trace) werrstr("r%ld = undef\n", arg1);
+                       if(trace) werrstr("r%ld = undef", arg1);
                        if(checkreg(s, arg1) < 0)
                                return -1;
                        s->r[arg1].type = RuleUndef;
@@ -280,7 +284,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
 
                case 0x08:      /* same value */
                        arg1 = dwarfget128(b);
-                       if(trace) werrstr("r%ld = same\n", arg1);
+                       if(trace) werrstr("r%ld = same", arg1);
                        if(checkreg(s, arg1) < 0)
                                return -1;
                        s->r[arg1].type = RuleSame;
@@ -289,7 +293,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
                case 0x09:      /* register */
                        arg1 = dwarfget128(b);
                        arg2 = dwarfget128(b);
-                       if(trace) werrstr("r%ld = r%ld\n", arg1, arg2);
+                       if(trace) werrstr("r%ld = r%ld", arg1, arg2);
                        if(checkreg(s, arg1) < 0 || checkreg(s, arg2) < 0)
                                return -1;
                        s->r[arg1].type = RuleRegister;
@@ -298,7 +302,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
 
                case 0x0A:      /* remember state */
                        e = malloc(s->nr*sizeof(e[0]));
-                       if(trace) werrstr("push\n");
+                       if(trace) werrstr("push");
                        if(e == nil)
                                return -1;
                        void *newstack = malloc(s->nstack*sizeof(s->stack[0]));
@@ -319,7 +323,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
                        continue;
 
                case 0x0B:      /* restore state */
-                       if(trace) werrstr("pop\n");
+                       if(trace) werrstr("pop");
                        if(s->nstack == 0){
                                werrstr("restore state underflow");
                                return -1;
@@ -334,7 +338,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
                        arg1 = dwarfget128(b);
                        arg2 = dwarfget128(b);
                defcfa:
-                       if(trace) werrstr("cfa %ld(r%ld)\n", arg2, arg1);
+                       if(trace) werrstr("cfa %ld(r%ld)", arg2, arg1);
                        if(checkreg(s, arg1) < 0)
                                return -1;
                        s->cfa->type = RuleRegOff;
@@ -344,7 +348,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
 
                case 0x0D:      /* def cfa register */
                        arg1 = dwarfget128(b);
-                       if(trace) werrstr("cfa reg r%ld\n", arg1);
+                       if(trace) werrstr("cfa reg r%ld", arg1);
                        if(s->cfa->type != RuleRegOff){
                                werrstr("change CFA register but CFA not in register+offset form");
                                return -1;
@@ -357,7 +361,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
                case 0x0E:      /* def cfa offset */
                        arg1 = dwarfget128(b);
                cfaoffset:
-                       if(trace) werrstr("cfa off %ld\n", arg1);
+                       if(trace) werrstr("cfa off %ld", arg1);
                        if(s->cfa->type != RuleRegOff){
                                werrstr("change CFA offset but CFA not in register+offset form");
                                return -1;
@@ -366,7 +370,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
                        continue;
 
                case 0x0F:      /* def cfa expression */
-                       if(trace) werrstr("cfa expr\n");
+                       if(trace) werrstr("cfa expr");
                        s->cfa->type = RuleLocation;
                        s->cfa->loc.len = dwarfget128(b);
                        s->cfa->loc.data = dwarfgetnref(b, s->cfa->loc.len);
@@ -374,7 +378,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
 
                case 0x10:      /* def reg expression */
                        arg1 = dwarfget128(b);
-                       if(trace) werrstr("reg expr r%ld\n", arg1);
+                       if(trace) werrstr("reg expr r%ld", arg1);
                        if(checkreg(s, arg1) < 0)
                                return -1;
                        s->r[arg1].type = RuleLocation;
@@ -397,11 +401,98 @@ dexec(DwarfBuf *b, State *s, int locstop)
                        goto cfaoffset;
 
                default:        /* unknown */
-                       werrstr("unknown opcode 0x%ux in cfa program", c);
+                       werrstr("unknown opcode 0x%x in cfa program", c);
                        return -1;
                }
        }
        /* not reached */
 }
 
+int dwarfcomputecfa(Dwarf *d, DwarfExpr *cfa, PROSSYM_REGISTERS registers, ulong *cfaLocation)
+{
+    switch (cfa->type) {
+    case RuleRegOff:
+        *cfaLocation = registers->Registers[cfa->reg] + cfa->offset;
+        werrstr("cfa reg %d (%x) offset %x = %x", cfa->reg, (ulong)registers->Registers[cfa->reg], cfa->offset, cfaLocation);
+        break;
+    default:
+        werrstr("cfa->type %x", cfa->type);
+        return -1;
+    }
+
+    return 0;
+}
 
+int dwarfregunwind(Dwarf *d, ulong pc, ulong fde, DwarfExpr *cfa, PROSSYM_REGISTERS registers)
+{
+       int i;
+       State s = { };
+       DwarfExpr initr[sizeof(registers->Registers) / sizeof(registers->Registers[0])] = { };
+       DwarfExpr r[sizeof(registers->Registers) / sizeof(registers->Registers[0])] = { };
+    DwarfExpr ra;
+
+       int nr = s.nr = sizeof(registers->Registers) / sizeof(registers->Registers[0]);
+       s.initr = initr;
+       s.r = r;
+       for (i = 0; i < sizeof(r) / sizeof(r[0]); i++) {
+               r[i].type = RuleRegister;
+               r[i].offset = registers->Registers[i];
+               r[i].reg = i;
+       }
+
+    int res = dwarfunwind(d, pc, cfa, &ra, initr, sizeof(initr) / sizeof(initr[0]));
+    if (res == -1) return -1;
+
+    ulong cfaLocation;
+
+    if (dwarfcomputecfa(d, cfa, registers, &cfaLocation) == -1)
+        return -1;
+
+    for (i = 0; i < nr; i++) {
+        switch (r[i].type) {
+        case RuleUndef:
+            werrstr("Undefined register slot %d", i);
+            assert(FALSE);
+            break;
+        case RuleSame:
+            break;
+        case RuleRegister:
+            registers->Registers[i] = registers->Registers[r[i].reg];
+            break;
+        case RuleRegOff: {
+            BOOLEAN success = 
+                RosSymCallbacks.MemGetProc
+                (d->pe->fd, 
+                 &registers->Registers[i],
+                 r[i].offset + registers->Registers[r[i].reg],
+                 d->addrsize);            
+            if (!success) return -1;
+        } break;
+        case RuleCfaOffset:
+        {
+            BOOLEAN success = 
+                RosSymCallbacks.MemGetProc
+                (d->pe->fd, 
+                 &registers->Registers[i],
+                 r[i].offset + cfaLocation,
+                 d->addrsize);
+            werrstr("reg[%d] = %x: cfa offset (cfa %x, offset %x) -> @%x", i, (ulong)registers->Registers[i], cfaLocation, initr[i].offset, r[i].offset + cfaLocation);
+            if (!success) return -1;
+        } break;
+        default:
+            werrstr("We don't yet support cfa rule %d in slot %d", r[i].type, i);
+            assert(FALSE);
+            break;
+        }
+    }
+
+    ulong cfaSpace[4];
+    for (i = 0; i < sizeof(cfaSpace) / sizeof(cfaSpace[0]); i++) {
+        RosSymCallbacks.MemGetProc
+            (d->pe->fd, &cfaSpace[i], cfaLocation + (i * 4), d->addrsize);
+    }
+    werrstr("CFA(%x) [%08x, %08x, %08x, %08x]", 
+            cfaLocation, cfaSpace[0], cfaSpace[1], cfaSpace[2], cfaSpace[3]);
+
+    return 0;
+}
index d32177c..7787163 100644 (file)
@@ -139,7 +139,7 @@ dwarfgetaddr(DwarfBuf *b)
                return dwarfget8(b);
        default:
                if(++nbad == 1)
-                       werrstr("dwarf: unexpected address size %lud in dwarfgetaddr\n", b->addrsize);
+                       werrstr("dwarf: unexpected address size %lud in dwarfgetaddr", b->addrsize);
                b->p = nil;
                return 0;
        }
@@ -190,7 +190,7 @@ dwarfget128(DwarfBuf *b)
        while(b->p<b->ep && *b->p&0x80)
                b->p++;
        if(++nbad == 1)
-               werrstr("dwarf: overflow during parsing of uleb128 integer\n");
+               werrstr("dwarf: overflow during parsing of uleb128 integer");
        return c;
 }
 
index cc25499..397702f 100644 (file)
 #include <debug.h>
 
 #include "dwarf.h"
+#include "pe.h"
 #include <windef.h>
 
 enum
 {
-       DwarfAttrSibling = 0x01,
-       DwarfAttrLocation = 0x02,
-       DwarfAttrName = 0x03,
-       DwarfAttrOrdering = 0x09,
-       DwarfAttrByteSize = 0x0B,
-       DwarfAttrBitOffset = 0x0C,
-       DwarfAttrBitSize = 0x0D,
-       DwarfAttrStmtList = 0x10,
-       DwarfAttrLowpc = 0x11,
-       DwarfAttrHighpc = 0x12,
-       DwarfAttrLanguage = 0x13,
-       DwarfAttrDiscr = 0x15,
-       DwarfAttrDiscrValue = 0x16,
-       DwarfAttrVisibility = 0x17,
-       DwarfAttrImport = 0x18,
-       DwarfAttrStringLength = 0x19,
-       DwarfAttrCommonRef = 0x1A,
-       DwarfAttrCompDir = 0x1B,
-       DwarfAttrConstValue = 0x1C,
-       DwarfAttrContainingType = 0x1D,
-       DwarfAttrDefaultValue = 0x1E,
-       DwarfAttrInline = 0x20,
-       DwarfAttrIsOptional = 0x21,
-       DwarfAttrLowerBound = 0x22,
-       DwarfAttrProducer = 0x25,
-       DwarfAttrPrototyped = 0x27,
-       DwarfAttrReturnAddr = 0x2A,
-       DwarfAttrStartScope = 0x2C,
-       DwarfAttrStrideSize = 0x2E,
-       DwarfAttrUpperBound = 0x2F,
-       DwarfAttrAbstractOrigin = 0x31,
-       DwarfAttrAccessibility = 0x32,
-       DwarfAttrAddrClass = 0x33,
-       DwarfAttrArtificial = 0x34,
-       DwarfAttrBaseTypes = 0x35,
-       DwarfAttrCalling = 0x36,
-       DwarfAttrCount = 0x37,
-       DwarfAttrDataMemberLoc = 0x38,
-       DwarfAttrDeclColumn = 0x39,
-       DwarfAttrDeclFile = 0x3A,
-       DwarfAttrDeclLine = 0x3B,
-       DwarfAttrDeclaration = 0x3C,
-       DwarfAttrDiscrList = 0x3D,
-       DwarfAttrEncoding = 0x3E,
-       DwarfAttrExternal = 0x3F,
-       DwarfAttrFrameBase = 0x40,
-       DwarfAttrFriend = 0x41,
-       DwarfAttrIdentifierCase = 0x42,
-       DwarfAttrMacroInfo = 0x43,
-       DwarfAttrNamelistItem = 0x44,
-       DwarfAttrPriority = 0x45,
-       DwarfAttrSegment = 0x46,
-       DwarfAttrSpecification = 0x47,
-       DwarfAttrStaticLink = 0x48,
-       DwarfAttrType = 0x49,
-       DwarfAttrUseLocation = 0x4A,
-       DwarfAttrVarParam = 0x4B,
-       DwarfAttrVirtuality = 0x4C,
-       DwarfAttrVtableElemLoc = 0x4D,
-       DwarfAttrAllocated = 0x4E,
-       DwarfAttrAssociated = 0x4F,
-       DwarfAttrDataLocation = 0x50,
-       DwarfAttrStride = 0x51,
-       DwarfAttrEntrypc = 0x52,
-       DwarfAttrUseUTF8 = 0x53,
-       DwarfAttrExtension = 0x54,
-       DwarfAttrRanges = 0x55,
-       DwarfAttrTrampoline = 0x56,
-       DwarfAttrCallColumn = 0x57,
-       DwarfAttrCallFile = 0x58,
-       DwarfAttrCallLine = 0x59,
-       DwarfAttrDescription = 0x5A,
-       DwarfAttrMax,
-
-       FormAddr = 0x01,
-       FormDwarfBlock2 = 0x03,
-       FormDwarfBlock4 = 0x04,
-       FormData2 = 0x05,
-       FormData4 = 0x06,
-       FormData8 = 0x07,
-       FormString = 0x08,
-       FormDwarfBlock = 0x09,
-       FormDwarfBlock1 = 0x0A,
-       FormData1 = 0x0B,
-       FormFlag = 0x0C,
-       FormSdata = 0x0D,
-       FormStrp = 0x0E,
-       FormUdata = 0x0F,
-       FormRefAddr = 0x10,
-       FormRef1 = 0x11,
-       FormRef2 = 0x12,
-       FormRef4 = 0x13,
-       FormRef8 = 0x14,
-       FormRefUdata = 0x15,
-       FormIndirect = 0x16
+    DwarfAttrSibling = 0x01,
+    DwarfAttrLocation = 0x02,
+    DwarfAttrName = 0x03,
+    DwarfAttrOrdering = 0x09,
+    DwarfAttrByteSize = 0x0B,
+    DwarfAttrBitOffset = 0x0C,
+    DwarfAttrBitSize = 0x0D,
+    DwarfAttrStmtList = 0x10,
+    DwarfAttrLowpc = 0x11,
+    DwarfAttrHighpc = 0x12,
+    DwarfAttrLanguage = 0x13,
+    DwarfAttrDiscr = 0x15,
+    DwarfAttrDiscrValue = 0x16,
+    DwarfAttrVisibility = 0x17,
+    DwarfAttrImport = 0x18,
+    DwarfAttrStringLength = 0x19,
+    DwarfAttrCommonRef = 0x1A,
+    DwarfAttrCompDir = 0x1B,
+    DwarfAttrConstValue = 0x1C,
+    DwarfAttrContainingType = 0x1D,
+    DwarfAttrDefaultValue = 0x1E,
+    DwarfAttrInline = 0x20,
+    DwarfAttrIsOptional = 0x21,
+    DwarfAttrLowerBound = 0x22,
+    DwarfAttrProducer = 0x25,
+    DwarfAttrPrototyped = 0x27,
+    DwarfAttrReturnAddr = 0x2A,
+    DwarfAttrStartScope = 0x2C,
+    DwarfAttrStrideSize = 0x2E,
+    DwarfAttrUpperBound = 0x2F,
+    DwarfAttrAbstractOrigin = 0x31,
+    DwarfAttrAccessibility = 0x32,
+    DwarfAttrAddrClass = 0x33,
+    DwarfAttrArtificial = 0x34,
+    DwarfAttrBaseTypes = 0x35,
+    DwarfAttrCalling = 0x36,
+    DwarfAttrCount = 0x37,
+    DwarfAttrDataMemberLoc = 0x38,
+    DwarfAttrDeclColumn = 0x39,
+    DwarfAttrDeclFile = 0x3A,
+    DwarfAttrDeclLine = 0x3B,
+    DwarfAttrDeclaration = 0x3C,
+    DwarfAttrDiscrList = 0x3D,
+    DwarfAttrEncoding = 0x3E,
+    DwarfAttrExternal = 0x3F,
+    DwarfAttrFrameBase = 0x40,
+    DwarfAttrFriend = 0x41,
+    DwarfAttrIdentifierCase = 0x42,
+    DwarfAttrMacroInfo = 0x43,
+    DwarfAttrNamelistItem = 0x44,
+    DwarfAttrPriority = 0x45,
+    DwarfAttrSegment = 0x46,
+    DwarfAttrSpecification = 0x47,
+    DwarfAttrStaticLink = 0x48,
+    DwarfAttrType = 0x49,
+    DwarfAttrUseLocation = 0x4A,
+    DwarfAttrVarParam = 0x4B,
+    DwarfAttrVirtuality = 0x4C,
+    DwarfAttrVtableElemLoc = 0x4D,
+    DwarfAttrAllocated = 0x4E,
+    DwarfAttrAssociated = 0x4F,
+    DwarfAttrDataLocation = 0x50,
+    DwarfAttrStride = 0x51,
+    DwarfAttrEntrypc = 0x52,
+    DwarfAttrUseUTF8 = 0x53,
+    DwarfAttrExtension = 0x54,
+    DwarfAttrRanges = 0x55,
+    DwarfAttrTrampoline = 0x56,
+    DwarfAttrCallColumn = 0x57,
+    DwarfAttrCallFile = 0x58,
+    DwarfAttrCallLine = 0x59,
+    DwarfAttrDescription = 0x5A,
+    DwarfAttrMax,
+
+    FormAddr = 0x01,
+    FormDwarfBlock2 = 0x03,
+    FormDwarfBlock4 = 0x04,
+    FormData2 = 0x05,
+    FormData4 = 0x06,
+    FormData8 = 0x07,
+    FormString = 0x08,
+    FormDwarfBlock = 0x09,
+    FormDwarfBlock1 = 0x0A,
+    FormData1 = 0x0B,
+    FormFlag = 0x0C,
+    FormSdata = 0x0D,
+    FormStrp = 0x0E,
+    FormUdata = 0x0F,
+    FormRefAddr = 0x10,
+    FormRef1 = 0x11,
+    FormRef2 = 0x12,
+    FormRef4 = 0x13,
+    FormRef8 = 0x14,
+    FormRefUdata = 0x15,
+    FormIndirect = 0x16
 };
 
-static int parseattrs(DwarfBuf*, ulong, DwarfAbbrev*, DwarfAttrs*);
+static int parseattrs(Dwarf *d, DwarfBuf*, ulong, ulong, DwarfAbbrev*, DwarfAttrs*);
 static int getulong(DwarfBuf*, int, ulong, ulong*, int*);
 static int getuchar(DwarfBuf*, int, uchar*);
-static int getstring(DwarfBuf*, int, char**);
+static int getstring(Dwarf *d, DwarfBuf*, int, char**);
 static int getblock(DwarfBuf*, int, DwarfBlock*);
-static int skipform(DwarfBuf*, int);
-static int constblock(Dwarf*, DwarfBlock*, ulong*);
+static int skipform(Dwarf *d, DwarfBuf*, int);
 
 int
 dwarflookupnameinunit(Dwarf *d, ulong unit, char *name, DwarfSym *s)
 {
-       if(dwarfenumunit(d, unit, s) < 0)
-               return -1;
-
-       dwarfnextsymat(d, s, 0);        /* s is now the CompileUnit */
-       while(dwarfnextsymat(d, s, 1) == 1)
-               if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
-                       return 0;
-       werrstr("symbol '%s' not found", name);
-       return -1;
+    DwarfSym compunit = { };
+    if(dwarfenumunit(d, unit, &compunit) < 0)
+        return -1;
+    while(dwarfnextsymat(d, &compunit, s) == 1)
+        if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
+            return 0;
+    werrstr("symbol '%s' not found", name);
+    return -1;
 }
-       
 
 int
 dwarflookupsubname(Dwarf *d, DwarfSym *parent, char *name, DwarfSym *s)
 {
-       *s = *parent;
-       while(dwarfnextsymat(d, s, parent->depth+1))
-               if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
-                       return 0;
-       werrstr("symbol '%s' not found", name);
-       return -1;
+    *s = *parent;
+    while(dwarfnextsymat(d, parent, s))
+        if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
+            return 0;
+    werrstr("symbol '%s' not found", name);
+    return -1;
 }
 
 int
-dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s)
+dwarflookupchildtag(Dwarf *d, DwarfSym *parent, ulong tag, DwarfSym *s)
 {
-       if(dwarfenumunit(d, unit, s) < 0) {
-               return -1;
-       }
+    int rsym = dwarfnextsymat(d, parent, s);
+    while (rsym == 0 && s->attrs.tag != tag) {
+        if (s->attrs.haskids) {
+            DwarfSym p = *s;
+            int csym = dwarflookupchildtag(d, &p, tag, s);
+            if (csym == 0) {
+                return csym;
+            }
+        }
+        rsym = dwarfnextsym(d, s);
+    }
+    return rsym;
+}
 
-       dwarfnextsymat(d, s, 0);        /* s is now the CompileUnit */
-       if(s->attrs.tag == tag) {
-               return 0;
-       }
-       while(dwarfnextsymat(d, s, 1) == 1)
-               if(s->attrs.tag == tag) {
-                       return 0;
-               }
-       werrstr("symbol with tag 0x%lux not found", tag);
-       return -1;
+int
+dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s)
+{
+    DwarfSym compunit = { };
+    if (dwarfenumunit(d, unit, &compunit) < 0) {
+        return -1;
+    }
+    do {
+        if (compunit.attrs.tag == tag) {
+            *s = compunit;
+            return 0;
+        }
+        if (dwarflookupchildtag(d, &compunit, tag, s) == 0)
+            return 0;
+    } while(dwarfnextsym(d, &compunit) == 0);
+    werrstr("symbol with tag 0x%lux not found", tag);
+    return -1;
 }
 
 int
 dwarfseeksym(Dwarf *d, ulong unit, ulong off, DwarfSym *s)
 {
-       if(dwarfenumunit(d, unit, s) < 0)
-               return -1;
-       s->b.p = d->info.data + unit + off;
-       if(dwarfnextsymat(d, s, 0) != 1)
-               return -1;
-       return 0;
+    DwarfSym compunit = { };
+    if(dwarfenumunit(d, unit, &compunit) < 0)
+        return -1;
+    s->b.p = d->info.data + unit + off;
+    if(dwarfnextsymat(d, &compunit, s) == -1)
+        return -1;
+    werrstr("dwarfseeksym: unit %x off %x, tag %x", unit, off, s->attrs.tag);
+    return 0;
 }
 
 int
 dwarflookupfn(Dwarf *d, ulong unit, ulong pc, DwarfSym *s)
 {
-       if(dwarfenumunit(d, unit, s) < 0)
-               return -1;
-
-       if(dwarfnextsymat(d, s, 0) != 1)
-               return -1;
-       /* s is now the CompileUnit */
-
-       while(dwarfnextsymat(d, s, 1) == 1){
-               if(s->attrs.tag != TagSubprogram)
-                       continue;
-               if(s->attrs.lowpc <= pc && pc < s->attrs.highpc)
-                       return 0;
-       } 
-       werrstr("fn containing pc 0x%lux not found", pc);
-       return -1;
+    DwarfSym compunit = { };
+    if(dwarfenumunit(d, unit, &compunit) < 0)
+        return -1;
+    while(dwarfnextsymat(d, &compunit, s) == 0){
+        if(s->attrs.tag != TagSubprogram)
+            continue;
+        if(s->attrs.lowpc <= pc && pc < s->attrs.highpc)
+            return 0;
+    }
+    werrstr("fn containing pc 0x%lux not found", pc);
+    return -1;
 }
 
 int
 dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s)
 {
-       int i;
-       ulong aoff, len;
-
-       if(unit >= d->info.len){
-               werrstr("dwarf unit address 0x%x >= 0x%x out of range", unit, d->info.len);
-               return -1;
-       }
-       memset(s, 0, sizeof *s);
-       memset(&s->b, 0, sizeof s->b);
-
-       s->b.d = d;
-       s->b.p = d->info.data + unit;
-       s->b.ep = d->info.data + d->info.len;
-       len = dwarfget4(&s->b);
-       s->nextunit = unit + 4 + len;
-
-       if(s->b.ep - s->b.p < len){
-       badheader:
-               werrstr("bad dwarf unit header at unit 0x%lux", unit);
-               return -1;
-       }
-       s->b.ep = s->b.p+len;
-       if((i=dwarfget2(&s->b)) != 2)
-               goto badheader;
-       aoff = dwarfget4(&s->b);
-       s->b.addrsize = dwarfget1(&s->b);
-       if(d->addrsize == 0)
-               d->addrsize = s->b.addrsize;
-       if(s->b.p == nil)
-               goto badheader;
-
-       s->aoff = aoff;
+    int i;
+    ulong aoff, len;
+
+    if(unit >= d->info.len){
+        werrstr("dwarf unit address 0x%x >= 0x%x out of range", unit, d->info.len);
+        return -1;
+    }
+    memset(s, 0, sizeof *s);
+    memset(&s->b, 0, sizeof s->b);
+
+    s->b.d = d;
+    s->b.p = d->info.data + unit;
+    s->b.ep = d->info.data + d->info.len;
+    len = dwarfget4(&s->b);
        s->unit = unit;
-       s->depth = 0;
-       return 0;
-}
-
-int
-dwarfenum(Dwarf *d, DwarfSym *s)
-{
-       if(dwarfenumunit(d, 0, s) < 0)
-               return -1;
-       s->allunits = 1;
-       return 0;
+    s->nextunit = unit + 4 + len;
+    s->b.ep = d->info.data + s->nextunit;
+
+    if(s->b.ep - s->b.p < len){
+    badheader:
+        werrstr("bad dwarf unit header at unit 0x%lux end %x start %x len %x", unit, s->b.ep - d->info.data, s->b.p - d->info.data, len);
+        return -1;
+    }
+    s->b.ep = s->b.p+len;
+    if((i=dwarfget2(&s->b)) != 2)
+        goto badheader;
+    aoff = dwarfget4(&s->b);
+    s->b.addrsize = dwarfget1(&s->b);
+    if(d->addrsize == 0)
+        d->addrsize = s->b.addrsize;
+    if(s->b.p == nil)
+        goto badheader;
+
+    s->aoff = aoff;
+
+    return dwarfnextsym(d, s);
 }
 
 int
 dwarfnextsym(Dwarf *d, DwarfSym *s)
 {
-       ulong num;
-       DwarfAbbrev *a;
-
-       if(s->attrs.haskids)
-               s->depth++;
-top:
-       if(s->b.p >= s->b.ep){
-               if(s->allunits && s->nextunit < d->info.len){
-                       if(dwarfenumunit(d, s->nextunit, s) < 0) {
-                               return -1;
-                       }
-                       s->allunits = 1;
-                       goto top;
-               }
-               return 0;
-       }
-
-       s->uoff = s->b.p - (d->info.data+s->unit);
-       num = dwarfget128(&s->b);
-       if(num == 0){
-               if(s->depth == 0) {
-                       return 0;
-               }
-               if(s->depth > 0)
-                       s->depth--;
-               goto top;
-       }
-
-       a = dwarfgetabbrev(d, s->aoff, num);
-       if(a == nil){
-               werrstr("getabbrev %ud %ud for %ud,%ud: %r\n", s->aoff, num, s->unit, s->uoff);
-               return -1;
-       }
-       if(parseattrs(&s->b, s->unit, a, &s->attrs) < 0) {
-               return -1;
-       }
-       return 1;
+    ulong num;
+    DwarfAbbrev *a;
+
+    num = dwarfget128(&s->b);
+    s->num = num;
+    if(num == 0){
+        return -1;
+    }
+
+    a = dwarfgetabbrev(d, s->aoff, num);
+    if(a == nil){
+        werrstr("getabbrev %ud %ud for %ud,%ud", s->aoff, num, s->unit);
+        return -1;
+    }
+
+    if(parseattrs(d, &s->b, s->attrs.tag, s->unit, a, &s->attrs) < 0) {
+        return -1;
+    }
+
+    if (s->attrs.haskids) {
+        DwarfSym childSkip = { };
+        s->childoff = s->b.p - d->info.data;
+        int r = dwarfnextsymat(d, s, &childSkip);
+        while (r == 0) {
+            r = dwarfnextsym(d, &childSkip);
+        }
+        s->b = childSkip.b;
+    } else {
+        s->childoff = 0;
+    }
+    return 0;
 }
 
 int
-dwarfnextsymat(Dwarf *d, DwarfSym *s, int depth)
+dwarfnextsymat(Dwarf *d, DwarfSym *parent, DwarfSym *child)
 {
-       int r;
-       DwarfSym t;
-       uint sib;
-
-       if(s->depth == depth && s->attrs.have.sibling){
-               sib = s->attrs.sibling;
-               if(sib < d->info.len && d->info.data+sib >= s->b.p)
-                       s->b.p = d->info.data+sib;
-               s->attrs.haskids = 0;
-       }
-
-       /*
-        * The funny game with t and s make sure that 
-        * if we get to the end of a run of a particular
-        * depth, we leave s so that a call to nextsymat with depth-1
-        * will actually produce the desired guy.  We could change
-        * the interface to dwarfnextsym instead, but I'm scared 
-        * to touch it.
-        */
-       t = *s;
-       for(;;){
-               if((r = dwarfnextsym(d, &t)) != 1) {
-                       return r;
-               }
-               if(t.depth < depth){
-                       /* went too far - nothing to see */
-                       return 0;
-               }
-               *s = t;
-               if(t.depth == depth) {
-                       return 1;
-               }
-       }
+    uint sib;
+
+    if (!parent->attrs.haskids || !parent->childoff)
+        return -1;
+
+       child->unit = parent->unit;
+    child->aoff = parent->aoff;
+    child->depth = parent->depth + 1;
+    if(child->attrs.have.sibling){
+        sib = child->attrs.sibling;
+        if(sib < d->info.len && d->info.data+sib > child->b.p)
+            child->b.p = d->info.data+sib;
+        else if (sib >= d->info.len) {
+            werrstr("sibling reported as out of bounds %d vs %d", sib, d->info.len);
+            return -1;
+        } else if (d->info.data+sib+parent->unit < child->b.p) {
+            werrstr("subsequent sibling is listed before prev %d vs %d", sib+parent->unit, child->b.p - d->info.data);
+            return -1;
+        }
+    }
+
+    // Uninitialized
+    if (!child->b.d) {
+        child->b = parent->b;
+        child->b.p = parent->childoff + parent->b.d->info.data;
+    }
+
+    return dwarfnextsym(d, child);
 }
 
 typedef struct Parse Parse;
 struct Parse {
-       int name;
-       int off;
-       int haveoff;
-       int type;
+    int name;
+    int off;
+    int haveoff;
+    int type;
 };
 
 #define OFFSET(x) offsetof(DwarfAttrs, x), offsetof(DwarfAttrs, have.x)
 
 static Parse plist[] = {       /* Font Tab 4 */
-       { DwarfAttrAbstractOrigin,      OFFSET(abstractorigin),         TReference },
-       { DwarfAttrAccessibility,       OFFSET(accessibility),          TConstant },
-       { DwarfAttrAddrClass,           OFFSET(addrclass),                      TConstant },
-       { DwarfAttrArtificial,          OFFSET(isartificial),           TFlag },
-       { DwarfAttrBaseTypes,           OFFSET(basetypes),                      TReference },
-       { DwarfAttrBitOffset,           OFFSET(bitoffset),                      TConstant },
-       { DwarfAttrBitSize,             OFFSET(bitsize),                        TConstant },
-       { DwarfAttrByteSize,            OFFSET(bytesize),                       TConstant },
-       { DwarfAttrCalling,             OFFSET(calling),                        TConstant },
-       { DwarfAttrCommonRef,           OFFSET(commonref),                      TReference },
-       { DwarfAttrCompDir,             OFFSET(compdir),                        TString },
-       { DwarfAttrConstValue,          OFFSET(constvalue),                     TString|TConstant|TBlock },
-       { DwarfAttrContainingType,      OFFSET(containingtype),         TReference },
-       { DwarfAttrCount,                       OFFSET(count),                          TConstant|TReference },
-       { DwarfAttrDataMemberLoc,       OFFSET(datamemberloc),          TBlock|TConstant|TReference },
-       { DwarfAttrDeclColumn,          OFFSET(declcolumn),                     TConstant },
-       { DwarfAttrDeclFile,            OFFSET(declfile),                       TConstant },
-       { DwarfAttrDeclLine,            OFFSET(declline),                       TConstant },
-       { DwarfAttrDeclaration, OFFSET(isdeclaration),          TFlag },
-       { DwarfAttrDefaultValue,        OFFSET(defaultvalue),           TReference },
-       { DwarfAttrDiscr,                       OFFSET(discr),                          TReference },
-       { DwarfAttrDiscrList,           OFFSET(discrlist),                      TBlock },
-       { DwarfAttrDiscrValue,          OFFSET(discrvalue),                     TConstant },
-       { DwarfAttrEncoding,            OFFSET(encoding),                       TConstant },
-       { DwarfAttrExternal,            OFFSET(isexternal),                     TFlag },
-       { DwarfAttrFrameBase,           OFFSET(framebase),                      TBlock|TConstant },
-       { DwarfAttrFriend,                      OFFSET(friend),                         TReference },
-       { DwarfAttrHighpc,                      OFFSET(highpc),                         TAddress },
-       { DwarfAttrEntrypc,         OFFSET(entrypc),            TAddress },
-       { DwarfAttrIdentifierCase,      OFFSET(identifiercase),         TConstant },
-       { DwarfAttrImport,                      OFFSET(import),                         TReference },
-       { DwarfAttrInline,                      OFFSET(inlined),                        TConstant },
-       { DwarfAttrIsOptional,          OFFSET(isoptional),                     TFlag },
-       { DwarfAttrLanguage,            OFFSET(language),                       TConstant },
-       { DwarfAttrLocation,            OFFSET(location),                       TBlock|TConstant },
-       { DwarfAttrLowerBound,          OFFSET(lowerbound),                     TConstant|TReference },
-       { DwarfAttrLowpc,                       OFFSET(lowpc),                          TAddress },
-       { DwarfAttrMacroInfo,           OFFSET(macroinfo),                      TConstant },
-       { DwarfAttrName,                        OFFSET(name),                           TString },
-       { DwarfAttrNamelistItem,        OFFSET(namelistitem),           TBlock },
-       { DwarfAttrOrdering,            OFFSET(ordering),                       TConstant },
-       { DwarfAttrPriority,            OFFSET(priority),                       TReference },
-       { DwarfAttrProducer,            OFFSET(producer),                       TString },
-       { DwarfAttrPrototyped,          OFFSET(isprototyped),           TFlag },
-       { DwarfAttrRanges,                      OFFSET(ranges),                         TReference },
-       { DwarfAttrReturnAddr,          OFFSET(returnaddr),                     TBlock|TConstant },
-       { DwarfAttrSegment,             OFFSET(segment),                        TBlock|TConstant },
-       { DwarfAttrSibling,             OFFSET(sibling),                        TReference },
-       { DwarfAttrSpecification,       OFFSET(specification),          TReference },
-       { DwarfAttrStartScope,          OFFSET(startscope),                     TConstant },
-       { DwarfAttrStaticLink,          OFFSET(staticlink),                     TBlock|TConstant },
-       { DwarfAttrStmtList,            OFFSET(stmtlist),                       TConstant },
-       { DwarfAttrStrideSize,          OFFSET(stridesize),                     TConstant },
-       { DwarfAttrStringLength,        OFFSET(stringlength),           TBlock|TConstant },
-       { DwarfAttrType,                        OFFSET(type),                           TReference },
-       { DwarfAttrUpperBound,          OFFSET(upperbound),                     TConstant|TReference },
-       { DwarfAttrUseLocation, OFFSET(uselocation),            TBlock|TConstant },
-       { DwarfAttrVarParam,            OFFSET(isvarparam),                     TFlag },
-       { DwarfAttrVirtuality,          OFFSET(virtuality),                     TConstant },
-       { DwarfAttrVisibility,          OFFSET(visibility),                     TConstant },
-       { DwarfAttrVtableElemLoc,       OFFSET(vtableelemloc),          TBlock|TReference },
-       { }
+    { DwarfAttrAbstractOrigin, OFFSET(abstractorigin),         TReference },
+    { DwarfAttrAccessibility,  OFFSET(accessibility),          TConstant },
+    { DwarfAttrAddrClass,              OFFSET(addrclass),                      TConstant },
+    { DwarfAttrArtificial,             OFFSET(isartificial),           TFlag },
+    { DwarfAttrBaseTypes,              OFFSET(basetypes),                      TReference },
+    { DwarfAttrBitOffset,              OFFSET(bitoffset),                      TConstant },
+    { DwarfAttrBitSize,                OFFSET(bitsize),                        TConstant },
+    { DwarfAttrByteSize,               OFFSET(bytesize),                       TConstant },
+    { DwarfAttrCalling,                OFFSET(calling),                        TConstant },
+    { DwarfAttrCommonRef,              OFFSET(commonref),                      TReference },
+    { DwarfAttrCompDir,                OFFSET(compdir),                        TString },
+    { DwarfAttrConstValue,             OFFSET(constvalue),                     TString|TConstant|TBlock },
+    { DwarfAttrContainingType, OFFSET(containingtype),         TReference },
+    { DwarfAttrCount,                  OFFSET(count),                          TConstant|TReference },
+    { DwarfAttrDataMemberLoc,  OFFSET(datamemberloc),          TBlock|TConstant|TReference },
+    { DwarfAttrDeclColumn,             OFFSET(declcolumn),                     TConstant },
+    { DwarfAttrDeclFile,               OFFSET(declfile),                       TConstant },
+    { DwarfAttrDeclLine,               OFFSET(declline),                       TConstant },
+    { DwarfAttrDeclaration,    OFFSET(isdeclaration),          TFlag },
+    { DwarfAttrDefaultValue,   OFFSET(defaultvalue),           TReference },
+    { DwarfAttrDiscr,                  OFFSET(discr),                          TReference },
+    { DwarfAttrDiscrList,              OFFSET(discrlist),                      TBlock },
+    { DwarfAttrDiscrValue,             OFFSET(discrvalue),                     TConstant },
+    { DwarfAttrEncoding,               OFFSET(encoding),                       TConstant },
+    { DwarfAttrExternal,               OFFSET(isexternal),                     TFlag },
+    { DwarfAttrFrameBase,              OFFSET(framebase),                      TBlock|TConstant },
+    { DwarfAttrFriend,                 OFFSET(friend),                         TReference },
+    { DwarfAttrHighpc,                 OFFSET(highpc),                         TAddress },
+    { DwarfAttrEntrypc,         OFFSET(entrypc),            TAddress },
+    { DwarfAttrIdentifierCase, OFFSET(identifiercase),         TConstant },
+    { DwarfAttrImport,                 OFFSET(import),                         TReference },
+    { DwarfAttrInline,                 OFFSET(inlined),                        TConstant },
+    { DwarfAttrIsOptional,             OFFSET(isoptional),                     TFlag },
+    { DwarfAttrLanguage,               OFFSET(language),                       TConstant },
+    { DwarfAttrLocation,               OFFSET(location),                       TReference|TBlock },
+    { DwarfAttrLowerBound,             OFFSET(lowerbound),                     TConstant|TReference },
+    { DwarfAttrLowpc,                  OFFSET(lowpc),                          TAddress },
+    { DwarfAttrMacroInfo,              OFFSET(macroinfo),                      TConstant },
+    { DwarfAttrName,                   OFFSET(name),                           TString },
+    { DwarfAttrNamelistItem,   OFFSET(namelistitem),           TBlock },
+    { DwarfAttrOrdering,               OFFSET(ordering),                       TConstant },
+    { DwarfAttrPriority,               OFFSET(priority),                       TReference },
+    { DwarfAttrProducer,               OFFSET(producer),                       TString },
+    { DwarfAttrPrototyped,             OFFSET(isprototyped),           TFlag },
+    { DwarfAttrRanges,                 OFFSET(ranges),                         TReference },
+    { DwarfAttrReturnAddr,             OFFSET(returnaddr),                     TBlock|TConstant },
+    { DwarfAttrSegment,                OFFSET(segment),                        TBlock|TConstant },
+    { DwarfAttrSibling,                OFFSET(sibling),                        TReference },
+    { DwarfAttrSpecification,  OFFSET(specification),          TReference },
+    { DwarfAttrStartScope,             OFFSET(startscope),                     TConstant },
+    { DwarfAttrStaticLink,             OFFSET(staticlink),                     TBlock|TConstant },
+    { DwarfAttrStmtList,               OFFSET(stmtlist),                       TConstant },
+    { DwarfAttrStrideSize,             OFFSET(stridesize),                     TConstant },
+    { DwarfAttrStringLength,   OFFSET(stringlength),           TBlock|TConstant },
+    { DwarfAttrType,                   OFFSET(type),                           TReference },
+    { DwarfAttrUpperBound,             OFFSET(upperbound),                     TConstant|TReference },
+    { DwarfAttrUseLocation,    OFFSET(uselocation),            TBlock|TConstant },
+    { DwarfAttrVarParam,               OFFSET(isvarparam),                     TFlag },
+    { DwarfAttrVirtuality,             OFFSET(virtuality),                     TConstant },
+    { DwarfAttrVisibility,             OFFSET(visibility),                     TConstant },
+    { DwarfAttrVtableElemLoc,  OFFSET(vtableelemloc),          TBlock|TReference },
+    { }
 };
 
 static Parse ptab[DwarfAttrMax];
 
 static int
-parseattrs(DwarfBuf *b, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs)
+parseattrs(Dwarf *d, DwarfBuf *b, ulong tag, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs)
 {
-       int i, f, n, got;
-       static int nbad;
-       void *v;
-
-       /* initialize ptab first time through for quick access */
-       if(ptab[DwarfAttrName].name != DwarfAttrName)
-               for(i=0; plist[i].name; i++)
-                       ptab[plist[i].name] = plist[i];
-
-       memset(attrs, 0, sizeof *attrs);
-       attrs->tag = a->tag;
-       attrs->haskids = a->haskids;
-
-       for(i=0; i<a->nattr; i++){
-               n = a->attr[i].name;
-               f = a->attr[i].form;
-               if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0){
-                       if(++nbad == 1)
-                               werrstr("dwarf parse attrs: unexpected attribute name 0x%x", n);
-                       continue; //return -1;
-               }
-               v = (char*)attrs + ptab[n].off;
-               got = 0;
-               if(f == FormIndirect)
-                       f = dwarfget128(b);
-               if((ptab[n].type&(TConstant|TReference|TAddress))
-               && getulong(b, f, unit, v, &got) >= 0)
-                       ;
-               else if((ptab[n].type&TFlag) && getuchar(b, f, v) >= 0)
-                       got = TFlag;
-               else if((ptab[n].type&TString) && getstring(b, f, v) >= 0)
-                       got = TString;
-               else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0)
-                       got = TBlock;
-               else{
-                       if(skipform(b, f) < 0){
-                               if(++nbad == 1)
-                                       werrstr("dwarf parse attrs: cannot skip form %d", f);
-                               return -1;
-                       }
-               }
-               if(got == TBlock && (ptab[n].type&TConstant))
-                       got = constblock(b->d, v, v);
-               *((uchar*)attrs+ptab[n].haveoff) = got;
-       }
-       return 0;
+    int i, f, n, got;
+    static int nbad;
+    void *v;
+
+    /* initialize ptab first time through for quick access */
+    if(ptab[DwarfAttrName].name != DwarfAttrName)
+        for(i=0; plist[i].name; i++)
+            ptab[plist[i].name] = plist[i];
+
+    memset(attrs, 0, sizeof *attrs);
+    attrs->tag = a->tag;
+    attrs->haskids = a->haskids;
+
+    for(i=0; i<a->nattr; i++){
+        n = a->attr[i].name;
+        f = a->attr[i].form;
+        if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0) {
+            if (skipform(d, b, f) < 0) {
+                if(++nbad == 1)
+                    werrstr("dwarf parse attrs: cannot skip form %d", f);
+                return -1;
+            }
+            continue;
+        }
+        v = (char*)attrs + ptab[n].off;
+        got = 0;
+        if(f == FormIndirect)
+            f = dwarfget128(b);
+        if((ptab[n].type&(TConstant|TReference|TAddress))
+           && getulong(b, f, unit, v, &got) >= 0)
+            ;
+        else if((ptab[n].type&TFlag) && getuchar(b, f, v) >= 0)
+            got = TFlag;
+        else if((ptab[n].type&TString) && getstring(d, b, f, v) >= 0)
+            got = TString;
+        else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0)
+            got = TBlock;
+        else {
+            if(skipform(d, b, f) < 0){
+                if(++nbad == 1)
+                    werrstr("dwarf parse attrs: cannot skip form %d", f);
+                return -1;
+            }
+        }
+#if 0
+        if(got == TBlock && (ptab[n].type&TConstant))
+            got = constblock(b->d, v, v);
+#endif
+        *((uchar*)attrs+ptab[n].haveoff) = got;
+    }
+    return 0;
 }
 
 static int
 getulong(DwarfBuf *b, int form, ulong unit, ulong *u, int *type)
 {
-       static int nbad;
-       uvlong uv;
+    static int nbad;
+    uvlong uv;
 
-       switch(form){
-       default:
-               return -1;
+    switch(form){
+    default:
+        return -1;
 
        /* addresses */
-       case FormAddr:
-               *type = TAddress;
-               *u = dwarfgetaddr(b);
-               return 0;
+    case FormAddr:
+        *type = TAddress;
+        *u = dwarfgetaddr(b);
+        return 0;
 
        /* references */
-       case FormRefAddr:
-               /* absolute ref in .debug_info */
-               *type = TReference;
-               *u = dwarfgetaddr(b);
-               return 0;
-       case FormRef1:
-               *u = dwarfget1(b);
-               goto relativeref;
-       case FormRef2:
-               *u = dwarfget2(b);
-               goto relativeref;
-       case FormRef4:
-               *u = dwarfget4(b);
-               goto relativeref;
-       case FormRef8:
-               *u = dwarfget8(b);
-               goto relativeref;
-       case FormRefUdata:
-               *u = dwarfget128(b);
-       relativeref:
-               *u += unit;
-               *type = TReference;
-               return 0;
+    case FormRefAddr:
+        /* absolute ref in .debug_info */
+        *type = TReference;
+        *u = dwarfgetaddr(b);
+        return 0;
+    case FormRef1:
+        *u = dwarfget1(b);
+        goto relativeref;
+    case FormRef2:
+        *u = dwarfget2(b);
+        goto relativeref;
+    case FormRef4:
+        *u = dwarfget4(b);
+        goto relativeref;
+    case FormRef8:
+        *u = dwarfget8(b);
+        goto relativeref;
+    case FormRefUdata:
+        *u = dwarfget128(b);
+    relativeref:
+        *u += unit;
+        *type = TReference;
+        return 0;
 
        /* constants */
-       case FormData1:
-               *u = dwarfget1(b);
-               goto constant;
-       case FormData2:
-               *u = dwarfget2(b);
-               goto constant;
-       case FormData4:
-               *u = dwarfget4(b);
-               goto constant;
-       case FormData8:
-               uv = dwarfget8(b);
-               *u = uv;
-               if(uv != *u && ++nbad == 1)
-                       werrstr("dwarf: truncating 64-bit attribute constants");
-               goto constant;
-       case FormSdata:
-               *u = dwarfget128s(b);
-               goto constant;
-       case FormUdata:
-               *u = dwarfget128(b);
-       constant:
-               *type = TConstant;
-               return 0;
-       }
+    case FormData1:
+        *u = dwarfget1(b);
+        goto constant;
+    case FormData2:
+        *u = dwarfget2(b);
+        goto constant;
+    case FormData4:
+        *u = dwarfget4(b);
+        goto constant;
+    case FormData8:
+        uv = dwarfget8(b);
+        *u = uv;
+        if(uv != *u && ++nbad == 1)
+            werrstr("dwarf: truncating 64-bit attribute constants");
+        goto constant;
+    case FormSdata:
+        *u = dwarfget128s(b);
+        goto constant;
+    case FormUdata:
+        *u = dwarfget128(b);
+    constant:
+        *type = TConstant;
+        return 0;
+    }
 }
 
 static int
 getuchar(DwarfBuf *b, int form, uchar *u)
 {
-       switch(form){
-       default:
-               return -1;
-
-       case FormFlag:
-               *u = dwarfget1(b);
-               return 0;
-       }
+    switch(form){
+    default:
+        return -1;
+
+    case FormFlag:
+        *u = dwarfget1(b);
+        return 0;
+    }
 }
 
 static int
-getstring(DwarfBuf *b, int form, char **s)
+getstring(Dwarf *d, DwarfBuf *b, int form, char **s)
 {
-       static int nbad;
-       ulong u;
-
-       switch(form){
-       default:
-               return -1;
-
-       case FormString:
-               *s = dwarfgetstring(b);
-               return 0;
-
-       case FormStrp:
-               u = dwarfget4(b);
-               if(u >= b->d->str.len){
-                       if(++nbad == 1)
-                               werrstr("dwarf: bad string pointer 0x%lux in attribute", u);
-                       /* don't return error - maybe can proceed */
-                       *s = nil;
-               }else
-                       *s = (char*)b->d->str.data + u;
-               return 0;
-
-       }
+    static int nbad;
+    ulong u, x;
+
+    switch(form){
+    default:
+        return -1;
+
+    case FormString:
+        x = b->p - d->info.data;
+        *s = dwarfgetstring(b);
+        for (u = 0; (*s)[u]; u++) {
+            assert(isprint((*s)[u]));
+        }
+        return 0;
+
+    case FormStrp:
+        u = dwarfget4(b);
+        if(u >= b->d->str.len){
+            if(++nbad == 1)
+                werrstr("dwarf: bad string pointer 0x%lux in attribute", u);
+            /* don't return error - maybe can proceed */
+            *s = nil;
+        }else
+            *s = (char*)b->d->str.data + u;
+        return 0;
+
+    }
 }
 
 static int
 getblock(DwarfBuf *b, int form, DwarfBlock *bl)
 {
-       ulong n;
-
-       switch(form){
-       default:
-               return -1;
-       case FormDwarfBlock:
-               n = dwarfget128(b);
-               goto copyn;
-       case FormDwarfBlock1:
-               n = dwarfget1(b);
-               goto copyn;
-       case FormDwarfBlock2:
-               n = dwarfget2(b);
-               goto copyn;
-       case FormDwarfBlock4:
-               n = dwarfget4(b);
-       copyn:
-               bl->data = dwarfgetnref(b, n);
-               bl->len = n;
-               if(bl->data == nil)
-                       return -1;
-               return 0;
-       }
+    ulong n;
+
+    switch(form){
+    default:
+        return -1;
+    case FormDwarfBlock:
+        n = dwarfget128(b);
+        goto copyn;
+    case FormDwarfBlock1:
+        n = dwarfget1(b);
+        goto copyn;
+    case FormDwarfBlock2:
+        n = dwarfget2(b);
+        goto copyn;
+    case FormDwarfBlock4:
+        n = dwarfget4(b);
+    copyn:
+        bl->data = dwarfgetnref(b, n);
+        bl->len = n;
+        if(bl->data == nil)
+            return -1;
+        return 0;
+    }
 }
 
+/* last resort */
 static int
-constblock(Dwarf *d, DwarfBlock *bl, ulong *pval)
+skipform(Dwarf *d, DwarfBuf *b, int form)
 {
-       DwarfBuf b;
-
-       memset(&b, 0, sizeof b);
-       b.p = bl->data;
-       b.ep = bl->data+bl->len;
-       b.d = d;
-
-       switch(dwarfget1(&b)){
-       case OpAddr:
-               *pval = dwarfgetaddr(&b);
-               return TConstant;
-       case OpConst1u:
-               *pval = dwarfget1(&b);
-               return TConstant;
-       case OpConst1s:
-               *pval = (schar)dwarfget1(&b);
-               return TConstant;
-       case OpConst2u:
-               *pval = dwarfget2(&b);
-               return TConstant;
-       case OpConst2s:
-               *pval = (s16int)dwarfget2(&b);
-               return TConstant;
-       case OpConst4u:
-               *pval = dwarfget4(&b);
-               return TConstant;
-       case OpConst4s:
-               *pval = (s32int)dwarfget4(&b);
-               return TConstant;
-       case OpConst8u:
-               *pval = (u64int)dwarfget8(&b);
-               return TConstant;
-       case OpConst8s:
-               *pval = (s64int)dwarfget8(&b);
-               return TConstant;
-       case OpConstu:
-               *pval = dwarfget128(&b);
-               return TConstant;
-       case OpConsts:
-               *pval = dwarfget128s(&b);
-               return TConstant;
-       case OpPlusUconst:
-               *pval = dwarfget128(&b);
-               return TConstant;
-       default:
-               return TBlock;
-       }
+    int type;
+    DwarfVal val;
+
+    if(getulong(b, form, 0, &val.c, &type) < 0
+       && getuchar(b, form, (uchar*)&val) < 0
+       && getstring(d, b, form, &val.s) < 0
+       && getblock(b, form, &val.b) < 0)
+        return -1;
+    return 0;
 }
 
-/* last resort */
-static int
-skipform(DwarfBuf *b, int form)
+void stackinit(DwarfStack *stack)
+{
+    memset(stack, 0, sizeof(*stack));
+    stack->data = stack->storage;
+    stack->length = 0; stack->max = sizeof(stack->storage) / sizeof(stack->storage[0]);
+}
+
+void stackpush(DwarfStack *stack, ulong value)
 {
-       int type;
-       DwarfVal val;
-
-       if(getulong(b, form, 0, &val.c, &type) < 0
-       && getuchar(b, form, (uchar*)&val) < 0
-       && getstring(b, form, &val.s) < 0
-       && getblock(b, form, &val.b) < 0)
-               return -1;
-       return 0;
+    if (stack->length == stack->max) {
+        ulong *newstack = malloc(sizeof(ulong)*stack->max*2);
+        memcpy(newstack, stack->data, sizeof(ulong)*stack->length);
+        if (stack->data != stack->storage)
+            free(stack->data);
+        stack->data = newstack;
+        stack->max *= 2;
+    }
+    werrstr("stack[%d] = %x", stack->length, value);
+    stack->data[stack->length++] = value;
 }
 
+ulong stackpop(DwarfStack *stack) 
+{
+    ASSERT(stack->length > 0);
+    ulong val = stack->data[--stack->length];
+    werrstr("pop stack[%d] -> %x", stack->length, val);
+    return val;
+}
+
+void stackfree(DwarfStack *stack)
+{
+    if (stack->data != stack->storage)
+        free(stack->data);
+}
+
+// Returns -1 on failure
+int dwarfgetarg(Dwarf *d, const char *name, DwarfBuf *buf, ulong cfa, PROSSYM_REGISTERS registers, ulong *result)
+{
+    int ret = 0;
+    DwarfStack stack = { };
+    stackinit(&stack);
+    while (buf->p < buf->ep) {
+        int opcode = dwarfget1(buf);
+        werrstr("opcode %x", opcode);
+        switch (opcode) {
+        case 0:
+            buf->p = buf->ep;
+            break;
+        case OpAddr:
+            if (d->addrsize == 4) {
+                stackpush(&stack, dwarfget4(buf));
+                break;
+            } else {
+                werrstr("%s: we only support 4 byte addrs", name);
+                goto fatal;
+            }
+        case OpConst1s: {
+            signed char c = dwarfget1(buf);
+            stackpush(&stack, c);
+        } break;
+        case OpConst1u:
+            stackpush(&stack, dwarfget1(buf));
+            break;
+        case OpConst2s: {
+            signed short s = dwarfget2(buf);
+            stackpush(&stack, s);
+        } break;
+        case OpConst2u:
+            stackpush(&stack, dwarfget2(buf));
+            break;
+        case OpConst4s: {
+            signed int i = dwarfget4(buf);
+            stackpush(&stack, i);
+        } break;
+        case OpConst4u:
+            stackpush(&stack, dwarfget4(buf));
+            break;
+        case OpConst8s:
+        case OpConst8u:
+            werrstr("const 8 not yet supported");
+            goto fatal;
+        case OpConsts:
+            stackpush(&stack, dwarfget128s(buf));
+            break;
+        case OpConstu:
+            stackpush(&stack, dwarfget128(buf));
+            break;
+        case OpDup: {
+            ulong popped = stackpop(&stack);
+            stackpush(&stack, popped);
+            stackpush(&stack, popped);
+        } break;
+        case OpDrop:
+            stackpop(&stack);
+            break;
+        case OpOver: {
+            if (stack.length < 2) goto fatal;
+            stackpush(&stack, stack.data[stack.length-2]);
+        } break;
+        case OpPick: {
+            ulong arg = dwarfget1(buf);
+            if (arg >= stack.length) goto fatal;
+            arg = stack.data[stack.length-1-arg];
+            stackpush(&stack, arg);
+        } break;
+        case OpSwap: {
+            ulong a = stackpop(&stack), b = stackpop(&stack);
+            stackpush(&stack, b);
+            stackpush(&stack, a);
+        } break;
+        case OpRot: {
+            ulong a = stackpop(&stack), b = stackpop(&stack), c = stackpop(&stack);
+            stackpush(&stack, b);
+            stackpush(&stack, c);
+            stackpush(&stack, a);
+        } break;
+        case OpXderef:
+        case OpXderefSize:
+            werrstr("Xderef not yet supported");
+            goto fatal;
+        case OpAbs: {
+            long a = stackpop(&stack);
+            stackpush(&stack, a < 0 ? -a : a);
+        } break;
+        case OpAnd:
+            stackpush(&stack, stackpop(&stack) & stackpop(&stack));
+            break;
+        case OpDiv: {
+            ulong a = stackpop(&stack), b = stackpop(&stack);
+            stackpush(&stack, b / a);
+        } break;
+        case OpMinus: {
+            ulong a = stackpop(&stack), b = stackpop(&stack);
+            stackpush(&stack, b - a);
+        } break;
+        case OpMod: {
+            ulong a = stackpop(&stack), b = stackpop(&stack);
+            stackpush(&stack, b % a);
+        } break;
+        case OpMul:
+            stackpush(&stack, stackpop(&stack) * stackpop(&stack));
+            break;
+        case OpNeg:
+            stackpush(&stack, -stackpop(&stack));
+            break;
+        case OpNot:
+            stackpush(&stack, ~stackpop(&stack));
+            break;
+        case OpOr:
+            stackpush(&stack, stackpop(&stack) | stackpop(&stack));
+            break;
+        case OpPlus:
+            stackpush(&stack, stackpop(&stack) + stackpop(&stack));
+            break;
+        case OpPlusUconst:
+            stackpush(&stack, stackpop(&stack) + dwarfget128(buf));
+            break;
+        case OpShl: {
+            ulong a = stackpop(&stack), b = stackpop(&stack);
+            stackpush(&stack, b << a);
+        } break;
+        case OpShr: {
+            ulong a = stackpop(&stack), b = stackpop(&stack);
+            stackpush(&stack, b >> a);
+        } break;
+        case OpShra: {
+            ulong a = stackpop(&stack);
+            long b = stackpop(&stack);
+            if (b < 0)
+                b = -(-b >> a);
+            else
+                b = b >> a;
+            stackpush(&stack, b);
+        } break;
+        case OpXor:
+            stackpush(&stack, stackpop(&stack) ^ stackpop(&stack));
+            break;
+        case OpSkip:
+            buf->p += dwarfget2(buf);
+            break;
+        case OpBra: {
+            ulong a = dwarfget2(buf);
+            if (stackpop(&stack))
+                buf->p += a;
+        } break;
+        case OpEq:
+            stackpush(&stack, stackpop(&stack) == stackpop(&stack));
+            break;
+        case OpGe: {
+            ulong a = stackpop(&stack), b = stackpop(&stack);
+            stackpush(&stack, b >= a);
+        } break;
+        case OpGt: {
+            ulong a = stackpop(&stack), b = stackpop(&stack);
+            stackpush(&stack, b > a);
+        } break;
+        case OpLe: {
+            ulong a = stackpop(&stack), b = stackpop(&stack);
+            stackpush(&stack, b <= a);
+        } break;
+        case OpLt: {
+            ulong a = stackpop(&stack), b = stackpop(&stack);
+            stackpush(&stack, b < a);
+        } break;
+        case OpNe:
+            stackpush(&stack, stackpop(&stack) != stackpop(&stack));
+            break;
+        case OpNop:
+            break;
+        case OpDeref: {
+            ulong val, addr = stackpop(&stack);
+            if (!RosSymCallbacks.MemGetProc
+                (d->pe->fd,
+                 &val,
+                 addr,
+                 d->addrsize))
+                goto fatal;
+            stackpush(&stack, val);
+        } break;
+        case OpDerefSize: {
+            ulong val, addr = stackpop(&stack), size = dwarfget1(buf);
+            if (!RosSymCallbacks.MemGetProc
+                (d->pe->fd,
+                 &val,
+                 addr,
+                 size))
+                goto fatal;
+            stackpush(&stack, val);
+        } break;
+        case OpFbreg: {
+            ulong val, addr = cfa, offset = dwarfget128s(buf);
+            werrstr("FBREG cfa %x offset %x", cfa, offset);
+            if (!RosSymCallbacks.MemGetProc
+                (d->pe->fd,
+                 &val,
+                 addr+offset,
+                 d->addrsize))
+                goto fatal;
+            stackpush(&stack, val);
+        } break;
+        case OpPiece:
+            werrstr("OpPiece not supported");
+            goto fatal;
+        default:
+            if (opcode >= OpLit0 && opcode < OpReg0)
+                stackpush(&stack, opcode - OpLit0);
+            else if (opcode >= OpReg0 && opcode < OpBreg0) {
+                ulong reg = opcode - OpReg0;
+                werrstr("REG[%d] value %x", reg, (ulong)registers->Registers[reg]);
+                stackpush(&stack, registers->Registers[reg]);
+            } else if (opcode >= OpBreg0 && opcode < OpRegx) {
+                ulong val, 
+                    reg = opcode - OpBreg0, 
+                    addr = registers->Registers[reg],
+                    offset = dwarfget128s(buf);
+                werrstr("BREG[%d] reg %x offset %x", reg, addr, offset);
+                if (!RosSymCallbacks.MemGetProc
+                    (d->pe->fd,
+                     &val,
+                     addr + offset,
+                     d->addrsize))
+                    goto fatal;
+                stackpush(&stack, val);
+            } else {
+                werrstr("opcode %x not supported", opcode);
+                goto fatal;
+            }
+            break;
+        }
+    }
+    if (stack.length < 1) goto fatal;
+    *result = stackpop(&stack);
+    werrstr("%s: value %x", name, *result);
+    goto finish;
+
+fatal:
+    ret = -1;
+
+finish:
+    stackfree(&stack);
+    return ret;
+}
+
+int dwarfargvalue(Dwarf *d, DwarfSym *proc, ulong pc, ulong cfa, PROSSYM_REGISTERS registers, DwarfParam *parameter)
+{
+    int gotarg;
+    DwarfSym unit = { };
+
+    if (dwarfenumunit(d, proc->unit, &unit) == -1)
+        return -1;
+
+    werrstr("lookup in unit %x-%x, pc %x", unit.attrs.lowpc, unit.attrs.highpc, pc);
+    pc -= unit.attrs.lowpc;
+    
+    werrstr("paramblock %s -> unit %x type %x fde %x len %d registers %x", 
+            parameter->name, 
+            parameter->unit, 
+            parameter->type, 
+            parameter->fde, 
+            parameter->len, 
+            registers);
+
+    // Seek our range in loc
+    DwarfBuf locbuf;
+    DwarfBuf instream = { };
+
+    locbuf.d = d;
+    locbuf.addrsize = d->addrsize;
+    
+    if (parameter->loctype == TConstant) {
+        locbuf.p = d->loc.data + parameter->fde;
+        locbuf.ep = d->loc.data + d->loc.len;
+        ulong start, end, len;
+        do {
+            len = 0;
+            start = dwarfget4(&locbuf);
+            end = dwarfget4(&locbuf);
+            if (start && end) {
+                len = dwarfget2(&locbuf);
+                instream = locbuf;
+                instream.ep = instream.p + len;
+                locbuf.p = instream.ep;
+            }
+            werrstr("ip %x s %x e %x (%x bytes)", pc, start, end, len);
+        } while (start && end && (start > pc || end <= pc));
+    } else if (parameter->loctype == TBlock) {
+        instream = locbuf;
+        instream.p = (void *)parameter->fde;
+        instream.ep = instream.p + parameter->len;
+    } else {
+        werrstr("Wrong block type for parameter %s", parameter->name);
+        return -1;
+    }
+
+    gotarg = dwarfgetarg(d, parameter->name, &instream, cfa, registers, &parameter->value);
+    if (gotarg == -1)
+        return -1;
+    
+    return 0;
+}
+
+int
+dwarfgetparams(Dwarf *d, DwarfSym *s, ulong pc, int pnum, DwarfParam *paramblocks)
+{
+       int ip = 0;
+       DwarfSym param = { };
+       int res = dwarfnextsymat(d, s, &param);
+       while (res == 0 && ip < pnum) {
+               if (param.attrs.tag == TagFormalParameter &&
+                       param.attrs.have.name && 
+                       param.attrs.have.location) {
+                       paramblocks[ip].name = malloc(strlen(param.attrs.name)+1);
+                       strcpy(paramblocks[ip].name, param.attrs.name);
+                       paramblocks[ip].unit = param.unit;
+                       paramblocks[ip].type = param.attrs.type;
+            paramblocks[ip].loctype = param.attrs.have.location;
+            paramblocks[ip].len = param.attrs.location.b.len;
+                       paramblocks[ip].fde = param.attrs.location.b.data;
+            werrstr("param[%d] block %s -> type %x loctype %x fde %x len %x", 
+                   ip, 
+                   paramblocks[ip].name, 
+                   paramblocks[ip].type,
+                   paramblocks[ip].loctype, 
+                   paramblocks[ip].fde,
+                   paramblocks[ip].len);
+            ip++;
+               }
+               res = dwarfnextsymat(d, s, &param);
+       }
+       return ip;
+}
index 9a5f20c..b3ea2cd 100644 (file)
@@ -31,7 +31,8 @@ dwarfopen(Pe *pe)
        || pe->loadsection(pe, ".debug_aranges", &d->aranges) < 0
        || pe->loadsection(pe, ".debug_line", &d->line) < 0
        || pe->loadsection(pe, ".debug_pubnames", &d->pubnames) < 0
-       || pe->loadsection(pe, ".debug_info", &d->info) < 0)
+       || pe->loadsection(pe, ".debug_info", &d->info) < 0
+    || pe->loadsection(pe, ".debug_loc", &d->loc) < 0)
                goto err;
        pe->loadsection(pe, ".debug_frame", &d->frame);
        pe->loadsection(pe, ".debug_ranges", &d->ranges);
@@ -49,6 +50,7 @@ err:
        free(d->ranges.data);
        free(d->str.data);
        free(d->info.data);
+    free(d->loc.data);
        free(d);
        return nil;
 }
index 4edb556..ec41e10 100644 (file)
 
 enum
 {
-       Isstmt = 1<<0,
-       BasicDwarfBlock = 1<<1,
-       EndSequence = 1<<2,
-       PrologueEnd = 1<<3,
-       EpilogueBegin = 1<<4
+    Isstmt = 1<<0,
+    BasicDwarfBlock = 1<<1,
+    EndSequence = 1<<2,
+    PrologueEnd = 1<<3,
+    EpilogueBegin = 1<<4
 };
 
 typedef struct State State;
 struct State
 {
-       ulong addr;
-       ulong file;
-       ulong line;
-       ulong column;
-       ulong flags;
-       ulong isa;
+    ulong addr;
+    ulong file;
+    ulong line;
+    ulong column;
+    ulong flags;
+    ulong isa;
 };
 
 int
-dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **function, ulong *line, ulong *mtime, ulong *length)
+dwarfpctoline(Dwarf *d, DwarfSym *proc, ulong pc, char **file, char **function, ulong *line)
 {
-       uchar *prog, *opcount, *end, *dirs;
-       ulong off, unit, len, vers, x, start, lastline;
-       int i, first, firstline, op, a, l, quantum, isstmt, linebase, linerange, opcodebase, nf;
-       char *files, *s;
-       DwarfBuf b;
-       DwarfSym sym;
-       State emit, cur, reset;
-       uchar **f, **newf;
+       char *cdir;
+    uchar *prog, *opcount, *end, *dirs;
+    ulong off, unit, len, vers, x, start, lastline;
+    int i, first, firstline, op, a, l, quantum, isstmt, linebase, linerange, opcodebase, nf;
+    char *files, *s;
+    DwarfBuf b;
+    DwarfSym sym;
+    State emit, cur, reset;
+    char **f, **newf;
 
-       f = nil;
+    f = nil;
+    memset(proc, 0, sizeof(*proc));
 
-       if(dwarfaddrtounit(d, pc, &unit) < 0
-          || dwarflookuptag(d, unit, TagCompileUnit, &sym) < 0)
-               return -1;
+    int runit = dwarfaddrtounit(d, pc, &unit);
+    if (runit < 0)
+        return -1;
+    int rtag = dwarflookuptag(d, unit, TagCompileUnit, &sym);
+    if (rtag < 0)
+        return -1;
 
-       if(!sym.attrs.have.stmtlist){
-               werrstr("no line mapping information for 0x%x", pc);
-               return -1;
-       }
-       off = sym.attrs.stmtlist;
-       if(off >= d->line.len){
-               werrstr("bad stmtlist\n");
-               goto bad;
-       }
+    if(!sym.attrs.have.stmtlist){
+        werrstr("no line mapping information for 0x%x", pc);
+        return -1;
+    }
+    off = sym.attrs.stmtlist;
+    if(off >= d->line.len){
+        werrstr("bad stmtlist");
+        goto bad;
+    }
 
-       if(trace) werrstr("unit 0x%x stmtlist 0x%x", unit, sym.attrs.stmtlist);
+    if(trace) werrstr("unit 0x%x stmtlist 0x%x", unit, sym.attrs.stmtlist);
 
-       memset(&b, 0, sizeof b);
-       b.d = d;
-       b.p = d->line.data + off;
-       b.ep = b.p + d->line.len;
-       b.addrsize = sym.b.addrsize;    /* should i get this from somewhere else? */
+    memset(&b, 0, sizeof b);
+    b.d = d;
+    b.p = d->line.data + off;
+    b.ep = b.p + d->line.len;
+    b.addrsize = sym.b.addrsize;       /* should i get this from somewhere else? */
 
-       len = dwarfget4(&b);
-       if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
-               werrstr("bad len\n");
-               goto bad;
-       }
+    len = dwarfget4(&b);
+    if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
+        werrstr("bad len");
+        goto bad;
+    }
 
-       b.ep = b.p+len;
-       vers = dwarfget2(&b);
-       if(vers != 2){
-               werrstr("bad dwarf version 0x%x", vers);
-               return -1;
-       }
+    b.ep = b.p+len;
+    vers = dwarfget2(&b);
+    if(vers != 2){
+        werrstr("bad dwarf version 0x%x", vers);
+        return -1;
+    }
 
-       len = dwarfget4(&b);
-       if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
-               werrstr("another bad len\n");
-               goto bad;
-       }
-       prog = b.p+len;
+    len = dwarfget4(&b);
+    if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
+        werrstr("another bad len");
+        goto bad;
+    }
+    prog = b.p+len;
 
-       quantum = dwarfget1(&b);
-       isstmt = dwarfget1(&b);
-       linebase = (schar)dwarfget1(&b);
-       linerange = (schar)dwarfget1(&b);
-       opcodebase = dwarfget1(&b);
+    quantum = dwarfget1(&b);
+    isstmt = dwarfget1(&b);
+    linebase = (schar)dwarfget1(&b);
+    linerange = (schar)dwarfget1(&b);
+    opcodebase = dwarfget1(&b);
 
-       opcount = b.p-1;
-       dwarfgetnref(&b, opcodebase-1);
-       if(b.p == nil){
-               werrstr("bad opcode chart\n");
-               goto bad;
-       }
+    opcount = b.p-1;
+    dwarfgetnref(&b, opcodebase-1);
+    if(b.p == nil){
+        werrstr("bad opcode chart");
+        goto bad;
+    }
 
-       /* just skip the files and dirs for now; we'll come back */
-       dirs = b.p;
-       while (b.p && *b.p)
-               dwarfgetstring(&b);
-       dwarfget1(&b);
+    /* just skip the files and dirs for now; we'll come back */
+    dirs = b.p;
+    while (b.p && *b.p)
+        dwarfgetstring(&b);
+    dwarfget1(&b);
 
-       files = (char*)b.p;
-       while(b.p!=nil && *b.p!=0){
-               dwarfgetstring(&b);
-               dwarfget128(&b);
-               dwarfget128(&b);
-               dwarfget128(&b);
-       }
-       dwarfget1(&b);
+    files = (char*)b.p;
+    while(b.p!=nil && *b.p!=0){
+        dwarfgetstring(&b);
+        dwarfget128(&b);
+        dwarfget128(&b);
+        dwarfget128(&b);
+    }
+    dwarfget1(&b);
 
-       /* move on to the program */
-       if(b.p == nil || b.p > prog){
-               werrstr("bad header\n");
-               goto bad;
-       }
-       b.p = prog;
+    /* move on to the program */
+    if(b.p == nil || b.p > prog){
+        werrstr("bad header");
+        goto bad;
+    }
+    b.p = prog;
 
-       reset.addr = 0;
-       reset.file = 1;
-       reset.line = 1;
-       reset.column = 0;
-       reset.flags = isstmt ? Isstmt : 0;
-       reset.isa = 0;
+    reset.addr = 0;
+    reset.file = 1;
+    reset.line = 1;
+    reset.column = 0;
+    reset.flags = isstmt ? Isstmt : 0;
+    reset.isa = 0;
 
-       cur = reset;
-       emit = reset;
-       nf = 0;
-       start = 0;
-       if(trace) werrstr("program @ %lu ... %.*H opbase = %d\n", b.p - d->line.data, b.ep-b.p, b.p, opcodebase);
-       first = 1;
-       while(b.p != nil){
-               firstline = 0;
-               op = dwarfget1(&b);
-               if(trace) werrstr("\tline %lu, addr 0x%x, op %d %.10H", cur.line, cur.addr, op, b.p);
-               if(op >= opcodebase){
-                       a = (op - opcodebase) / linerange;
-                       l = (op - opcodebase) % linerange + linebase;
-                       cur.line += l;
-                       cur.addr += a * quantum;
-                       if(trace) werrstr(" +%d,%d\n", a, l);
-               emit:
-                       if(first){
-                               if(cur.addr > pc){
-                                       werrstr("found wrong line mapping 0x%x for pc 0x%x", cur.addr, pc);
-                                       /* This is an overzealous check.  gcc can produce discontiguous ranges
-                                          and reorder statements, so it's possible for a future line to start
-                                          ahead of pc and still find a matching one. */
-                                       /*goto out;*/
-                                       firstline = 1;
-                               }
-                               first = 0;
-                               start = cur.addr;
-                       }
-                       if(cur.addr > pc && !firstline)
-                               break;
-                       if(b.p == nil){
-                               werrstr("buffer underflow in line mapping");
-                               goto out;
-                       }
-                       emit = cur;
-                       if(emit.flags & EndSequence){
-                               werrstr("found wrong line mapping 0x%x-0x%x for pc 0x%x", start, cur.addr, pc);
-                               goto out;
-                       }
-                       cur.flags &= ~(BasicDwarfBlock|PrologueEnd|EpilogueBegin);
-               }else{
-                       switch(op){
-                       case 0: /* extended op code */
-                               if(trace) werrstr(" ext");
-                               len = dwarfget128(&b);
-                               end = b.p+len;
-                               if(b.p == nil || end > b.ep || end < b.p || len < 1)
-                                       goto bad;
-                               switch(dwarfget1(&b)){
-                               case 1: /* end sequence */
-                                       if(trace) werrstr(" end\n");
-                                       cur.flags |= EndSequence;
-                                       goto emit;
-                               case 2: /* set address */
-                                       cur.addr = dwarfgetaddr(&b);
-                                       if(trace) werrstr(" set pc 0x%x\n", cur.addr);
-                                       break;
-                               case 3: /* define file */
-                                       newf = malloc(nf+1*sizeof(f[0]));
-                                       if (newf)
-                                               RtlMoveMemory(newf, f, nf*sizeof(f[0]));
-                                       if(newf == nil)
-                                               goto out;
-                                       f[nf++] = b.p;
-                                       s = dwarfgetstring(&b);
-                                       dwarfget128(&b);
-                                       dwarfget128(&b);
-                                       dwarfget128(&b);
-                                       if(trace) werrstr(" def file %s\n", s);
-                                       break;
-                               }
-                               if(b.p == nil || b.p > end)
-                                       goto bad;
-                               b.p = end;
-                               break;
-                       case 1: /* emit */
-                               if(trace) werrstr(" emit\n");
-                               goto emit;
-                       case 2: /* advance pc */
-                               a = dwarfget128(&b);
-                               if(trace) werrstr(" advance pc + %lu\n", a*quantum);
-                               cur.addr += a * quantum;
-                               break;
-                       case 3: /* advance line */
-                               l = dwarfget128s(&b);
-                               if(trace) werrstr(" advance line + %ld\n", l);
-                               cur.line += l;
-                               break;
-                       case 4: /* set file */
-                               if(trace) werrstr(" set file\n");
-                               cur.file = dwarfget128s(&b);
-                               break;
-                       case 5: /* set column */
-                               if(trace) werrstr(" set column\n");
-                               cur.column = dwarfget128(&b);
-                               break;
-                       case 6: /* negate stmt */
-                               if(trace) werrstr(" negate stmt\n");
-                               cur.flags ^= Isstmt;
-                               break;
-                       case 7: /* set basic block */
-                               if(trace) werrstr(" set basic block\n");
-                               cur.flags |= BasicDwarfBlock;
-                               break;
-                       case 8: /* const add pc */
-                               a = (255 - opcodebase) / linerange * quantum;
-                               if(trace) werrstr(" const add pc + %d\n", a);
-                               cur.addr += a;
-                               break;
-                       case 9: /* fixed advance pc */
-                               a = dwarfget2(&b);
-                               if(trace) werrstr(" fixed advance pc + %d\n", a);
-                               cur.addr += a;
-                               break;
-                       case 10:        /* set prologue end */
-                               if(trace) werrstr(" set prologue end\n");
-                               cur.flags |= PrologueEnd;
-                               break;
-                       case 11:        /* set epilogue begin */
-                               if(trace) werrstr(" set epilogue begin\n");
-                               cur.flags |= EpilogueBegin;
-                               break;
-                       case 12:        /* set isa */
-                               if(trace) werrstr(" set isa\n");
-                               cur.isa = dwarfget128(&b);
-                               break;
-                       default:        /* something new - skip it */
-                               if(trace) werrstr(" unknown %d\n", opcount[op]);
-                               for(i=0; i<opcount[op]; i++)
-                                       dwarfget128(&b);
-                               break;
-                       }
-               }
-       }
-       if(b.p == nil)
-               goto bad;
+    cur = reset;
+    emit = reset;
+    nf = 0;
+    start = 0;
+    if(trace) werrstr("program @ %lu ... %.*H opbase = %d", b.p - d->line.data, b.ep-b.p, b.p, opcodebase);
+    first = 1;
+    while(b.p != nil){
+        firstline = 0;
+        op = dwarfget1(&b);
+        if(trace) werrstr("\tline %lu, addr 0x%x, op %d %.10H", cur.line, cur.addr, op, b.p);
+        if(op >= opcodebase){
+            a = (op - opcodebase) / linerange;
+            l = (op - opcodebase) % linerange + linebase;
+            cur.line += l;
+            cur.addr += a * quantum;
+            if(trace) werrstr(" +%d,%d", a, l);
+        emit:
+            if(first){
+                if(cur.addr > pc){
+                    werrstr("found wrong line mapping 0x%x for pc 0x%x", cur.addr, pc);
+                    /* This is an overzealous check.  gcc can produce discontiguous ranges
+                       and reorder statements, so it's possible for a future line to start
+                       ahead of pc and still find a matching one. */
+                    /*goto out;*/
+                    firstline = 1;
+                }
+                first = 0;
+                start = cur.addr;
+            }
+            if(cur.addr > pc && !firstline)
+                break;
+            if(b.p == nil){
+                werrstr("buffer underflow in line mapping");
+                goto out;
+            }
+            emit = cur;
+            if(emit.flags & EndSequence){
+                werrstr("found wrong line mapping 0x%x-0x%x for pc 0x%x", start, cur.addr, pc);
+                goto out;
+            }
+            cur.flags &= ~(BasicDwarfBlock|PrologueEnd|EpilogueBegin);
+        }else{
+            switch(op){
+            case 0:    /* extended op code */
+                if(trace) werrstr(" ext");
+                len = dwarfget128(&b);
+                end = b.p+len;
+                if(b.p == nil || end > b.ep || end < b.p || len < 1)
+                    goto bad;
+                switch(dwarfget1(&b)){
+                case 1:        /* end sequence */
+                    if(trace) werrstr(" end");
+                    cur.flags |= EndSequence;
+                    goto emit;
+                case 2:        /* set address */
+                    cur.addr = dwarfgetaddr(&b);
+                    if(trace) werrstr(" set pc 0x%x", cur.addr);
+                    break;
+                case 3:        /* define file */
+                    newf = malloc(nf+1*sizeof(f[0]));
+                    if (newf)
+                        RtlMoveMemory(newf, f, nf*sizeof(f[0]));
+                    if(newf == nil)
+                        goto out;
+                                       free(f);
+                    f = newf;
+                                       f[nf++] = s = dwarfgetstring(&b);
+                                       DPRINT1("str %s", s);
+                    dwarfget128(&b);
+                    dwarfget128(&b);
+                    dwarfget128(&b);
+                    if(trace) werrstr(" def file %s", s);
+                    break;
+                }
+                if(b.p == nil || b.p > end)
+                    goto bad;
+                b.p = end;
+                break;
+            case 1:    /* emit */
+                if(trace) werrstr(" emit");
+                goto emit;
+            case 2:    /* advance pc */
+                a = dwarfget128(&b);
+                if(trace) werrstr(" advance pc + %lu", a*quantum);
+                cur.addr += a * quantum;
+                break;
+            case 3:    /* advance line */
+                l = dwarfget128s(&b);
+                if(trace) werrstr(" advance line + %ld", l);
+                cur.line += l;
+                break;
+            case 4:    /* set file */
+                if(trace) werrstr(" set file");
+                cur.file = dwarfget128s(&b);
+                break;
+            case 5:    /* set column */
+                if(trace) werrstr(" set column");
+                cur.column = dwarfget128(&b);
+                break;
+            case 6:    /* negate stmt */
+                if(trace) werrstr(" negate stmt");
+                cur.flags ^= Isstmt;
+                break;
+            case 7:    /* set basic block */
+                if(trace) werrstr(" set basic block");
+                cur.flags |= BasicDwarfBlock;
+                break;
+            case 8:    /* const add pc */
+                a = (255 - opcodebase) / linerange * quantum;
+                if(trace) werrstr(" const add pc + %d", a);
+                cur.addr += a;
+                break;
+            case 9:    /* fixed advance pc */
+                a = dwarfget2(&b);
+                if(trace) werrstr(" fixed advance pc + %d", a);
+                cur.addr += a;
+                break;
+            case 10:   /* set prologue end */
+                if(trace) werrstr(" set prologue end");
+                cur.flags |= PrologueEnd;
+                break;
+            case 11:   /* set epilogue begin */
+                if(trace) werrstr(" set epilogue begin");
+                cur.flags |= EpilogueBegin;
+                break;
+            case 12:   /* set isa */
+                if(trace) werrstr(" set isa");
+                cur.isa = dwarfget128(&b);
+                break;
+            default:   /* something new - skip it */
+                if(trace) werrstr(" unknown %d", opcount[op]);
+                for(i=0; i<opcount[op]; i++)
+                    dwarfget128(&b);
+                break;
+            }
+        }
+    }
+    if(b.p == nil)
+        goto bad;
 
-       /* finally!  the data we seek is in "emit" */
+    /* finally!  the data we seek is in "emit" */
 
-       if(emit.file == 0){
-               werrstr("invalid file index in mapping data");
-               goto out;
-       }
-       if(line)
-               *line = emit.line;
+    if(emit.file == 0){
+        werrstr("invalid file index in mapping data");
+        goto out;
+    }
+    if(line)
+        *line = emit.line;
 
-       /* skip over first emit.file-2 guys */
-       b.p = (uchar*)files;
-       for(i=emit.file-1; i > 0 && b.p!=nil && *b.p!=0; i--){
-               dwarfgetstring(&b);
-               dwarfget128(&b);
-               dwarfget128(&b);
-               dwarfget128(&b);
-       }
-       if(b.p == nil){
-               werrstr("problem parsing file data second time (cannot happen)");
-               goto bad;
-       }
-       if(*b.p == 0){
-               if(i >= nf){
-                       werrstr("bad file index in mapping data");
-                       goto bad;
-               }
-               b.p = f[i];
-       }
-       s = dwarfgetstring(&b);
-       if(file)
-               *file = s;
-       i = dwarfget128(&b);            /* directory */
-       x = dwarfget128(&b);
-       if(mtime)
-               *mtime = x;
-       x = dwarfget128(&b);
-       if(length)
-               *length = x;
+    /* skip over first emit.file-2 guys */
+    b.p = (uchar*)files;
+    for(i=emit.file-1; i > 0 && b.p!=nil && *b.p!=0; i--){
+        dwarfgetstring(&b);
+        dwarfget128(&b);
+        dwarfget128(&b);
+        dwarfget128(&b);
+    }
+    if(b.p == nil){
+        werrstr("problem parsing file data second time (cannot happen)");
+        goto bad;
+    }
+    if(*b.p == 0){
+        if(i >= nf){
+            werrstr("bad file index in mapping data");
+            goto bad;
+        }
+        b.p = (uchar*)f[i];
+    }
+    s = dwarfgetstring(&b);
+       *file = s;
+    i = dwarfget128(&b);               /* directory */
+    x = dwarfget128(&b);
+    x = dwarfget128(&b);
 
-       /* fetch dir name */
-       if(cdir)
-               *cdir = sym.attrs.compdir;
+    /* fetch dir name */
+       cdir = sym.attrs.have.compdir ? sym.attrs.compdir : 0;
 
-       if(dir){
-               *dir = nil;
-               b.p = dirs;
-               for (x = 1; b.p && *b.p; x++)
-                       if (x == i) {
-                               *dir = dwarfgetstring(&b);
-                               break;
-                       }
+       char *dwarfdir;
+       dwarfdir = nil;
+       b.p = dirs;
+       for (x = 1; b.p && *b.p; x++) {
+               dwarfdir = dwarfgetstring(&b);
+               if (x == i) break;
        }
 
-       *function = nil;
-       lastline = 0;
-#if 0
-       if (dwarfenumunit(d, unit, &proc) >= 0) {
-               dwarfnextsymat(d, &proc, 0);
-               while (dwarfnextsymat(d, &proc, 1) == 1) {
-                       if (proc.attrs.tag == TagSubprogram && 
-                               proc.attrs.have.name &&
-                               proc.attrs.declfile == emit.file && 
-                               proc.attrs.declline <= *line && 
-                               proc.attrs.declline > lastline) {
-                               lastline = proc.attrs.declline;
-                               free(*function);
-                               *function = malloc(strlen(proc.attrs.name)+1);
-                               strcpy(*function, proc.attrs.name);
+       if (!cdir && dwarfdir)
+               cdir = dwarfdir;
+       
+       char *filefull = malloc(strlen(cdir) + strlen(*file) + 2);
+       strcpy(filefull, cdir);
+       strcat(filefull, "/");
+       strcat(filefull, *file);
+       *file = filefull;
+       
+    *function = nil;
+    lastline = 0;
+       
+    runit = dwarfaddrtounit(d, pc, &unit);
+    if (runit == 0) {
+        DwarfSym compunit = { };
+        int renum = dwarfenumunit(d, unit, &compunit);
+        if (renum < 0)
+            return -1;
+        renum = dwarfnextsymat(d, &compunit, proc);
+        while (renum == 0) {
+            if (proc->attrs.tag == TagSubprogram && 
+                               proc->attrs.have.name)
+                       {
+                if (proc->attrs.lowpc <= pc && proc->attrs.highpc > pc) {
+                    *function = malloc(strlen(proc->attrs.name)+1);
+                                       strcpy(*function, proc->attrs.name);
+                    goto done;
+                               }
                        }
-               }
-       }
-#elif 1
-       ulong lastaddr = 0;
-       *function = NULL;
-       for (i = 0; i < d->pe->nsymbols; i++) {
-               if (d->pe->symtab[i].address > lastaddr &&
-                       d->pe->symtab[i].address <= pc - d->pe->imagebase &&
-                       d->pe->symtab[i].address < d->pe->imagesize) {
-                       lastaddr = d->pe->symtab[i].address;
-                       *function = d->pe->symtab[i].name;
-               }
-       }
-#else
-       // *sigh* we get unrelocated low_pc and high_pc because the dwarf symbols
-       // are not 'loaded' in the PE sense.
-       if (dwarflookupfn(d, unit, pc, &proc) >= 0) {
-               *function = malloc(strlen(proc.attrs.name)+1);
-               strcpy(*function, proc.attrs.name);
-       }
-#endif
+            renum = dwarfnextsym(d, proc);
+        }
+    }
 
-       /* free at last, free at last */
-       free(f);
-       return 0;
+    // Next search by declaration
+    runit = dwarfaddrtounit(d, pc, &unit);
+    if (runit == 0) {
+        DwarfSym compunit = { };
+        int renum = dwarfenumunit(d, unit, &compunit);
+        if (renum < 0)
+            return -1;
+        renum = dwarfnextsymat(d, &compunit, proc);
+        while (renum == 0) {
+            if (proc->attrs.tag == TagSubprogram && 
+                               proc->attrs.have.name &&
+                               proc->attrs.declfile == emit.file)
+                       {
+                if (proc->attrs.declline <= *line &&
+                    proc->attrs.declline > lastline) {
+                    free(*function);
+                    *function = malloc(strlen(proc->attrs.name)+1);
+                                       strcpy(*function, proc->attrs.name);
+                    goto done;
+                               }
+                lastline = proc->attrs.declline;
+                       }
+            renum = dwarfnextsym(d, proc);
+        }
+    }
 
+    /* free at last, free at last */
+done:
+    free(f);
+    return 0;
 bad:
-       werrstr("corrupted line mapping for 0x%x", pc);
+    werrstr("corrupted line mapping for 0x%x", pc);
 out:
-       free(f);
-       return -1;
+    free(f);
+    return -1;
 }
 
+VOID RosSymFreeInfo(PROSSYM_LINEINFO LineInfo)
+{
+    int i;
+       free(LineInfo->FileName);
+       LineInfo->FileName = NULL;
+       free(LineInfo->FunctionName);
+       LineInfo->FunctionName = NULL;
+    for (i = 0; i < sizeof(LineInfo->Parameters)/sizeof(LineInfo->Parameters[0]); i++)
+        free(LineInfo->Parameters[i].ValueName);
+}
index 5f613dc..9cc5aee 100644 (file)
 #include "pe.h"
 
 BOOLEAN
-RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
-                            ULONG_PTR RelativeAddress,
-                            ULONG *LineNumber,
-                            char *FileName,
-                            char *FunctionName)
+RosSymGetAddressInformation
+(PROSSYM_INFO RosSymInfo,
+ ULONG_PTR RelativeAddress,
+ PROSSYM_LINEINFO RosSymLineInfo)
 {
-       char *cdir, *dir, *file, *function;
-       ulong line, mtime, length;
+    ROSSYM_REGISTERS registers;
+    DwarfParam params[sizeof(RosSymLineInfo->Parameters)/sizeof(RosSymLineInfo->Parameters[0])];
+    DwarfSym proc = { };
+    int i;
        int res = dwarfpctoline
                (RosSymInfo, 
+         &proc,
                 RelativeAddress + RosSymInfo->pe->imagebase, 
-                &cdir,
-                &dir,
-                &file,
-                &function,
-                &line,
-                &mtime,
-                &length);
-       if (res != -1) {
-               *LineNumber = line;
-               FileName[0] = 0;
-               if (dir) {
-                       strcpy(FileName, dir);
-                       strcat(FileName, "/");
-               }
-               if (file)
-                       strcat(FileName, file);
-               FunctionName[0] = 0;
-               if (function)
-                       strcpy(FunctionName, function);
-               return TRUE;
-       } else {
+                &RosSymLineInfo->FileName,
+                &RosSymLineInfo->FunctionName,
+                &RosSymLineInfo->LineNumber);
+       if (res == -1) {
+        werrstr("Could not get basic function info");
                return FALSE;
-       }
+    }
+
+    if (!(RosSymLineInfo->Flags & ROSSYM_LINEINFO_HAS_REGISTERS))
+        return TRUE;
+
+    registers = RosSymLineInfo->Registers;
+
+    DwarfExpr cfa = { };
+    ulong cfaLocation;
+    if (dwarfregunwind
+        (RosSymInfo, 
+         RelativeAddress + RosSymInfo->pe->imagebase, 
+         proc.attrs.framebase.c, 
+         &cfa,
+         &registers) == -1) {
+        werrstr("Can't get cfa location for %s", RosSymLineInfo->FunctionName);
+        return TRUE;
+    }
+
+    res = dwarfgetparams
+        (RosSymInfo,
+         &proc,
+         RelativeAddress + RosSymInfo->pe->imagebase,
+         sizeof(params)/sizeof(params[0]),
+         params);
+
+    if (res == -1) {
+        werrstr("%s: could not get params at all", RosSymLineInfo->FunctionName);
+        RosSymLineInfo->NumParams = 0;
+        return TRUE;
+    }
+
+    werrstr("%s: res %d", RosSymLineInfo->FunctionName, res);
+    RosSymLineInfo->NumParams = res;
+
+    res = dwarfcomputecfa(RosSymInfo, &cfa, &registers, &cfaLocation);
+    if (res == -1) {
+        werrstr("%s: could not get our own cfa", RosSymLineInfo->FunctionName);
+        return TRUE;
+    }
+
+    for (i = 0; i < RosSymLineInfo->NumParams; i++) {
+        werrstr("Getting arg %s, unit %x, type %x", 
+                params[i].name, params[i].unit, params[i].type);
+        res = dwarfargvalue
+            (RosSymInfo, 
+             &proc, 
+             RelativeAddress + RosSymInfo->pe->imagebase,
+             cfaLocation,
+             &registers,
+             &params[i]);
+        if (res == -1) { RosSymLineInfo->NumParams = i; return TRUE; }
+        werrstr("%s: %x", params[i].name, params[i].value);
+        RosSymLineInfo->Parameters[i].ValueName = malloc(strlen(params[i].name)+1);
+        strcpy(RosSymLineInfo->Parameters[i].ValueName, params[i].name);
+        free(params[i].name);
+        RosSymLineInfo->Parameters[i].Value = params[i].value;
+    }
+
+    return TRUE;
 }
 
 /* EOF */
index 00884a5..c26ea3e 100644 (file)
 #define NDEBUG
 #include <debug.h>
 
+#define SYMBOL_SIZE 18
+
 extern NTSTATUS RosSymStatus;
 
 BOOLEAN
 RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
 {
-  IMAGE_DOS_HEADER DosHeader;
-  IMAGE_NT_HEADERS NtHeaders;
-  PIMAGE_SECTION_HEADER SectionHeaders;
-  unsigned SectionIndex;
-  unsigned SymbolTable, NumSymbols;
-
-  /* Load DOS header */
-  if (! RosSymSeekFile(FileContext, 0))
+    IMAGE_DOS_HEADER DosHeader;
+    IMAGE_NT_HEADERS NtHeaders;
+    PIMAGE_SECTION_HEADER SectionHeaders;
+    unsigned SectionIndex;
+    unsigned SymbolTable, NumSymbols;
+
+    /* Load DOS header */
+    if (! RosSymSeekFile(FileContext, 0))
     {
-         DPRINT1("Could not rewind file\n");
-         return FALSE;
-       }
-  if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER)))
+        werrstr("Could not rewind file\n");
+        return FALSE;
+    }
+    if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER)))
     {
-         DPRINT1("Failed to read DOS header %x\n", RosSymStatus);
-      return FALSE;
+        werrstr("Failed to read DOS header %x\n", RosSymStatus);
+        return FALSE;
     }
-  if (! ROSSYM_IS_VALID_DOS_HEADER(&DosHeader))
+    if (! ROSSYM_IS_VALID_DOS_HEADER(&DosHeader))
     {
-      DPRINT1("Image doesn't have a valid DOS header\n");
-      return FALSE;
+        werrstr("Image doesn't have a valid DOS header\n");
+        return FALSE;
     }
 
-  /* Load NT headers */
-  if (! RosSymSeekFile(FileContext, DosHeader.e_lfanew))
+    /* Load NT headers */
+    if (! RosSymSeekFile(FileContext, DosHeader.e_lfanew))
     {
-      DPRINT1("Failed seeking to NT headers\n");
-      return FALSE;
+        werrstr("Failed seeking to NT headers\n");
+        return FALSE;
     }
-  if (! RosSymReadFile(FileContext, &NtHeaders, sizeof(IMAGE_NT_HEADERS)))
+    if (! RosSymReadFile(FileContext, &NtHeaders, sizeof(IMAGE_NT_HEADERS)))
     {
-      DPRINT1("Failed to read NT headers\n");
-      return FALSE;
+        werrstr("Failed to read NT headers\n");
+        return FALSE;
     }
-  if (! ROSSYM_IS_VALID_NT_HEADERS(&NtHeaders))
+    if (! ROSSYM_IS_VALID_NT_HEADERS(&NtHeaders))
     {
-      DPRINT1("Image doesn't have a valid PE header\n");
-      return FALSE;
+        werrstr("Image doesn't have a valid PE header\n");
+        return FALSE;
     }
 
-  SymbolTable = NtHeaders.FileHeader.PointerToSymbolTable;
-  NumSymbols = NtHeaders.FileHeader.NumberOfSymbols;
+    SymbolTable = NtHeaders.FileHeader.PointerToSymbolTable;
+    NumSymbols = NtHeaders.FileHeader.NumberOfSymbols;
 
-  if (!NumSymbols)
+    if (!NumSymbols)
     {
-      DPRINT1("Image doesn't have debug symbols\n");
-      return FALSE;
+        werrstr("Image doesn't have debug symbols\n");
+        return FALSE;
     }
 
-  DPRINT("SymbolTable %x NumSymbols %x\n", SymbolTable, NumSymbols);
+    DPRINT("SymbolTable %x NumSymbols %x\n", SymbolTable, NumSymbols);
 
-  /* Load section headers */
-  if (! RosSymSeekFile(FileContext, (char *) IMAGE_FIRST_SECTION(&NtHeaders) -
-                                    (char *) &NtHeaders + DosHeader.e_lfanew))
+    /* Load section headers */
+    if (! RosSymSeekFile(FileContext, (char *) IMAGE_FIRST_SECTION(&NtHeaders) -
+                         (char *) &NtHeaders + DosHeader.e_lfanew))
     {
-      DPRINT1("Failed seeking to section headers\n");
-      return FALSE;
+        werrstr("Failed seeking to section headers\n");
+        return FALSE;
     }
-  DPRINT("Alloc section headers\n");
-  SectionHeaders = RosSymAllocMem(NtHeaders.FileHeader.NumberOfSections
-                                  * sizeof(IMAGE_SECTION_HEADER));
-  if (NULL == SectionHeaders)
+    DPRINT("Alloc section headers\n");
+    SectionHeaders = RosSymAllocMem(NtHeaders.FileHeader.NumberOfSections
+                                    * sizeof(IMAGE_SECTION_HEADER));
+    if (NULL == SectionHeaders)
     {
-      DPRINT1("Failed to allocate memory for %u section headers\n",
-              NtHeaders.FileHeader.NumberOfSections);
-      return FALSE;
+        werrstr("Failed to allocate memory for %u section headers\n",
+                NtHeaders.FileHeader.NumberOfSections);
+        return FALSE;
     }
-  if (! RosSymReadFile(FileContext, SectionHeaders,
-                       NtHeaders.FileHeader.NumberOfSections
-                       * sizeof(IMAGE_SECTION_HEADER)))
+    if (! RosSymReadFile(FileContext, SectionHeaders,
+                         NtHeaders.FileHeader.NumberOfSections
+                         * sizeof(IMAGE_SECTION_HEADER)))
+    {
+        RosSymFreeMem(SectionHeaders);
+        werrstr("Failed to read section headers\n");
+        return FALSE;
+    }
+
+    // Convert names to ANSI_STRINGs
+    for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
+         SectionIndex++) 
     {
-      RosSymFreeMem(SectionHeaders);
-      DPRINT1("Failed to read section headers\n");
-      return FALSE;
+        ANSI_STRING astr;
+        if (SectionHeaders[SectionIndex].Name[0] != '/') {
+            DPRINT("Short name string %d, %s\n", SectionIndex, SectionHeaders[SectionIndex].Name);
+            astr.Buffer = RosSymAllocMem(IMAGE_SIZEOF_SHORT_NAME);
+            memcpy(astr.Buffer, SectionHeaders[SectionIndex].Name, IMAGE_SIZEOF_SHORT_NAME);
+            astr.MaximumLength = IMAGE_SIZEOF_SHORT_NAME;
+            astr.Length = GetStrnlen(astr.Buffer, IMAGE_SIZEOF_SHORT_NAME);
+        } else {
+            UNICODE_STRING intConv;
+            NTSTATUS Status;
+            ULONG StringOffset;
+
+            Status = RtlCreateUnicodeStringFromAsciiz(&intConv, (PCSZ)SectionHeaders[SectionIndex].Name + 1);
+            if (!NT_SUCCESS(Status)) goto freeall;
+            Status = RtlUnicodeStringToInteger(&intConv, 10, &StringOffset);
+            RtlFreeUnicodeString(&intConv);
+            if (!NT_SUCCESS(Status)) goto freeall;
+            if (!RosSymSeekFile(FileContext, SymbolTable + NumSymbols * SYMBOL_SIZE + StringOffset))
+                goto freeall;
+            astr.Buffer = RosSymAllocMem(MAXIMUM_DWARF_NAME_SIZE);
+            if (!RosSymReadFile(FileContext, astr.Buffer, MAXIMUM_DWARF_NAME_SIZE))
+                goto freeall;
+            astr.Length = GetStrnlen(astr.Buffer, MAXIMUM_DWARF_NAME_SIZE);
+            astr.MaximumLength = MAXIMUM_DWARF_NAME_SIZE;                
+            DPRINT("Long name %d, %s\n", SectionIndex, astr.Buffer);
+        }
+        *ANSI_NAME_STRING(&SectionHeaders[SectionIndex]) = astr;
     }
 
-  // Convert names to ANSI_STRINGs
-  for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
-          SectionIndex++) 
-  {
-         ANSI_STRING astr;
-         if (SectionHeaders[SectionIndex].Name[0] != '/') {
-                 DPRINT("Short name string %d, %s\n", SectionIndex, SectionHeaders[SectionIndex].Name);
-                 astr.Buffer = RosSymAllocMem(IMAGE_SIZEOF_SHORT_NAME);
-                 memcpy(astr.Buffer, SectionHeaders[SectionIndex].Name, IMAGE_SIZEOF_SHORT_NAME);
-                 astr.MaximumLength = IMAGE_SIZEOF_SHORT_NAME;
-                 astr.Length = GetStrnlen(astr.Buffer, IMAGE_SIZEOF_SHORT_NAME);
-         } else {
-                 UNICODE_STRING intConv;
-                 NTSTATUS Status;
-                 ULONG StringOffset;
-
-                 Status = RtlCreateUnicodeStringFromAsciiz(&intConv, (PCSZ)SectionHeaders[SectionIndex].Name + 1);
-                 if (!NT_SUCCESS(Status)) goto freeall;
-                 Status = RtlUnicodeStringToInteger(&intConv, 10, &StringOffset);
-                 RtlFreeUnicodeString(&intConv);
-                 if (!NT_SUCCESS(Status)) goto freeall;
-                 if (!RosSymSeekFile(FileContext, SymbolTable + NumSymbols * SYMBOL_SIZE + StringOffset))
-                         goto freeall;
-                 astr.Buffer = RosSymAllocMem(MAXIMUM_DWARF_NAME_SIZE);
-                 if (!RosSymReadFile(FileContext, astr.Buffer, MAXIMUM_DWARF_NAME_SIZE))
-                         goto freeall;
-                 astr.Length = GetStrnlen(astr.Buffer, MAXIMUM_DWARF_NAME_SIZE);
-                 astr.MaximumLength = MAXIMUM_DWARF_NAME_SIZE;           
-                 DPRINT("Long name %d, %s\n", SectionIndex, astr.Buffer);
-         }
-         *ANSI_NAME_STRING(&SectionHeaders[SectionIndex]) = astr;
-  }
-
-  DPRINT("Done with sections\n");
-  Pe *pe = RosSymAllocMem(sizeof(*pe));
-  pe->fd = FileContext;
-  pe->e2 = peget2;
-  pe->e4 = peget4;
-  pe->e8 = peget8;
-  pe->nsections = NtHeaders.FileHeader.NumberOfSections;
-  pe->sect = SectionHeaders;
-  pe->nsymbols = NtHeaders.FileHeader.NumberOfSymbols;
-  pe->symtab = malloc(pe->nsymbols * sizeof(CoffSymbol));
-  SYMENT SymbolData;
-  int i, j;
-  DPRINT("Getting symbol data\n");
-  ASSERT(sizeof(SymbolData) == 18);
-  for (i = 0, j = 0; i < pe->nsymbols; i++) {
-         if (!RosSymSeekFile
-                 (FileContext, 
-                  NtHeaders.FileHeader.PointerToSymbolTable + i * sizeof(SymbolData)))
-                 goto freeall;
-         if (!RosSymReadFile(FileContext, &SymbolData, sizeof(SymbolData)))
-                 goto freeall;
-         if ((SymbolData.e_scnum < 1) || 
-                 (SymbolData.e_sclass != C_EXT &&
-                  SymbolData.e_sclass != C_STAT))
-                 continue;
-         int section = SymbolData.e_scnum - 1;
-         if (SymbolData.e.e.e_zeroes) {
-                 pe->symtab[j].name = malloc(sizeof(SymbolData.e.e_name)+1);
-                 memcpy(pe->symtab[j].name, SymbolData.e.e_name, sizeof(SymbolData.e.e_name));
-                 pe->symtab[j].name[sizeof(SymbolData.e.e_name)] = 0;
-         } else {
-                 if (!RosSymSeekFile
-                         (FileContext, 
-                          NtHeaders.FileHeader.PointerToSymbolTable + 
-                          (NtHeaders.FileHeader.NumberOfSymbols * 18) + 
-                          SymbolData.e.e.e_offset))
-                         goto freeall;
-                 pe->symtab[j].name = malloc(MAXIMUM_COFF_SYMBOL_LENGTH+1);
-                 pe->symtab[j].name[MAXIMUM_COFF_SYMBOL_LENGTH] = 0;
-                 // It's possible that we've got a string just at the end of the file
-                 // we'll skip that symbol if needed
-                 if (!RosSymReadFile(FileContext, pe->symtab[j].name, MAXIMUM_COFF_SYMBOL_LENGTH)) {
-                         free(pe->symtab[j].name);
-                         continue;
-                 }
-         }
-         if (pe->symtab[j].name[0] == '.') {
-                 free(pe->symtab[j].name);
-                 continue;
-         }
-         pe->symtab[j].address = pe->sect[section].VirtualAddress + SymbolData.e_value;
-         j++;
-  }
-  DPRINT("%d symbols\n", j);
-  pe->nsymbols = j;
-  pe->imagebase = pe->loadbase = NtHeaders.OptionalHeader.ImageBase;
-  pe->imagesize = NtHeaders.OptionalHeader.SizeOfImage;
-  pe->loadsection = loaddisksection;
-  DPRINT("do dwarfopen\n");
-  *RosSymInfo = dwarfopen(pe);
-  DPRINT("done %x\n", *RosSymInfo);
-
-  return TRUE;
+    DPRINT("Done with sections\n");
+    Pe *pe = RosSymAllocMem(sizeof(*pe));
+    pe->fd = FileContext;
+    pe->e2 = peget2;
+    pe->e4 = peget4;
+    pe->e8 = peget8;
+    pe->nsections = NtHeaders.FileHeader.NumberOfSections;
+    pe->sect = SectionHeaders;
+    pe->imagebase = pe->loadbase = NtHeaders.OptionalHeader.ImageBase;
+    pe->imagesize = NtHeaders.OptionalHeader.SizeOfImage;
+    pe->loadsection = loaddisksection;
+    *RosSymInfo = dwarfopen(pe);
+
+    return TRUE;
 
 freeall:
-  for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
-          SectionIndex++)
-         RtlFreeAnsiString(ANSI_NAME_STRING(&SectionHeaders[SectionIndex]));
-  RosSymFreeMem(SectionHeaders);
+    for (SectionIndex = 0; SectionIndex < NtHeaders.FileHeader.NumberOfSections;
+         SectionIndex++)
+        RtlFreeAnsiString(ANSI_NAME_STRING(&SectionHeaders[SectionIndex]));
+    RosSymFreeMem(SectionHeaders);
 
-  return FALSE;
+    return FALSE;
 }
 
 /* EOF */
index 5a80fd3..eb59c0f 100644 (file)
@@ -13,6 +13,7 @@
 #include "rossympriv.h"
 #define NTOS_MODE_USER
 #include <ndk/ntndk.h>
+#include <pseh/pseh.h>
 
 #define NDEBUG
 #include <debug.h>
@@ -29,6 +30,12 @@ RosSymFreeMemUM(PVOID Area)
   RtlFreeHeap(RtlGetProcessHeap(), 0, Area);
 }
 
+static BOOLEAN
+RosSymGetMemUM(ULONG_PTR *Target, PVOID SourceMem, ULONG Size)
+{
+  return FALSE;
+}
+
 VOID
 RosSymInitUserMode(VOID)
 {
@@ -37,7 +44,8 @@ RosSymInitUserMode(VOID)
       RosSymAllocMemUM,
       RosSymFreeMemUM,
       RosSymZwReadFile,
-      RosSymZwSeekFile
+      RosSymZwSeekFile,
+         RosSymGetMemUM
     };
 
   RosSymInit(&KmCallbacks);
index a00716c..cace420 100644 (file)
@@ -111,10 +111,6 @@ void pefree(Pe *pe) {
        for (i = 0; i < pe->nsections; i++) {
                RtlFreeAnsiString(ANSI_NAME_STRING(&pe->sect[i]));
        }
-       for (i = 0; i < pe->nsymbols; i++) {
-               free(pe->symtab[i].name);
-       }
-       free(pe->symtab);
        free(pe->sect);
        free(pe);
 }
index 5e659a2..6b5bbda 100644 (file)
@@ -6,49 +6,19 @@
 struct DwarfBlock;
 typedef struct _IMAGE_SECTION_HEADER PeSect;
 
-typedef struct _CoffSymbol {
-       ulong address;
-       char *name;
-} CoffSymbol;
-
 typedef struct _Pe {
        void *fd;
        u16int (*e2)(const unsigned char *data);
        u32int (*e4)(const unsigned char *data);
        u64int (*e8)(const unsigned char *data);
        ulong imagebase, imagesize, loadbase;
-       ulong nsymbols;
-       CoffSymbol *symtab;
        int (*loadsection)(struct _Pe *pe, char *name, struct DwarfBlock *b);
        int nsections;
        struct _IMAGE_SECTION_HEADER *sect;
 } Pe;
 
-#define E_SYMNMLEN 8
-#include <pshpack1.h>
-typedef struct {
-       union {
-               char e_name[E_SYMNMLEN];
-               struct {
-                       unsigned long e_zeroes;
-                       unsigned long e_offset;
-               } e;
-       } e;
-       unsigned long e_value;
-       short e_scnum;
-       unsigned short e_type;
-       unsigned char e_sclass;
-       unsigned char e_numaux;
-} SYMENT, *PSYMENT;
-#include <poppack.h>
-
-#define C_EXT 2
-#define C_STAT 3
-#define DT_FCN 0x40
-
 Pe *peopen(const char *name);
 int loaddisksection(struct _Pe *pe, char *name, struct DwarfBlock *b);
-int loadmemsection(struct _Pe *pe, char *name, struct DwarfBlock *b);
 u16int peget2(const unsigned char *ptr);
 u32int peget4(const unsigned char *ptr);
 u64int peget8(const unsigned char *ptr);
index ffeb2ce..1a604ef 100644 (file)
@@ -9,19 +9,19 @@
 
 #pragma once
 
+#define HIGHBIT 0x80000000
+
 extern ROSSYM_CALLBACKS RosSymCallbacks;
 
 #define RosSymAllocMem(Size) (*RosSymCallbacks.AllocMemProc)(Size)
 #define RosSymFreeMem(Area) (*RosSymCallbacks.FreeMemProc)(Area)
 #define RosSymReadFile(FileContext, Buffer, Size) (*RosSymCallbacks.ReadFileProc)((FileContext), (Buffer), (Size))
 #define RosSymSeekFile(FileContext, Position) (*RosSymCallbacks.SeekFileProc)((FileContext), (Position))
+#define RosSymGetMem(TargetAddress, Address, Size) (*RosSymCallbacks.MemGetProc)((TargetAddress), (Address), (Size))
 
 extern BOOLEAN RosSymZwReadFile(PVOID FileContext, PVOID Buffer, ULONG Size);
 extern BOOLEAN RosSymZwSeekFile(PVOID FileContext, ULONG_PTR Position);
 
-extern BOOLEAN RosSymIoReadFile(PVOID FileContext, PVOID Buffer, ULONG Size);
-extern BOOLEAN RosSymIoSeekFile(PVOID FileContext, ULONG_PTR Position);
-
 #define ROSSYM_IS_VALID_DOS_HEADER(DosHeader) (IMAGE_DOS_SIGNATURE == (DosHeader)->e_magic \
                                                && 0L != (DosHeader)->e_lfanew)
 #define ROSSYM_IS_VALID_NT_HEADERS(NtHeaders) (IMAGE_NT_SIGNATURE == (NtHeaders)->Signature \
index 5bb1060..096416a 100644 (file)
@@ -75,15 +75,14 @@ KdbSymProcessSymbols(
 
 BOOLEAN
 KdbSymPrintAddress(
-    IN PVOID Address);
+    IN PVOID Address,
+    IN PKTRAP_FRAME Context);
 
 NTSTATUS
 KdbSymGetAddressInformation(
     IN PROSSYM_INFO  RosSymInfo,
     IN ULONG_PTR  RelativeAddress,
-    OUT PULONG LineNumber  OPTIONAL,
-    OUT PCH FileName  OPTIONAL,
-    OUT PCH FunctionName  OPTIONAL
+       IN PROSSYM_LINEINFO RosSymLineInfo
 );
 #endif
 
index 95425a2..2e06195 100644 (file)
@@ -78,7 +78,7 @@ KdbpMemoryError(int Status, unsigned int Addr,
 static void
 KdbpPrintAddressInCode(unsigned int Addr, struct disassemble_info * Ignored)
 {
-  if (!KdbSymPrintAddress((void*)Addr))
+    if (!KdbSymPrintAddress((void*)Addr, NULL))
     {
       DbgPrint("<%08x>", Addr);
     }
index a45009c..6d349f1 100644 (file)
@@ -595,7 +595,7 @@ KdbpCmdDisassembleX(
 
         while (Count > 0)
         {
-            if (!KdbSymPrintAddress((PVOID)Address))
+            if (!KdbSymPrintAddress((PVOID)Address, NULL))
                 KdbpPrint("<%x>:", Address);
             else
                 KdbpPrint(":");
@@ -621,7 +621,7 @@ KdbpCmdDisassembleX(
         /* Disassemble */
         while (Count-- > 0)
         {
-            if (!KdbSymPrintAddress((PVOID)Address))
+            if (!KdbSymPrintAddress((PVOID)Address, NULL))
                 KdbpPrint("<%08x>: ", Address);
             else
                 KdbpPrint(": ");
@@ -794,6 +794,7 @@ KdbpCmdBackTrace(
     ULONGLONG Result = 0;
     ULONG_PTR Frame = KdbCurrentTrapFrame->Tf.Ebp;
     ULONG_PTR Address;
+    KTRAP_FRAME TrapFrame;
 
     if (Argc >= 2)
     {
@@ -853,15 +854,19 @@ KdbpCmdBackTrace(
         KdbpPrint("Eip:\n");
 
         /* Try printing the function at EIP */
-        if (!KdbSymPrintAddress((PVOID)KdbCurrentTrapFrame->Tf.Eip))
+        if (!KdbSymPrintAddress((PVOID)KdbCurrentTrapFrame->Tf.Eip, &KdbCurrentTrapFrame->Tf))
             KdbpPrint("<%08x>\n", KdbCurrentTrapFrame->Tf.Eip);
         else
             KdbpPrint("\n");
     }
 
+    TrapFrame = KdbCurrentTrapFrame->Tf;
     KdbpPrint("Frames:\n");
+
     for (;;)
     {
+        BOOLEAN GotNextFrame;
+
         if (Frame == 0)
             break;
 
@@ -871,8 +876,11 @@ KdbpCmdBackTrace(
             break;
         }
 
+        if ((GotNextFrame = NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof (ULONG_PTR)))))
+            TrapFrame.Ebp = Frame;
+
         /* Print the location of the call instruction */
-        if (!KdbSymPrintAddress((PVOID)(Address - 5)))
+        if (!KdbSymPrintAddress((PVOID)(Address - 5), &TrapFrame))
             KdbpPrint("<%08x>\n", Address);
         else
             KdbpPrint("\n");
@@ -882,7 +890,7 @@ KdbpCmdBackTrace(
         if (Address == 0)
             break;
 
-        if (!NT_SUCCESS(KdbpSafeReadMemory(&Frame, (PVOID)Frame, sizeof (ULONG_PTR))))
+        if (!GotNextFrame)
         {
             KdbpPrint("Couldn't access memory at 0x%p!\n", Frame);
             break;
@@ -2666,7 +2674,7 @@ KdbpCliMainLoop(
 
     if (EnteredOnSingleStep)
     {
-        if (!KdbSymPrintAddress((PVOID)KdbCurrentTrapFrame->Tf.Eip))
+        if (!KdbSymPrintAddress((PVOID)KdbCurrentTrapFrame->Tf.Eip, &KdbCurrentTrapFrame->Tf))
         {
             KdbpPrint("<%x>", KdbCurrentTrapFrame->Tf.Eip);
         }
index 64325b1..98176e3 100644 (file)
@@ -28,7 +28,6 @@ typedef struct _IMAGE_SYMBOL_INFO_CACHE
 IMAGE_SYMBOL_INFO_CACHE, *PIMAGE_SYMBOL_INFO_CACHE;
 
 typedef struct _ROSSYM_KM_OWN_CONTEXT {
-    ROSSYM_OWN_FILECONTEXT Rossym;
     LARGE_INTEGER FileOffset;
     PFILE_OBJECT FileObject;
 } ROSSYM_KM_OWN_CONTEXT, *PROSSYM_KM_OWN_CONTEXT;
@@ -65,7 +64,7 @@ KdbpReadSymFile(PVOID FileContext, PVOID Buffer, ULONG Length)
     return NT_SUCCESS(Status);
 }
 
-static PROSSYM_OWN_FILECONTEXT
+static PROSSYM_KM_OWN_CONTEXT 
 KdbpCaptureFileForSymbols(PFILE_OBJECT FileObject)
 {
     PROSSYM_KM_OWN_CONTEXT Context = ExAllocatePool(NonPagedPool, sizeof(*Context));
@@ -73,15 +72,12 @@ KdbpCaptureFileForSymbols(PFILE_OBJECT FileObject)
     ObReferenceObject(FileObject);
     Context->FileOffset.QuadPart = 0;
     Context->FileObject = FileObject;
-    Context->Rossym.ReadFileProc = KdbpReadSymFile;
-    Context->Rossym.SeekFileProc = KdbpSeekSymFile;
-    return &Context->Rossym;
+    return Context;
 }
 
 static VOID
-KdbpReleaseFileForSymbols(PROSSYM_OWN_FILECONTEXT FileContext)
+KdbpReleaseFileForSymbols(PROSSYM_KM_OWN_CONTEXT Context)
 {
-    PROSSYM_KM_OWN_CONTEXT Context = (PROSSYM_KM_OWN_CONTEXT)FileContext;
     ObDereferenceObject(Context->FileObject);
     ExFreePool(Context);
 }
@@ -175,31 +171,75 @@ KdbpSymFindModule(
  */
 BOOLEAN
 KdbSymPrintAddress(
-    IN PVOID Address)
+    IN PVOID Address,
+    IN PKTRAP_FRAME Context)
 {
+    int i;
        PMEMORY_AREA MemoryArea = NULL;
        PROS_SECTION_OBJECT SectionObject;
     PLDR_DATA_TABLE_ENTRY LdrEntry;
-    PROSSYM_OWN_FILECONTEXT FileContext;
+    PROSSYM_KM_OWN_CONTEXT FileContext;
     ULONG_PTR RelativeAddress;
     NTSTATUS Status;
-    ULONG LineNumber;
-    CHAR FileName[256];
-    CHAR FunctionName[256];
+       ROSSYM_LINEINFO LineInfo = { };
+
+    struct {
+        enum _ROSSYM_REGNAME regname;
+        size_t ctx_offset;
+    } regmap[] = {
+        { ROSSYM_X86_EDX, FIELD_OFFSET(KTRAP_FRAME, Edx) },
+        { ROSSYM_X86_EAX, FIELD_OFFSET(KTRAP_FRAME, Eax) },
+        { ROSSYM_X86_ECX, FIELD_OFFSET(KTRAP_FRAME, Ecx) },
+        { ROSSYM_X86_EBX, FIELD_OFFSET(KTRAP_FRAME, Ebx) },
+        { ROSSYM_X86_ESI, FIELD_OFFSET(KTRAP_FRAME, Esi) },
+        { ROSSYM_X86_EDI, FIELD_OFFSET(KTRAP_FRAME, Edi) },
+        { ROSSYM_X86_EBP, FIELD_OFFSET(KTRAP_FRAME, Ebp) },
+        { ROSSYM_X86_ESP, FIELD_OFFSET(KTRAP_FRAME, HardwareEsp) }
+    };
+
+    if (Context) 
+    {
+        DPRINT("Has Context %x (EBP %x)\n", Context, Context->Ebp);
+        LineInfo.Flags = ROSSYM_LINEINFO_HAS_REGISTERS;
+        
+        for (i = 0; i < sizeof(regmap) / sizeof(regmap[0]); i++) {
+            memcpy
+                (&LineInfo.Registers.Registers[regmap[i].regname], 
+                 ((PCHAR)Context)+regmap[i].ctx_offset, 
+                 sizeof(ULONG_PTR));
+            DPRINT("DWARF REG[%d] -> %x\n", regmap[i].regname, LineInfo.Registers.Registers[regmap[i].regname]);
+        }
+    }
 
     if (!KdbpSymbolsInitialized || !KdbpSymFindModule(Address, NULL, -1, &LdrEntry))
         return FALSE;
 
     RelativeAddress = (ULONG_PTR)Address - (ULONG_PTR)LdrEntry->DllBase;
-    Status = KdbSymGetAddressInformation(LdrEntry->PatchInformation,
-                                         RelativeAddress,
-                                         &LineNumber,
-                                         FileName,
-                                         FunctionName);
+    Status = KdbSymGetAddressInformation
+               (LdrEntry->PatchInformation,
+                RelativeAddress,
+                &LineInfo);
+
     if (NT_SUCCESS(Status))
     {
         DbgPrint("<%wZ:%x (%s:%d (%s))>",
-            &LdrEntry->BaseDllName, RelativeAddress, FileName, LineNumber, FunctionName);
+            &LdrEntry->BaseDllName, RelativeAddress, LineInfo.FileName, LineInfo.LineNumber, LineInfo.FunctionName);
+        if (Context)
+        {
+            int i;
+            char *comma = "";
+            DbgPrint("(");
+            for (i = 0; i < LineInfo.NumParams; i++) {
+                DbgPrint
+                    ("%s%s=%llx", 
+                     comma,
+                     LineInfo.Parameters[i].ValueName, 
+                     LineInfo.Parameters[i].Value);
+                comma = ",";
+            }
+            DbgPrint(")");
+        }
+
                return TRUE;
     }
        else if (Address < MmSystemRangeStart)
@@ -232,18 +272,37 @@ KdbSymPrintAddress(
                if (KdbpRosSymInfo)
                {
                        RelativeAddress = (ULONG_PTR)Address - KdbpImageBase;
+                       RosSymFreeInfo(&LineInfo);
                        Status = KdbSymGetAddressInformation
                                (KdbpRosSymInfo,
                                 RelativeAddress,
-                                &LineNumber,
-                                FileName,
-                                FunctionName);
+                                &LineInfo);
                        if (NT_SUCCESS(Status))
                        {
                                DbgPrint
                                        ("<%wZ:%x (%s:%d (%s))>",
-                                        &SectionObject->FileObject->FileName,
-                                        RelativeAddress, FileName, LineNumber, FunctionName);
+                                        &SectionObject->FileObject->FileName, 
+                                        RelativeAddress, 
+                                        LineInfo.FileName, 
+                                        LineInfo.LineNumber, 
+                                        LineInfo.FunctionName);
+
+                if (Context)
+                {
+                    int i;
+                    char *comma = "";
+                    DbgPrint("(");
+                    for (i = 0; i < LineInfo.NumParams; i++) {
+                        DbgPrint
+                            ("%s%s=%llx", 
+                             comma,
+                             LineInfo.Parameters[i].ValueName, 
+                             LineInfo.Parameters[i].Value);
+                        comma = ",";
+                    }
+                    DbgPrint(")");
+                }
+
                                return TRUE;
                        }
                }
@@ -276,13 +335,11 @@ NTSTATUS
 KdbSymGetAddressInformation(
     IN PROSSYM_INFO RosSymInfo,
     IN ULONG_PTR RelativeAddress,
-    OUT PULONG LineNumber  OPTIONAL,
-    OUT PCH FileName  OPTIONAL,
-    OUT PCH FunctionName  OPTIONAL)
+       IN PROSSYM_LINEINFO LineInfo)
 {
     if (!KdbpSymbolsInitialized ||
         !RosSymInfo ||
-        !RosSymGetAddressInformation(RosSymInfo, RelativeAddress, LineNumber, FileName, FunctionName))
+        !RosSymGetAddressInformation(RosSymInfo, RelativeAddress, LineInfo))
     {
         return STATUS_UNSUCCESSFUL;
     }
@@ -429,7 +486,7 @@ KdbpSymLoadModuleSymbols(
     NTSTATUS Status;
     IO_STATUS_BLOCK IoStatusBlock;
     PFILE_OBJECT FileObject;
-    PROSSYM_OWN_FILECONTEXT FileContext;
+    PROSSYM_KM_OWN_CONTEXT FileContext;
 
     /* Allow KDB to break on module load */
     KdbModuleLoaded(FileName);
@@ -536,6 +593,26 @@ KdbDebugPrint(
     /* Nothing here */
 }
 
+static PVOID KdbpSymAllocMem(ULONG_PTR size)
+{
+       return ExAllocatePoolWithTag(NonPagedPool, size, 'RSYM');
+}
+
+static VOID KdbpSymFreeMem(PVOID Area)
+{
+       return ExFreePool(Area);
+}
+
+static BOOLEAN KdbpSymReadMem(PVOID FileContext, PVOID TargetDebug, PVOID SourceMem, ULONG Size)
+{
+       return NT_SUCCESS(KdbpSafeReadMemory(TargetDebug, SourceMem, Size));
+}
+
+static ROSSYM_CALLBACKS KdbpRosSymCallbacks = {
+       KdbpSymAllocMem, KdbpSymFreeMem,
+       KdbpReadSymFile, KdbpSeekSymFile,
+       KdbpSymReadMem
+};
 
 /*! \brief Initializes the KDB symbols implementation.
  *
@@ -621,7 +698,7 @@ KdbInitialize(
             p1 = p2;
         }
 
-        RosSymInitKernelMode();
+        RosSymInit(&KdbpRosSymCallbacks);
     }
     else if (BootPhase == 3)
     {
index 284f425..54a7528 100644 (file)
@@ -266,7 +266,7 @@ KeRosDumpStackFrameArray(IN PULONG_PTR Frames,
         if (p)
         {
 #ifdef KDBG
-            if (!KdbSymPrintAddress((PVOID)Addr))
+            if (!KdbSymPrintAddress((PVOID)Addr, NULL))
 #endif
             {
                 /* Print out the module name */