2

I see that the virtual method table (VMT, a.k.a. VFT) contains some odd values, e.g.:

obj:0x123c1a8 [704] vmt:0x611f77f8
data: 0123c1a8 f8 77 1f 61 00 96 23 01 00 00 00 00 c4 e0 b4 5c 00 00 00 00 00 00 00 00 00 00 00 00 30 f2 76 5e 78 a2 23 01 78 e0 b4 5c 00 00 00 00 14 b1 75 5e 00 00 00 00 f8 7c 1f 61 f0 a2 23 01 00 00 00 00 `w`a``#````````\````````````0`v^x`#`x``\``````u^`````|`a``#`````
vmt:  611f77f8 09 63 98 60 25 63 98 60 95 67 98 60 e5 67 98 60 9d 68 98 60 e1 2f 9f 5c 51 07 9f 5c 45 07 9f 5c 49 07 9f 5c 4d 07 9f 5c 99 a3 69 5e a1 a3 69 5e 31 dd 68 5e a1 dd 68 5e d1 dd 68 5e c1 dd 68 5e `c``%c```g```g```h```/`\Q``\E``\I``\M``\``i^``i^1`h^``h^``h^``h^

(You see these odd 0x60986309 and 60986325 in the beginning of the virtual function table.)

What is stored in the virtual function table?

The compiler is GCC, more precisely, G++ (GNU C++) for ARM from the Android NDK.

EDIT: I see that the VMT contains entries that are not pointers to functions.

Here's the disassembled code for the Qt class QSystemLocale, you see pairs of lines, these are the IDA output lines followed by the same lines processed by c++filt:

 _ZTV13QSystemLocale      DCD 0, _ZTI13QSystemLocale, _ZN13QSystemLocaleD2Ev+1, _ZN13QSystemLocaleD0Ev+1
 vtable for QSystemLocale DCD 0, typeinfo for QSystemLocale, QSystemLocale::~QSystemLocale()+1, QSystemLocale::~QSystemLocale()+1

             DCD _ZNK13QSystemLocale5queryENS_9QueryTypeE8QVariant+1
             DCD QSystemLocale::query(QSystemLocale::QueryType, QVariant) const+1

             DCD _ZNK13QSystemLocale14fallbackLocaleEv+1
             DCD QSystemLocale::fallbackLocale() const+1

Here we see that:

  1. there is a suspicious 0 in the very beginning of VMT. It is reasonable to suggest that sometimes it may be not 0, as it happened in the dump above, but what is it then? See here.

  2. there is typeinfo. What does it allow to do? See here.

  3. there are two destructors, _ZN13QSystemLocaleD2Ev and _ZN13QSystemLocaleD0Ev. See why.

    and, finally:

  4. can I be sure that VMT is not initialized/modified at run-time? If it is written to, what gets written?

The typeinfo is:

             EXPORT _ZTI13QSystemLocale
             EXPORT typeinfo for QSystemLocale

 _ZTI13QSystemLocale DCD _ZTVN10__cxxabiv117__class_type_infoE+8, _ZTS13QSystemLocale
 typeinfo for QSystemLocale DCD vtable for __cxxabiv1::__class_type_info+8, typeinfo name for QSystemLocale

2 Answers 2

2

Why do you think these values are "odd"? Odd in the sense of "strange", or "not divisible by 2"?

The values in the vmt are pointers to the functions (or methods, thus vmt vs. vft) of the class object. These seem quite ok, because the vmt's address 0x611f77f8 is slightly above the methods 60986309, 60986325. As the compiler compiles all class methods first, then creates the vmt, a vmt at a memory address a bit higher than the methods seems quite normal.

Now, instructions on an ARM are 4-byte-aligned, and in THUMB mode, they're 2-byte-aligned, but the addresses your function pointers point to aren't. This is because, when executing an indirect branch, the ARM processor uses the lowest bit to switch between THUMB and ARM mode. So, an address of 0x60986309 actually means "switch the processor to THUMB mode, then begin executing at 0x60986308. When calling one of the vmt functions, the compiler generates an instruction to put the vmt reference into a register, then does a BLX on that register, so the lowest bit will have its meaning to switch the instruction type.

From this ARM reference:

Rm is a register containing an address to branch to.
....
The BX and BLX instructions can change the processor state from ARM to Thumb, or from Thumb to ARM.
BLX label always changes the state.
BX Rm and BLX Rm derive the target state from bit[0] of Rm:
    if bit[0] of Rm is 0, the processor changes to, or remains in, ARM state
    if bit[0] of Rm is 1, the processor changes to, or remains in, Thumb state.
1
  • I edited the question and mentioned things like VMT items that are not pointers to functions. May 13, 2014 at 7:31
1

As to the 0 in the beginning of VFT, it must be the offset to top as described in http://mentorembedded.github.io/cxx-abi/abi.html#vtable-components . The value is used when a class is derived from several base classes.

This 0 is vmt[-2] when you obtain the vmt address at run-time, but in the IDA disassembly it is the very first element of vtable.

; DerivedStuff::DerivedStuff(int, int)
            EXPORT _ZN12DerivedStuffC2Eii
_ZN12DerivedStuffC2Eii
            PUSH            {R4,LR}
            MOV             R4, R0
            BL              _ZN9BaseStuffC2Eii ; BaseStuff::BaseStuff(int,int)
            LDR             R3, =(_ZTV12DerivedStuff_ptr - 0x1AF4)
            MOV             R0, R4
            ADD             R3, PC ; _ZTV12DerivedStuff_ptr
            LDR             R3, [R3] ; `vtable for'DerivedStuff
            ADDS            R3, #8 ; <===== this is where 8 is added to the vmt address!!!
            STR             R3, [R4]
            POP             {R4,PC}
; End of function DerivedStuff::DerivedStuff(int,int)

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.