mirror of
https://github.com/reactos/reactos.git
synced 2024-07-01 18:24:24 +00:00
[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
This commit is contained in:
parent
2489556d2b
commit
295bc5ef26
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
@ -375,16 +387,13 @@ struct DwarfSym
|
|||
DwarfAttrs attrs;
|
||||
|
||||
/* not for consumer use... */
|
||||
uint num;
|
||||
DwarfBuf b;
|
||||
ulong unit;
|
||||
uint uoff;
|
||||
ulong aoff;
|
||||
int depth;
|
||||
int allunits;
|
||||
ulong nextunit;
|
||||
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
|
||||
|
|
|
@ -64,7 +64,7 @@ parseabbrevs(Dwarf *d, ulong off, DwarfAbbrev *abbrev, DwarfAttr *attr, int *pna
|
|||
DwarfBuf b;
|
||||
|
||||
if(off >= d->abbrev.len){
|
||||
werrstr("bad abbrev section offset 0x%lux >= 0x%lux\n", off, d->abbrev.len);
|
||||
werrstr("bad abbrev section offset 0x%lux >= 0x%lux", off, d->abbrev.len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -83,10 +83,12 @@ parseabbrevs(Dwarf *d, ulong off, DwarfAbbrev *abbrev, DwarfAttr *attr, int *pna
|
|||
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){
|
||||
|
@ -121,6 +123,7 @@ findabbrev(DwarfAbbrev *a, int na, ulong num)
|
|||
for(i=0; i<na; i++)
|
||||
if(a[i].num == num)
|
||||
return &a[i];
|
||||
assert(0);
|
||||
werrstr("abbrev not found");
|
||||
return nil;
|
||||
}
|
||||
|
@ -138,4 +141,3 @@ dwarfgetabbrev(Dwarf *d, ulong off, ulong num)
|
|||
return findabbrev(a, na, num);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -67,5 +67,3 @@ dwarfaddrtounit(Dwarf *d, ulong addr, ulong *unit)
|
|||
werrstr("address 0x%lux is not listed in dwarf debugging symbols", addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,9 +17,10 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#include "pe.h"
|
||||
#include "dwarf.h"
|
||||
|
||||
#define trace 0
|
||||
#define trace 1
|
||||
|
||||
typedef struct State State;
|
||||
struct State
|
||||
|
@ -71,7 +72,7 @@ dwarfunwind(Dwarf *d, ulong pc, DwarfExpr *cfa, DwarfExpr *ra, DwarfExpr *r, int
|
|||
memset(r, 0, nr*sizeof(r[0]));
|
||||
for(i=0; i<nr; i++)
|
||||
r[i].type = RuleSame;
|
||||
if(trace) werrstr("s.init %p-%p, fde %p-%p\n", s.init.p, s.init.ep, fde.p, fde.ep);
|
||||
if(trace) werrstr("s.init %p-%p, fde %p-%p", s.init.p, s.init.ep, fde.p, fde.ep);
|
||||
b = s.init;
|
||||
if(dexec(&b, &s, 0) < 0)
|
||||
goto err;
|
||||
|
@ -79,9 +80,9 @@ dwarfunwind(Dwarf *d, ulong pc, DwarfExpr *cfa, DwarfExpr *ra, DwarfExpr *r, int
|
|||
s.initr = initr;
|
||||
memmove(initr, r, nr*sizeof(initr[0]));
|
||||
|
||||
if(trace) werrstr("s.loc 0x%lux pc 0x%lux\n", s.loc, pc);
|
||||
if(trace) werrstr("s.loc 0x%lx pc 0x%lx", s.loc, pc);
|
||||
while(s.loc < pc){
|
||||
if(trace) werrstr("s.loc 0x%lux pc 0x%lux\n", s.loc, pc);
|
||||
if(trace) werrstr("s.loc 0x%lx pc 0x%lx", s.loc, pc);
|
||||
if(dexec(&fde, &s, 1) < 0)
|
||||
goto err;
|
||||
}
|
||||
|
@ -139,15 +140,16 @@ findfde(Dwarf *d, ulong pc, State *s, DwarfBuf *fde)
|
|||
id = dwarfget4(&b);
|
||||
if(id == 0xFFFFFFFF){ /* CIE */
|
||||
vers = dwarfget1(&b);
|
||||
if (trace) werrstr("CIE len %x id %x vers %x", len, id, vers);
|
||||
if(vers != 1 && vers != 2 && vers != 3){
|
||||
if(++nbad == 1)
|
||||
werrstr("unknown cie version %d (wanted 1-3)\n", vers);
|
||||
werrstr("unknown cie version %d (wanted 1-3)", vers);
|
||||
continue;
|
||||
}
|
||||
aug = dwarfgetstring(&b);
|
||||
if(aug && *aug){
|
||||
if(++nbad == 1)
|
||||
werrstr("unknown augmentation: %s\n", aug);
|
||||
werrstr("unknown augmentation: %s", aug);
|
||||
continue;
|
||||
}
|
||||
s->iquantum = dwarfget128(&b);
|
||||
|
@ -163,6 +165,7 @@ findfde(Dwarf *d, ulong pc, State *s, DwarfBuf *fde)
|
|||
}else{ /* FDE */
|
||||
base = dwarfgetaddr(&b);
|
||||
size = dwarfgetaddr(&b);
|
||||
if (trace) werrstr("FDE: base %x-%x (want pc %x)", base, base+size, pc);
|
||||
fde->p = b.p;
|
||||
fde->ep = next;
|
||||
s->loc = base;
|
||||
|
@ -171,7 +174,7 @@ findfde(Dwarf *d, ulong pc, State *s, DwarfBuf *fde)
|
|||
return 0;
|
||||
}
|
||||
}
|
||||
werrstr("cannot find call frame information for pc 0x%lux", pc);
|
||||
werrstr("cannot find call frame information for pc 0x%lx", pc);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
@ -180,7 +183,7 @@ static int
|
|||
checkreg(State *s, long r)
|
||||
{
|
||||
if(r < 0 || r >= s->nr){
|
||||
werrstr("bad register number 0x%lux", r);
|
||||
werrstr("bad register number 0x%lx", r);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
@ -197,20 +200,21 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
if(b->p == b->ep){
|
||||
if(s->initr)
|
||||
s->loc = s->endloc;
|
||||
werrstr("end dexec");
|
||||
return 0;
|
||||
}
|
||||
c = dwarfget1(b);
|
||||
if(b->p == nil){
|
||||
werrstr("ran out of instructions during cfa program");
|
||||
if(trace) werrstr("%r\n");
|
||||
if(trace) werrstr("%r");
|
||||
return -1;
|
||||
}
|
||||
if(trace) werrstr("+ loc=0x%lux op 0x%ux ", s->loc, c);
|
||||
if(trace) werrstr("+ loc=0x%x op 0x%x ", s->loc, c);
|
||||
switch(c>>6){
|
||||
case 1: /* advance location */
|
||||
arg1 = c&0x3F;
|
||||
advance:
|
||||
if(trace) werrstr("loc += %ld\n", arg1*s->iquantum);
|
||||
if(trace) werrstr("loc += %ld", arg1*s->iquantum);
|
||||
s->loc += arg1 * s->iquantum;
|
||||
if(locstop)
|
||||
return 0;
|
||||
|
@ -220,7 +224,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
arg1 = c&0x3F;
|
||||
arg2 = dwarfget128(b);
|
||||
offset:
|
||||
if(trace) werrstr("r%ld += %ld\n", arg1, arg2*s->dquantum);
|
||||
if(trace) werrstr("r%ld += %ld", arg1, arg2*s->dquantum);
|
||||
if(checkreg(s, arg1) < 0)
|
||||
return -1;
|
||||
s->r[arg1].type = RuleCfaOffset;
|
||||
|
@ -230,7 +234,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
case 3: /* restore initial setting */
|
||||
arg1 = c&0x3F;
|
||||
restore:
|
||||
if(trace) werrstr("r%ld = init\n", arg1);
|
||||
if(trace) werrstr("r%ld = init", arg1);
|
||||
if(checkreg(s, arg1) < 0)
|
||||
return -1;
|
||||
s->r[arg1] = s->initr[arg1];
|
||||
|
@ -239,12 +243,12 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
|
||||
switch(c){
|
||||
case 0: /* nop */
|
||||
if(trace) werrstr("nop\n");
|
||||
if(trace) werrstr("nop");
|
||||
continue;
|
||||
|
||||
case 0x01: /* set location */
|
||||
s->loc = dwarfgetaddr(b);
|
||||
if(trace) werrstr("loc = 0x%lux\n", s->loc);
|
||||
if(trace) werrstr("loc = 0x%lx", s->loc);
|
||||
if(locstop)
|
||||
return 0;
|
||||
continue;
|
||||
|
@ -272,7 +276,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
|
||||
case 0x07: /* undefined */
|
||||
arg1 = dwarfget128(b);
|
||||
if(trace) werrstr("r%ld = undef\n", arg1);
|
||||
if(trace) werrstr("r%ld = undef", arg1);
|
||||
if(checkreg(s, arg1) < 0)
|
||||
return -1;
|
||||
s->r[arg1].type = RuleUndef;
|
||||
|
@ -280,7 +284,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
|
||||
case 0x08: /* same value */
|
||||
arg1 = dwarfget128(b);
|
||||
if(trace) werrstr("r%ld = same\n", arg1);
|
||||
if(trace) werrstr("r%ld = same", arg1);
|
||||
if(checkreg(s, arg1) < 0)
|
||||
return -1;
|
||||
s->r[arg1].type = RuleSame;
|
||||
|
@ -289,7 +293,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
case 0x09: /* register */
|
||||
arg1 = dwarfget128(b);
|
||||
arg2 = dwarfget128(b);
|
||||
if(trace) werrstr("r%ld = r%ld\n", arg1, arg2);
|
||||
if(trace) werrstr("r%ld = r%ld", arg1, arg2);
|
||||
if(checkreg(s, arg1) < 0 || checkreg(s, arg2) < 0)
|
||||
return -1;
|
||||
s->r[arg1].type = RuleRegister;
|
||||
|
@ -298,7 +302,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
|
||||
case 0x0A: /* remember state */
|
||||
e = malloc(s->nr*sizeof(e[0]));
|
||||
if(trace) werrstr("push\n");
|
||||
if(trace) werrstr("push");
|
||||
if(e == nil)
|
||||
return -1;
|
||||
void *newstack = malloc(s->nstack*sizeof(s->stack[0]));
|
||||
|
@ -319,7 +323,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
continue;
|
||||
|
||||
case 0x0B: /* restore state */
|
||||
if(trace) werrstr("pop\n");
|
||||
if(trace) werrstr("pop");
|
||||
if(s->nstack == 0){
|
||||
werrstr("restore state underflow");
|
||||
return -1;
|
||||
|
@ -334,7 +338,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
arg1 = dwarfget128(b);
|
||||
arg2 = dwarfget128(b);
|
||||
defcfa:
|
||||
if(trace) werrstr("cfa %ld(r%ld)\n", arg2, arg1);
|
||||
if(trace) werrstr("cfa %ld(r%ld)", arg2, arg1);
|
||||
if(checkreg(s, arg1) < 0)
|
||||
return -1;
|
||||
s->cfa->type = RuleRegOff;
|
||||
|
@ -344,7 +348,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
|
||||
case 0x0D: /* def cfa register */
|
||||
arg1 = dwarfget128(b);
|
||||
if(trace) werrstr("cfa reg r%ld\n", arg1);
|
||||
if(trace) werrstr("cfa reg r%ld", arg1);
|
||||
if(s->cfa->type != RuleRegOff){
|
||||
werrstr("change CFA register but CFA not in register+offset form");
|
||||
return -1;
|
||||
|
@ -357,7 +361,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
case 0x0E: /* def cfa offset */
|
||||
arg1 = dwarfget128(b);
|
||||
cfaoffset:
|
||||
if(trace) werrstr("cfa off %ld\n", arg1);
|
||||
if(trace) werrstr("cfa off %ld", arg1);
|
||||
if(s->cfa->type != RuleRegOff){
|
||||
werrstr("change CFA offset but CFA not in register+offset form");
|
||||
return -1;
|
||||
|
@ -366,7 +370,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
continue;
|
||||
|
||||
case 0x0F: /* def cfa expression */
|
||||
if(trace) werrstr("cfa expr\n");
|
||||
if(trace) werrstr("cfa expr");
|
||||
s->cfa->type = RuleLocation;
|
||||
s->cfa->loc.len = dwarfget128(b);
|
||||
s->cfa->loc.data = dwarfgetnref(b, s->cfa->loc.len);
|
||||
|
@ -374,7 +378,7 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
|
||||
case 0x10: /* def reg expression */
|
||||
arg1 = dwarfget128(b);
|
||||
if(trace) werrstr("reg expr r%ld\n", arg1);
|
||||
if(trace) werrstr("reg expr r%ld", arg1);
|
||||
if(checkreg(s, arg1) < 0)
|
||||
return -1;
|
||||
s->r[arg1].type = RuleLocation;
|
||||
|
@ -397,11 +401,98 @@ dexec(DwarfBuf *b, State *s, int locstop)
|
|||
goto cfaoffset;
|
||||
|
||||
default: /* unknown */
|
||||
werrstr("unknown opcode 0x%ux in cfa program", c);
|
||||
werrstr("unknown opcode 0x%x in cfa program", c);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
int dwarfcomputecfa(Dwarf *d, DwarfExpr *cfa, PROSSYM_REGISTERS registers, ulong *cfaLocation)
|
||||
{
|
||||
switch (cfa->type) {
|
||||
case RuleRegOff:
|
||||
*cfaLocation = registers->Registers[cfa->reg] + cfa->offset;
|
||||
werrstr("cfa reg %d (%x) offset %x = %x", cfa->reg, (ulong)registers->Registers[cfa->reg], cfa->offset, cfaLocation);
|
||||
break;
|
||||
default:
|
||||
werrstr("cfa->type %x", cfa->type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dwarfregunwind(Dwarf *d, ulong pc, ulong fde, DwarfExpr *cfa, PROSSYM_REGISTERS registers)
|
||||
{
|
||||
int i;
|
||||
State s = { };
|
||||
DwarfExpr initr[sizeof(registers->Registers) / sizeof(registers->Registers[0])] = { };
|
||||
DwarfExpr r[sizeof(registers->Registers) / sizeof(registers->Registers[0])] = { };
|
||||
DwarfExpr ra;
|
||||
|
||||
int nr = s.nr = sizeof(registers->Registers) / sizeof(registers->Registers[0]);
|
||||
s.initr = initr;
|
||||
s.r = r;
|
||||
for (i = 0; i < sizeof(r) / sizeof(r[0]); i++) {
|
||||
r[i].type = RuleRegister;
|
||||
r[i].offset = registers->Registers[i];
|
||||
r[i].reg = i;
|
||||
}
|
||||
|
||||
int res = dwarfunwind(d, pc, cfa, &ra, initr, sizeof(initr) / sizeof(initr[0]));
|
||||
if (res == -1) return -1;
|
||||
|
||||
ulong cfaLocation;
|
||||
|
||||
if (dwarfcomputecfa(d, cfa, registers, &cfaLocation) == -1)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < nr; i++) {
|
||||
switch (r[i].type) {
|
||||
case RuleUndef:
|
||||
werrstr("Undefined register slot %d", i);
|
||||
assert(FALSE);
|
||||
break;
|
||||
case RuleSame:
|
||||
break;
|
||||
case RuleRegister:
|
||||
registers->Registers[i] = registers->Registers[r[i].reg];
|
||||
break;
|
||||
case RuleRegOff: {
|
||||
BOOLEAN success =
|
||||
RosSymCallbacks.MemGetProc
|
||||
(d->pe->fd,
|
||||
®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;
|
||||
}
|
||||
|
|
|
@ -139,7 +139,7 @@ dwarfgetaddr(DwarfBuf *b)
|
|||
return dwarfget8(b);
|
||||
default:
|
||||
if(++nbad == 1)
|
||||
werrstr("dwarf: unexpected address size %lud in dwarfgetaddr\n", b->addrsize);
|
||||
werrstr("dwarf: unexpected address size %lud in dwarfgetaddr", b->addrsize);
|
||||
b->p = nil;
|
||||
return 0;
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ dwarfget128(DwarfBuf *b)
|
|||
while(b->p<b->ep && *b->p&0x80)
|
||||
b->p++;
|
||||
if(++nbad == 1)
|
||||
werrstr("dwarf: overflow during parsing of uleb128 integer\n");
|
||||
werrstr("dwarf: overflow during parsing of uleb128 integer");
|
||||
return c;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <debug.h>
|
||||
|
||||
#include "dwarf.h"
|
||||
#include "pe.h"
|
||||
#include <windef.h>
|
||||
|
||||
enum
|
||||
|
@ -114,55 +115,69 @@ enum
|
|||
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)
|
||||
DwarfSym compunit = { };
|
||||
if(dwarfenumunit(d, unit, &compunit) < 0)
|
||||
return -1;
|
||||
|
||||
dwarfnextsymat(d, s, 0); /* s is now the CompileUnit */
|
||||
while(dwarfnextsymat(d, s, 1) == 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))
|
||||
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) {
|
||||
DwarfSym compunit = { };
|
||||
if (dwarfenumunit(d, unit, &compunit) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dwarfnextsymat(d, s, 0); /* s is now the CompileUnit */
|
||||
if(s->attrs.tag == tag) {
|
||||
do {
|
||||
if (compunit.attrs.tag == tag) {
|
||||
*s = compunit;
|
||||
return 0;
|
||||
}
|
||||
while(dwarfnextsymat(d, s, 1) == 1)
|
||||
if(s->attrs.tag == tag) {
|
||||
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;
|
||||
}
|
||||
|
@ -170,25 +185,23 @@ dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s)
|
|||
int
|
||||
dwarfseeksym(Dwarf *d, ulong unit, ulong off, DwarfSym *s)
|
||||
{
|
||||
if(dwarfenumunit(d, unit, s) < 0)
|
||||
DwarfSym compunit = { };
|
||||
if(dwarfenumunit(d, unit, &compunit) < 0)
|
||||
return -1;
|
||||
s->b.p = d->info.data + unit + off;
|
||||
if(dwarfnextsymat(d, s, 0) != 1)
|
||||
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)
|
||||
DwarfSym compunit = { };
|
||||
if(dwarfenumunit(d, unit, &compunit) < 0)
|
||||
return -1;
|
||||
|
||||
if(dwarfnextsymat(d, s, 0) != 1)
|
||||
return -1;
|
||||
/* s is now the CompileUnit */
|
||||
|
||||
while(dwarfnextsymat(d, s, 1) == 1){
|
||||
while(dwarfnextsymat(d, &compunit, s) == 0){
|
||||
if(s->attrs.tag != TagSubprogram)
|
||||
continue;
|
||||
if(s->attrs.lowpc <= pc && pc < s->attrs.highpc)
|
||||
|
@ -215,11 +228,13 @@ dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s)
|
|||
s->b.p = d->info.data + unit;
|
||||
s->b.ep = d->info.data + d->info.len;
|
||||
len = dwarfget4(&s->b);
|
||||
s->unit = unit;
|
||||
s->nextunit = unit + 4 + len;
|
||||
s->b.ep = d->info.data + s->nextunit;
|
||||
|
||||
if(s->b.ep - s->b.p < len){
|
||||
badheader:
|
||||
werrstr("bad dwarf unit header at unit 0x%lux", unit);
|
||||
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;
|
||||
|
@ -233,18 +248,8 @@ dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s)
|
|||
goto badheader;
|
||||
|
||||
s->aoff = aoff;
|
||||
s->unit = unit;
|
||||
s->depth = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dwarfenum(Dwarf *d, DwarfSym *s)
|
||||
{
|
||||
if(dwarfenumunit(d, 0, s) < 0)
|
||||
return -1;
|
||||
s->allunits = 1;
|
||||
return 0;
|
||||
return dwarfnextsym(d, s);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -253,78 +258,67 @@ dwarfnextsym(Dwarf *d, DwarfSym *s)
|
|||
ulong num;
|
||||
DwarfAbbrev *a;
|
||||
|
||||
if(s->attrs.haskids)
|
||||
s->depth++;
|
||||
top:
|
||||
if(s->b.p >= s->b.ep){
|
||||
if(s->allunits && s->nextunit < d->info.len){
|
||||
if(dwarfenumunit(d, s->nextunit, s) < 0) {
|
||||
return -1;
|
||||
}
|
||||
s->allunits = 1;
|
||||
goto top;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s->uoff = s->b.p - (d->info.data+s->unit);
|
||||
num = dwarfget128(&s->b);
|
||||
s->num = num;
|
||||
if(num == 0){
|
||||
if(s->depth == 0) {
|
||||
return 0;
|
||||
}
|
||||
if(s->depth > 0)
|
||||
s->depth--;
|
||||
goto top;
|
||||
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);
|
||||
werrstr("getabbrev %ud %ud for %ud,%ud", s->aoff, num, s->unit);
|
||||
return -1;
|
||||
}
|
||||
if(parseattrs(&s->b, s->unit, a, &s->attrs) < 0) {
|
||||
|
||||
if(parseattrs(d, &s->b, s->attrs.tag, s->unit, a, &s->attrs) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
|
||||
if (s->attrs.haskids) {
|
||||
DwarfSym childSkip = { };
|
||||
s->childoff = s->b.p - d->info.data;
|
||||
int r = dwarfnextsymat(d, s, &childSkip);
|
||||
while (r == 0) {
|
||||
r = dwarfnextsym(d, &childSkip);
|
||||
}
|
||||
s->b = childSkip.b;
|
||||
} else {
|
||||
s->childoff = 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
dwarfnextsymat(Dwarf *d, DwarfSym *s, int depth)
|
||||
dwarfnextsymat(Dwarf *d, DwarfSym *parent, DwarfSym *child)
|
||||
{
|
||||
int r;
|
||||
DwarfSym t;
|
||||
uint sib;
|
||||
|
||||
if(s->depth == depth && s->attrs.have.sibling){
|
||||
sib = s->attrs.sibling;
|
||||
if(sib < d->info.len && d->info.data+sib >= s->b.p)
|
||||
s->b.p = d->info.data+sib;
|
||||
s->attrs.haskids = 0;
|
||||
if (!parent->attrs.haskids || !parent->childoff)
|
||||
return -1;
|
||||
|
||||
child->unit = parent->unit;
|
||||
child->aoff = parent->aoff;
|
||||
child->depth = parent->depth + 1;
|
||||
if(child->attrs.have.sibling){
|
||||
sib = child->attrs.sibling;
|
||||
if(sib < d->info.len && d->info.data+sib > child->b.p)
|
||||
child->b.p = d->info.data+sib;
|
||||
else if (sib >= d->info.len) {
|
||||
werrstr("sibling reported as out of bounds %d vs %d", sib, d->info.len);
|
||||
return -1;
|
||||
} else if (d->info.data+sib+parent->unit < child->b.p) {
|
||||
werrstr("subsequent sibling is listed before prev %d vs %d", sib+parent->unit, child->b.p - d->info.data);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
// 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;
|
||||
|
@ -372,7 +366,7 @@ static Parse plist[] = { /* Font Tab 4 */
|
|||
{ DwarfAttrInline, OFFSET(inlined), TConstant },
|
||||
{ DwarfAttrIsOptional, OFFSET(isoptional), TFlag },
|
||||
{ DwarfAttrLanguage, OFFSET(language), TConstant },
|
||||
{ DwarfAttrLocation, OFFSET(location), TBlock|TConstant },
|
||||
{ DwarfAttrLocation, OFFSET(location), TReference|TBlock },
|
||||
{ DwarfAttrLowerBound, OFFSET(lowerbound), TConstant|TReference },
|
||||
{ DwarfAttrLowpc, OFFSET(lowpc), TAddress },
|
||||
{ DwarfAttrMacroInfo, OFFSET(macroinfo), TConstant },
|
||||
|
@ -405,7 +399,7 @@ static Parse plist[] = { /* Font Tab 4 */
|
|||
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;
|
||||
|
@ -423,10 +417,13 @@ parseattrs(DwarfBuf *b, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs)
|
|||
for(i=0; i<a->nattr; i++){
|
||||
n = a->attr[i].name;
|
||||
f = a->attr[i].form;
|
||||
if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0){
|
||||
if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0) {
|
||||
if (skipform(d, b, f) < 0) {
|
||||
if(++nbad == 1)
|
||||
werrstr("dwarf parse attrs: unexpected attribute name 0x%x", n);
|
||||
continue; //return -1;
|
||||
werrstr("dwarf parse attrs: cannot skip form %d", f);
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
v = (char*)attrs + ptab[n].off;
|
||||
got = 0;
|
||||
|
@ -437,19 +434,21 @@ parseattrs(DwarfBuf *b, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs)
|
|||
;
|
||||
else if((ptab[n].type&TFlag) && getuchar(b, f, v) >= 0)
|
||||
got = TFlag;
|
||||
else if((ptab[n].type&TString) && getstring(b, f, v) >= 0)
|
||||
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(b, f) < 0){
|
||||
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;
|
||||
|
@ -537,17 +536,21 @@ getuchar(DwarfBuf *b, int form, uchar *u)
|
|||
}
|
||||
|
||||
static int
|
||||
getstring(DwarfBuf *b, int form, char **s)
|
||||
getstring(Dwarf *d, DwarfBuf *b, int form, char **s)
|
||||
{
|
||||
static int nbad;
|
||||
ulong u;
|
||||
ulong u, x;
|
||||
|
||||
switch(form){
|
||||
default:
|
||||
return -1;
|
||||
|
||||
case FormString:
|
||||
x = b->p - d->info.data;
|
||||
*s = dwarfgetstring(b);
|
||||
for (u = 0; (*s)[u]; u++) {
|
||||
assert(isprint((*s)[u]));
|
||||
}
|
||||
return 0;
|
||||
|
||||
case FormStrp:
|
||||
|
@ -592,70 +595,389 @@ getblock(DwarfBuf *b, int form, DwarfBlock *bl)
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* last resort */
|
||||
static int
|
||||
skipform(DwarfBuf *b, int form)
|
||||
skipform(Dwarf *d, DwarfBuf *b, int form)
|
||||
{
|
||||
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
|
||||
&& 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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -46,8 +46,9 @@ struct State
|
|||
};
|
||||
|
||||
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)
|
||||
{
|
||||
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;
|
||||
|
@ -55,12 +56,16 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
DwarfBuf b;
|
||||
DwarfSym sym;
|
||||
State emit, cur, reset;
|
||||
uchar **f, **newf;
|
||||
char **f, **newf;
|
||||
|
||||
f = nil;
|
||||
memset(proc, 0, sizeof(*proc));
|
||||
|
||||
if(dwarfaddrtounit(d, pc, &unit) < 0
|
||||
|| dwarflookuptag(d, unit, TagCompileUnit, &sym) < 0)
|
||||
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){
|
||||
|
@ -69,7 +74,7 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
}
|
||||
off = sym.attrs.stmtlist;
|
||||
if(off >= d->line.len){
|
||||
werrstr("bad stmtlist\n");
|
||||
werrstr("bad stmtlist");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
@ -83,7 +88,7 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
|
||||
len = dwarfget4(&b);
|
||||
if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
|
||||
werrstr("bad len\n");
|
||||
werrstr("bad len");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
@ -96,7 +101,7 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
|
||||
len = dwarfget4(&b);
|
||||
if(b.p==nil || b.p+len > b.ep || b.p+len < b.p){
|
||||
werrstr("another bad len\n");
|
||||
werrstr("another bad len");
|
||||
goto bad;
|
||||
}
|
||||
prog = b.p+len;
|
||||
|
@ -110,7 +115,7 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
opcount = b.p-1;
|
||||
dwarfgetnref(&b, opcodebase-1);
|
||||
if(b.p == nil){
|
||||
werrstr("bad opcode chart\n");
|
||||
werrstr("bad opcode chart");
|
||||
goto bad;
|
||||
}
|
||||
|
||||
|
@ -131,7 +136,7 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
|
||||
/* move on to the program */
|
||||
if(b.p == nil || b.p > prog){
|
||||
werrstr("bad header\n");
|
||||
werrstr("bad header");
|
||||
goto bad;
|
||||
}
|
||||
b.p = prog;
|
||||
|
@ -147,7 +152,7 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
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);
|
||||
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;
|
||||
|
@ -158,7 +163,7 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
l = (op - opcodebase) % linerange + linebase;
|
||||
cur.line += l;
|
||||
cur.addr += a * quantum;
|
||||
if(trace) werrstr(" +%d,%d\n", a, l);
|
||||
if(trace) werrstr(" +%d,%d", a, l);
|
||||
emit:
|
||||
if(first){
|
||||
if(cur.addr > pc){
|
||||
|
@ -194,12 +199,12 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
goto bad;
|
||||
switch(dwarfget1(&b)){
|
||||
case 1: /* end sequence */
|
||||
if(trace) werrstr(" end\n");
|
||||
if(trace) werrstr(" end");
|
||||
cur.flags |= EndSequence;
|
||||
goto emit;
|
||||
case 2: /* set address */
|
||||
cur.addr = dwarfgetaddr(&b);
|
||||
if(trace) werrstr(" set pc 0x%x\n", cur.addr);
|
||||
if(trace) werrstr(" set pc 0x%x", cur.addr);
|
||||
break;
|
||||
case 3: /* define file */
|
||||
newf = malloc(nf+1*sizeof(f[0]));
|
||||
|
@ -207,12 +212,14 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
RtlMoveMemory(newf, f, nf*sizeof(f[0]));
|
||||
if(newf == nil)
|
||||
goto out;
|
||||
f[nf++] = b.p;
|
||||
s = dwarfgetstring(&b);
|
||||
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\n", s);
|
||||
if(trace) werrstr(" def file %s", s);
|
||||
break;
|
||||
}
|
||||
if(b.p == nil || b.p > end)
|
||||
|
@ -220,58 +227,58 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
b.p = end;
|
||||
break;
|
||||
case 1: /* emit */
|
||||
if(trace) werrstr(" emit\n");
|
||||
if(trace) werrstr(" emit");
|
||||
goto emit;
|
||||
case 2: /* advance pc */
|
||||
a = dwarfget128(&b);
|
||||
if(trace) werrstr(" advance pc + %lu\n", a*quantum);
|
||||
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\n", l);
|
||||
if(trace) werrstr(" advance line + %ld", l);
|
||||
cur.line += l;
|
||||
break;
|
||||
case 4: /* set file */
|
||||
if(trace) werrstr(" set file\n");
|
||||
if(trace) werrstr(" set file");
|
||||
cur.file = dwarfget128s(&b);
|
||||
break;
|
||||
case 5: /* set column */
|
||||
if(trace) werrstr(" set column\n");
|
||||
if(trace) werrstr(" set column");
|
||||
cur.column = dwarfget128(&b);
|
||||
break;
|
||||
case 6: /* negate stmt */
|
||||
if(trace) werrstr(" negate stmt\n");
|
||||
if(trace) werrstr(" negate stmt");
|
||||
cur.flags ^= Isstmt;
|
||||
break;
|
||||
case 7: /* set basic block */
|
||||
if(trace) werrstr(" set basic block\n");
|
||||
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\n", a);
|
||||
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\n", a);
|
||||
if(trace) werrstr(" fixed advance pc + %d", a);
|
||||
cur.addr += a;
|
||||
break;
|
||||
case 10: /* set prologue end */
|
||||
if(trace) werrstr(" set prologue end\n");
|
||||
if(trace) werrstr(" set prologue end");
|
||||
cur.flags |= PrologueEnd;
|
||||
break;
|
||||
case 11: /* set epilogue begin */
|
||||
if(trace) werrstr(" set epilogue begin\n");
|
||||
if(trace) werrstr(" set epilogue begin");
|
||||
cur.flags |= EpilogueBegin;
|
||||
break;
|
||||
case 12: /* set isa */
|
||||
if(trace) werrstr(" set isa\n");
|
||||
if(trace) werrstr(" set isa");
|
||||
cur.isa = dwarfget128(&b);
|
||||
break;
|
||||
default: /* something new - skip it */
|
||||
if(trace) werrstr(" unknown %d\n", opcount[op]);
|
||||
if(trace) werrstr(" unknown %d", opcount[op]);
|
||||
for(i=0; i<opcount[op]; i++)
|
||||
dwarfget128(&b);
|
||||
break;
|
||||
|
@ -307,75 +314,88 @@ dwarfpctoline(Dwarf *d, ulong pc, char **cdir, char **dir, char **file, char **f
|
|||
werrstr("bad file index in mapping data");
|
||||
goto bad;
|
||||
}
|
||||
b.p = f[i];
|
||||
b.p = (uchar*)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;
|
||||
cdir = sym.attrs.have.compdir ? sym.attrs.compdir : 0;
|
||||
|
||||
if(dir){
|
||||
*dir = nil;
|
||||
char *dwarfdir;
|
||||
dwarfdir = nil;
|
||||
b.p = dirs;
|
||||
for (x = 1; b.p && *b.p; x++)
|
||||
if (x == i) {
|
||||
*dir = dwarfgetstring(&b);
|
||||
break;
|
||||
}
|
||||
for (x = 1; b.p && *b.p; x++) {
|
||||
dwarfdir = dwarfgetstring(&b);
|
||||
if (x == i) break;
|
||||
}
|
||||
|
||||
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;
|
||||
#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;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
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);
|
||||
*function = malloc(strlen(proc->attrs.name)+1);
|
||||
strcpy(*function, proc->attrs.name);
|
||||
goto done;
|
||||
}
|
||||
lastline = proc->attrs.declline;
|
||||
}
|
||||
renum = dwarfnextsym(d, proc);
|
||||
}
|
||||
}
|
||||
}
|
||||
#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 */
|
||||
done:
|
||||
free(f);
|
||||
return 0;
|
||||
|
||||
bad:
|
||||
werrstr("corrupted line mapping for 0x%x", pc);
|
||||
out:
|
||||
|
@ -383,3 +403,13 @@ out:
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -47,40 +47,85 @@
|
|||
#include "pe.h"
|
||||
|
||||
BOOLEAN
|
||||
RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
|
||||
RosSymGetAddressInformation
|
||||
(PROSSYM_INFO RosSymInfo,
|
||||
ULONG_PTR RelativeAddress,
|
||||
ULONG *LineNumber,
|
||||
char *FileName,
|
||||
char *FunctionName)
|
||||
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 */
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
#define SYMBOL_SIZE 18
|
||||
|
||||
extern NTSTATUS RosSymStatus;
|
||||
|
||||
BOOLEAN
|
||||
|
@ -34,34 +36,34 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
|||
/* Load DOS header */
|
||||
if (! RosSymSeekFile(FileContext, 0))
|
||||
{
|
||||
DPRINT1("Could not rewind file\n");
|
||||
werrstr("Could not rewind file\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (! RosSymReadFile(FileContext, &DosHeader, sizeof(IMAGE_DOS_HEADER)))
|
||||
{
|
||||
DPRINT1("Failed to read DOS header %x\n", RosSymStatus);
|
||||
werrstr("Failed to read DOS header %x\n", RosSymStatus);
|
||||
return FALSE;
|
||||
}
|
||||
if (! ROSSYM_IS_VALID_DOS_HEADER(&DosHeader))
|
||||
{
|
||||
DPRINT1("Image doesn't have a valid DOS header\n");
|
||||
werrstr("Image doesn't have a valid DOS header\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Load NT headers */
|
||||
if (! RosSymSeekFile(FileContext, DosHeader.e_lfanew))
|
||||
{
|
||||
DPRINT1("Failed seeking to NT headers\n");
|
||||
werrstr("Failed seeking to NT headers\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (! RosSymReadFile(FileContext, &NtHeaders, sizeof(IMAGE_NT_HEADERS)))
|
||||
{
|
||||
DPRINT1("Failed to read NT headers\n");
|
||||
werrstr("Failed to read NT headers\n");
|
||||
return FALSE;
|
||||
}
|
||||
if (! ROSSYM_IS_VALID_NT_HEADERS(&NtHeaders))
|
||||
{
|
||||
DPRINT1("Image doesn't have a valid PE header\n");
|
||||
werrstr("Image doesn't have a valid PE header\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -70,7 +72,7 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
|||
|
||||
if (!NumSymbols)
|
||||
{
|
||||
DPRINT1("Image doesn't have debug symbols\n");
|
||||
werrstr("Image doesn't have debug symbols\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -80,7 +82,7 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
|||
if (! RosSymSeekFile(FileContext, (char *) IMAGE_FIRST_SECTION(&NtHeaders) -
|
||||
(char *) &NtHeaders + DosHeader.e_lfanew))
|
||||
{
|
||||
DPRINT1("Failed seeking to section headers\n");
|
||||
werrstr("Failed seeking to section headers\n");
|
||||
return FALSE;
|
||||
}
|
||||
DPRINT("Alloc section headers\n");
|
||||
|
@ -88,7 +90,7 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
|||
* sizeof(IMAGE_SECTION_HEADER));
|
||||
if (NULL == SectionHeaders)
|
||||
{
|
||||
DPRINT1("Failed to allocate memory for %u section headers\n",
|
||||
werrstr("Failed to allocate memory for %u section headers\n",
|
||||
NtHeaders.FileHeader.NumberOfSections);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -97,7 +99,7 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
|||
* sizeof(IMAGE_SECTION_HEADER)))
|
||||
{
|
||||
RosSymFreeMem(SectionHeaders);
|
||||
DPRINT1("Failed to read section headers\n");
|
||||
werrstr("Failed to read section headers\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -142,59 +144,10 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
|
|||
pe->e8 = peget8;
|
||||
pe->nsections = NtHeaders.FileHeader.NumberOfSections;
|
||||
pe->sect = SectionHeaders;
|
||||
pe->nsymbols = NtHeaders.FileHeader.NumberOfSymbols;
|
||||
pe->symtab = malloc(pe->nsymbols * sizeof(CoffSymbol));
|
||||
SYMENT SymbolData;
|
||||
int i, j;
|
||||
DPRINT("Getting symbol data\n");
|
||||
ASSERT(sizeof(SymbolData) == 18);
|
||||
for (i = 0, j = 0; i < pe->nsymbols; i++) {
|
||||
if (!RosSymSeekFile
|
||||
(FileContext,
|
||||
NtHeaders.FileHeader.PointerToSymbolTable + i * sizeof(SymbolData)))
|
||||
goto freeall;
|
||||
if (!RosSymReadFile(FileContext, &SymbolData, sizeof(SymbolData)))
|
||||
goto freeall;
|
||||
if ((SymbolData.e_scnum < 1) ||
|
||||
(SymbolData.e_sclass != C_EXT &&
|
||||
SymbolData.e_sclass != C_STAT))
|
||||
continue;
|
||||
int section = SymbolData.e_scnum - 1;
|
||||
if (SymbolData.e.e.e_zeroes) {
|
||||
pe->symtab[j].name = malloc(sizeof(SymbolData.e.e_name)+1);
|
||||
memcpy(pe->symtab[j].name, SymbolData.e.e_name, sizeof(SymbolData.e.e_name));
|
||||
pe->symtab[j].name[sizeof(SymbolData.e.e_name)] = 0;
|
||||
} else {
|
||||
if (!RosSymSeekFile
|
||||
(FileContext,
|
||||
NtHeaders.FileHeader.PointerToSymbolTable +
|
||||
(NtHeaders.FileHeader.NumberOfSymbols * 18) +
|
||||
SymbolData.e.e.e_offset))
|
||||
goto freeall;
|
||||
pe->symtab[j].name = malloc(MAXIMUM_COFF_SYMBOL_LENGTH+1);
|
||||
pe->symtab[j].name[MAXIMUM_COFF_SYMBOL_LENGTH] = 0;
|
||||
// It's possible that we've got a string just at the end of the file
|
||||
// we'll skip that symbol if needed
|
||||
if (!RosSymReadFile(FileContext, pe->symtab[j].name, MAXIMUM_COFF_SYMBOL_LENGTH)) {
|
||||
free(pe->symtab[j].name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (pe->symtab[j].name[0] == '.') {
|
||||
free(pe->symtab[j].name);
|
||||
continue;
|
||||
}
|
||||
pe->symtab[j].address = pe->sect[section].VirtualAddress + SymbolData.e_value;
|
||||
j++;
|
||||
}
|
||||
DPRINT("%d symbols\n", j);
|
||||
pe->nsymbols = j;
|
||||
pe->imagebase = pe->loadbase = NtHeaders.OptionalHeader.ImageBase;
|
||||
pe->imagesize = NtHeaders.OptionalHeader.SizeOfImage;
|
||||
pe->loadsection = loaddisksection;
|
||||
DPRINT("do dwarfopen\n");
|
||||
*RosSymInfo = dwarfopen(pe);
|
||||
DPRINT("done %x\n", *RosSymInfo);
|
||||
|
||||
return TRUE;
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "rossympriv.h"
|
||||
#define NTOS_MODE_USER
|
||||
#include <ndk/ntndk.h>
|
||||
#include <pseh/pseh.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
@ -29,6 +30,12 @@ RosSymFreeMemUM(PVOID Area)
|
|||
RtlFreeHeap(RtlGetProcessHeap(), 0, Area);
|
||||
}
|
||||
|
||||
static BOOLEAN
|
||||
RosSymGetMemUM(ULONG_PTR *Target, PVOID SourceMem, ULONG Size)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
RosSymInitUserMode(VOID)
|
||||
{
|
||||
|
@ -37,7 +44,8 @@ RosSymInitUserMode(VOID)
|
|||
RosSymAllocMemUM,
|
||||
RosSymFreeMemUM,
|
||||
RosSymZwReadFile,
|
||||
RosSymZwSeekFile
|
||||
RosSymZwSeekFile,
|
||||
RosSymGetMemUM
|
||||
};
|
||||
|
||||
RosSymInit(&KmCallbacks);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -6,49 +6,19 @@
|
|||
struct DwarfBlock;
|
||||
typedef struct _IMAGE_SECTION_HEADER PeSect;
|
||||
|
||||
typedef struct _CoffSymbol {
|
||||
ulong address;
|
||||
char *name;
|
||||
} CoffSymbol;
|
||||
|
||||
typedef struct _Pe {
|
||||
void *fd;
|
||||
u16int (*e2)(const unsigned char *data);
|
||||
u32int (*e4)(const unsigned char *data);
|
||||
u64int (*e8)(const unsigned char *data);
|
||||
ulong imagebase, imagesize, loadbase;
|
||||
ulong nsymbols;
|
||||
CoffSymbol *symtab;
|
||||
int (*loadsection)(struct _Pe *pe, char *name, struct DwarfBlock *b);
|
||||
int nsections;
|
||||
struct _IMAGE_SECTION_HEADER *sect;
|
||||
} Pe;
|
||||
|
||||
#define E_SYMNMLEN 8
|
||||
#include <pshpack1.h>
|
||||
typedef struct {
|
||||
union {
|
||||
char e_name[E_SYMNMLEN];
|
||||
struct {
|
||||
unsigned long e_zeroes;
|
||||
unsigned long e_offset;
|
||||
} e;
|
||||
} e;
|
||||
unsigned long e_value;
|
||||
short e_scnum;
|
||||
unsigned short e_type;
|
||||
unsigned char e_sclass;
|
||||
unsigned char e_numaux;
|
||||
} SYMENT, *PSYMENT;
|
||||
#include <poppack.h>
|
||||
|
||||
#define C_EXT 2
|
||||
#define C_STAT 3
|
||||
#define DT_FCN 0x40
|
||||
|
||||
Pe *peopen(const char *name);
|
||||
int loaddisksection(struct _Pe *pe, char *name, struct DwarfBlock *b);
|
||||
int loadmemsection(struct _Pe *pe, char *name, struct DwarfBlock *b);
|
||||
u16int peget2(const unsigned char *ptr);
|
||||
u32int peget4(const unsigned char *ptr);
|
||||
u64int peget8(const unsigned char *ptr);
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
Status = KdbSymGetAddressInformation
|
||||
(LdrEntry->PatchInformation,
|
||||
RelativeAddress,
|
||||
&LineNumber,
|
||||
FileName,
|
||||
FunctionName);
|
||||
&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)
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in a new issue