* Add yet another awesome rossym/kdbg feature: struct printing using the command "dt". Brought to you by the Arty.

svn path=/trunk/; revision=52571
This commit is contained in:
Amine Khaldi 2011-07-08 11:16:26 +00:00
parent 81a39fdab6
commit 31ee5fc3a7
12 changed files with 495 additions and 92 deletions

View file

@ -12,6 +12,10 @@
#define ROSSYM_SECTION_NAME ".rossym"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _ROSSYM_HEADER {
unsigned long SymbolsOffset;
unsigned long SymbolsLength;
@ -86,6 +90,18 @@ typedef struct _ROSSYM_LINEINFO {
ROSSYM_PARAMETER Parameters[16];
} ROSSYM_LINEINFO, *PROSSYM_LINEINFO;
typedef struct _ROSSYM_AGGREGATE_MEMBER {
PCHAR Name, Type;
ULONG BaseOffset, Size;
ULONG FirstBit, Bits;
ULONG TypeId;
} ROSSYM_AGGREGATE_MEMBER, *PROSSYM_AGGREGATE_MEMBER;
typedef struct _ROSSYM_AGGREGATE {
ULONG NumElements;
PROSSYM_AGGREGATE_MEMBER Elements;
} ROSSYM_AGGREGATE, *PROSSYM_AGGREGATE;
typedef struct _ROSSYM_CALLBACKS {
PVOID (*AllocMemProc)(ULONG_PTR Size);
VOID (*FreeMemProc)(PVOID Area);
@ -132,6 +148,13 @@ BOOLEAN RosSymGetAddressInformation(PROSSYM_INFO RosSymInfo,
#endif
VOID RosSymFreeInfo(PROSSYM_LINEINFO RosSymLineInfo);
VOID RosSymDelete(PROSSYM_INFO RosSymInfo);
BOOLEAN
RosSymAggregate(PROSSYM_INFO RosSymInfo, PCHAR Type, PROSSYM_AGGREGATE Aggregate);
VOID RosSymFreeAggregate(PROSSYM_AGGREGATE Aggregate);
#ifdef __cplusplus
}
#endif
#endif /* REACTOS_ROSSYM_H_INCLUDED */

View file

@ -19,6 +19,19 @@ typedef long long s64int;
typedef ulong size_t;
#endif
DECLSPEC_NORETURN
NTSYSAPI
VOID
NTAPI
RtlRaiseStatus(IN NTSTATUS Status);
#undef assert
#define assert(x) do { \
if (!(x)) { \
werrstr("(%s:%d) assertion " #x " failed\n", __FILE__, __LINE__); \
RtlRaiseStatus(STATUS_ASSERTION_FAILURE); \
} \
} while (0)
#define offsetof(x,y) FIELD_OFFSET(x,y)
#define nil (0)
@ -32,7 +45,13 @@ 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__)
#if 0
#ifdef NDEBUG
#define werrstr(x, ...)
#else
#define werrstr(x, ...) printf("(%s:%d) " x "\n",__FILE__,__LINE__,##__VA_ARGS__)
#endif
#endif
#define malloc(x) RosSymAllocMem(x)
#define mallocz(x,y) RosSymAllocMemZero(x,y)

View file

@ -483,5 +483,6 @@ struct DwarfStack
DwarfAbbrev *dwarfgetabbrev(Dwarf*, ulong, ulong);
int dwarfgetinfounit(Dwarf*, ulong, DwarfBlock*);
void dwarfdumpsym(Dwarf *d, DwarfSym *s);
#define MAXIMUM_DWARF_NAME_SIZE 64

View file

