2

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
2
  • OK - I've found the answer thanks to a comment inside ehdata_forceinclude.h. It's useful when multiple inheritance is used.
    – rec
    Apr 23, 2020 at 16:13
  • please add an answer so other people with the same question also know what it is
    – Igor Skochinsky
    Apr 23, 2020 at 22:05

1 Answer 1

2

It seems that inheritance does it. If we do something like:

#include <stdio.h>
struct B {
    int a, b;
};

struct B1 {
    B1() = default;
    B1(const B1& tmp) {
        a1 = tmp.a1;
        printf("B1::B1 copy constr\n");
    }
    int a1, b1;
};

struct A : B, B1 {
    int b, c;
};

int main() try {

    struct A tmp;

    tmp.a1 = 9;

    throw tmp;
}
catch (B1 tmp) {
    printf("%d\n", tmp.a1);
}

We got RTTI for the throw of struct A containing an entry of struct B1 with the following info:

.rdata:00419D8C __CT??_R0?AUB1@@@8_401150 dd 0          ; DATA XREF: .rdata:00419D50↑o
.rdata:00419D8C                                         ; attributes
.rdata:00419D90                 dd offset ??_R0?AUB1@@@8 ; B1 `RTTI Type Descriptor'
.rdata:00419D94                 dd 8                    ; mdisp
.rdata:00419D98                 dd -1                   ; pdisp
.rdata:00419D9C                 dd 0                    ; vdisp
.rdata:00419DA0                 dd 8                    ; size of thrown object
.rdata:00419DA4                 dd offset sub_401150    ; reference to optional copy constructo

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.