dfhack/reversing/ms_rtti.idc

996 lines
23 KiB
C

2010-03-06 07:14:18 -07:00
#include <idc.idc>
//Microsoft C++ RTTI support for IDA
//Version 3.0 2006.01.20 Igor Skochinsky <skochinsky@mail.ru>
//#define DEBUG
//////////////////////////////////////
// Unknown(long ea, long length)
//////////////////////////////////////
// Mark the ea as unknown for a length
// of length, but don't propagate.
static Unknown( ea, length )
{
auto i;
if (ea==BADADDR)
return;
// Message("Unknown(%x,%d)\n",ea, length);
for(i=0; i < length; i++)
{
MakeUnkn(ea+i,0);
}
}
static ForceQword( x ) { //Make dword, undefine as needed
if (x==BADADDR || x==0)
return;
if (!MakeQword( x ))
{
Unknown(x,8);
MakeQword(x);
}
}
static ForceDword( x ) { //Make dword, undefine as needed
if (x==BADADDR || x==0)
return;
if (!MakeDword( x ))
{
Unknown(x,4);
MakeDword(x);
}
}
static ForceWord( x ) { //Make word, undefine as needed
if (x==BADADDR || x==0)
return;
if (!MakeWord( x ))
{
Unknown(x,2);
MakeWord( x );
}
}
static ForceByte( x ) { //Make byte, undefine as needed
if (x==BADADDR || x==0)
return;
if (!MakeByte( x ))
{
MakeUnkn(x,0);
MakeByte( x );
}
}
static SoftOff ( x ) { //Make offset if !=0
if (x==BADADDR || x==0)
return;
ForceDword(x);
if (Dword(x)>0 && Dword(x)<=MaxEA()) OpOff(x,0,0);
}
static GetAsciizStr(x)
{
auto s,c;
if (x==BADADDR || x==0)
return "";
s = "";
while (c=Byte(x))
{
s = form("%s%c",s,c);
x = x+1;
}
return s;
}
//check if Dword(vtbl-4) points to typeinfo record and extract the type name from it
static GetTypeName(vtbl)
{
auto x, s, c;
if (vtbl==BADADDR)
return;
x = Dword(vtbl-4);
if ((!x) || (x==BADADDR)) return "";
// if (Dword(x)||Dword(x+4)||Dword(x+8)) return "";
x = Dword(x+12);
if ((!x) || (x==BADADDR)) return "";
s = "";
x = x+8;
while (c=Byte(x))
{
s = form("%s%c",s,c);
x = x+1;
}
return s;
}
static DwordCmt(x, cmt)
{
if (x==BADADDR || x==0)
return;
ForceDword(x);
MakeComm(x, cmt);
}
static OffCmt(x, cmt)
{
if (x==BADADDR || x==0)
return;
SoftOff(x);
MakeComm(x, cmt);
}
static StrCmt(x, cmt)
{
auto save_str;
if (x==BADADDR || x==0)
return;
MakeUnkn(x, 0);
save_str = GetLongPrm(INF_STRTYPE);
SetLongPrm(INF_STRTYPE,0);
MakeStr(x, BADADDR);
MakeName(x, "");
MakeComm(x, cmt);
SetLongPrm(INF_STRTYPE,save_str);
}
static DwordArrayCmt(x, n, cmt)
{
if (x==BADADDR || x==0)
return;
Unknown(x,4*n);
ForceDword(x);
MakeArray(x,n);
MakeComm(x, cmt);
}
//check if values match a pattern
static matchBytes(addr,match)
{
auto i,len,s;
len = strlen(match);
if (len%2)
{
Warning("Bad match string in matchBytes: %s",match);
return 0;
}
i=0;
while (i<len)
{
s = substr(match,i,i+2);
if (s!="??" && form("%02X",Byte(addr))!=s)
return 0;//mismatch
i = i+2;
addr++;
}
return 1;
}
static ForceDWMember(id, offset, name)
{
if (0!=AddStrucMember(id, name,offset, FF_DWRD, -1, 4))
SetMemberName(id, offset, name);
}
static ForceStrucMember(id, offset, sub_id, name)
{
auto a,i;
i = GetStrucSize(sub_id);
if (0!=AddStrucMember(id,name,offset,FF_DATA|FF_STRU,sub_id,i))
{
for (a=offset;a<offset+i;a++)
DelStrucMember(id,a);
AddStrucMember(id,name,offset,FF_DATA|FF_STRU,sub_id,i);
//SetMemberName(id, offset, name);
}
}
//add (or rename) a stack variable named name at frame offset offset (i.e. bp-based)
//struc_id = structure variable
//if struc_id == -1, then add a dword
static CommentStack(start, offset, name, struc_id)
{
auto id,l,bp;
id = GetFrame(start);
l = GetFrameLvarSize(start);
if ( (GetFunctionFlags(start) & FUNC_FRAME) == 0)
l = l + GetFrameRegsSize(start);
l = l+offset;
//Message("%a: ebp offset = %02Xh\n",start,l);
if (l<0)
{
//Message("growing the frame to locals=%d, regs=4, args=%d.\n",-offset, GetFrameArgsSize(start));
//we need to grow the locals
MakeFrame(start, -offset, GetFrameRegsSize(start), GetFrameArgsSize(start));
l = 0;
}
if (struc_id==-1)
ForceDWMember(id, l, name);
else
ForceStrucMember(id, l, struc_id, name);
}
static getRelJmpTarget(a)
{
auto b;
b = Byte(a);
if (b == 0xEB)
{
b = Byte(a+1);
if (b&0x80)
return a+2-((~b&0xFF)+1);
else
return a+2+b;
}
else if (b==0xE9)
{
b = Dword(a+1);
if (b&0x80000000)
return a+5-(~b+1);
else
return a+5+b;
}
else
return BADADDR;
}
static getRelCallTarget(a)
{
auto b;
b = Byte(a);
if (b==0xE8)
{
b = Dword(a+1);
if (b&0x80000000)
return a+5-(~b+1);
else
return a+5+b;
}
else
return BADADDR;
}
static MangleNumber(x)
{
//
// 0 = A@
// X = X-1 (1<=X<=10)
// -X = ?(X-1)
// 0x0..0xF = 'A'..'P'
auto s, sign;
s=""; sign=0;
if (x<0)
{
sign = 1;
x = -x;
}
if (x==0)
return "A@";
else if (x<=10)
return form("%s%d",sign?"?":"",x-1);
else
{
while (x>0)
{
s = form("%c%s",'A'+x%16,s);
x = x / 16;
}
return sign?"?":""+s+"@";
}
}
static Parse_BCD(x, indent)
{
auto indent_str,i,a,s;
if (x==BADADDR || x==0)
return;
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
/*
struct _s_RTTIBaseClassDescriptor
{
struct TypeDescriptor* pTypeDescriptor; //type descriptor of the class
DWORD numContainedBases; //number of nested classes following in the array
struct PMD where; //some displacement info
DWORD attributes; //usually 0, sometimes 10h
};
struct PMD
{
int mdisp; //member displacement
int pdisp; //vbtable displacement
int vdisp; //displacement inside vbtable
};
*/
#ifdef DEBUG
Message(indent_str+"0x%08.8X: RTTIBaseClassDescriptor\n", x);
Message(indent_str+" pTypeDescriptor: %08.8Xh (%s)\n", Dword(x), GetAsciizStr(Dword(x)+8));
Message(indent_str+" numContainedBases: %08.8Xh\n", Dword(x+4));
Message(indent_str+" PMD where: (%d,%d,%d)\n", Dword(x+8), Dword(x+12), Dword(x+16));
Message(indent_str+" attributes: %08.8Xh\n", Dword(x+20));
#endif
OffCmt(x, "pTypeDescriptor");
DwordCmt(x+4, "numContainedBases");
DwordArrayCmt(x+8, 3, "PMD where");
DwordCmt(x+20, "attributes");
s = Parse_TD(Dword(x), indent+1);
//??_R1A@?0A@A@B@@8 = B::`RTTI Base Class Descriptor at (0,-1,0,0)'
MakeName(x,"??_R1"+MangleNumber(Dword(x+8))+MangleNumber(Dword(x+12))+
MangleNumber(Dword(x+16))+MangleNumber(Dword(x+20))+substr(s,4,-1)+'8');
return s;
}
static GetClassName(p)
{
/*auto s;
s = GetAsciizStr(Dword(p)+8);
Message("demangling %s\n",s);
return DemangleTIName(s);*/
auto s,s2;
s = "??_7"+GetAsciizStr(Dword(p)+12)+"6B@";
//Message("demangling %s\n",s);
s2 = Demangle(s,8);
if (s2!=0)
//CObject::`vftable'
return substr(s2,0,strlen(s2)-11);
else
return s;
}
static DumpNestedClass(x, indent, contained)
{
auto indent_str,i,a,n,p,s,off;
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
i=0;
//indent=indent+1;
a = x;
while(i<contained)
{
p = Dword(a);
off = Dword(p+8);
s = form("%.4X: ",off);
Message("%s%s%s\n", s, indent_str, GetClassName(p));
//fprintf(f, form("%s%s%s\n",s,indent_str,GetClassName(p)));
n = Dword(p+4);
if (n>0) //check numContainedBases
DumpNestedClass(a+4, indent+1, n); //nested classes following
a=a+4*(n+1);
i=i+n+1;
}
}
static Parse_CHD(x, indent)
{
auto indent_str,i,a,n,p,s;
if (x==BADADDR || x==0)
return;
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
//Message(indent_str+"0x%08.8X: RTTIClassHierarchyDescriptor\n", x);
/*
struct _s_RTTIClassHierarchyDescriptor
{
DWORD signature; //always zero?
DWORD attributes; //bit 0 = multiple inheritance, bit 1 = virtual inheritance
DWORD numBaseClasses; //number of classes in pBaseClassArray
struct _s_RTTIBaseClassArray* pBaseClassArray;
};
*/
a = Dword(x+4);
if ((a&3)==1)
p = "(MI)";
else if ((a&3)==2)
p = "(VI)";
else if ((a&3)==3)
p = "(MI VI)";
else
p="(SI)";
#ifdef DEBUG
Message(indent_str+" signature: %08.8Xh\n", Dword(x));
Message(indent_str+" attributes: %08.8Xh %s\n", a, p);
Message(indent_str+" numBaseClasses: %08.8Xh\n", n);
Message(indent_str+" pBaseClassArray: %08.8Xh\n", a);
#endif
DwordCmt(x, "signature");
DwordCmt(x+4, "attributes");
DwordCmt(x+8, "numBaseClasses");
OffCmt(x+12, "pBaseClassArray");
a=Dword(x+12);
n=Dword(x+8);
i=0;
DumpNestedClass(a, indent, n);
indent=indent+1;
while(i<n)
{
p = Dword(a);
//Message(indent_str+" BaseClass[%02d]: %08.8Xh\n", i, p);
OffCmt(a, form("BaseClass[%02d]", i));
if (i==0)
{
s = Parse_BCD(p,indent);
//??_R2A@@8 = A::`RTTI Base Class Array'
MakeName(a,"??_R2"+substr(s,4,-1)+'8');
//??_R3A@@8 = A::`RTTI Class Hierarchy Descriptor'
MakeName(x,"??_R3"+substr(s,4,-1)+'8');
}
else
Parse_BCD(p,indent);
i=i+1;
a=a+4;
}
return s;
}
static Parse_TD(x, indent)
{
auto indent_str,i,a;
if (x==BADADDR || x==0)
return;
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
//Message(indent_str+"0x%08.8X: TypeDescriptor\n", x);
/*
struct TypeDescriptor
{
void* pVFTable; //always pointer to type_info::vftable ?
void* spare; //seems to be zero for most classes, and default constructor for exceptions
char name[0]; //mangled name, starting with .?A (.?AV=classes, .?AU=structs)
};
*/
a = GetAsciizStr(x+8);
#ifdef DEBUG
Message(indent_str+" pVFTable: %08.8Xh\n", Dword(x));
Message(indent_str+" spare: %08.8Xh\n", Dword(x+4));
Message(indent_str+" name: '%s'\n", a);
#endif
OffCmt(x, "pVFTable");
OffCmt(x+4, "spare");
StrCmt(x+8, "name");
//??_R0?AVA@@@8 = A `RTTI Type Descriptor'
MakeName(x,"??_R0"+substr(a,1,-1)+"@8");
return a;
}
static Parse_COL(x, indent)
{
/*
struct _s_RTTICompleteObjectLocator
{
DWORD signature; //always zero ?
DWORD offset; //offset of this vtable in the class ?
DWORD cdOffset; //no idea
struct TypeDescriptor* pTypeDescriptor; //TypeDescriptor of the class
struct _s_RTTIClassHierarchyDescriptor* pClassDescriptor; //inheritance hierarchy
};*/
auto indent_str,i,a,s;
if (x==BADADDR || x==0)
return;
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
s = GetAsciizStr(Dword(x+12)+8);
//Message(indent_str+"0x%08.8X: RTTICompleteObjectLocator\n", x);
#ifdef DEBUG
Message(indent_str+" signature: %08.8Xh\n", Dword(x));
Message(indent_str+" offset: %08.8Xh\n", Dword(x+4));
Message(indent_str+" cdOffset: %08.8Xh\n", Dword(x+8));
Message(indent_str+" pTypeDescriptor: %08.8Xh (%s)\n", Dword(x+12), DemangleTIName(s));
Message(indent_str+" pClassDescriptor: %08.8Xh\n", Dword(x+16));
#endif
DwordCmt(x, "signature");
DwordCmt(x+4, "offset");
DwordCmt(x+8, "cdOffset");
OffCmt(x+12, "pTypeDescriptor");
OffCmt(x+16, "pClassDescriptor");
//
Parse_CHD(Dword(x+16),indent+1);
}
static Parse_CT(x, indent)
{
auto indent_str,i,a,s;
if (x==BADADDR || x==0)
return;
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
/*
typedef const struct _s__CatchableType {
unsigned int properties;
_TypeDescriptor *pType;
_PMD thisDisplacement;
int sizeOrOffset;
_PMFN copyFunction;
} _CatchableType;
struct PMD
{
int mdisp; //members displacement ???
int pdisp; //
int vdisp; //vtable displacement ???
};
*/
s = GetAsciizStr(Dword(x+4)+8);
#ifdef DEBUG
Message(indent_str+"0x%08.8X: CatchableType\n", x);
Message(indent_str+" properties: %08.8Xh\n", Dword(x));
Message(indent_str+" pType: %08.8Xh (%s)\n", Dword(x+4), DemangleTIName(s));
Message(indent_str+" thisDisplacement: (%d,%d,%d)\n", Dword(x+8), Dword(x+12), Dword(x+16));
Message(indent_str+" sizeOrOffset: %08.8Xh\n", Dword(x+20));
Message(indent_str+" copyFunction: %08.8Xh\n", Dword(x+24));
#endif
a = "properties";
i = Dword(x);
if (i!=0) a = a+":";
if (i&1) a = a+" simple type";
if (i&2) a = a+" byref only";
if (i&4) a = a+" has vbases";
DwordCmt(x, a);
OffCmt(x+4, "pType");
DwordArrayCmt(x+8, 3, "thisDisplacement");
DwordCmt(x+20, "sizeOrOffset");
OffCmt(x+24, "copyFunction");
ForceDword(x+28);
//__CT??_R0 ?AVCTest@@ @81 = CTest::`catchable type'
MakeName(x,"__CT??_R0?"+substr(s,1,-1)+"@81");
if (Dword(x+24)) //we have a copy constructor
//.?AVexception@@ -> ??0exception@@QAE@ABV0@@Z = exception::exception(exception const &)
MakeName(Dword(x+24),"??0"+substr(s,4,-1)+"QAE@ABV0@@Z");
return s;
}
static Parse_CTA(x, indent)
{
/*
typedef const struct _s__CatchableTypeArray {
int nCatchableTypes;
_CatchableType *arrayOfCatchableTypes[];
} _CatchableTypeArray;
*/
auto indent_str,i,a,n,p,s;
if (x==BADADDR || x==0)
return;
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
#ifdef DEBUG
Message(indent_str+" nCatchableTypes: %08.8Xh\n", Dword(x));
Message(indent_str+" arrayOfCatchableTypes: %08.8Xh\n", Dword(x+4));
#endif
DwordCmt(x, "nCatchableTypes");
//OffCmt(x+4, "arrayOfCatchableTypes");
a=x+4;
n=Dword(x);
i=0;
indent=indent+1;
while(i<n)
{
p = Dword(a);
//Message(indent_str+" BaseClass[%02d]: %08.8Xh\n", i, p);
OffCmt(a, form("CatchableType[%02d]", i));
if (i==0)
{
s = Parse_CT(p,indent);
//__CTA1 ?AVCTest@@ = CTest::`catchable type array'
MakeName(x,"__CTA1?"+substr(s,1,-1));
}
else
Parse_CT(p,indent);
i=i+1;
a=a+4;
}
return s;
}
//demangle names like .?AVxxx, .PAD, .H etc
static DemangleTIName(s)
{
auto i;
if (substr(s,0,1)!=".")
return "";
s = Demangle("??_R0"+substr(s,1,-1)+"@8",8);
i = strstr(s,"`RTTI Type Descriptor'");
if (i==-1)
return "";
else
{
s = substr(s,0,i-1);
//Message("throw %s;\n",s);
return s;
}
}
static Parse_ThrowInfo(x, indent)
{
/*
typedef const struct _s__ThrowInfo {
unsigned int attributes;
_PMFN pmfnUnwind;
int (__cdecl*pForwardCompat)(...);
_CatchableTypeArray *pCatchableTypeArray;
} _ThrowInfo;
*/
auto indent_str,i,a,s;
if (x==BADADDR || x==0)
return;
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
#ifdef DEBUG
Message(indent_str+"0x%08.8X: ThrowInfo\n", x);
Message(indent_str+" attributes: %08.8Xh\n", Dword(x));
Message(indent_str+" pmfnUnwind: %08.8Xh\n", Dword(x+4));
Message(indent_str+" pForwardCompat: %08.8Xh\n", Dword(x+8));
Message(indent_str+" pCatchableTypeArray: %08.8Xh\n", Dword(x+12));
#endif
a = "attributes";
i = Dword(x);
if (i!=0) a = a+":";
if (i&1) a = a+" const";
if (i&2) a = a+" volatile";
DwordCmt(x, a);
OffCmt(x+4, "pmfnUnwind");
OffCmt(x+8, "pForwardCompat");
OffCmt(x+12, "pCatchableTypeArray");
s = Parse_CTA(Dword(x+12), indent+1);
if (s!="")
{
MakeName(x,"__TI1?"+substr(s,1,-1));
if (Dword(x+4)) //we have a destructor
//.?AVexception@@ -> ??1exception@@UAE@XZ = exception::~exception(void)
MakeName(Dword(x+4),"??1"+substr(s,4,-1)+"UAE@XZ");
i = Dword(x); //attributes
a = DemangleTIName(s);
if (i&1) a = "const "+a;
if (i&2) a = "volatile "+a;
a = "throw "+a;
Message("%s\n",a);
MakeRptCmt(x, a);
}
return s;
}
static Parse_TryBlock(x, indent)
{
/*
typedef const struct _s_TryBlockMapEntry {
int tryLow; //00
int tryHigh; //04
int catchHigh; //08
int nCatches; //0C
const struct _s_HandlerType * pHandlerArray; //10
} TryBlockMapEntry;
typedef const struct _s_HandlerType {
unsigned int adjectives; //00
struct TypeDescriptor * pType; //04
int dispCatchObj; //08
void * addressOfHandler; //0C
}
*/
auto indent_str,i,a,n,p,s;
if (x==BADADDR || x==0)
return;
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
#ifdef DEBUG
Message(indent_str+" tryLow: %d\n", Dword(x));
Message(indent_str+" tryHigh: %d\n", Dword(x+4));
Message(indent_str+" catchHigh: %d\n", Dword(x+8));
Message(indent_str+" nCatches: %d\n", Dword(x+12));
Message(indent_str+" pHandlerArray: %08.8Xh\n", Dword(x+16));
#endif
DwordCmt(x, "tryLow");
DwordCmt(x+4, "tryHigh");
DwordCmt(x+8, "catchHigh");
DwordCmt(x+12, "nCatches");
OffCmt(x+16, "pHandlerArray");
a=Dword(x+16);
n=Dword(x+12);
if (a==BADADDR || a==0 || n==0)
return;
i=0;
indent=indent+1;
while(i<n)
{
#ifdef DEBUG
Message(indent_str+" adjectives: %08.8Xh\n", Dword(a));
Message(indent_str+" pType: %08.8Xh\n", Dword(a+4));
Message(indent_str+" dispCatchObj: %08.8Xh\n", Dword(a+8));
Message(indent_str+" addressOfHandler: %08.8Xh\n", Dword(a+12));
#endif
DwordCmt(a, "adjectives");
OffCmt(a+4,"pType");
DwordCmt(a+8, "dispCatchObj");
OffCmt(a+12,"addressOfHandler");
p = Dword(a+4);
if (p)
{
s = DemangleTIName(Parse_TD(p, indent+1));
if (Dword(a)&8) //reference
s = s+"&";
if (Dword(a)&2) //volatile
s = "volatile "+s;
if (Dword(a)&1) //const
s = "const "+s;
s = s+" e";
}
else
s = "...";
p = Dword(a+12);
if (p!=0 && p!=BADADDR)
{
ExtLinA(Dword(a+12),0,form("; catch (%s)",s));
ExtLinA(Dword(a+12),1,form("; states %d..%d",Dword(x),Dword(x+4)));
p = Dword(a+8);
if (p)
{
if (p&0x80000000)
s = form("; e = [epb-%Xh]",-p);
else
s = form("; e = [epb+%Xh]",p);
ExtLinA(Dword(a+12),2,s);
}
}
i=i+1;
a=a+16;
}
return s;
}
static Parse_FuncInfo(x, indent)
{
/*
typedef const struct _s_FuncInfo {
unsigned int magicNumber:29; //0
unsigned int bbtFlags:3;
int maxState; //4
const struct _s_UnwindMapEntry * pUnwindMap; //8
unsigned int nTryBlocks; //C
const struct _s_TryBlockMapEntry * pTryBlockMap; //10
unsigned int nIPMapEntries; //14
void * pIPtoStateMap; //18
const struct _s_ESTypeList * pESTypeList; //1C
int EHFlags; //present only in vc8? //20
} FuncInfo;
typedef const struct _s_UnwindMapEntry {
int toState; //0
function * action; //4
} UnwindMapEntry;
*/
auto indent_str,i,a,s,n;
if (x==BADADDR || x==0)
return;
if ((Dword(x)^0x19930520)>0xF) {
Message("Magic is not 1993052Xh!\n");
return;
}
indent_str="";i=0;
while(i<indent)
{
indent_str=indent_str+" ";
i++;
}
#ifdef DEBUG
Message(indent_str+"0x%08.8X: FuncInfo\n", x);
Message(indent_str+" magicNumber: %08.8Xh\n", Dword(x));
Message(indent_str+" maxState: %d\n", Dword(x+4));
Message(indent_str+" pUnwindMap: %08.8Xh\n", Dword(x+8));
#endif
n = Dword(x+4);
i = 0; a = Dword(x+8);
while (i<n)
{
#ifdef DEBUG
Message(indent_str+" toState: %d\n", Dword(a));
Message(indent_str+" action: %08.8Xh\n", Dword(a+4));
#endif
DwordCmt(a, "toState");
OffCmt(a+4, "action");
a = a+8;
i = i+1;
}
#ifdef DEBUG
Message(indent_str+" nTryBlocks: %d\n", Dword(x+12));
Message(indent_str+" pTryBlockMap: %08.8Xh\n", Dword(x+16));
#endif
n = Dword(x+12);
i = 0; a = Dword(x+16);
while (i<n)
{
Parse_TryBlock(a, indent+1);
a = a+20;
i = i+1;
}
#ifdef DEBUG
Message(indent_str+" nIPMapEntries: %d\n", Dword(x+20));
Message(indent_str+" pIPtoStateMap: %08.8Xh\n", Dword(x+24));
#endif
DwordCmt(x, "magicNumber");
DwordCmt(x+4, "maxState");
OffCmt(x+8, "pUnwindMap");
//Parse_UnwindMap(Dword(x+8), indent+1);
DwordCmt(x+12, "nTryBlocks");
OffCmt(x+16, "pTryBlockMap");
DwordCmt(x+20, "nIPMapEntries");
OffCmt(x+24, "pIPtoStateMap");
if ((Dword(x+8)-x)>=32 || Dword(x)>0x19930520)
{
#ifdef DEBUG
Message(indent_str+" pESTypeList: %08.8Xh\n", Dword(x+28));
#endif
OffCmt(x+28, "pESTypeList");
}
if ((Dword(x+8)-x)>=36 || Dword(x)>0x19930521)
{
#ifdef DEBUG
Message(indent_str+" EHFlags: %08.8Xh\n", Dword(x+32));
#endif
OffCmt(x+32, "EHFlags");
}
return s;
}
//get class name for this vtable instance
static GetVtableClass(x)
{
auto offset, n, i, s, a, p;
offset = Dword(x+4);
x = Dword(x+16); //Class Hierarchy Descriptor
a=Dword(x+12); //pBaseClassArray
n=Dword(x+8); //numBaseClasses
i = 0;
s = "";
while(i<n)
{
p = Dword(a);
//Message(indent_str+" BaseClass[%02d]: %08.8Xh\n", i, p);
if (Dword(p+8)==offset)
{
//found it
s = GetAsciizStr(Dword(p)+8);
return s;
}
i=i+1;
a=a+4;
}
//didn't find matching one, let's get the first vbase
i=0;
a=Dword(x+12);
while(i<n)
{
p = Dword(a);
if (Dword(p+12)!=-1)
{
s = GetAsciizStr(Dword(p)+8);
return s;
}
i=i+1;
a=a+4;
}
return s;
}
static Parse_Vtable(a)
{
auto i,s,s2;
s=GetTypeName(a);
if (substr(s,0,3)==".?A")
{
#ifdef DEBUG
Message("RTTICompleteObjectLocator: %08.8Xh\n", Dword(a-4));
#endif
Parse_COL(Dword(a-4),0);
Unknown(a-4,4);
SoftOff(a-4);
i = Dword(a-4); //COL
s2 = Dword(i+4); //offset
i = Dword(i+16); //CHD
i = Dword(i+4); //Attributes
if ((i&3)==0 && s2==0)
{ //Single inheritance, so we don't need to worry about duplicate names (several vtables)
s=substr(s,4,-1);
MakeName(a,"??_7"+s+"6B@");
MakeName(Dword(a-4),"??_R4"+s+"6B@");
}
else// if ((i&3)==1)
{
//Message("Multiple inheritance\n");
s2 = GetVtableClass(Dword(a-4));
s2 = substr(s2,4,-1);
s = substr(s,4,-1);
s = s+"6B"+s2+"@";
MakeName(a,"??_7"+s);
MakeName(Dword(a-4),"??_R4"+s);
}
}
}
static ParseVtbl()
{
Parse_Vtable(ScreenEA());
}
static ParseExc()
{
Parse_ThrowInfo(ScreenEA(), 0);
}
static ParseFI()
{
Parse_FuncInfo(ScreenEA(), 0);
}
static AddHotkeys()
{
AddHotkey("Alt-F7","ParseFI");
AddHotkey("Alt-F8","ParseVtbl");
AddHotkey("Alt-F9","ParseExc");
Message("Use Alt-F7 to parse FuncInfo\n");
Message("Use Alt-F8 to parse vtable\n");
Message("Use Alt-F9 to parse throw info\n");
}
#ifndef __INCLUDED
static main(void)
{
AddHotkeys();
}
#endif