class A { int a1; public: virtual int A_virt1(); virtual int A_virt2(); static void A_static1(); void A_simple1(); }; class B { int b1; int b2; public: virtual int B_virt1(); virtual int B_virt2(); }; class C: public A, public B { int c1; public: virtual int A_virt2(); virtual int B_virt2(); };
class A size(8): +--- 0 | {vfptr} 4 | a1 +--- A's vftable: 0 | &A::A_virt1 4 | &A::A_virt2 class B size(12): +--- 0 | {vfptr} 4 | b1 8 | b2 +--- B's vftable: 0 | &B::B_virt1 4 | &B::B_virt2 class C size(24): +--- | +--- (base class A) 0 | | {vfptr} 4 | | a1 | +--- | +--- (base class B) 8 | | {vfptr} 12 | | b1 16 | | b2 | +--- 20 | c1 +--- C's vftable for A: 0 | &A::A_virt1 4 | &C::A_virt2 C's vftable for B: 0 | &B::B_virt1 4 | &C::B_virt2
A::A_static1(); call A::A_static1
;pC->A_simple1(1); ;esi = pC push 1 mov ecx, esi call A::A_simple1 ;pC->B_simple1(2,3); ;esi = pC lea edi, [esi+8] ;adjust this push 3 push 2 mov ecx, edi call B::B_simple1
;pC->A_virt2() ;esi = pC mov eax, [esi] ;fetch virtual table pointer mov ecx, esi call [eax+4] ;call second virtual method ;pC->B_virt1() ;edi = pC lea edi, [esi+8] ;adjust this pointer mov eax, [edi] ;fetch virtual table pointer mov ecx, edi call [eax] ;call first virtual method
struct RTTICompleteObjectLocator { DWORD signature; //always zero ? DWORD offset; //offset of this vtable in the complete class DWORD cdOffset; //constructor displacement offset struct TypeDescriptor* pTypeDescriptor; //TypeDescriptor of the complete class struct RTTIClassHierarchyDescriptor* pClassDescriptor; //describes inheritance hierarchy };
struct RTTIClassHierarchyDescriptor { DWORD signature; //always zero? DWORD attributes; //bit 0 set = multiple inheritance, bit 1 set = virtual inheritance DWORD numBaseClasses; //number of classes in pBaseClassArray struct RTTIBaseClassArray* pBaseClassArray; };
struct RTTIBaseClassDescriptor { struct TypeDescriptor* pTypeDescriptor; //type descriptor of the class DWORD numContainedBases; //number of nested classes following in the Base Class Array struct PMD where; //pointer-to-member displacement info DWORD attributes; //flags, usually 0 }; struct PMD { int mdisp; //member displacement int pdisp; //vbtable displacement int vdisp; //displacement inside vbtable };
//char* pThis; struct PMD pmd; pThis+=pmd.mdisp; if (pmd.pdisp!=-1) { char *vbtable = pThis+pmd.pdisp; pThis += *(int*)(vbtable+pmd.vdisp); }
_init_gA1: mov ecx, offset _gA1 call A::A() push offset _term_gA1 call _atexit pop ecx retn _term_gA1: mov ecx, offset _gA1 call A::~A() retn
unwind_1tobase: ; state 1 -> -1 lea ecx, [ebp+a1] jmp A::~A()
lea ecx, [ebp+a1] call A::A() mov [ebp+__$EHRec$.state], 1
unwind_0tobase: ; state 0 -> -1 mov eax, [ebp+pA1] push eax call operator delete(void *) pop ecx retn
;A* pA1 = new A(); push call operator new(uint) add esp, 4 mov [ebp+pA1], eax test eax, eax mov [ebp+__$EHRec$.state], 0; state 0: memory allocated but object is not yet constructed jz short @@new_failed mov ecx, eax call A::A() mov esi, eax jmp short @@constructed_ok @@new_failed: xor esi, esi @@constructed_ok: mov [esp+14h+__$EHRec$.state], -1 ;state -1: either object was constructed successfully or memory allocation failed ;in both cases further memory management is done by the programmer
unwind_2to1: mov ecx, [ebp+_this] ; state 2 -> 1 add ecx, 4Ch jmp B1::~B1
A* pA = new A[n]; delete [] pA;
array = new char(sizeof(A)*n+sizeof(int)) if (array) { *(int*)array=n; //store array size in the beginning 'eh vector constructor iterator'(array+sizeof(int),sizeof(A),count,&A::A,&A::~A); } pA = array; 'eh vector destructor iterator'(pA,sizeof(A),count,&A::~A);
;pA->'vector deleting destructor'(3); mov ecx, pA push 3 ; flags: 0x2=deleting an array, 0x1=free the memory call A::'vector deleting destructor'
mov ecx, pA push 3 mov eax, [ecx] ;fetch vtable pointer call [eax] ;call deleting destructor
virtual void * A::'scalar deleting destructor'(uint flags) { this->~A(); if (flags&1) A::operator delete(this); };
virtual void * A::'vector deleting destructor'(uint flags) { if (flags&2) //destructing a vector { array = ((int*)this)-1; //array size is stored just before the this pointer count = array[0]; 'eh vector destructor iterator'(this,sizeof(A),count,A::~A); if (flags&1) A::operator delete(array); } else { this->~A(); if (flags&1) A::operator delete(this); } };
mov eax, offset FuncInfo1 jmp _CxxFrameHandler
lea ecx, [ebp+e] call E::E() push offset ThrowInfo_E lea eax, [ebp+e] push eax call _CxxThrowException
CContentMenuItem::CContentMenuItem proc near this = esi push this push edi mov this, ecx call sub_4CA77A lea edi, [this+24h] mov ecx, edi call sub_4CBFDB or dword ptr [this+48h], 0FFFFFFFFh lea ecx, [this+4Ch] mov dword ptr [this], offset const CContentMenuItem::'vftable'{for 'CContentMenuItem'} mov dword ptr [edi], offset const CContentMenuItem::'vftable'{for 'CNativeEventSource'} call sub_4D8000 lea ecx, [this+50h] call sub_4D8000 lea ecx, [this+54h] call sub_4D8000 lea ecx, [this+58h] call sub_4D8000 lea ecx, [this+5Ch] call sub_4D8000 xor eax, eax mov [this+64h], eax mov [this+68h], eax mov [this+6Ch], eax pop edi mov dword ptr [this+60h], offset const CEventSinkList::'vftable' mov eax, this pop this retn sub_52B5E0 endp
class CContentMenuItem: public CDownloader, public CNativeEventSource { /* 00 CDownloader */ /* 24 CNativeEventSource */ /* 48 */ DWORD m_unknown48; /* 4C */ RefCountedPtr m_ptr4C; /* 50 */ RefCountedPtr m_ptr50; /* 54 */ RefCountedPtr m_ptr54; /* 58 */ RefCountedPtr m_ptr58; /* 5C */ RefCountedPtr m_ptr5C; /* 60 */ CEventSinkList m_EventSinkList; /* size = 70? */ };
public: __thiscall CContentMenuItem::CContentMenuItem(void) proc near push this push edi mov this, ecx call CDownloader::CDownloader(void) lea edi, [this+CContentMenuItem._CNativeEventSource] mov ecx, edi call CNativeEventSource::CNativeEventSource(void) or [this+CContentMenuItem.m_unknown48], -1 lea ecx, [this+CContentMenuItem.m_ptr4C] mov [this+CContentMenuItem._CDownloader._vfptr], offset const CContentMenuItem::'vftable'{for 'CContentMenuItem'} mov [edi+CNativeEventSource._vfptr], offset const CContentMenuItem::'vftable'{for 'CNativeEventSource'} call RefCountedPtr::RefCountedPtr(void) lea ecx, [this+CContentMenuItem.m_ptr50] call RefCountedPtr::RefCountedPtr(void) lea ecx, [this+CContentMenuItem.m_ptr54] call RefCountedPtr::RefCountedPtr(void) lea ecx, [this+CContentMenuItem.m_ptr58] call RefCountedPtr::RefCountedPtr(void) lea ecx, [this+CContentMenuItem.m_ptr5C] call RefCountedPtr::RefCountedPtr(void) xor eax, eax mov [this+CContentMenuItem.m_EventSinkList.field_4], eax mov [this+CContentMenuItem.m_EventSinkList.field_8], eax mov [this+CContentMenuItem.m_EventSinkList.field_C], eax pop edi mov [this+CContentMenuItem.m_EventSinkList._vfptr], offset const CEventSinkList::'vftable' mov eax, this pop this retn public: __thiscall CContentMenuItem::CContentMenuItem(void) endp
There are 31,320 total registered users.
[+] expand