gpt4 book ai didi

c++ - 从 Objdump 实用程序检索 vptr(指向虚拟表又名 VTABLE 的指针)?

转载 作者:行者123 更新时间:2023-11-28 00:57:00 25 4
gpt4 key购买 nike

我们如何使用 objdump 实用程序和反汇编代码知道 VTABLEs(即相应的 vptr)的地址。vptr 通常存储在对象的第一个字节中。(更正/编辑此)。有一个使用虚函数的简单代码:

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;
}

以下是代码的输出:

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

以下是主要功能的一部分-代码的反汇编:

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>

这里显示_ZN4baseC1Ev是基础对象的地址,_ZN3derC1Ev是派生对象的地址。

在 _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>:
}

};

这是 objdump 输出的链接-S exe文件

还有 objdump -t virtualfunctionsize | grep vtable 给出了这个:

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

我想知道- 它是什么 VTABLE 地址和它表示的相应虚函数。

  • Vptr 的地址 = 0x7fff86a78fe0,这代表什么 - VTABLE 位置?

  • Vptr 的值 = 0x400c30 - 这代表什么 - 基类的第一个虚函数?

  • 如何找到派生类的虚函数的后续地址?

Rgds,柔软的

最佳答案

Gcc 遵循这个 C++ ABI:http://refspecs.linuxbase.org/cxxabi-1.83.html#vtable

要查看gcc生成的vtable,可以用“gcc -S”编译生成汇编源码,然后通过c++filt过滤

可以看到生成了如下虚表:

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

您可以看到前两个 8 字节的值是零(这是到顶部的偏移量,派生类在基类中的偏移量),并且是指向类型信息的指针。然后真正的 vtable(指向虚函数的指针)开始。这就是您在调试输出中看到的 vptr 值。这解释了 +0x10 偏移量。

关于c++ - 从 Objdump 实用程序检索 vptr(指向虚拟表又名 VTABLE 的指针)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10549311/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com