Retrieving vptr(pointer to virtual Table aka VTABLE)from the Objdump utility?
Asked Answered
L

2

0

How can we know the address of the VTABLEs (i.e corresponding vptr) using the objdump utility and dissembled code. vptr is generally stored in the first byte of object .(correct/edit this). There is this simple code using the virtual function :

class base
{
public:
    int x;
    virtual void func()
    {
        //test function

    }

};

class der : public base
{
   void func()
    {
        //test function

    }

};

/*
 * 
 */
int main() {
    int s = 9;
    base b;
    der d ;
    std::cout<<"the address of Vptr is = "<<(&b+0)<<std::endl;
    std::cout<<"the value at Vptr is = "<<(int*)*(int*)((&b+0))<<std::endl;

    return 0;
}

following is the output of the code :

the address of Vptr is = 0x7fff86a78fe0
the value at Vptr is = **0x400c30**

Following is the part of main function - diassembly of the code :

base b;
  4009b4:   48 8d 45 d0             lea    -0x30(%rbp),%rax
  4009b8:   48 89 c7                mov    %rax,%rdi
  4009bb:   e8 f4 00 00 00          callq  400ab4 <_ZN4baseC1Ev>
    der d ;
  4009c0:   48 8d 45 c0             lea    -0x40(%rbp),%rax
  4009c4:   48 89 c7                mov    %rax,%rdi
  4009c7:   e8 fe 00 00 00          callq  400aca <_ZN3derC1Ev>

It shows here that _ZN4baseC1Ev is the address of the base object and _ZN3derC1Ev is the address of the derived object.

in the _ZN4baseC1Ev

0000000000400ab4 <_ZN4baseC1Ev>:
  400ab4:   55                      push   %rbp
  400ab5:   48 89 e5                mov    %rsp,%rbp
  400ab8:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
  400abc:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  400ac0:   48 c7 00 30 0c 40 00    movq   $0x400c30,(%rax)
  400ac7:   c9                      leaveq 
  400ac8:   c3                      retq   
  400ac9:   90                      nop

    0000000000400aca <_ZN3derC1Ev>:
        }


#include<iostream>
class base
{
public:
    int x;
    virtual void func()
  400a8a:   55                      push   %rbp
  400a8b:   48 89 e5                mov    %rsp,%rbp
  400a8e:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
    {
        //test function

    }
  400a92:   c9                      leaveq 
  400a93:   c3                      retq   

0000000000400a94 <_ZN3der4funcEv>:

};

class der : public base
{
   void func()
  400a94:   55                      push   %rbp
  400a95:   48 89 e5                mov    %rsp,%rbp
  400a98:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
    {
        //test function

    }
  400a9c:   c9                      leaveq 
  400a9d:   c3                      retq   

0000000000400a9e <_ZN4baseC2Ev>:
 */

#include <stdlib.h>
#include<iostream>
class base
{
  400a9e:   55                      push   %rbp
  400a9f:   48 89 e5                mov    %rsp,%rbp
  400aa2:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
  400aa6:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  400aaa:   48 c7 00 50 0c 40 00    movq   $0x400c50,(%rax)
  400ab1:   c9                      leaveq 
  400ab2:   c3                      retq   
  400ab3:   90                      nop

0000000000400ab4 <_ZN4baseC1Ev>:
  400ab4:   55                      push   %rbp
  400ab5:   48 89 e5                mov    %rsp,%rbp
  400ab8:   48 89 7d f8             mov    %rdi,-0x8(%rbp)
  400abc:   48 8b 45 f8             mov    -0x8(%rbp),%rax
  400ac0:   48 c7 00 50 0c 40 00    movq   $0x400c50,(%rax)
  400ac7:   c9                      leaveq 
  400ac8:   c3                      retq   
  400ac9:   90                      nop

0000000000400aca <_ZN3derC1Ev>:
    }

};

Here is the link to output of objdump -S exe file

also objdump -t virtualfunctionsize | grep vtable gives this :

0000000000400c40  w    O .rodata    0000000000000018              vtable for base
0000000000601e00 g     O .dtors 0000000000000000              .hidden __DTOR_END__
0000000000400b00 g     F .text  0000000000000089              __libc_csu_init
0000000000400c20  w    O .rodata    0000000000000018              vtable for der

I wanted to know - what it is the VTABLE address and corresponding virtual function's denoted by it.

  • the address of Vptr is = 0x7fff86a78fe0 , what does this represent - VTABLE location?

  • the value at Vptr is = 0x400c30 - What does this represent - the first Virtual function of the base class?

  • How can the subsequent addresses of the virtual functions of the derived classes can be found?

Rgds, softy

Lepidus answered 11/5, 2012 at 10:3 Comment(6)
Have you considered looking for the symbols with vtable in their name?Thickknee
yes I did, which specific function you want me to look into.?Lepidus
@soty: not function, the symbols with vtable in their name are the vtablesThickknee
@Thickknee dump added.Sorry dint understand what you are trying to tell.!Lepidus
@soty: try objdump -Ct binary | grep vtable maybe that is helpfulThickknee
yes it was helpful, a small question here can we access the vptr using the this pointer?Lepidus
H
2

Gcc follows this C++ ABI: http://refspecs.linuxbase.org/cxxabi-1.83.html#vtable

To see vtable that gcc generates, you can compile it with "gcc -S" to produce assembly source, and then filter it through c++filt

You can see the following vtable generated:

    .type   vtable for base, @object
    .size   vtable for base, 24
vtable for base:
    .quad   0
    .quad   typeinfo for base
    .quad   base::func()

You can see that first two 8-byte values are zero (which is offset-to-top, offset of derived class within the base), and pointer to typeinfo. Then the real vtable (pointers to virtual functions) begins. And that is the vptr value you see in debug output. That explains the +0x10 offset.

Halinahalite answered 11/5, 2012 at 11:31 Comment(0)
S
1

_ZN4baseC1Ev is the base::base(), the base constructor, _ZN3derC1Ev is the derived constructor. You can use a tool like c++filt to demangle the names. They are not the addresses of the actual objects.

The address of the base object b is 0x7fff86a78fe0, which is on the stack, as expected. For this compiler this is the same as the address of the vptr, which is an pointer to an array of function pointers to virtual members.

If you dereference it, you get the address of a pointer to the first virtual function (0x400c30) in your base class.

EDIT: You need to dereference it one more time to obtain the address of base::func(). Use something like (int*)*(int*)*(int*)(&b)

Symons answered 11/5, 2012 at 10:25 Comment(1)
I must get the address of the virtual function that is func in this case correct?but func is having different address - 400a8a.Plz have a look at the question again.I have update it.Lepidus

© 2022 - 2024 — McMap. All rights reserved.