TransWikia.com

What is a non-virtual thunk?

Reverse Engineering Asked by 18446744073709551615 on March 3, 2021

In real code I have encountered some “non-virtual thunk” functions:

; `non-virtual thunk to'QTextCodecPlugin::create(QString  const&)
    EXPORT _ZThn8_N16QTextCodecPlugin6createERK7QString
_ZThn8_N16QTextCodecPlugin6createERK7QString
   SUB.W   R0, R0, #8
   B.W     _ZN16QTextCodecPlugin6createERK7QString; QTextCodecPlugin::create(QString  const&)

; End of function `non-virtual thunk to'QTextCodecPlugin::create(QString  const&)


; `non-virtual thunk to'QTextCodecPlugin::~QTextCodecPlugin()
    EXPORT _ZThn8_N16QTextCodecPluginD1Ev

_ZThn8_N16QTextCodecPluginD1Ev
    SUB.W  R0, R0, #8
    B.W    _ZN16QTextCodecPluginD2Ev; QTextCodecPlugin::~QTextCodecPlugin()

; End of function `non-virtual thunk to'QTextCodecPlugin::~QTextCodecPlugin()

(GCC, C++, Android NDK, Qt, Necessitas, ARM)

c++filt says:

$ c++filt _ZThn8_N16QTextCodecPlugin6createERK7QString
non-virtual thunk to QTextCodecPlugin::create(QString const&)
$ c++filt _ZThn8_N16QTextCodecPluginD1Ev
non-virtual thunk to QTextCodecPlugin::~QTextCodecPlugin()

What and why do these “non-virtual thunks” do?

2 Answers

These are object virtual table entries used to implement multiple inheritance.

The short story is, the sub instruction is to do with offsetting the correct derived class object size to the virtual table; but the following (long) article does a much better job of explaining than I could fit here : http://thomas-sanchez.net/computer-sciences/2011/08/15/what-every-c-programmer-should-know-the-hard-part/

UPDATE: the link above does not work anymore, but there's a copy of this page at webarchive.org: http://web.archive.org/web/20131210001207/http://thomas-sanchez.net/computer-sciences/2011/08/15/what-every-c-programmer-should-know-the-hard-part/

Answered by 6EQUJ5 on March 3, 2021

The answer should really state what the difference is between a virtual thunk and a non virtual thunk. They are identical in operation but just have a different name. The thunk for a virtually inherited base class is called a virtual thunk and the base object will be at the end of the object, whereas a thunk for a regularly inherited class whose object is not at the start of the object is called a non virtual thunk.

If you have C inherits from A and B, then A's virtual pointer will be at the start of the object (with C's vtable pointer for A pasted over it) and therefore doesn't require a pointer offset to the start when calling methods of type C* with an A*, and subobject B (with C's vtable pointer for B pasted over it) will be at an offset in the object. The virtual table for B will have to contain a non-virtual thunk that will offset to the pointer to the start of the object because the method that's being called virtually is one of C that accepts a pointer to a C object and if this virtual table is used then it will be receiving a polymorphically cast pointer to B, hence the need for the call in the table to be a thunk.

If you have D inherits from B and C, and B and C inherit virtually from A, then this means that B's virtual table pointer will be at the start of the object (with D's vtable for B pasted over it) and C's vtable pointer (with D's vtable pointer for C pasted over it) will be at an offset and requires a non virtual thunk when it is called which will be when the object pointer it is called on is cast to a C* type. A and its vtable pointer (with D's vtable for A pasted over it) will be at the end of the object and will instead require a virtual thunk in the vtable instead of the actual virtual method, and the virtual thunk calls the actual virtual method, and this gets called when the method is called on an object pointer cast to A*.

The virtual thunk offsets the object address by e.g. - 32 (wherever the virtual base object is) and the non virtual thunk offsets the object address by e.g. - 16 (wherever the 2nd subobject is). Basically, a virtual thunk offsets an object of type of a virtually inherited class to the start of the object when calling a method that is defined in the most derived class. The virtual thunk is for virtually inherited classes, which only have 1 special object within the object rather than multiple. If you didn't virtually inherit, there would be multiple of those objects within the object, and youd use a non virtual thunk to offset them when calling a method in the most derived class

Answered by Lewis Kelsey on March 3, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP