mirror of
https://github.com/reactos/reactos.git
synced 2024-08-20 18:35:32 +00:00
662 lines
16 KiB
C
662 lines
16 KiB
C
![]() |
/*
|
||
|
* Dwarf info parse and search.
|
||
|
*/
|
||
|
|
||
|
#define NTOSAPI
|
||
|
#include <ntifs.h>
|
||
|
#include <ndk/ntndk.h>
|
||
|
#include <reactos/rossym.h>
|
||
|
#include "rossympriv.h"
|
||
|
#include <ntimage.h>
|
||
|
|
||
|
#define NDEBUG
|
||
|
#include <debug.h>
|
||
|
|
||
|
#include "dwarf.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
|
||
|
};
|
||
|
|
||
|
static int parseattrs(DwarfBuf*, 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 getblock(DwarfBuf*, int, DwarfBlock*);
|
||
|
static int skipform(DwarfBuf*, int);
|
||
|
static int constblock(Dwarf*, DwarfBlock*, ulong*);
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
dwarflookuptag(Dwarf *d, ulong unit, ulong tag, DwarfSym *s)
|
||
|
{
|
||
|
if(dwarfenumunit(d, unit, s) < 0) {
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
dwarfnextsymat(d, s, 0); /* s is now the CompileUnit */
|
||
|
if(s->attrs.tag == tag) {
|
||
|
return 0;
|
||
|
}
|
||
|
while(dwarfnextsymat(d, s, 1) == 1)
|
||
|
if(s->attrs.tag == tag) {
|
||
|
return 0;
|
||
|
}
|
||
|
werrstr("symbol with tag 0x%lux not found", tag);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
dwarfnextsymat(Dwarf *d, DwarfSym *s, int depth)
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
typedef struct Parse Parse;
|
||
|
struct Parse {
|
||
|
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 },
|
||
|
{ }
|
||
|
};
|
||
|
|
||
|
static Parse ptab[DwarfAttrMax];
|
||
|
|
||
|
static int
|
||
|
parseattrs(DwarfBuf *b, 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;
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
getulong(DwarfBuf *b, int form, ulong unit, ulong *u, int *type)
|
||
|
{
|
||
|
static int nbad;
|
||
|
uvlong uv;
|
||
|
|
||
|
switch(form){
|
||
|
default:
|
||
|
return -1;
|
||
|
|
||
|
/* addresses */
|
||
|
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;
|
||
|
|
||
|
/* 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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
getuchar(DwarfBuf *b, int form, uchar *u)
|
||
|
{
|
||
|
switch(form){
|
||
|
default:
|
||
|
return -1;
|
||
|
|
||
|
case FormFlag:
|
||
|
*u = dwarfget1(b);
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
getstring(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
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static int
|
||
|
constblock(Dwarf *d, DwarfBlock *bl, ulong *pval)
|
||
|
{
|
||
|
DwarfBuf b;
|
||
|
|
||
|
memset(&b, 0, sizeof b);
|
||
|
b.p = bl->data;
|
||
|
b.ep = bl->data+bl->len;
|
||
|
b.d = d;
|
||
|
|
||
|
switch(dwarfget1(&b)){
|
||
|
case OpAddr:
|
||
|
*pval = dwarfgetaddr(&b);
|
||
|
return TConstant;
|
||
|
case OpConst1u:
|
||
|
*pval = dwarfget1(&b);
|
||
|
return TConstant;
|
||
|
case OpConst1s:
|
||
|
*pval = (schar)dwarfget1(&b);
|
||
|
return TConstant;
|
||
|
case OpConst2u:
|
||
|
*pval = dwarfget2(&b);
|
||
|
return TConstant;
|
||
|
case OpConst2s:
|
||
|
*pval = (s16int)dwarfget2(&b);
|
||
|
return TConstant;
|
||
|
case OpConst4u:
|
||
|
*pval = dwarfget4(&b);
|
||
|
return TConstant;
|
||
|
case OpConst4s:
|
||
|
*pval = (s32int)dwarfget4(&b);
|
||
|
return TConstant;
|
||
|
case OpConst8u:
|
||
|
*pval = (u64int)dwarfget8(&b);
|
||
|
return TConstant;
|
||
|
case OpConst8s:
|
||
|
*pval = (s64int)dwarfget8(&b);
|
||
|
return TConstant;
|
||
|
case OpConstu:
|
||
|
*pval = dwarfget128(&b);
|
||
|
return TConstant;
|
||
|
case OpConsts:
|
||
|
*pval = dwarfget128s(&b);
|
||
|
return TConstant;
|
||
|
case OpPlusUconst:
|
||
|
*pval = dwarfget128(&b);
|
||
|
return TConstant;
|
||
|
default:
|
||
|
return TBlock;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* last resort */
|
||
|
static int
|
||
|
skipform(DwarfBuf *b, int form)
|
||
|
{
|
||
|
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;
|
||
|
}
|
||
|
|