First of here is the article from which I'm looking up the fields.
I was trying out different combinations to see how they affect the RTTI for a C++ throw. It seems that having a virtual base class changes the two fields below mdisp
but I wasn't able to change the actual mdisp
field here is what I've tried:
struct B {
int a, b;
};
struct A : virtual B {
int b, c;
};
int main() {
struct A* tmp = 0;
throw tmp;
}
The above will change the catchabletypes of struct A *
and struct B *
to have different values for pdisp
and vdisp
because of the virtual base class.
I've also tried pointer to members but with the no luck of changing the field as well:
struct A::* tmp = &A::c;
I assumed that the above will cause the field for the type to change because there is an offset for the fields of A relative to B. I also tried removing the virtual specifier for the inheritance in this particular case.
Here is what the dissasembly looks like:
push offset __TI3PAUA@@ ; throw info for 'struct A *'
lea ecx, [ebp+var_8]
push ecx
call sub_401BB4
.rdata:004130C0 __TI3PAUA@@ dd 0 ; DATA XREF: _main+13↑o
.rdata:004130C0 ; attributes
.rdata:004130C4 dd 0 ; destructor of exception object
.rdata:004130C8 dd 0 ; forward compatibility frame handler
.rdata:004130CC dd offset __CTA3PAUA@@ ; address of catchable types array
.rdata:004130D0 __CTA3PAUA@@ dd 3 ; DATA XREF: .rdata:004130CC↑o
.rdata:004130D0 ; count of catchable type addresses following
.rdata:004130D4 dd offset __CT??_R0PAUA@@@8 ; catchable type 'struct A *'
.rdata:004130D8 dd offset __CT??_R0PAUB@@@8 ; catchable type 'struct B *'
.rdata:004130DC dd offset __CT??_R0PAX@8 ; catchable type 'void *'
.rdata:004130E0 __CT??_R0PAUA@@@8 dd CT_IsSimpleType or CT_HasVirtualBase
.rdata:004130E0 ; DATA XREF: .rdata:004130D4↑o
.rdata:004130E0 ; attributes
.rdata:004130E4 dd offset ??_R0PAUA@@@8 ; A * `RTTI Type Descriptor'
.rdata:004130E8 dd 0 ; mdisp
.rdata:004130EC dd -1 ; pdisp
.rdata:004130F0 dd 0 ; vdisp
.rdata:004130F4 dd 4 ; size of thrown object
.rdata:004130F8 dd 0 ; reference to optional copy constructor
.rdata:004130FC __CT??_R0PAUB@@@8 dd CT_IsSimpleType ; DATA XREF: .rdata:004130D8↑o
.rdata:004130FC ; attributes
.rdata:00413100 dd offset ??_R0PAUB@@@8 ; B * `RTTI Type Descriptor'
.rdata:00413104 dd 0 ; mdisp
.rdata:00413108 dd 0 ; pdisp
.rdata:0041310C dd 4 ; vdisp
.rdata:00413110 dd 4 ; size of thrown object
.rdata:00413114 dd 0 ; reference to optional copy constructor
.rdata:00413118 __CT??_R0PAX@8 dd CT_IsSimpleType ; DATA XREF: .rdata:004130DC↑o
.rdata:00413118 ; attributes
.rdata:0041311C dd offset ??_R0PAX@8 ; void * `RTTI Type Descriptor'
.rdata:00413120 dd 0 ; mdisp
.rdata:00413124 dd -1 ; pdisp
.rdata:00413128 dd 0 ; vdisp
.rdata:0041312C dd 4 ; size of thrown object
.rdata:00413130 dd 0 ; reference to optional copy constructor
ehdata_forceinclude.h
. It's useful when multiple inheritance is used.