Virtual database offset in the virtual function table for virtual inheritance

The codes are as follows (C ++ 11 codes compiled with g ++ - 5.4 on Ubuntu 16.04):

#include <iostream> using namespace std; class Base { public: virtual void show() { cout << "Base" << endl; } virtual void func() { cout << "func in Base" << endl; } protected: int base = 15; }; class A: public virtual Base { public: void show() override { cout << this << endl; cout << 'A' << endl; } void func() override { cout << this << endl; cout << "func in A" << endl; } protected: int a = 31; }; int main(int argc, const char *argv[]) { A obj_a; return 0; } 

I am trying to use GDB to check the memory layout of the object "obj_a" (firstly, I set "set print object on", "set print pretty on", "set print vtbl on", "set print asm-demangle on" "in Gdb):

 (gdb) p sizeof(obj_a) $1 = 32 (gdb) x/8aw &obj_a 0x7fffffffe320: 0x400d20 <vtable for A+24> 0x0 0x1f 0x0 0x7fffffffe330: 0x400d50 <vtable for A+72> 0x0 0xf 0x0 

We can know that the offset between the beginning of obj_a and its subobject is 16B (virtual base offset). And then I check the virtual function table specified by 0x400d08 (0x400d20 - 24):

 (gdb) x/14ag 0x400d08 0x400d08 <vtable for A>: 0x10 0x0 0x400d18 <vtable for A+16>: 0x400d90 <typeinfo for A> 0x400b46 <A::show()> 0x400d28 <vtable for A+32>: 0x400b98 <A::func()> 0xfffffffffffffff0 0x400d38 <vtable for A+48>: 0xfffffffffffffff0 0xfffffffffffffff0 0x400d48 <vtable for A+64>: 0x400d90 <typeinfo for A> 0x400b8f <virtual thunk to A::show()> 0x400d58 <vtable for A+80>: 0x400be1 <virtual thunk to A::func()> 0x400d20 <vtable for A+24> 0x400d68 <VTT for A+8>: 0x400d50 <vtable for A+72> 0x0 

As we can see, there are two β€œvirtual thunk to xxx”, namely β€œ0x400b8f” and β€œ0x400be1”. I refer to these two addresses.

 (gdb) x/3i 0x400b8f 0x400b8f <virtual thunk to A::show()>: mov (%rdi),%r10 0x400b92 <virtual thunk to A::show()+3>: add -0x18(%r10),%rdi 0x400b96 <virtual thunk to A::show()+7>: jmp 0x400b46 <A::show()> (gdb) x/3i 0x400be1 0x400be1 <virtual thunk to A::func()>: mov (%rdi),%r10 0x400be4 <virtual thunk to A::func()+3>: add -0x20(%r10),%rdi 0x400be8 <virtual thunk to A::func()+7>: jmp 0x400b98 <A::func()> 

My questions are: what does "add -0x18 (% r10),% rdi" and "add -0x20 (% r10),% rdi" really mean? why is -24 (-0x18) and -32 (-0x20)? (I think they should all be -16)

+5
source share
1 answer

Thank you, Rerito, sorry.

My problem is that I am not familiar with the build code.

 (gdb) x/3i 0x400b8f 0x400b8f <virtual thunk to A::show()>: mov (%rdi),%r10 0x400b92 <virtual thunk to A::show()+3>: add -0x18(%r10),%rdi 0x400b96 <virtual thunk to A::show()+7>: jmp 0x400b46 <A::show()> 

In the build code for "virtual thunk to A :: show ()"% rdi stores the value "this". "mov (% rdi),% r10" means moving the value "vptr" (its address is "this") to the r10 register. "add -0x18 (% r10),% rdi" means that adding a value whose address is "vptr-24" (ie 0xffffffffffffffff0 in the virtual table) is equal to "this". Thus, the value of "this" can be corrected as the address of object A.

+1
source

Source: https://habr.com/ru/post/1259815/


All Articles