diff --git a/reactos/include/reactos/rossym.h b/reactos/include/reactos/rossym.h index 785299f8779..0c6c9d98f39 100644 --- a/reactos/include/reactos/rossym.h +++ b/reactos/include/reactos/rossym.h @@ -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 */ diff --git a/reactos/lib/rossym_new/compat.h b/reactos/lib/rossym_new/compat.h index 375b498fa3e..80f0e94d0e4 100644 --- a/reactos/lib/rossym_new/compat.h +++ b/reactos/lib/rossym_new/compat.h @@ -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) diff --git a/reactos/lib/rossym_new/dwarf.h b/reactos/lib/rossym_new/dwarf.h index 7308d7deab0..3d1101e2e99 100644 --- a/reactos/lib/rossym_new/dwarf.h +++ b/reactos/lib/rossym_new/dwarf.h @@ -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 diff --git a/reactos/lib/rossym_new/dwarfabbrev.c b/reactos/lib/rossym_new/dwarfabbrev.c index 365d44232d4..a9d3c49b027 100644 --- a/reactos/lib/rossym_new/dwarfabbrev.c +++ b/reactos/lib/rossym_new/dwarfabbrev.c @@ -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; iattrs.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; inattr; 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) { diff --git a/reactos/lib/rossym_new/dwarfopen.c b/reactos/lib/rossym_new/dwarfopen.c index b3ea2cd18d6..bcb0429ab40 100644 --- a/reactos/lib/rossym_new/dwarfopen.c +++ b/reactos/lib/rossym_new/dwarfopen.c @@ -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); diff --git a/reactos/lib/rossym_new/find.c b/reactos/lib/rossym_new/find.c index 9cc5aeeeece..beb6f170eea 100644 --- a/reactos/lib/rossym_new/find.c +++ b/reactos/lib/rossym_new/find.c @@ -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 */ diff --git a/reactos/lib/rossym_new/fromfile.c b/reactos/lib/rossym_new/fromfile.c index c26ea3e2a80..a3ed16fd946 100644 --- a/reactos/lib/rossym_new/fromfile.c +++ b/reactos/lib/rossym_new/fromfile.c @@ -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); diff --git a/reactos/lib/rossym_new/pe.c b/reactos/lib/rossym_new/pe.c index cace420fec2..63fd9df6906 100644 --- a/reactos/lib/rossym_new/pe.c +++ b/reactos/lib/rossym_new/pe.c @@ -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; } } diff --git a/reactos/lib/rossym_new/pe.h b/reactos/lib/rossym_new/pe.h index 6b5bbdaa8f4..066d79b2ac6 100644 --- a/reactos/lib/rossym_new/pe.h +++ b/reactos/lib/rossym_new/pe.h @@ -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; diff --git a/reactos/ntoskrnl/kdbg/kdb_cli.c b/reactos/ntoskrnl/kdbg/kdb_cli.c index 9f9d6c1d3bd..8e842f8169d 100644 --- a/reactos/ntoskrnl/kdbg/kdb_cli.c +++ b/reactos/ntoskrnl/kdbg/kdb_cli.c @@ -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 : ""); + 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 diff --git a/reactos/ntoskrnl/kdbg/kdb_symbols.cmake.c b/reactos/ntoskrnl/kdbg/kdb_symbols.cmake.c index 2d43732b20f..98890094139 100644 --- a/reactos/ntoskrnl/kdbg/kdb_symbols.cmake.c +++ b/reactos/ntoskrnl/kdbg/kdb_symbols.cmake.c @@ -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,