@ -83,7 +83,7 @@ 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);
werrstr("abbrev: num %d tag %x @ %x", num, tag, b.p - d->abbrev.data);
haskids = dwarfget1(&b);
for(i=0;; i++){
name = dwarfget128(&b);
@ -120,11 +120,12 @@ findabbrev(DwarfAbbrev *a, int na, ulong num)
{
int i;
for(i=0; i<na; i++)
if(a[i].num == num)
for(i=0; i<na; i++) {
if(a[i].num == num) {
return &a[i];
assert(0);
werrstr("abbrev not found");
}
}
werrstr("abbrev not found (%x)", na);
return nil;
}
@ -133,7 +134,7 @@ dwarfgetabbrev(Dwarf *d, ulong off, ulong num)
{
DwarfAbbrev *a;
int na;
werrstr("want num %d\n", num);
if((na = loadabbrevs(d, off, &a)) < 0){
werrstr("loadabbrevs: %r");
return nil;

View file

@ -128,9 +128,11 @@ dwarflookupnameinunit(Dwarf *d, ulong unit, char *name, DwarfSym *s)
DwarfSym compunit = { };
if(dwarfenumunit(d, unit, &compunit) < 0)
return -1;
while(dwarfnextsymat(d, &compunit, s) == 1)
while(dwarfnextsymat(d, &compunit, s) == 0) {
werrstr("got %s looking for %s\n", s->attrs.name, name);
if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
return 0;
}
werrstr("symbol '%s' not found", name);
return -1;
}
@ -188,7 +190,10 @@ dwarfseeksym(Dwarf *d, ulong unit, ulong off, DwarfSym *s)
DwarfSym compunit = { };
if(dwarfenumunit(d, unit, &compunit) < 0)
return -1;
werrstr("dwarfseeksym: unit %x off %x\n", unit, off);
s->b.d = d;
s->b.p = d->info.data + unit + off;
s->b.ep = compunit.b.ep;
if(dwarfnextsymat(d, &compunit, s) == -1)
return -1;
werrstr("dwarfseeksym: unit %x off %x, tag %x", unit, off, s->attrs.tag);
@ -238,7 +243,7 @@ dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s)
return -1;
}
s->b.ep = s->b.p+len;
if((i=dwarfget2(&s->b)) != 2)
if((i=dwarfget2(&s->b)) > 4)
goto badheader;
aoff = dwarfget4(&s->b);
s->b.addrsize = dwarfget1(&s->b);
@ -258,15 +263,19 @@ dwarfnextsym(Dwarf *d, DwarfSym *s)
ulong num;
DwarfAbbrev *a;
werrstr("sym at %x (left %x)\n", s->b.p - d->info.data, s->b.ep - s->b.p);
num = dwarfget128(&s->b);
werrstr("abbrev num %x\n", num);
s->num = num;
if(num == 0){
return -1;
}
a = dwarfgetabbrev(d, s->aoff, num);
werrstr("a %p\n", a);
if(a == nil){
werrstr("getabbrev %ud %ud for %ud,%ud", s->aoff, num, s->unit);
werrstr("getabbrev %x %x for %x", s->aoff, num, s->unit);
return -1;
}
@ -277,6 +286,7 @@ dwarfnextsym(Dwarf *d, DwarfSym *s)
if (s->attrs.haskids) {
DwarfSym childSkip = { };
s->childoff = s->b.p - d->info.data;
werrstr("Set childoff at %x\n", s->childoff);
int r = dwarfnextsymat(d, s, &childSkip);
while (r == 0) {
r = dwarfnextsym(d, &childSkip);
@ -316,6 +326,7 @@ dwarfnextsymat(Dwarf *d, DwarfSym *parent, DwarfSym *child)
if (!child->b.d) {
child->b = parent->b;
child->b.p = parent->childoff + parent->b.d->info.data;
werrstr("Rewound to childoff %x\n", parent->childoff);
}
return dwarfnextsym(d, child);
@ -323,76 +334,78 @@ dwarfnextsymat(Dwarf *d, DwarfSym *parent, DwarfSym *child)
typedef struct Parse Parse;
struct Parse {
const char *namestr;
int name;
int off;
int haveoff;
int type;
};
#define ATTR(x) (#x)+9, x
#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), 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 },
{ ATTR(DwarfAttrAbstractOrigin), OFFSET(abstractorigin), TReference },
{ ATTR(DwarfAttrAccessibility), OFFSET(accessibility), TConstant },
{ ATTR(DwarfAttrAddrClass), OFFSET(addrclass), TConstant },
{ ATTR(DwarfAttrBaseTypes), OFFSET(basetypes), TReference },
{ ATTR(DwarfAttrBitOffset), OFFSET(bitoffset), TConstant },
{ ATTR(DwarfAttrBitSize), OFFSET(bitsize), TConstant },
{ ATTR(DwarfAttrByteSize), OFFSET(bytesize), TConstant },
{ ATTR(DwarfAttrCalling), OFFSET(calling), TConstant },
{ ATTR(DwarfAttrCommonRef), OFFSET(commonref), TReference },
{ ATTR(DwarfAttrCompDir), OFFSET(compdir), TString },
{ ATTR(DwarfAttrConstValue), OFFSET(constvalue), TString|TConstant|TBlock },
{ ATTR(DwarfAttrContainingType), OFFSET(containingtype), TReference },
{ ATTR(DwarfAttrCount), OFFSET(count), TConstant|TReference },
{ ATTR(DwarfAttrDataMemberLoc), OFFSET(datamemberloc), TBlock|TConstant|TReference },
{ ATTR(DwarfAttrDeclColumn), OFFSET(declcolumn), TConstant },
{ ATTR(DwarfAttrDeclFile), OFFSET(declfile), TConstant },
{ ATTR(DwarfAttrDeclLine), OFFSET(declline), TConstant },
{ ATTR(DwarfAttrDefaultValue), OFFSET(defaultvalue), TReference },
{ ATTR(DwarfAttrDiscr), OFFSET(discr), TReference },
{ ATTR(DwarfAttrDiscrList), OFFSET(discrlist), TBlock },
{ ATTR(DwarfAttrDiscrValue), OFFSET(discrvalue), TConstant },
{ ATTR(DwarfAttrEncoding), OFFSET(encoding), TConstant },
{ ATTR(DwarfAttrFrameBase), OFFSET(framebase), TBlock|TConstant },
{ ATTR(DwarfAttrFriend), OFFSET(friend), TReference },
{ ATTR(DwarfAttrHighpc), OFFSET(highpc), TAddress },
{ ATTR(DwarfAttrEntrypc), OFFSET(entrypc), TAddress },
{ ATTR(DwarfAttrIdentifierCase), OFFSET(identifiercase), TConstant },
{ ATTR(DwarfAttrImport), OFFSET(import), TReference },
{ ATTR(DwarfAttrInline), OFFSET(inlined), TConstant },
{ ATTR(DwarfAttrArtificial), OFFSET(isartificial), TFlag },
{ ATTR(DwarfAttrDeclaration), OFFSET(isdeclaration), TFlag },
{ ATTR(DwarfAttrExternal), OFFSET(isexternal), TFlag },
{ ATTR(DwarfAttrIsOptional), OFFSET(isoptional), TFlag },
{ ATTR(DwarfAttrPrototyped), OFFSET(isprototyped), TFlag },
{ ATTR(DwarfAttrVarParam), OFFSET(isvarparam), TFlag },
{ ATTR(DwarfAttrLanguage), OFFSET(language), TConstant },
{ ATTR(DwarfAttrLocation), OFFSET(location), TReference|TBlock },
{ ATTR(DwarfAttrLowerBound), OFFSET(lowerbound), TConstant|TReference },
{ ATTR(DwarfAttrLowpc), OFFSET(lowpc), TAddress },
{ ATTR(DwarfAttrMacroInfo), OFFSET(macroinfo), TConstant },
{ ATTR(DwarfAttrName), OFFSET(name), TString },
{ ATTR(DwarfAttrNamelistItem), OFFSET(namelistitem), TBlock },
{ ATTR(DwarfAttrOrdering), OFFSET(ordering), TConstant },
{ ATTR(DwarfAttrPriority), OFFSET(priority), TReference },
{ ATTR(DwarfAttrProducer), OFFSET(producer), TString },
{ ATTR(DwarfAttrRanges), OFFSET(ranges), TReference },
{ ATTR(DwarfAttrReturnAddr), OFFSET(returnaddr), TBlock|TConstant },
{ ATTR(DwarfAttrSegment), OFFSET(segment), TBlock|TConstant },
{ ATTR(DwarfAttrSibling), OFFSET(sibling), TReference },
{ ATTR(DwarfAttrSpecification), OFFSET(specification), TReference },
{ ATTR(DwarfAttrStartScope), OFFSET(startscope), TConstant },
{ ATTR(DwarfAttrStaticLink), OFFSET(staticlink), TBlock|TConstant },
{ ATTR(DwarfAttrStmtList), OFFSET(stmtlist), TConstant },
{ ATTR(DwarfAttrStrideSize), OFFSET(stridesize), TConstant },
{ ATTR(DwarfAttrStringLength), OFFSET(stringlength), TBlock|TConstant },
{ ATTR(DwarfAttrType), OFFSET(type), TReference },
{ ATTR(DwarfAttrUpperBound), OFFSET(upperbound), TConstant|TReference },
{ ATTR(DwarfAttrUseLocation), OFFSET(uselocation), TBlock|TConstant },
{ ATTR(DwarfAttrVirtuality), OFFSET(virtuality), TConstant },
{ ATTR(DwarfAttrVisibility), OFFSET(visibility), TConstant },
{ ATTR(DwarfAttrVtableElemLoc), OFFSET(vtableelemloc), TBlock|TReference },
{ }
};
@ -417,6 +430,7 @@ parseattrs(Dwarf *d, DwarfBuf *b, ulong tag, ulong unit, DwarfAbbrev *a, DwarfAt
for(i=0; i<a->nattr; i++){
n = a->attr[i].name;
f = a->attr[i].form;
werrstr("struct: (@%x) n %x f %x (%d %d)\n", b->p - d->info.data, n, f, ptab[n].haveoff, ptab[n].off);
if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0) {
if (skipform(d, b, f) < 0) {
if(++nbad == 1)
@ -436,11 +450,12 @@ parseattrs(Dwarf *d, DwarfBuf *b, ulong tag, ulong unit, DwarfAbbrev *a, DwarfAt
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)
else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0) {
got = TBlock;
else {
} else {
werrstr("Skipping form %x\n", f);
if(skipform(d, b, f) < 0){
if(++nbad == 1)
//if(++nbad == 1)
werrstr("dwarf parse attrs: cannot skip form %d", f);
return -1;
}
@ -451,6 +466,10 @@ parseattrs(Dwarf *d, DwarfBuf *b, ulong tag, ulong unit, DwarfAbbrev *a, DwarfAt
#endif
*((uchar*)attrs+ptab[n].haveoff) = got;
}
if (attrs->have.name)
werrstr("%s: tag %x kids %d (last %x)\n", attrs->name, attrs->tag, attrs->haskids, b->p - b->d->info.data);
return 0;
}
@ -651,6 +670,7 @@ int dwarfgetarg(Dwarf *d, const char *name, DwarfBuf *buf, ulong cfa, PROSSYM_RE
int ret = 0;
DwarfStack stack = { };
stackinit(&stack);
stackpush(&stack, cfa);
while (buf->p < buf->ep) {
int opcode = dwarfget1(buf);
werrstr("opcode %x", opcode);
@ -951,6 +971,25 @@ int dwarfargvalue(Dwarf *d, DwarfSym *proc, ulong pc, ulong cfa, PROSSYM_REGISTE
return 0;
}
void
dwarfdumpsym(Dwarf *d, DwarfSym *s)
{
int i, j;
werrstr("tag %x\n", s->attrs.tag);
for (j = 0; plist[j].name; j++) {
char *have = ((char*)&s->attrs) + plist[j].haveoff;
char *attr = ((char*)&s->attrs) + plist[j].off;
if (*have == TString) {
char *str = *((char **)attr);
werrstr("%s: %s\n", plist[j].namestr, str);
} else if (*have == TReference) {
DwarfVal *val = ((DwarfVal*)attr);
werrstr("%s: %x:%x\n", plist[j].namestr, val->b.data, val->b.len);
} else if (*have)
werrstr("%s: (%x)\n", plist[j].namestr, *have);
}
}
int
dwarfgetparams(Dwarf *d, DwarfSym *s, ulong pc, int pnum, DwarfParam *paramblocks)
{

View file

@ -30,10 +30,10 @@ dwarfopen(Pe *pe)
if(pe->loadsection(pe, ".debug_abbrev", &d->abbrev) < 0
|| 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_loc", &d->loc) < 0)
goto err;
pe->loadsection(pe, ".debug_pubnames", &d->pubnames);
pe->loadsection(pe, ".debug_frame", &d->frame);
pe->loadsection(pe, ".debug_ranges", &d->ranges);
pe->loadsection(pe, ".debug_str", &d->str);

View file

@ -128,4 +128,136 @@ RosSymGetAddressInformation
return TRUE;
}
VOID
RosSymFreeAggregate(PROSSYM_AGGREGATE Aggregate)
{
int i;
for (i = 0; i < Aggregate->NumElements; i++) {
free(Aggregate->Elements[i].Name);
free(Aggregate->Elements[i].Type);
}
free(Aggregate->Elements);
}
BOOLEAN
RosSymAggregate(PROSSYM_INFO RosSymInfo, PCHAR Type, PROSSYM_AGGREGATE Aggregate)
{
char *tchar;
ulong unit, typeoff = 0;
DwarfSym type = { };
// Get the first unit
if (dwarfaddrtounit(RosSymInfo, RosSymInfo->pe->codestart + RosSymInfo->pe->imagebase, &unit) == -1)
return FALSE;
if (Type[0] == '#') {
for (tchar = Type + 1; *tchar; tchar++) {
typeoff *= 10;
typeoff += *tchar - '0';
}
if (dwarfseeksym(RosSymInfo, unit, typeoff, &type) == -1)
return FALSE;
} else if (dwarflookupnameinunit(RosSymInfo, unit, Type, &type) != 0 ||
(type.attrs.tag != TagStructType && type.attrs.tag != TagUnionType))
return FALSE;
DwarfSym element = { }, inner = { };
int count = 0;
werrstr("type %s (want %s) type %x\n", type.attrs.name, Type, type.attrs.type);
if (type.attrs.have.type) {
if (dwarfseeksym(RosSymInfo, unit, type.attrs.type, &inner) == -1)
return FALSE;
type = inner;
}
werrstr("finding members %d\n", type.attrs.haskids);
while (dwarfnextsymat(RosSymInfo, &type, &element) != -1) {
if (element.attrs.have.name)
werrstr("%x %s\n", element.attrs.tag, element.attrs.name);
if (element.attrs.tag == TagMember) count++;
}
werrstr("%d members\n", count);
if (!count) return FALSE;
memset(&element, 0, sizeof(element));
Aggregate->NumElements = count;
Aggregate->Elements = malloc(sizeof(ROSSYM_AGGREGATE_MEMBER) * count);
count = 0;
werrstr("Enumerating %s\n", Type);
while (dwarfnextsymat(RosSymInfo, &type, &element) != -1) {
memset(&Aggregate->Elements[count], 0, sizeof(*Aggregate->Elements));
if (element.attrs.tag == TagMember) {
if (element.attrs.have.name) {
Aggregate->Elements[count].Name = malloc(strlen(element.attrs.name) + 1);
strcpy(Aggregate->Elements[count].Name, element.attrs.name);
}
Aggregate->Elements[count].TypeId = element.attrs.type;
// Seek our range in loc
DwarfBuf locbuf;
DwarfBuf instream = { };
locbuf.d = RosSymInfo;
locbuf.addrsize = RosSymInfo->addrsize;
if (element.attrs.have.datamemberloc) {
instream = locbuf;
instream.p = element.attrs.datamemberloc.b.data;
instream.ep = element.attrs.datamemberloc.b.data + element.attrs.datamemberloc.b.len;
werrstr("datamemberloc type %x %p:%x\n",
element.attrs.have.datamemberloc,
element.attrs.datamemberloc.b.data, element.attrs.datamemberloc.b.len);
}
if (dwarfgetarg(RosSymInfo, element.attrs.name, &instream, 0, NULL, &Aggregate->Elements[count].BaseOffset) == -1)
Aggregate->Elements[count].BaseOffset = -1;
werrstr("tag %x name %s base %x type %x\n",
element.attrs.tag, element.attrs.name,
Aggregate->Elements[count].BaseOffset,
Aggregate->Elements[count].TypeId);
count++;
}
}
for (count = 0; count < Aggregate->NumElements; count++) {
memset(&type, 0, sizeof(type));
memset(&inner, 0, sizeof(inner));
werrstr("seeking type %x (%s) from %s\n",
Aggregate->Elements[count].TypeId,
Aggregate->Elements[count].Type,
Aggregate->Elements[count].Name);
dwarfseeksym(RosSymInfo, unit, Aggregate->Elements[count].TypeId, &type);
while (type.attrs.have.type && type.attrs.tag != TagPointerType) {
if (dwarfseeksym(RosSymInfo, unit, type.attrs.type, &inner) == -1)
return FALSE;
type = inner;
}
//dwarfdumpsym(RosSymInfo, &type);
if (type.attrs.have.name) {
Aggregate->Elements[count].Type = malloc(strlen(type.attrs.name) + 1);
strcpy(Aggregate->Elements[count].Type, type.attrs.name);
} else {
char strbuf[128] = {'#'}, *bufptr = strbuf + 1;
ulong idcopy = Aggregate->Elements[count].TypeId;
ulong mult = 1;
while (mult * 10 < idcopy) mult *= 10;
while (mult > 0) {
*bufptr++ = '0' + ((idcopy / mult) % 10);
mult /= 10;
}
Aggregate->Elements[count].Type = malloc(strlen(strbuf) + 1);
strcpy(Aggregate->Elements[count].Type, strbuf);
}
if (type.attrs.tag == TagPointerType)
Aggregate->Elements[count].Size = RosSymInfo->addrsize;
else
Aggregate->Elements[count].Size = type.attrs.bytesize;
if (type.attrs.have.bitsize)
Aggregate->Elements[count].Bits = type.attrs.bitsize;
if (type.attrs.have.bitoffset)
Aggregate->Elements[count].FirstBit = type.attrs.bitoffset;
}
return TRUE;
}
/* EOF */

View file

@ -146,6 +146,8 @@ RosSymCreateFromFile(PVOID FileContext, PROSSYM_INFO *RosSymInfo)
pe->sect = SectionHeaders;
pe->imagebase = pe->loadbase = NtHeaders.OptionalHeader.ImageBase;
pe->imagesize = NtHeaders.OptionalHeader.SizeOfImage;
pe->codestart = NtHeaders.OptionalHeader.BaseOfCode;
pe->datastart = NtHeaders.OptionalHeader.BaseOfData;
pe->loadsection = loaddisksection;
*RosSymInfo = dwarfopen(pe);

View file

@ -17,18 +17,18 @@ PeSect *pesection(Pe *pe, const char *name)
int i;
ANSI_STRING WantName;
RtlInitAnsiString(&WantName, name);
DPRINT("Searching for section %s\n", name);
werrstr("Searching for section %s\n", name);
for (i = 0; i < pe->nsections; i++) {
PANSI_STRING AnsiString = ANSI_NAME_STRING(&pe->sect[i]);
if (WantName.Length == AnsiString->Length &&
!memcmp(AnsiString->Buffer, name, WantName.Length)) {
DPRINT("Found %s (%d) @ %x (%x)\n", name, i,
werrstr("Found %s (%d) @ %x (%x)\n", name, i,
((PCHAR)pe->imagebase)+pe->sect[i].VirtualAddress,
pe->sect[i].SizeOfRawData);
return &pe->sect[i];
}
}
DPRINT("%s not found\n", name);
werrstr("%s not found\n", name);
return nil;
}
@ -84,11 +84,11 @@ loadmemsection(Pe *pe, char *name, DwarfBlock *b)
if((s = pesection(pe, name)) == nil)
return -1;
DPRINT("Loading section %s (ImageBase %x RVA %x)\n", name, pe->fd, s->VirtualAddress);
werrstr("Loading section %s (ImageBase %x RVA %x)\n", name, pe->fd, s->VirtualAddress);
b->data = RosSymAllocMem(s->SizeOfRawData);
b->len = s->SizeOfRawData;
PCHAR DataSource = ((char *)pe->fd) + s->VirtualAddress;
DPRINT("Copying to %x from %x (%x)\n", DataSource, b->data, b->len);
werrstr("Copying to %x from %x (%x)\n", DataSource, b->data, b->len);
RtlCopyMemory(b->data, DataSource, s->SizeOfRawData);
return s->SizeOfRawData;
@ -121,16 +121,16 @@ void xfree(void *v) {
ulong pefindrva(struct _IMAGE_SECTION_HEADER *SectionHeaders, int NumberOfSections, ulong TargetPhysical) {
int i;
DPRINT("Finding RVA for Physical %x\n", TargetPhysical);
werrstr("Finding RVA for Physical %x\n", TargetPhysical);
for (i = 0; i < NumberOfSections; i++) {
DPRINT("Section %d name %s Raw %x Virt %x\n",
werrstr("Section %d name %s Raw %x Virt %x\n",
i,
ANSI_NAME_STRING(&SectionHeaders[i])->Buffer,
SectionHeaders[i].PointerToRawData,
SectionHeaders[i].VirtualAddress);
if (TargetPhysical >= SectionHeaders[i].PointerToRawData &&
TargetPhysical < SectionHeaders[i].PointerToRawData + SectionHeaders[i].SizeOfRawData) {
DPRINT("RVA %x\n", TargetPhysical - SectionHeaders[i].PointerToRawData + SectionHeaders[i].VirtualAddress);
werrstr("RVA %x\n", TargetPhysical - SectionHeaders[i].PointerToRawData + SectionHeaders[i].VirtualAddress);
return TargetPhysical - SectionHeaders[i].PointerToRawData + SectionHeaders[i].VirtualAddress;
}
}

View file

@ -12,6 +12,7 @@ typedef struct _Pe {
u32int (*e4)(const unsigned char *data);
u64int (*e8)(const unsigned char *data);
ulong imagebase, imagesize, loadbase;
ulong codestart, datastart;
int (*loadsection)(struct _Pe *pe, char *name, struct DwarfBlock *b);
int nsections;
struct _IMAGE_SECTION_HEADER *sect;

View file

@ -90,6 +90,10 @@ static BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]);
static BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]);
static BOOLEAN KdbpCmdDmesg(ULONG Argc, PCHAR Argv[]);
#ifdef __ROS_CMAKE__
static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
#endif
/* GLOBALS *******************************************************************/
static BOOLEAN KdbUseIntelSyntax = FALSE; /* Set to TRUE for intel syntax */
@ -135,6 +139,9 @@ static const struct
{ "sregs", "sregs", "Display status registers.", KdbpCmdRegs },
{ "dregs", "dregs", "Display debug registers.", KdbpCmdRegs },
{ "bt", "bt [*frameaddr|thread id]", "Prints current backtrace or from given frame addr", KdbpCmdBackTrace },
#ifdef __ROS_CMAKE__
{ "dt", "dt [mod] [type] [addr]", "Print a struct. Addr is optional.", KdbpCmdPrintStruct },
#endif
/* Flow control */
{ NULL, NULL, "Flow control", NULL },
@ -453,6 +460,142 @@ KdbpCmdEvalExpression(
return TRUE;
}
#ifdef __ROS_CMAKE__
/*!\brief Print a struct
*/
static VOID
KdbpPrintStructInternal
(PROSSYM_INFO Info,
PCHAR Indent,
BOOLEAN DoRead,
PVOID BaseAddress,
PROSSYM_AGGREGATE Aggregate)
{
ULONG i;
ULONGLONG Result;
PROSSYM_AGGREGATE_MEMBER Member;
ULONG IndentLen = strlen(Indent);
ROSSYM_AGGREGATE MemberAggregate = { };
for (i = 0; i < Aggregate->NumElements; i++) {
Member = &Aggregate->Elements[i];
KdbpPrint("%s%p+%x: %s", Indent, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size, Member->Name ? Member->Name : "<anoymous>");
if (DoRead) {
if (!strcmp(Member->Type, "_UNICODE_STRING")) {
KdbpPrint("\"%wZ\"\n", ((PCHAR)BaseAddress) + Member->BaseOffset);
continue;
} else if (!strcmp(Member->Type, "PUNICODE_STRING")) {
KdbpPrint("\"%wZ\"\n", *(((PUNICODE_STRING*)((PCHAR)BaseAddress) + Member->BaseOffset)));
continue;
}
switch (Member->Size) {
case 1:
case 2:
case 4:
case 8: {
Result = 0;
if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) {
if (Member->Bits) {
Result >>= Member->FirstBit;
Result &= ((1 << Member->Bits) - 1);
}
KdbpPrint(" %lx\n", Result);
}
else goto readfail;
break;
}
default: {
if (Member->Size < 8) {
if (NT_SUCCESS(KdbpSafeReadMemory(&Result, ((PCHAR)BaseAddress) + Member->BaseOffset, Member->Size))) {
int j;
for (j = 0; j < Member->Size; j++) {
KdbpPrint(" %02x", (int)(Result & 0xff));
Result >>= 8;
}
} else goto readfail;
} else {
KdbpPrint(" %s @ %p {\n", Member->Type, ((PCHAR)BaseAddress) + Member->BaseOffset);
Indent[IndentLen] = ' ';
if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) {
KdbpPrintStructInternal(Info, Indent, DoRead, ((PCHAR)BaseAddress) + Member->BaseOffset, &MemberAggregate);
RosSymFreeAggregate(&MemberAggregate);
}
Indent[IndentLen] = 0;
KdbpPrint("%s}\n", Indent);
} break;
}
}
} else {
readfail:
if (Member->Size <= 8) {
KdbpPrint(" ??\n");
} else {
KdbpPrint(" %s @ %x {\n", Member->Type, Member->BaseOffset);
Indent[IndentLen] = ' ';
if (RosSymAggregate(Info, Member->Type, &MemberAggregate)) {
KdbpPrintStructInternal(Info, Indent, DoRead, BaseAddress, &MemberAggregate);
RosSymFreeAggregate(&MemberAggregate);
}
Indent[IndentLen] = 0;
KdbpPrint("%s}\n", Indent);
}
}
}
}
PROSSYM_INFO KdbpSymFindCachedFile(PUNICODE_STRING ModName);
static BOOLEAN
KdbpCmdPrintStruct(
ULONG Argc,
PCHAR Argv[])
{
int i;
ULONGLONG Result = 0;
PVOID BaseAddress = 0;
ROSSYM_AGGREGATE Aggregate = { };
UNICODE_STRING ModName = { };
ANSI_STRING AnsiName = { };
CHAR Indent[100] = { };
if (Argc < 3) goto end;
AnsiName.Length = AnsiName.MaximumLength = strlen(Argv[1]);
AnsiName.Buffer = Argv[1];
RtlAnsiStringToUnicodeString(&ModName, &AnsiName, TRUE);
PROSSYM_INFO Info = KdbpSymFindCachedFile(&ModName);
if (!Info || !RosSymAggregate(Info, Argv[2], &Aggregate)) {
DPRINT1("Could not get aggregate\n");
goto end;
}
// Get an argument for location if it was given
if (Argc > 3) {
ULONG len;
PCHAR ArgStart = Argv[3];
DPRINT1("Trying to get expression\n");
for (i = 3; i < Argc - 1; i++)
{
len = strlen(Argv[i]);
Argv[i][len] = ' ';
}
/* Evaluate the expression */
DPRINT1("Arg: %s\n", ArgStart);
if (KdbpEvaluateExpression(ArgStart, strlen(ArgStart), &Result)) {
BaseAddress = (PVOID)(ULONG_PTR)Result;
DPRINT1("BaseAddress: %p\n", BaseAddress);
}
}
DPRINT1("BaseAddress %p\n", BaseAddress);
KdbpPrintStructInternal(Info, Indent, !!BaseAddress, BaseAddress, &Aggregate);
end:
RosSymFreeAggregate(&Aggregate);
RtlFreeUnicodeString(&ModName);
return TRUE;
}
#endif
/*!\brief Display list of active debug channels
*/
static BOOLEAN

View file

@ -359,7 +359,7 @@ KdbSymGetAddressInformation(
*
* \sa KdbpSymAddCachedFile
*/
static PROSSYM_INFO
PROSSYM_INFO
KdbpSymFindCachedFile(
IN PUNICODE_STRING FileName)
{
@ -405,7 +405,7 @@ KdbpSymAddCachedFile(
{
PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
DPRINT("Adding symbol file: RosSymInfo = %p\n", RosSymInfo);
DPRINT("Adding symbol file: %wZ RosSymInfo = %p\n", FileName, RosSymInfo);
/* allocate entry */
CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS);
@ -416,6 +416,7 @@ KdbpSymAddCachedFile(
CacheEntry->FileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
FileName->Length,
TAG_KDBS);
CacheEntry->FileName.MaximumLength = FileName->Length;
RtlCopyUnicodeString(&CacheEntry->FileName, FileName);
ASSERT(CacheEntry->FileName.Buffer);
CacheEntry->RefCount = 1;
@ -476,7 +477,7 @@ KdbpSymRemoveCachedFile(
*
* \sa KdbpSymUnloadModuleSymbols
*/
static VOID
VOID
KdbpSymLoadModuleSymbols(
IN PUNICODE_STRING FileName,
OUT PROSSYM_INFO *RosSymInfo)
@ -508,7 +509,7 @@ KdbpSymLoadModuleSymbols(
/* Open the file */
InitializeObjectAttributes(&ObjectAttributes,
FileName,
OBJ_CASE_INSENSITIVE,
OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE,
NULL,
NULL);
@ -519,10 +520,10 @@ KdbpSymLoadModuleSymbols(
&ObjectAttributes,
&IoStatusBlock,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_NONALERT);
FILE_NON_DIRECTORY_FILE|FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(Status))
{
DPRINT("Could not open image file: %wZ\n", FileName);
DPRINT("Could not open image file(%x): %wZ\n", Status, FileName);
return;
}
@ -548,8 +549,17 @@ KdbpSymLoadModuleSymbols(
if (RosSymCreateFromFile(FileContext, RosSymInfo))
{
/* add file to cache */
KdbpSymAddCachedFile(FileName, *RosSymInfo);
DPRINT("Installed symbols: %wZ %p\n", FileName, *RosSymInfo);
int i;
UNICODE_STRING TruncatedName = *FileName;
for (i = (TruncatedName.Length / sizeof(WCHAR)) - 1; i >= 0; i--)
if (TruncatedName.Buffer[i] == '\\') {
TruncatedName.Buffer += i+1;
TruncatedName.Length -= (i+1)*sizeof(WCHAR);
TruncatedName.MaximumLength -= (i+1)*sizeof(WCHAR);
break;
}
KdbpSymAddCachedFile(&TruncatedName, *RosSymInfo);
DPRINT("Installed symbols: %wZ %p\n", &TruncatedName, *RosSymInfo);
}
KdbpReleaseFileForSymbols(FileContext);
}
@ -569,13 +579,45 @@ KdbSymProcessSymbols(
}
/* Remove symbol info if it already exists */
if (LdrEntry->PatchInformation)
if (LdrEntry->PatchInformation) {
KdbpSymRemoveCachedFile(LdrEntry->PatchInformation);
}
/* Error loading symbol info, try to load it from file */
KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
(PROSSYM_INFO*)&LdrEntry->PatchInformation);
if (!LdrEntry->PatchInformation) {
// HACK: module dll names don't identify the real files
UNICODE_STRING SystemRoot;
UNICODE_STRING ModuleNameCopy;
RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot\\system32\\Drivers\\");
ModuleNameCopy.Length = 0;
ModuleNameCopy.MaximumLength =
LdrEntry->BaseDllName.MaximumLength + SystemRoot.MaximumLength;
ModuleNameCopy.Buffer = ExAllocatePool(NonPagedPool, SystemRoot.MaximumLength + LdrEntry->BaseDllName.MaximumLength);
RtlCopyUnicodeString(&ModuleNameCopy, &SystemRoot);
RtlCopyMemory
(ModuleNameCopy.Buffer + ModuleNameCopy.Length / sizeof(WCHAR),
LdrEntry->BaseDllName.Buffer,
LdrEntry->BaseDllName.Length);
ModuleNameCopy.Length += LdrEntry->BaseDllName.Length;
KdbpSymLoadModuleSymbols(&ModuleNameCopy,
(PROSSYM_INFO*)&LdrEntry->PatchInformation);
if (!LdrEntry->PatchInformation) {
SystemRoot.Length -= strlen("Drivers\\") * sizeof(WCHAR);
RtlCopyUnicodeString(&ModuleNameCopy, &SystemRoot);
RtlCopyMemory
(ModuleNameCopy.Buffer + ModuleNameCopy.Length / sizeof(WCHAR),
LdrEntry->BaseDllName.Buffer,
LdrEntry->BaseDllName.Length);
ModuleNameCopy.Length += LdrEntry->BaseDllName.Length;
KdbpSymLoadModuleSymbols(&ModuleNameCopy,
(PROSSYM_INFO*)&LdrEntry->PatchInformation);
}
RtlFreeUnicodeString(&ModuleNameCopy);
}
/* It already added symbols to cache */
DPRINT("Installed symbols: %wZ@%p-%p %p\n",
&LdrEntry->BaseDllName,