From 295bc5ef2636dab7d553db63aa0516a3bf3c3818 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Wed, 1 Jun 2011 20:36:40 +0000 Subject: [PATCH] [NTOSKRNL] Merge r52027 from cmake branch: * 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. * works only with cmake builds svn path=/trunk/; revision=52050 --- reactos/include/reactos/rossym.h | 70 ++ reactos/lib/rossym_new/CMakeLists.txt | 3 - reactos/lib/rossym_new/compat.h | 2 + reactos/lib/rossym_new/dwarf.h | 56 +- reactos/lib/rossym_new/dwarfabbrev.c | 174 +-- reactos/lib/rossym_new/dwarfaranges.c | 98 +- reactos/lib/rossym_new/dwarfcfa.c | 143 ++- reactos/lib/rossym_new/dwarfget.c | 4 +- reactos/lib/rossym_new/dwarfinfo.c | 1384 +++++++++++++-------- reactos/lib/rossym_new/dwarfopen.c | 4 +- reactos/lib/rossym_new/dwarfpc.c | 696 ++++++----- reactos/lib/rossym_new/find.c | 103 +- reactos/lib/rossym_new/fromfile.c | 251 ++-- reactos/lib/rossym_new/initum.c | 10 +- reactos/lib/rossym_new/pe.c | 4 - reactos/lib/rossym_new/pe.h | 30 - reactos/lib/rossym_new/rossympriv.h | 6 +- reactos/ntoskrnl/include/internal/kd.h | 8 +- reactos/ntoskrnl/kdbg/i386/i386-dis.c | 2 +- reactos/ntoskrnl/kdbg/kdb_cli.c | 20 +- reactos/ntoskrnl/kdbg/kdb_symbols.c | 3 +- reactos/ntoskrnl/kdbg/kdb_symbols.cmake.c | 133 +- reactos/ntoskrnl/ke/bug.c | 2 +- 23 files changed, 1900 insertions(+), 1306 deletions(-) diff --git a/reactos/include/reactos/rossym.h b/reactos/include/reactos/rossym.h index 4bdf02f0e5f..785299f8779 100644 --- a/reactos/include/reactos/rossym.h +++ b/reactos/include/reactos/rossym.h @@ -26,11 +26,72 @@ 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; #ifdef __ROS_CMAKE__ @@ -46,7 +107,9 @@ typedef struct _ROSSYM_INFO *PROSSYM_INFO; #endif VOID RosSymInit(PROSSYM_CALLBACKS Callbacks); +#ifndef __ROS_CMAKE__ VOID RosSymInitKernelMode(VOID); +#endif VOID RosSymInitUserMode(VOID); BOOLEAN RosSymCreateFromRaw(PVOID RawData, ULONG_PTR DataSize, @@ -56,11 +119,18 @@ BOOLEAN RosSymCreateFromMem(PVOID ImageStart, ULONG_PTR ImageSize, BOOLEAN RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo); ULONG RosSymGetRawDataLength(PROSSYM_INFO RosSymInfo); VOID RosSymGetRawData(PROSSYM_INFO RosSymInfo, PVOID RawData); +#ifdef __ROS_CMAKE__ +BOOLEAN RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo, + ULONG_PTR RelativeAddress, + PROSSYM_LINEINFO RosSymLineInfo); +#else BOOLEAN RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo, ULONG_PTR RelativeAddress, ULONG *LineNumber, char *FileName, char *FunctionName); +#endif +VOID RosSymFreeInfo(PROSSYM_LINEINFO RosSymLineInfo); VOID RosSymDelete(PROSSYM_INFO RosSymInfo); #endif /* REACTOS_ROSSYM_H_INCLUDED */ diff --git a/reactos/lib/rossym_new/CMakeLists.txt b/reactos/lib/rossym_new/CMakeLists.txt index 2b05860e247..73387942ae8 100644 --- a/reactos/lib/rossym_new/CMakeLists.txt +++ b/reactos/lib/rossym_new/CMakeLists.txt @@ -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) diff --git a/reactos/lib/rossym_new/compat.h b/reactos/lib/rossym_new/compat.h index 64dc549f11c..375b498fa3e 100644 --- a/reactos/lib/rossym_new/compat.h +++ b/reactos/lib/rossym_new/compat.h @@ -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) diff --git a/reactos/lib/rossym_new/dwarf.h b/reactos/lib/rossym_new/dwarf.h index 04689814bd7..7308d7deab0 100644 --- a/reactos/lib/rossym_new/dwarf.h +++ b/reactos/lib/rossym_new/dwarf.h @@ -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 diff --git a/reactos/lib/rossym_new/dwarfabbrev.c b/reactos/lib/rossym_new/dwarfabbrev.c index d21ca6a25d1..365d44232d4 100644 --- a/reactos/lib/rossym_new/dwarfabbrev.c +++ b/reactos/lib/rossym_new/dwarfabbrev.c @@ -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; + int nattr, nabbrev; + DwarfAbbrev *abbrev; + DwarfAttr *attr; - if(d->acache.off == off && d->acache.na){ - *aa = d->acache.a; - return d->acache.na; - } + 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; - } + /* 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); + 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; - } + 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; + free(d->acache.a); + d->acache.a = abbrev; + d->acache.na = nabbrev; + d->acache.off = off; - *aa = abbrev; - return nabbrev; + *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; + 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; - } + 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; + 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; + 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; + int i; - for(i=0; iaranges.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.paddrsize == 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 +#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; iiquantum = 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, + ®isters->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, + ®isters->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; +} diff --git a/reactos/lib/rossym_new/dwarfget.c b/reactos/lib/rossym_new/dwarfget.c index d32177cd1db..7787163a21b 100644 --- a/reactos/lib/rossym_new/dwarfget.c +++ b/reactos/lib/rossym_new/dwarfget.c @@ -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->pep && *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; } diff --git a/reactos/lib/rossym_new/dwarfinfo.c b/reactos/lib/rossym_new/dwarfinfo.c index cc25499483a..397702f1180 100644 --- a/reactos/lib/rossym_new/dwarfinfo.c +++ b/reactos/lib/rossym_new/dwarfinfo.c @@ -13,649 +13,971 @@ #include #include "dwarf.h" +#include "pe.h" #include 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, + 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 + 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 +dwarflookupchildtag(Dwarf *d, DwarfSym *parent, ulong tag, DwarfSym *s) +{ + 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; } int dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s) { - if(dwarfenumunit(d, unit, s) < 0) { - return -1; - } - - 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; + 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; + 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); + 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; + 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; -} + s->nextunit = unit + 4 + len; + s->b.ep = d->info.data + s->nextunit; -int -dwarfenum(Dwarf *d, DwarfSym *s) -{ - if(dwarfenumunit(d, 0, s) < 0) - return -1; - s->allunits = 1; - return 0; + 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; + 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; - } + num = dwarfget128(&s->b); + s->num = num; + if(num == 0){ + return -1; + } - 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", s->aoff, num, s->unit); + return -1; + } - 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; + 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; + 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; - } + if (!parent->attrs.haskids || !parent->childoff) + return -1; - /* - * 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; - } - } + 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; + 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]; + /* 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; + memset(attrs, 0, sizeof *attrs); + attrs->tag = a->tag; + attrs->haskids = a->haskids; - for(i=0; inattr; 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; + for(i=0; inattr; 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; + switch(form){ + default: + return -1; - case FormFlag: - *u = dwarfget1(b); - return 0; - } + 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; + static int nbad; + ulong u, x; - switch(form){ - default: - return -1; + switch(form){ + default: + return -1; - case FormString: - *s = dwarfgetstring(b); - return 0; + 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; + 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; + 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; - } -} - -static int -constblock(Dwarf *d, DwarfBlock *bl, ulong *pval) -{ - 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; - } + 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 -skipform(DwarfBuf *b, int form) +skipform(Dwarf *d, DwarfBuf *b, int form) { - int type; - DwarfVal val; + 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(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; } +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) +{ + 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, ¶meter->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, ¶m); + 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, ¶m); + } + return ip; +} diff --git a/reactos/lib/rossym_new/dwarfopen.c b/reactos/lib/rossym_new/dwarfopen.c index 9a5f20c80fa..b3ea2cd18d6 100644 --- a/reactos/lib/rossym_new/dwarfopen.c +++ b/reactos/lib/rossym_new/dwarfopen.c @@ -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; } diff --git a/reactos/lib/rossym_new/dwarfpc.c b/reactos/lib/rossym_new/dwarfpc.c index 4edb5569ae9..ec41e10d16c 100644 --- a/reactos/lib/rossym_new/dwarfpc.c +++ b/reactos/lib/rossym_new/dwarfpc.c @@ -27,359 +27,389 @@ 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); + + 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"); + goto bad; + } + + 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"); + goto bad; + } + prog = b.p+len; + + 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"); + 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); + + 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"); + 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; + + 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 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 */ + cdir = sym.attrs.have.compdir ? sym.attrs.compdir : 0; + + char *dwarfdir; + dwarfdir = nil; + b.p = dirs; + for (x = 1; b.p && *b.p; x++) { + dwarfdir = dwarfgetstring(&b); + if (x == i) break; } - 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? */ - - len = dwarfget4(&b); - if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){ - werrstr("bad len\n"); - goto bad; - } - - 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; - - 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; - } - - /* 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); - - /* move on to the program */ - if(b.p == nil || b.p > prog){ - werrstr("bad header\n"); - 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; - - 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; + 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; } - 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; + renum = dwarfnextsym(d, proc); + } + } + + // 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; } - 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; iattrs.declline; } - } - } - if(b.p == nil) - goto bad; - - /* 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; - - /* 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; - - /* fetch dir name */ - if(cdir) - *cdir = sym.attrs.compdir; - - if(dir){ - *dir = nil; - b.p = dirs; - for (x = 1; b.p && *b.p; x++) - if (x == i) { - *dir = dwarfgetstring(&b); - 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); - } - } - } -#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 - - /* free at last, free at last */ - free(f); - return 0; + 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); +} diff --git a/reactos/lib/rossym_new/find.c b/reactos/lib/rossym_new/find.c index 5f613dc573d..9cc5aeeeece 100644 --- a/reactos/lib/rossym_new/find.c +++ b/reactos/lib/rossym_new/find.c @@ -47,40 +47,85 @@ #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, + ®isters) == -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, ®isters, &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, + ®isters, + ¶ms[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 */ diff --git a/reactos/lib/rossym_new/fromfile.c b/reactos/lib/rossym_new/fromfile.c index 00884a5a56b..c26ea3e2a80 100644 --- a/reactos/lib/rossym_new/fromfile.c +++ b/reactos/lib/rossym_new/fromfile.c @@ -20,191 +20,144 @@ #define NDEBUG #include +#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; + IMAGE_DOS_HEADER DosHeader; + IMAGE_NT_HEADERS NtHeaders; + PIMAGE_SECTION_HEADER SectionHeaders; + unsigned SectionIndex; + unsigned SymbolTable, NumSymbols; - /* Load DOS header */ - if (! RosSymSeekFile(FileContext, 0)) + /* Load DOS header */ + if (! RosSymSeekFile(FileContext, 0)) { - DPRINT1("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("Could not rewind file\n"); + return FALSE; } - if (! ROSSYM_IS_VALID_DOS_HEADER(&DosHeader)) + if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER))) { - DPRINT1("Image doesn't have a valid DOS header\n"); - return FALSE; + werrstr("Failed to read DOS header %x\n", RosSymStatus); + return FALSE; + } + if (! ROSSYM_IS_VALID_DOS_HEADER(&DosHeader)) + { + 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); - DPRINT1("Failed to read section headers\n"); - return FALSE; + RosSymFreeMem(SectionHeaders); + werrstr("Failed to read section headers\n"); + return FALSE; } - // 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; + // 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; - } + 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); + 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; + 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 */ diff --git a/reactos/lib/rossym_new/initum.c b/reactos/lib/rossym_new/initum.c index 5a80fd37eef..eb59c0f185e 100644 --- a/reactos/lib/rossym_new/initum.c +++ b/reactos/lib/rossym_new/initum.c @@ -13,6 +13,7 @@ #include "rossympriv.h" #define NTOS_MODE_USER #include +#include #define NDEBUG #include @@ -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); diff --git a/reactos/lib/rossym_new/pe.c b/reactos/lib/rossym_new/pe.c index a00716cd185..cace420fec2 100644 --- a/reactos/lib/rossym_new/pe.c +++ b/reactos/lib/rossym_new/pe.c @@ -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); } diff --git a/reactos/lib/rossym_new/pe.h b/reactos/lib/rossym_new/pe.h index 5e659a216e9..6b5bbdaa8f4 100644 --- a/reactos/lib/rossym_new/pe.h +++ b/reactos/lib/rossym_new/pe.h @@ -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 -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 - -#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); diff --git a/reactos/lib/rossym_new/rossympriv.h b/reactos/lib/rossym_new/rossympriv.h index ffeb2ce6782..1a604ef3f47 100644 --- a/reactos/lib/rossym_new/rossympriv.h +++ b/reactos/lib/rossym_new/rossympriv.h @@ -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 \ diff --git a/reactos/ntoskrnl/include/internal/kd.h b/reactos/ntoskrnl/include/internal/kd.h index 5bb1060b548..22729be76ef 100644 --- a/reactos/ntoskrnl/include/internal/kd.h +++ b/reactos/ntoskrnl/include/internal/kd.h @@ -75,15 +75,21 @@ KdbSymProcessSymbols( BOOLEAN KdbSymPrintAddress( - IN PVOID Address); + IN PVOID Address, + IN PKTRAP_FRAME Context +); NTSTATUS KdbSymGetAddressInformation( IN PROSSYM_INFO RosSymInfo, IN ULONG_PTR RelativeAddress, +#ifdef __ROS_CMAKE__ + IN PROSSYM_LINEINFO RosSymLineInfo +#else OUT PULONG LineNumber OPTIONAL, OUT PCH FileName OPTIONAL, OUT PCH FunctionName OPTIONAL +#endif ); #endif diff --git a/reactos/ntoskrnl/kdbg/i386/i386-dis.c b/reactos/ntoskrnl/kdbg/i386/i386-dis.c index 95425a227a0..2e0619515d9 100644 --- a/reactos/ntoskrnl/kdbg/i386/i386-dis.c +++ b/reactos/ntoskrnl/kdbg/i386/i386-dis.c @@ -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); } diff --git a/reactos/ntoskrnl/kdbg/kdb_cli.c b/reactos/ntoskrnl/kdbg/kdb_cli.c index a45009cf7c1..6d349f1658e 100644 --- a/reactos/ntoskrnl/kdbg/kdb_cli.c +++ b/reactos/ntoskrnl/kdbg/kdb_cli.c @@ -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); } diff --git a/reactos/ntoskrnl/kdbg/kdb_symbols.c b/reactos/ntoskrnl/kdbg/kdb_symbols.c index d54b871a20a..f54f1cc14c1 100644 --- a/reactos/ntoskrnl/kdbg/kdb_symbols.c +++ b/reactos/ntoskrnl/kdbg/kdb_symbols.c @@ -122,7 +122,8 @@ KdbpSymFindModule( */ BOOLEAN KdbSymPrintAddress( - IN PVOID Address) + IN PVOID Address, + IN PKTRAP_FRAME Context) { PLDR_DATA_TABLE_ENTRY LdrEntry; ULONG_PTR RelativeAddress; diff --git a/reactos/ntoskrnl/kdbg/kdb_symbols.cmake.c b/reactos/ntoskrnl/kdbg/kdb_symbols.cmake.c index 64325b1ba17..a3652d6e7f6 100644 --- a/reactos/ntoskrnl/kdbg/kdb_symbols.cmake.c +++ b/reactos/ntoskrnl/kdbg/kdb_symbols.cmake.c @@ -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); + 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) { diff --git a/reactos/ntoskrnl/ke/bug.c b/reactos/ntoskrnl/ke/bug.c index 284f4252ccd..54a752842c2 100644 --- a/reactos/ntoskrnl/ke/bug.c +++ b/reactos/ntoskrnl/ke/bug.c @@ -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 */