#include <debug.h>
#include "dwarf.h"
+#include "pe.h"
#include <windef.h>
enum
{
- DwarfAttrSibling = 0x01,
- DwarfAttrLocation = 0x02,
- DwarfAttrName = 0x03,
- DwarfAttrOrdering = 0x09,
- DwarfAttrByteSize = 0x0B,
- DwarfAttrBitOffset = 0x0C,
- DwarfAttrBitSize = 0x0D,
- DwarfAttrStmtList = 0x10,
- DwarfAttrLowpc = 0x11,
- DwarfAttrHighpc = 0x12,
- DwarfAttrLanguage = 0x13,
- DwarfAttrDiscr = 0x15,
- DwarfAttrDiscrValue = 0x16,
- DwarfAttrVisibility = 0x17,
- DwarfAttrImport = 0x18,
- DwarfAttrStringLength = 0x19,
- DwarfAttrCommonRef = 0x1A,
- DwarfAttrCompDir = 0x1B,
- DwarfAttrConstValue = 0x1C,
- DwarfAttrContainingType = 0x1D,
- DwarfAttrDefaultValue = 0x1E,
- DwarfAttrInline = 0x20,
- DwarfAttrIsOptional = 0x21,
- DwarfAttrLowerBound = 0x22,
- DwarfAttrProducer = 0x25,
- DwarfAttrPrototyped = 0x27,
- DwarfAttrReturnAddr = 0x2A,
- DwarfAttrStartScope = 0x2C,
- DwarfAttrStrideSize = 0x2E,
- DwarfAttrUpperBound = 0x2F,
- DwarfAttrAbstractOrigin = 0x31,
- DwarfAttrAccessibility = 0x32,
- DwarfAttrAddrClass = 0x33,
- DwarfAttrArtificial = 0x34,
- DwarfAttrBaseTypes = 0x35,
- DwarfAttrCalling = 0x36,
- DwarfAttrCount = 0x37,
- DwarfAttrDataMemberLoc = 0x38,
- DwarfAttrDeclColumn = 0x39,
- DwarfAttrDeclFile = 0x3A,
- DwarfAttrDeclLine = 0x3B,
- DwarfAttrDeclaration = 0x3C,
- DwarfAttrDiscrList = 0x3D,
- DwarfAttrEncoding = 0x3E,
- DwarfAttrExternal = 0x3F,
- DwarfAttrFrameBase = 0x40,
- DwarfAttrFriend = 0x41,
- DwarfAttrIdentifierCase = 0x42,
- DwarfAttrMacroInfo = 0x43,
- DwarfAttrNamelistItem = 0x44,
- DwarfAttrPriority = 0x45,
- DwarfAttrSegment = 0x46,
- DwarfAttrSpecification = 0x47,
- DwarfAttrStaticLink = 0x48,
- DwarfAttrType = 0x49,
- DwarfAttrUseLocation = 0x4A,
- DwarfAttrVarParam = 0x4B,
- DwarfAttrVirtuality = 0x4C,
- DwarfAttrVtableElemLoc = 0x4D,
- DwarfAttrAllocated = 0x4E,
- DwarfAttrAssociated = 0x4F,
- DwarfAttrDataLocation = 0x50,
- DwarfAttrStride = 0x51,
- DwarfAttrEntrypc = 0x52,
- DwarfAttrUseUTF8 = 0x53,
- DwarfAttrExtension = 0x54,
- DwarfAttrRanges = 0x55,
- DwarfAttrTrampoline = 0x56,
- DwarfAttrCallColumn = 0x57,
- DwarfAttrCallFile = 0x58,
- DwarfAttrCallLine = 0x59,
- DwarfAttrDescription = 0x5A,
- DwarfAttrMax,
-
- FormAddr = 0x01,
- FormDwarfBlock2 = 0x03,
- FormDwarfBlock4 = 0x04,
- FormData2 = 0x05,
- FormData4 = 0x06,
- FormData8 = 0x07,
- FormString = 0x08,
- FormDwarfBlock = 0x09,
- FormDwarfBlock1 = 0x0A,
- FormData1 = 0x0B,
- FormFlag = 0x0C,
- FormSdata = 0x0D,
- FormStrp = 0x0E,
- FormUdata = 0x0F,
- FormRefAddr = 0x10,
- FormRef1 = 0x11,
- FormRef2 = 0x12,
- FormRef4 = 0x13,
- FormRef8 = 0x14,
- FormRefUdata = 0x15,
- FormIndirect = 0x16
+ DwarfAttrSibling = 0x01,
+ DwarfAttrLocation = 0x02,
+ DwarfAttrName = 0x03,
+ DwarfAttrOrdering = 0x09,
+ DwarfAttrByteSize = 0x0B,
+ DwarfAttrBitOffset = 0x0C,
+ DwarfAttrBitSize = 0x0D,
+ DwarfAttrStmtList = 0x10,
+ DwarfAttrLowpc = 0x11,
+ DwarfAttrHighpc = 0x12,
+ DwarfAttrLanguage = 0x13,
+ DwarfAttrDiscr = 0x15,
+ DwarfAttrDiscrValue = 0x16,
+ DwarfAttrVisibility = 0x17,
+ DwarfAttrImport = 0x18,
+ DwarfAttrStringLength = 0x19,
+ DwarfAttrCommonRef = 0x1A,
+ DwarfAttrCompDir = 0x1B,
+ DwarfAttrConstValue = 0x1C,
+ DwarfAttrContainingType = 0x1D,
+ DwarfAttrDefaultValue = 0x1E,
+ DwarfAttrInline = 0x20,
+ DwarfAttrIsOptional = 0x21,
+ DwarfAttrLowerBound = 0x22,
+ DwarfAttrProducer = 0x25,
+ DwarfAttrPrototyped = 0x27,
+ DwarfAttrReturnAddr = 0x2A,
+ DwarfAttrStartScope = 0x2C,
+ DwarfAttrStrideSize = 0x2E,
+ DwarfAttrUpperBound = 0x2F,
+ DwarfAttrAbstractOrigin = 0x31,
+ DwarfAttrAccessibility = 0x32,
+ DwarfAttrAddrClass = 0x33,
+ DwarfAttrArtificial = 0x34,
+ DwarfAttrBaseTypes = 0x35,
+ DwarfAttrCalling = 0x36,
+ DwarfAttrCount = 0x37,
+ DwarfAttrDataMemberLoc = 0x38,
+ DwarfAttrDeclColumn = 0x39,
+ DwarfAttrDeclFile = 0x3A,
+ DwarfAttrDeclLine = 0x3B,
+ DwarfAttrDeclaration = 0x3C,
+ DwarfAttrDiscrList = 0x3D,
+ DwarfAttrEncoding = 0x3E,
+ DwarfAttrExternal = 0x3F,
+ DwarfAttrFrameBase = 0x40,
+ DwarfAttrFriend = 0x41,
+ DwarfAttrIdentifierCase = 0x42,
+ DwarfAttrMacroInfo = 0x43,
+ DwarfAttrNamelistItem = 0x44,
+ DwarfAttrPriority = 0x45,
+ DwarfAttrSegment = 0x46,
+ DwarfAttrSpecification = 0x47,
+ DwarfAttrStaticLink = 0x48,
+ DwarfAttrType = 0x49,
+ DwarfAttrUseLocation = 0x4A,
+ DwarfAttrVarParam = 0x4B,
+ DwarfAttrVirtuality = 0x4C,
+ DwarfAttrVtableElemLoc = 0x4D,
+ DwarfAttrAllocated = 0x4E,
+ DwarfAttrAssociated = 0x4F,
+ DwarfAttrDataLocation = 0x50,
+ DwarfAttrStride = 0x51,
+ DwarfAttrEntrypc = 0x52,
+ DwarfAttrUseUTF8 = 0x53,
+ DwarfAttrExtension = 0x54,
+ DwarfAttrRanges = 0x55,
+ DwarfAttrTrampoline = 0x56,
+ DwarfAttrCallColumn = 0x57,
+ DwarfAttrCallFile = 0x58,
+ DwarfAttrCallLine = 0x59,
+ DwarfAttrDescription = 0x5A,
+ DwarfAttrMax,
+
+ FormAddr = 0x01,
+ FormDwarfBlock2 = 0x03,
+ FormDwarfBlock4 = 0x04,
+ FormData2 = 0x05,
+ FormData4 = 0x06,
+ FormData8 = 0x07,
+ FormString = 0x08,
+ FormDwarfBlock = 0x09,
+ FormDwarfBlock1 = 0x0A,
+ FormData1 = 0x0B,
+ FormFlag = 0x0C,
+ FormSdata = 0x0D,
+ FormStrp = 0x0E,
+ FormUdata = 0x0F,
+ FormRefAddr = 0x10,
+ FormRef1 = 0x11,
+ FormRef2 = 0x12,
+ FormRef4 = 0x13,
+ FormRef8 = 0x14,
+ FormRefUdata = 0x15,
+ FormIndirect = 0x16
};
-static int parseattrs(DwarfBuf*, ulong, DwarfAbbrev*, DwarfAttrs*);
+static int parseattrs(Dwarf *d, DwarfBuf*, ulong, ulong, DwarfAbbrev*, DwarfAttrs*);
static int getulong(DwarfBuf*, int, ulong, ulong*, int*);
static int getuchar(DwarfBuf*, int, uchar*);
-static int getstring(DwarfBuf*, int, char**);
+static int getstring(Dwarf *d, DwarfBuf*, int, char**);
static int getblock(DwarfBuf*, int, DwarfBlock*);
-static int skipform(DwarfBuf*, int);
-static int constblock(Dwarf*, DwarfBlock*, ulong*);
+static int skipform(Dwarf *d, DwarfBuf*, int);
int
dwarflookupnameinunit(Dwarf *d, ulong unit, char *name, DwarfSym *s)
{
- if(dwarfenumunit(d, unit, s) < 0)
- return -1;
-
- dwarfnextsymat(d, s, 0); /* s is now the CompileUnit */
- while(dwarfnextsymat(d, s, 1) == 1)
- if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
- return 0;
- werrstr("symbol '%s' not found", name);
- return -1;
+ DwarfSym compunit = { };
+ if(dwarfenumunit(d, unit, &compunit) < 0)
+ return -1;
+ while(dwarfnextsymat(d, &compunit, s) == 1)
+ if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
+ return 0;
+ werrstr("symbol '%s' not found", name);
+ return -1;
}
-
int
dwarflookupsubname(Dwarf *d, DwarfSym *parent, char *name, DwarfSym *s)
{
- *s = *parent;
- while(dwarfnextsymat(d, s, parent->depth+1))
- if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
- return 0;
- werrstr("symbol '%s' not found", name);
- return -1;
+ *s = *parent;
+ while(dwarfnextsymat(d, parent, s))
+ if(s->attrs.name && strcmp(s->attrs.name, name) == 0)
+ return 0;
+ werrstr("symbol '%s' not found", name);
+ return -1;
}
int
-dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s)
+dwarflookupchildtag(Dwarf *d, DwarfSym *parent, ulong tag, DwarfSym *s)
{
- if(dwarfenumunit(d, unit, s) < 0) {
- return -1;
- }
+ int rsym = dwarfnextsymat(d, parent, s);
+ while (rsym == 0 && s->attrs.tag != tag) {
+ if (s->attrs.haskids) {
+ DwarfSym p = *s;
+ int csym = dwarflookupchildtag(d, &p, tag, s);
+ if (csym == 0) {
+ return csym;
+ }
+ }
+ rsym = dwarfnextsym(d, s);
+ }
+ return rsym;
+}
- dwarfnextsymat(d, s, 0); /* s is now the CompileUnit */
- if(s->attrs.tag == tag) {
- return 0;
- }
- while(dwarfnextsymat(d, s, 1) == 1)
- if(s->attrs.tag == tag) {
- return 0;
- }
- werrstr("symbol with tag 0x%lux not found", tag);
- return -1;
+int
+dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s)
+{
+ DwarfSym compunit = { };
+ if (dwarfenumunit(d, unit, &compunit) < 0) {
+ return -1;
+ }
+ do {
+ if (compunit.attrs.tag == tag) {
+ *s = compunit;
+ return 0;
+ }
+ if (dwarflookupchildtag(d, &compunit, tag, s) == 0)
+ return 0;
+ } while(dwarfnextsym(d, &compunit) == 0);
+ werrstr("symbol with tag 0x%lux not found", tag);
+ return -1;
}
int
dwarfseeksym(Dwarf *d, ulong unit, ulong off, DwarfSym *s)
{
- if(dwarfenumunit(d, unit, s) < 0)
- return -1;
- s->b.p = d->info.data + unit + off;
- if(dwarfnextsymat(d, s, 0) != 1)
- return -1;
- return 0;
+ DwarfSym compunit = { };
+ if(dwarfenumunit(d, unit, &compunit) < 0)
+ return -1;
+ s->b.p = d->info.data + unit + off;
+ if(dwarfnextsymat(d, &compunit, s) == -1)
+ return -1;
+ werrstr("dwarfseeksym: unit %x off %x, tag %x", unit, off, s->attrs.tag);
+ return 0;
}
int
dwarflookupfn(Dwarf *d, ulong unit, ulong pc, DwarfSym *s)
{
- if(dwarfenumunit(d, unit, s) < 0)
- return -1;
-
- if(dwarfnextsymat(d, s, 0) != 1)
- return -1;
- /* s is now the CompileUnit */
-
- while(dwarfnextsymat(d, s, 1) == 1){
- if(s->attrs.tag != TagSubprogram)
- continue;
- if(s->attrs.lowpc <= pc && pc < s->attrs.highpc)
- return 0;
- }
- werrstr("fn containing pc 0x%lux not found", pc);
- return -1;
+ DwarfSym compunit = { };
+ if(dwarfenumunit(d, unit, &compunit) < 0)
+ return -1;
+ while(dwarfnextsymat(d, &compunit, s) == 0){
+ if(s->attrs.tag != TagSubprogram)
+ continue;
+ if(s->attrs.lowpc <= pc && pc < s->attrs.highpc)
+ return 0;
+ }
+ werrstr("fn containing pc 0x%lux not found", pc);
+ return -1;
}
int
dwarfenumunit(Dwarf *d, ulong unit, DwarfSym *s)
{
- int i;
- ulong aoff, len;
-
- if(unit >= d->info.len){
- werrstr("dwarf unit address 0x%x >= 0x%x out of range", unit, d->info.len);
- return -1;
- }
- memset(s, 0, sizeof *s);
- memset(&s->b, 0, sizeof s->b);
-
- s->b.d = d;
- s->b.p = d->info.data + unit;
- s->b.ep = d->info.data + d->info.len;
- len = dwarfget4(&s->b);
- s->nextunit = unit + 4 + len;
-
- if(s->b.ep - s->b.p < len){
- badheader:
- werrstr("bad dwarf unit header at unit 0x%lux", unit);
- return -1;
- }
- s->b.ep = s->b.p+len;
- if((i=dwarfget2(&s->b)) != 2)
- goto badheader;
- aoff = dwarfget4(&s->b);
- s->b.addrsize = dwarfget1(&s->b);
- if(d->addrsize == 0)
- d->addrsize = s->b.addrsize;
- if(s->b.p == nil)
- goto badheader;
-
- s->aoff = aoff;
+ int i;
+ ulong aoff, len;
+
+ if(unit >= d->info.len){
+ werrstr("dwarf unit address 0x%x >= 0x%x out of range", unit, d->info.len);
+ return -1;
+ }
+ memset(s, 0, sizeof *s);
+ memset(&s->b, 0, sizeof s->b);
+
+ s->b.d = d;
+ s->b.p = d->info.data + unit;
+ s->b.ep = d->info.data + d->info.len;
+ len = dwarfget4(&s->b);
s->unit = unit;
- s->depth = 0;
- return 0;
-}
-
-int
-dwarfenum(Dwarf *d, DwarfSym *s)
-{
- if(dwarfenumunit(d, 0, s) < 0)
- return -1;
- s->allunits = 1;
- return 0;
+ s->nextunit = unit + 4 + len;
+ s->b.ep = d->info.data + s->nextunit;
+
+ if(s->b.ep - s->b.p < len){
+ badheader:
+ werrstr("bad dwarf unit header at unit 0x%lux end %x start %x len %x", unit, s->b.ep - d->info.data, s->b.p - d->info.data, len);
+ return -1;
+ }
+ s->b.ep = s->b.p+len;
+ if((i=dwarfget2(&s->b)) != 2)
+ goto badheader;
+ aoff = dwarfget4(&s->b);
+ s->b.addrsize = dwarfget1(&s->b);
+ if(d->addrsize == 0)
+ d->addrsize = s->b.addrsize;
+ if(s->b.p == nil)
+ goto badheader;
+
+ s->aoff = aoff;
+
+ return dwarfnextsym(d, s);
}
int
dwarfnextsym(Dwarf *d, DwarfSym *s)
{
- ulong num;
- DwarfAbbrev *a;
-
- if(s->attrs.haskids)
- s->depth++;
-top:
- if(s->b.p >= s->b.ep){
- if(s->allunits && s->nextunit < d->info.len){
- if(dwarfenumunit(d, s->nextunit, s) < 0) {
- return -1;
- }
- s->allunits = 1;
- goto top;
- }
- return 0;
- }
-
- s->uoff = s->b.p - (d->info.data+s->unit);
- num = dwarfget128(&s->b);
- if(num == 0){
- if(s->depth == 0) {
- return 0;
- }
- if(s->depth > 0)
- s->depth--;
- goto top;
- }
-
- a = dwarfgetabbrev(d, s->aoff, num);
- if(a == nil){
- werrstr("getabbrev %ud %ud for %ud,%ud: %r\n", s->aoff, num, s->unit, s->uoff);
- return -1;
- }
- if(parseattrs(&s->b, s->unit, a, &s->attrs) < 0) {
- return -1;
- }
- return 1;
+ ulong num;
+ DwarfAbbrev *a;
+
+ num = dwarfget128(&s->b);
+ s->num = num;
+ if(num == 0){
+ return -1;
+ }
+
+ a = dwarfgetabbrev(d, s->aoff, num);
+ if(a == nil){
+ werrstr("getabbrev %ud %ud for %ud,%ud", s->aoff, num, s->unit);
+ return -1;
+ }
+
+ if(parseattrs(d, &s->b, s->attrs.tag, s->unit, a, &s->attrs) < 0) {
+ return -1;
+ }
+
+ if (s->attrs.haskids) {
+ DwarfSym childSkip = { };
+ s->childoff = s->b.p - d->info.data;
+ int r = dwarfnextsymat(d, s, &childSkip);
+ while (r == 0) {
+ r = dwarfnextsym(d, &childSkip);
+ }
+ s->b = childSkip.b;
+ } else {
+ s->childoff = 0;
+ }
+ return 0;
}
int
-dwarfnextsymat(Dwarf *d, DwarfSym *s, int depth)
+dwarfnextsymat(Dwarf *d, DwarfSym *parent, DwarfSym *child)
{
- int r;
- DwarfSym t;
- uint sib;
-
- if(s->depth == depth && s->attrs.have.sibling){
- sib = s->attrs.sibling;
- if(sib < d->info.len && d->info.data+sib >= s->b.p)
- s->b.p = d->info.data+sib;
- s->attrs.haskids = 0;
- }
-
- /*
- * The funny game with t and s make sure that
- * if we get to the end of a run of a particular
- * depth, we leave s so that a call to nextsymat with depth-1
- * will actually produce the desired guy. We could change
- * the interface to dwarfnextsym instead, but I'm scared
- * to touch it.
- */
- t = *s;
- for(;;){
- if((r = dwarfnextsym(d, &t)) != 1) {
- return r;
- }
- if(t.depth < depth){
- /* went too far - nothing to see */
- return 0;
- }
- *s = t;
- if(t.depth == depth) {
- return 1;
- }
- }
+ uint sib;
+
+ if (!parent->attrs.haskids || !parent->childoff)
+ return -1;
+
+ child->unit = parent->unit;
+ child->aoff = parent->aoff;
+ child->depth = parent->depth + 1;
+ if(child->attrs.have.sibling){
+ sib = child->attrs.sibling;
+ if(sib < d->info.len && d->info.data+sib > child->b.p)
+ child->b.p = d->info.data+sib;
+ else if (sib >= d->info.len) {
+ werrstr("sibling reported as out of bounds %d vs %d", sib, d->info.len);
+ return -1;
+ } else if (d->info.data+sib+parent->unit < child->b.p) {
+ werrstr("subsequent sibling is listed before prev %d vs %d", sib+parent->unit, child->b.p - d->info.data);
+ return -1;
+ }
+ }
+
+ // Uninitialized
+ if (!child->b.d) {
+ child->b = parent->b;
+ child->b.p = parent->childoff + parent->b.d->info.data;
+ }
+
+ return dwarfnextsym(d, child);
}
typedef struct Parse Parse;
struct Parse {
- int name;
- int off;
- int haveoff;
- int type;
+ int name;
+ int off;
+ int haveoff;
+ int type;
};
#define OFFSET(x) offsetof(DwarfAttrs, x), offsetof(DwarfAttrs, have.x)
static Parse plist[] = { /* Font Tab 4 */
- { DwarfAttrAbstractOrigin, OFFSET(abstractorigin), TReference },
- { DwarfAttrAccessibility, OFFSET(accessibility), TConstant },
- { DwarfAttrAddrClass, OFFSET(addrclass), TConstant },
- { DwarfAttrArtificial, OFFSET(isartificial), TFlag },
- { DwarfAttrBaseTypes, OFFSET(basetypes), TReference },
- { DwarfAttrBitOffset, OFFSET(bitoffset), TConstant },
- { DwarfAttrBitSize, OFFSET(bitsize), TConstant },
- { DwarfAttrByteSize, OFFSET(bytesize), TConstant },
- { DwarfAttrCalling, OFFSET(calling), TConstant },
- { DwarfAttrCommonRef, OFFSET(commonref), TReference },
- { DwarfAttrCompDir, OFFSET(compdir), TString },
- { DwarfAttrConstValue, OFFSET(constvalue), TString|TConstant|TBlock },
- { DwarfAttrContainingType, OFFSET(containingtype), TReference },
- { DwarfAttrCount, OFFSET(count), TConstant|TReference },
- { DwarfAttrDataMemberLoc, OFFSET(datamemberloc), TBlock|TConstant|TReference },
- { DwarfAttrDeclColumn, OFFSET(declcolumn), TConstant },
- { DwarfAttrDeclFile, OFFSET(declfile), TConstant },
- { DwarfAttrDeclLine, OFFSET(declline), TConstant },
- { DwarfAttrDeclaration, OFFSET(isdeclaration), TFlag },
- { DwarfAttrDefaultValue, OFFSET(defaultvalue), TReference },
- { DwarfAttrDiscr, OFFSET(discr), TReference },
- { DwarfAttrDiscrList, OFFSET(discrlist), TBlock },
- { DwarfAttrDiscrValue, OFFSET(discrvalue), TConstant },
- { DwarfAttrEncoding, OFFSET(encoding), TConstant },
- { DwarfAttrExternal, OFFSET(isexternal), TFlag },
- { DwarfAttrFrameBase, OFFSET(framebase), TBlock|TConstant },
- { DwarfAttrFriend, OFFSET(friend), TReference },
- { DwarfAttrHighpc, OFFSET(highpc), TAddress },
- { DwarfAttrEntrypc, OFFSET(entrypc), TAddress },
- { DwarfAttrIdentifierCase, OFFSET(identifiercase), TConstant },
- { DwarfAttrImport, OFFSET(import), TReference },
- { DwarfAttrInline, OFFSET(inlined), TConstant },
- { DwarfAttrIsOptional, OFFSET(isoptional), TFlag },
- { DwarfAttrLanguage, OFFSET(language), TConstant },
- { DwarfAttrLocation, OFFSET(location), TBlock|TConstant },
- { DwarfAttrLowerBound, OFFSET(lowerbound), TConstant|TReference },
- { DwarfAttrLowpc, OFFSET(lowpc), TAddress },
- { DwarfAttrMacroInfo, OFFSET(macroinfo), TConstant },
- { DwarfAttrName, OFFSET(name), TString },
- { DwarfAttrNamelistItem, OFFSET(namelistitem), TBlock },
- { DwarfAttrOrdering, OFFSET(ordering), TConstant },
- { DwarfAttrPriority, OFFSET(priority), TReference },
- { DwarfAttrProducer, OFFSET(producer), TString },
- { DwarfAttrPrototyped, OFFSET(isprototyped), TFlag },
- { DwarfAttrRanges, OFFSET(ranges), TReference },
- { DwarfAttrReturnAddr, OFFSET(returnaddr), TBlock|TConstant },
- { DwarfAttrSegment, OFFSET(segment), TBlock|TConstant },
- { DwarfAttrSibling, OFFSET(sibling), TReference },
- { DwarfAttrSpecification, OFFSET(specification), TReference },
- { DwarfAttrStartScope, OFFSET(startscope), TConstant },
- { DwarfAttrStaticLink, OFFSET(staticlink), TBlock|TConstant },
- { DwarfAttrStmtList, OFFSET(stmtlist), TConstant },
- { DwarfAttrStrideSize, OFFSET(stridesize), TConstant },
- { DwarfAttrStringLength, OFFSET(stringlength), TBlock|TConstant },
- { DwarfAttrType, OFFSET(type), TReference },
- { DwarfAttrUpperBound, OFFSET(upperbound), TConstant|TReference },
- { DwarfAttrUseLocation, OFFSET(uselocation), TBlock|TConstant },
- { DwarfAttrVarParam, OFFSET(isvarparam), TFlag },
- { DwarfAttrVirtuality, OFFSET(virtuality), TConstant },
- { DwarfAttrVisibility, OFFSET(visibility), TConstant },
- { DwarfAttrVtableElemLoc, OFFSET(vtableelemloc), TBlock|TReference },
- { }
+ { DwarfAttrAbstractOrigin, OFFSET(abstractorigin), TReference },
+ { DwarfAttrAccessibility, OFFSET(accessibility), TConstant },
+ { DwarfAttrAddrClass, OFFSET(addrclass), TConstant },
+ { DwarfAttrArtificial, OFFSET(isartificial), TFlag },
+ { DwarfAttrBaseTypes, OFFSET(basetypes), TReference },
+ { DwarfAttrBitOffset, OFFSET(bitoffset), TConstant },
+ { DwarfAttrBitSize, OFFSET(bitsize), TConstant },
+ { DwarfAttrByteSize, OFFSET(bytesize), TConstant },
+ { DwarfAttrCalling, OFFSET(calling), TConstant },
+ { DwarfAttrCommonRef, OFFSET(commonref), TReference },
+ { DwarfAttrCompDir, OFFSET(compdir), TString },
+ { DwarfAttrConstValue, OFFSET(constvalue), TString|TConstant|TBlock },
+ { DwarfAttrContainingType, OFFSET(containingtype), TReference },
+ { DwarfAttrCount, OFFSET(count), TConstant|TReference },
+ { DwarfAttrDataMemberLoc, OFFSET(datamemberloc), TBlock|TConstant|TReference },
+ { DwarfAttrDeclColumn, OFFSET(declcolumn), TConstant },
+ { DwarfAttrDeclFile, OFFSET(declfile), TConstant },
+ { DwarfAttrDeclLine, OFFSET(declline), TConstant },
+ { DwarfAttrDeclaration, OFFSET(isdeclaration), TFlag },
+ { DwarfAttrDefaultValue, OFFSET(defaultvalue), TReference },
+ { DwarfAttrDiscr, OFFSET(discr), TReference },
+ { DwarfAttrDiscrList, OFFSET(discrlist), TBlock },
+ { DwarfAttrDiscrValue, OFFSET(discrvalue), TConstant },
+ { DwarfAttrEncoding, OFFSET(encoding), TConstant },
+ { DwarfAttrExternal, OFFSET(isexternal), TFlag },
+ { DwarfAttrFrameBase, OFFSET(framebase), TBlock|TConstant },
+ { DwarfAttrFriend, OFFSET(friend), TReference },
+ { DwarfAttrHighpc, OFFSET(highpc), TAddress },
+ { DwarfAttrEntrypc, OFFSET(entrypc), TAddress },
+ { DwarfAttrIdentifierCase, OFFSET(identifiercase), TConstant },
+ { DwarfAttrImport, OFFSET(import), TReference },
+ { DwarfAttrInline, OFFSET(inlined), TConstant },
+ { DwarfAttrIsOptional, OFFSET(isoptional), TFlag },
+ { DwarfAttrLanguage, OFFSET(language), TConstant },
+ { DwarfAttrLocation, OFFSET(location), TReference|TBlock },
+ { DwarfAttrLowerBound, OFFSET(lowerbound), TConstant|TReference },
+ { DwarfAttrLowpc, OFFSET(lowpc), TAddress },
+ { DwarfAttrMacroInfo, OFFSET(macroinfo), TConstant },
+ { DwarfAttrName, OFFSET(name), TString },
+ { DwarfAttrNamelistItem, OFFSET(namelistitem), TBlock },
+ { DwarfAttrOrdering, OFFSET(ordering), TConstant },
+ { DwarfAttrPriority, OFFSET(priority), TReference },
+ { DwarfAttrProducer, OFFSET(producer), TString },
+ { DwarfAttrPrototyped, OFFSET(isprototyped), TFlag },
+ { DwarfAttrRanges, OFFSET(ranges), TReference },
+ { DwarfAttrReturnAddr, OFFSET(returnaddr), TBlock|TConstant },
+ { DwarfAttrSegment, OFFSET(segment), TBlock|TConstant },
+ { DwarfAttrSibling, OFFSET(sibling), TReference },
+ { DwarfAttrSpecification, OFFSET(specification), TReference },
+ { DwarfAttrStartScope, OFFSET(startscope), TConstant },
+ { DwarfAttrStaticLink, OFFSET(staticlink), TBlock|TConstant },
+ { DwarfAttrStmtList, OFFSET(stmtlist), TConstant },
+ { DwarfAttrStrideSize, OFFSET(stridesize), TConstant },
+ { DwarfAttrStringLength, OFFSET(stringlength), TBlock|TConstant },
+ { DwarfAttrType, OFFSET(type), TReference },
+ { DwarfAttrUpperBound, OFFSET(upperbound), TConstant|TReference },
+ { DwarfAttrUseLocation, OFFSET(uselocation), TBlock|TConstant },
+ { DwarfAttrVarParam, OFFSET(isvarparam), TFlag },
+ { DwarfAttrVirtuality, OFFSET(virtuality), TConstant },
+ { DwarfAttrVisibility, OFFSET(visibility), TConstant },
+ { DwarfAttrVtableElemLoc, OFFSET(vtableelemloc), TBlock|TReference },
+ { }
};
static Parse ptab[DwarfAttrMax];
static int
-parseattrs(DwarfBuf *b, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs)
+parseattrs(Dwarf *d, DwarfBuf *b, ulong tag, ulong unit, DwarfAbbrev *a, DwarfAttrs *attrs)
{
- int i, f, n, got;
- static int nbad;
- void *v;
-
- /* initialize ptab first time through for quick access */
- if(ptab[DwarfAttrName].name != DwarfAttrName)
- for(i=0; plist[i].name; i++)
- ptab[plist[i].name] = plist[i];
-
- memset(attrs, 0, sizeof *attrs);
- attrs->tag = a->tag;
- attrs->haskids = a->haskids;
-
- for(i=0; i<a->nattr; i++){
- n = a->attr[i].name;
- f = a->attr[i].form;
- if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0){
- if(++nbad == 1)
- werrstr("dwarf parse attrs: unexpected attribute name 0x%x", n);
- continue; //return -1;
- }
- v = (char*)attrs + ptab[n].off;
- got = 0;
- if(f == FormIndirect)
- f = dwarfget128(b);
- if((ptab[n].type&(TConstant|TReference|TAddress))
- && getulong(b, f, unit, v, &got) >= 0)
- ;
- else if((ptab[n].type&TFlag) && getuchar(b, f, v) >= 0)
- got = TFlag;
- else if((ptab[n].type&TString) && getstring(b, f, v) >= 0)
- got = TString;
- else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0)
- got = TBlock;
- else{
- if(skipform(b, f) < 0){
- if(++nbad == 1)
- werrstr("dwarf parse attrs: cannot skip form %d", f);
- return -1;
- }
- }
- if(got == TBlock && (ptab[n].type&TConstant))
- got = constblock(b->d, v, v);
- *((uchar*)attrs+ptab[n].haveoff) = got;
- }
- return 0;
+ int i, f, n, got;
+ static int nbad;
+ void *v;
+
+ /* initialize ptab first time through for quick access */
+ if(ptab[DwarfAttrName].name != DwarfAttrName)
+ for(i=0; plist[i].name; i++)
+ ptab[plist[i].name] = plist[i];
+
+ memset(attrs, 0, sizeof *attrs);
+ attrs->tag = a->tag;
+ attrs->haskids = a->haskids;
+
+ for(i=0; i<a->nattr; i++){
+ n = a->attr[i].name;
+ f = a->attr[i].form;
+ if(n < 0 || n >= DwarfAttrMax || ptab[n].name==0) {
+ if (skipform(d, b, f) < 0) {
+ if(++nbad == 1)
+ werrstr("dwarf parse attrs: cannot skip form %d", f);
+ return -1;
+ }
+ continue;
+ }
+ v = (char*)attrs + ptab[n].off;
+ got = 0;
+ if(f == FormIndirect)
+ f = dwarfget128(b);
+ if((ptab[n].type&(TConstant|TReference|TAddress))
+ && getulong(b, f, unit, v, &got) >= 0)
+ ;
+ else if((ptab[n].type&TFlag) && getuchar(b, f, v) >= 0)
+ got = TFlag;
+ else if((ptab[n].type&TString) && getstring(d, b, f, v) >= 0)
+ got = TString;
+ else if((ptab[n].type&TBlock) && getblock(b, f, v) >= 0)
+ got = TBlock;
+ else {
+ if(skipform(d, b, f) < 0){
+ if(++nbad == 1)
+ werrstr("dwarf parse attrs: cannot skip form %d", f);
+ return -1;
+ }
+ }
+#if 0
+ if(got == TBlock && (ptab[n].type&TConstant))
+ got = constblock(b->d, v, v);
+#endif
+ *((uchar*)attrs+ptab[n].haveoff) = got;
+ }
+ return 0;
}
static int
getulong(DwarfBuf *b, int form, ulong unit, ulong *u, int *type)
{
- static int nbad;
- uvlong uv;
+ static int nbad;
+ uvlong uv;
- switch(form){
- default:
- return -1;
+ switch(form){
+ default:
+ return -1;
/* addresses */
- case FormAddr:
- *type = TAddress;
- *u = dwarfgetaddr(b);
- return 0;
+ case FormAddr:
+ *type = TAddress;
+ *u = dwarfgetaddr(b);
+ return 0;
/* references */
- case FormRefAddr:
- /* absolute ref in .debug_info */
- *type = TReference;
- *u = dwarfgetaddr(b);
- return 0;
- case FormRef1:
- *u = dwarfget1(b);
- goto relativeref;
- case FormRef2:
- *u = dwarfget2(b);
- goto relativeref;
- case FormRef4:
- *u = dwarfget4(b);
- goto relativeref;
- case FormRef8:
- *u = dwarfget8(b);
- goto relativeref;
- case FormRefUdata:
- *u = dwarfget128(b);
- relativeref:
- *u += unit;
- *type = TReference;
- return 0;
+ case FormRefAddr:
+ /* absolute ref in .debug_info */
+ *type = TReference;
+ *u = dwarfgetaddr(b);
+ return 0;
+ case FormRef1:
+ *u = dwarfget1(b);
+ goto relativeref;
+ case FormRef2:
+ *u = dwarfget2(b);
+ goto relativeref;
+ case FormRef4:
+ *u = dwarfget4(b);
+ goto relativeref;
+ case FormRef8:
+ *u = dwarfget8(b);
+ goto relativeref;
+ case FormRefUdata:
+ *u = dwarfget128(b);
+ relativeref:
+ *u += unit;
+ *type = TReference;
+ return 0;
/* constants */
- case FormData1:
- *u = dwarfget1(b);
- goto constant;
- case FormData2:
- *u = dwarfget2(b);
- goto constant;
- case FormData4:
- *u = dwarfget4(b);
- goto constant;
- case FormData8:
- uv = dwarfget8(b);
- *u = uv;
- if(uv != *u && ++nbad == 1)
- werrstr("dwarf: truncating 64-bit attribute constants");
- goto constant;
- case FormSdata:
- *u = dwarfget128s(b);
- goto constant;
- case FormUdata:
- *u = dwarfget128(b);
- constant:
- *type = TConstant;
- return 0;
- }
+ case FormData1:
+ *u = dwarfget1(b);
+ goto constant;
+ case FormData2:
+ *u = dwarfget2(b);
+ goto constant;
+ case FormData4:
+ *u = dwarfget4(b);
+ goto constant;
+ case FormData8:
+ uv = dwarfget8(b);
+ *u = uv;
+ if(uv != *u && ++nbad == 1)
+ werrstr("dwarf: truncating 64-bit attribute constants");
+ goto constant;
+ case FormSdata:
+ *u = dwarfget128s(b);
+ goto constant;
+ case FormUdata:
+ *u = dwarfget128(b);
+ constant:
+ *type = TConstant;
+ return 0;
+ }
}
static int
getuchar(DwarfBuf *b, int form, uchar *u)
{
- switch(form){
- default:
- return -1;
-
- case FormFlag:
- *u = dwarfget1(b);
- return 0;
- }
+ switch(form){
+ default:
+ return -1;
+
+ case FormFlag:
+ *u = dwarfget1(b);
+ return 0;
+ }
}
static int
-getstring(DwarfBuf *b, int form, char **s)
+getstring(Dwarf *d, DwarfBuf *b, int form, char **s)
{
- static int nbad;
- ulong u;
-
- switch(form){
- default:
- return -1;
-
- case FormString:
- *s = dwarfgetstring(b);
- return 0;
-
- case FormStrp:
- u = dwarfget4(b);
- if(u >= b->d->str.len){
- if(++nbad == 1)
- werrstr("dwarf: bad string pointer 0x%lux in attribute", u);
- /* don't return error - maybe can proceed */
- *s = nil;
- }else
- *s = (char*)b->d->str.data + u;
- return 0;
-
- }
+ static int nbad;
+ ulong u, x;
+
+ switch(form){
+ default:
+ return -1;
+
+ case FormString:
+ x = b->p - d->info.data;
+ *s = dwarfgetstring(b);
+ for (u = 0; (*s)[u]; u++) {
+ assert(isprint((*s)[u]));
+ }
+ return 0;
+
+ case FormStrp:
+ u = dwarfget4(b);
+ if(u >= b->d->str.len){
+ if(++nbad == 1)
+ werrstr("dwarf: bad string pointer 0x%lux in attribute", u);
+ /* don't return error - maybe can proceed */
+ *s = nil;
+ }else
+ *s = (char*)b->d->str.data + u;
+ return 0;
+
+ }
}
static int
getblock(DwarfBuf *b, int form, DwarfBlock *bl)
{
- ulong n;
-
- switch(form){
- default:
- return -1;
- case FormDwarfBlock:
- n = dwarfget128(b);
- goto copyn;
- case FormDwarfBlock1:
- n = dwarfget1(b);
- goto copyn;
- case FormDwarfBlock2:
- n = dwarfget2(b);
- goto copyn;
- case FormDwarfBlock4:
- n = dwarfget4(b);
- copyn:
- bl->data = dwarfgetnref(b, n);
- bl->len = n;
- if(bl->data == nil)
- return -1;
- return 0;
- }
+ ulong n;
+
+ switch(form){
+ default:
+ return -1;
+ case FormDwarfBlock:
+ n = dwarfget128(b);
+ goto copyn;
+ case FormDwarfBlock1:
+ n = dwarfget1(b);
+ goto copyn;
+ case FormDwarfBlock2:
+ n = dwarfget2(b);
+ goto copyn;
+ case FormDwarfBlock4:
+ n = dwarfget4(b);
+ copyn:
+ bl->data = dwarfgetnref(b, n);
+ bl->len = n;
+ if(bl->data == nil)
+ return -1;
+ return 0;
+ }
}
+/* last resort */
static int
-constblock(Dwarf *d, DwarfBlock *bl, ulong *pval)
+skipform(Dwarf *d, DwarfBuf *b, int form)
{
- DwarfBuf b;
-
- memset(&b, 0, sizeof b);
- b.p = bl->data;
- b.ep = bl->data+bl->len;
- b.d = d;
-
- switch(dwarfget1(&b)){
- case OpAddr:
- *pval = dwarfgetaddr(&b);
- return TConstant;
- case OpConst1u:
- *pval = dwarfget1(&b);
- return TConstant;
- case OpConst1s:
- *pval = (schar)dwarfget1(&b);
- return TConstant;
- case OpConst2u:
- *pval = dwarfget2(&b);
- return TConstant;
- case OpConst2s:
- *pval = (s16int)dwarfget2(&b);
- return TConstant;
- case OpConst4u:
- *pval = dwarfget4(&b);
- return TConstant;
- case OpConst4s:
- *pval = (s32int)dwarfget4(&b);
- return TConstant;
- case OpConst8u:
- *pval = (u64int)dwarfget8(&b);
- return TConstant;
- case OpConst8s:
- *pval = (s64int)dwarfget8(&b);
- return TConstant;
- case OpConstu:
- *pval = dwarfget128(&b);
- return TConstant;
- case OpConsts:
- *pval = dwarfget128s(&b);
- return TConstant;
- case OpPlusUconst:
- *pval = dwarfget128(&b);
- return TConstant;
- default:
- return TBlock;
- }
+ int type;
+ DwarfVal val;
+
+ if(getulong(b, form, 0, &val.c, &type) < 0
+ && getuchar(b, form, (uchar*)&val) < 0
+ && getstring(d, b, form, &val.s) < 0
+ && getblock(b, form, &val.b) < 0)
+ return -1;
+ return 0;
}
-/* last resort */
-static int
-skipform(DwarfBuf *b, int form)
+void stackinit(DwarfStack *stack)
+{
+ memset(stack, 0, sizeof(*stack));
+ stack->data = stack->storage;
+ stack->length = 0; stack->max = sizeof(stack->storage) / sizeof(stack->storage[0]);
+}
+
+void stackpush(DwarfStack *stack, ulong value)
{
- int type;
- DwarfVal val;
-
- if(getulong(b, form, 0, &val.c, &type) < 0
- && getuchar(b, form, (uchar*)&val) < 0
- && getstring(b, form, &val.s) < 0
- && getblock(b, form, &val.b) < 0)
- return -1;
- return 0;
+ if (stack->length == stack->max) {
+ ulong *newstack = malloc(sizeof(ulong)*stack->max*2);
+ memcpy(newstack, stack->data, sizeof(ulong)*stack->length);
+ if (stack->data != stack->storage)
+ free(stack->data);
+ stack->data = newstack;
+ stack->max *= 2;
+ }
+ werrstr("stack[%d] = %x", stack->length, value);
+ stack->data[stack->length++] = value;
}
+ulong stackpop(DwarfStack *stack)
+{
+ ASSERT(stack->length > 0);
+ ulong val = stack->data[--stack->length];
+ werrstr("pop stack[%d] -> %x", stack->length, val);
+ return val;
+}
+
+void stackfree(DwarfStack *stack)
+{
+ if (stack->data != stack->storage)
+ free(stack->data);
+}
+
+// Returns -1 on failure
+int dwarfgetarg(Dwarf *d, const char *name, DwarfBuf *buf, ulong cfa, PROSSYM_REGISTERS registers, ulong *result)
+{
+ int ret = 0;
+ DwarfStack stack = { };
+ stackinit(&stack);
+ while (buf->p < buf->ep) {
+ int opcode = dwarfget1(buf);
+ werrstr("opcode %x", opcode);
+ switch (opcode) {
+ case 0:
+ buf->p = buf->ep;
+ break;
+ case OpAddr:
+ if (d->addrsize == 4) {
+ stackpush(&stack, dwarfget4(buf));
+ break;
+ } else {
+ werrstr("%s: we only support 4 byte addrs", name);
+ goto fatal;
+ }
+ case OpConst1s: {
+ signed char c = dwarfget1(buf);
+ stackpush(&stack, c);
+ } break;
+ case OpConst1u:
+ stackpush(&stack, dwarfget1(buf));
+ break;
+ case OpConst2s: {
+ signed short s = dwarfget2(buf);
+ stackpush(&stack, s);
+ } break;
+ case OpConst2u:
+ stackpush(&stack, dwarfget2(buf));
+ break;
+ case OpConst4s: {
+ signed int i = dwarfget4(buf);
+ stackpush(&stack, i);
+ } break;
+ case OpConst4u:
+ stackpush(&stack, dwarfget4(buf));
+ break;
+ case OpConst8s:
+ case OpConst8u:
+ werrstr("const 8 not yet supported");
+ goto fatal;
+ case OpConsts:
+ stackpush(&stack, dwarfget128s(buf));
+ break;
+ case OpConstu:
+ stackpush(&stack, dwarfget128(buf));
+ break;
+ case OpDup: {
+ ulong popped = stackpop(&stack);
+ stackpush(&stack, popped);
+ stackpush(&stack, popped);
+ } break;
+ case OpDrop:
+ stackpop(&stack);
+ break;
+ case OpOver: {
+ if (stack.length < 2) goto fatal;
+ stackpush(&stack, stack.data[stack.length-2]);
+ } break;
+ case OpPick: {
+ ulong arg = dwarfget1(buf);
+ if (arg >= stack.length) goto fatal;
+ arg = stack.data[stack.length-1-arg];
+ stackpush(&stack, arg);
+ } break;
+ case OpSwap: {
+ ulong a = stackpop(&stack), b = stackpop(&stack);
+ stackpush(&stack, b);
+ stackpush(&stack, a);
+ } break;
+ case OpRot: {
+ ulong a = stackpop(&stack), b = stackpop(&stack), c = stackpop(&stack);
+ stackpush(&stack, b);
+ stackpush(&stack, c);
+ stackpush(&stack, a);
+ } break;
+ case OpXderef:
+ case OpXderefSize:
+ werrstr("Xderef not yet supported");
+ goto fatal;
+ case OpAbs: {
+ long a = stackpop(&stack);
+ stackpush(&stack, a < 0 ? -a : a);
+ } break;
+ case OpAnd:
+ stackpush(&stack, stackpop(&stack) & stackpop(&stack));
+ break;
+ case OpDiv: {
+ ulong a = stackpop(&stack), b = stackpop(&stack);
+ stackpush(&stack, b / a);
+ } break;
+ case OpMinus: {
+ ulong a = stackpop(&stack), b = stackpop(&stack);
+ stackpush(&stack, b - a);
+ } break;
+ case OpMod: {
+ ulong a = stackpop(&stack), b = stackpop(&stack);
+ stackpush(&stack, b % a);
+ } break;
+ case OpMul:
+ stackpush(&stack, stackpop(&stack) * stackpop(&stack));
+ break;
+ case OpNeg:
+ stackpush(&stack, -stackpop(&stack));
+ break;
+ case OpNot:
+ stackpush(&stack, ~stackpop(&stack));
+ break;
+ case OpOr:
+ stackpush(&stack, stackpop(&stack) | stackpop(&stack));
+ break;
+ case OpPlus:
+ stackpush(&stack, stackpop(&stack) + stackpop(&stack));
+ break;
+ case OpPlusUconst:
+ stackpush(&stack, stackpop(&stack) + dwarfget128(buf));
+ break;
+ case OpShl: {
+ ulong a = stackpop(&stack), b = stackpop(&stack);
+ stackpush(&stack, b << a);
+ } break;
+ case OpShr: {
+ ulong a = stackpop(&stack), b = stackpop(&stack);
+ stackpush(&stack, b >> a);
+ } break;
+ case OpShra: {
+ ulong a = stackpop(&stack);
+ long b = stackpop(&stack);
+ if (b < 0)
+ b = -(-b >> a);
+ else
+ b = b >> a;
+ stackpush(&stack, b);
+ } break;
+ case OpXor:
+ stackpush(&stack, stackpop(&stack) ^ stackpop(&stack));
+ break;
+ case OpSkip:
+ buf->p += dwarfget2(buf);
+ break;
+ case OpBra: {
+ ulong a = dwarfget2(buf);
+ if (stackpop(&stack))
+ buf->p += a;
+ } break;
+ case OpEq:
+ stackpush(&stack, stackpop(&stack) == stackpop(&stack));
+ break;
+ case OpGe: {
+ ulong a = stackpop(&stack), b = stackpop(&stack);
+ stackpush(&stack, b >= a);
+ } break;
+ case OpGt: {
+ ulong a = stackpop(&stack), b = stackpop(&stack);
+ stackpush(&stack, b > a);
+ } break;
+ case OpLe: {
+ ulong a = stackpop(&stack), b = stackpop(&stack);
+ stackpush(&stack, b <= a);
+ } break;
+ case OpLt: {
+ ulong a = stackpop(&stack), b = stackpop(&stack);
+ stackpush(&stack, b < a);
+ } break;
+ case OpNe:
+ stackpush(&stack, stackpop(&stack) != stackpop(&stack));
+ break;
+ case OpNop:
+ break;
+ case OpDeref: {
+ ulong val, addr = stackpop(&stack);
+ if (!RosSymCallbacks.MemGetProc
+ (d->pe->fd,
+ &val,
+ addr,
+ d->addrsize))
+ goto fatal;
+ stackpush(&stack, val);
+ } break;
+ case OpDerefSize: {
+ ulong val, addr = stackpop(&stack), size = dwarfget1(buf);
+ if (!RosSymCallbacks.MemGetProc
+ (d->pe->fd,
+ &val,
+ addr,
+ size))
+ goto fatal;
+ stackpush(&stack, val);
+ } break;
+ case OpFbreg: {
+ ulong val, addr = cfa, offset = dwarfget128s(buf);
+ werrstr("FBREG cfa %x offset %x", cfa, offset);
+ if (!RosSymCallbacks.MemGetProc
+ (d->pe->fd,
+ &val,
+ addr+offset,
+ d->addrsize))
+ goto fatal;
+ stackpush(&stack, val);
+ } break;
+ case OpPiece:
+ werrstr("OpPiece not supported");
+ goto fatal;
+ default:
+ if (opcode >= OpLit0 && opcode < OpReg0)
+ stackpush(&stack, opcode - OpLit0);
+ else if (opcode >= OpReg0 && opcode < OpBreg0) {
+ ulong reg = opcode - OpReg0;
+ werrstr("REG[%d] value %x", reg, (ulong)registers->Registers[reg]);
+ stackpush(&stack, registers->Registers[reg]);
+ } else if (opcode >= OpBreg0 && opcode < OpRegx) {
+ ulong val,
+ reg = opcode - OpBreg0,
+ addr = registers->Registers[reg],
+ offset = dwarfget128s(buf);
+ werrstr("BREG[%d] reg %x offset %x", reg, addr, offset);
+ if (!RosSymCallbacks.MemGetProc
+ (d->pe->fd,
+ &val,
+ addr + offset,
+ d->addrsize))
+ goto fatal;
+ stackpush(&stack, val);
+ } else {
+ werrstr("opcode %x not supported", opcode);
+ goto fatal;
+ }
+ break;
+ }
+ }
+ if (stack.length < 1) goto fatal;
+ *result = stackpop(&stack);
+ werrstr("%s: value %x", name, *result);
+ goto finish;
+
+fatal:
+ ret = -1;
+
+finish:
+ stackfree(&stack);
+ return ret;
+}
+
+int dwarfargvalue(Dwarf *d, DwarfSym *proc, ulong pc, ulong cfa, PROSSYM_REGISTERS registers, DwarfParam *parameter)
+{
+ int gotarg;
+ DwarfSym unit = { };
+
+ if (dwarfenumunit(d, proc->unit, &unit) == -1)
+ return -1;
+
+ werrstr("lookup in unit %x-%x, pc %x", unit.attrs.lowpc, unit.attrs.highpc, pc);
+ pc -= unit.attrs.lowpc;
+
+ werrstr("paramblock %s -> unit %x type %x fde %x len %d registers %x",
+ parameter->name,
+ parameter->unit,
+ parameter->type,
+ parameter->fde,
+ parameter->len,
+ registers);
+
+ // Seek our range in loc
+ DwarfBuf locbuf;
+ DwarfBuf instream = { };
+
+ locbuf.d = d;
+ locbuf.addrsize = d->addrsize;
+
+ if (parameter->loctype == TConstant) {
+ locbuf.p = d->loc.data + parameter->fde;
+ locbuf.ep = d->loc.data + d->loc.len;
+ ulong start, end, len;
+ do {
+ len = 0;
+ start = dwarfget4(&locbuf);
+ end = dwarfget4(&locbuf);
+ if (start && end) {
+ len = dwarfget2(&locbuf);
+ instream = locbuf;
+ instream.ep = instream.p + len;
+ locbuf.p = instream.ep;
+ }
+ werrstr("ip %x s %x e %x (%x bytes)", pc, start, end, len);
+ } while (start && end && (start > pc || end <= pc));
+ } else if (parameter->loctype == TBlock) {
+ instream = locbuf;
+ instream.p = (void *)parameter->fde;
+ instream.ep = instream.p + parameter->len;
+ } else {
+ werrstr("Wrong block type for parameter %s", parameter->name);
+ return -1;
+ }
+
+ gotarg = dwarfgetarg(d, parameter->name, &instream, cfa, registers, ¶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;
+}