打印GDB中任何类的vtbl函数
Print vtbl functions of any class in GDB
gdb的较新版本允许在C++中方便地解析vtables。
假设我有这个样本代码
class Matcher {
public:
virtual void match() { cout << "base";}
};
class NMatcher: public Matcher{
public:
void match() { cout << "derived";}
};
int main() {
Matcher* m = new Matcher();
m->match();
Matcher *m2 = new NMatcher();
m2->match();
}
我可以通过info vtbl ...
访问主变量的虚拟表
(gdb) info vtbl m
vtable for 'Matcher' @ 0x400ef0 (subobject @ 0x603010):
[0]: 0x400d9a <Matcher::match()>
现在想象一种情况,我的作用域中没有变量,我想检查任何虚拟对象(或任何纯虚拟基类)的vtable。为此,我并不严格需要一个对象。vtable是静态的,应该是可访问的。
让我们看看符号来定位vtable:
(gdb) info variables .*Matcher
All variables matching regular expression ".*Matcher":
Non-debugging symbols:
0x0000000000400ec0 vtable for NMatcher
0x0000000000400ee0 vtable for Matcher
0x0000000000400ef8 typeinfo name for NMatcher
0x0000000000400f10 typeinfo for NMatcher
0x0000000000400f28 typeinfo name for Matcher
0x0000000000400f40 typeinfo for Matcher
我不能直接使用上面列出的内存位置。虚拟方法不会从vtable的开头开始。对于前x个字节,存在偏移量和RTI。在匹配器的情况下,它是16,但它可以是任意数字:
(gdb) p *m
$22 = {
_vptr.Matcher = 0x400ef0 <vtable for Matcher+16>
}
理论上,我可以直接访问vtable的存储位置,并手动检查字节:
(gdb) x /4a 0x0000000000400ee0
0x400ee0 <_ZTV7Matcher>: 0x0 0x400f40 <_ZTI7Matcher>
0x400ef0 <_ZTV7Matcher+16>: 0x400d9a <Matcher::match()>
但这太痛苦了,我想知道一种类似(gdb) info vtbl 'vtable for Matcher'
的方便方法
我使用的是GDB7.8,但任何版本都可以。
GDB恐怕没有提供内置的方法来实现这一点。
你也许可以用黑客来近似它。黑客会这样工作:
-
获取vtable的基地址,如
print &'vtable for Type'
。 -
获取该类型的typeinfo的基地址,如
print &'typeinfo for Type'
。 -
逐字搜索vtable,查找指向typeinfo的指针。下一个单词是vtable指针应该指向的位置。
-
现在,制作一个虚拟对象,并将其作为vtable指针。
但是,如果您有一个子对象vtable,这是不起作用的。在这种情况下,你必须制作一个更正确的假物体。
总的来说,最好将这种支持添加到gdb中。它可以尝试在没有黑客攻击的情况下做正确的事情。
以下是上面程序的工作原理:
(gdb) p &'vtable for NMatcher'
$1 = (<data variable, no debug info> *) 0x400ab0 <vtable for NMatcher>
(gdb) p &'typeinfo for NMatcher'
$2 = (<data variable, no debug info> *) 0x400ae0 <typeinfo for NMatcher>
现在转储vtable,看看指针应该在哪里。这是这里的第二个词,因为没有虚拟基:
(gdb) x/10a $1
0x400ab0 <_ZTV8NMatcher>: 0x0 0x400ae0 <_ZTI8NMatcher>
0x400ac0 <_ZTV8NMatcher+16>: 0x4009b2 <NMatcher::match()> 0x0
0x400ad0 <_ZTV7Matcher+8>: 0x400b08 <_ZTI7Matcher> 0x400994 <Matcher::match()>
0x400ae0 <_ZTI8NMatcher>: 0x6011e0 <_ZTVN10__cxxabiv120__si_class_type_infoE@@CXXABI_1.3+16> 0x400af8 <_ZTS8NMatcher>
0x400af0 <_ZTI8NMatcher+16>: 0x400b08 <_ZTI7Matcher> 0x65686374614d4e38
所以,做一个假的物体。不幸的是,你需要较差的运行来做到这一点:-(
(gdb) set $v = malloc(sizeof(void*))
设置伪vtable指针。注意,我们在指向typeinfo对象的指针后面使用一个词:
(gdb) set *$v = ((void **) $1) + 2
现在它工作了:
(gdb) info vtbl (NMatcher*) $v
vtable for 'NMatcher' @ 0x400ac0 (subobject @ 0x613c20):
[0]: 0x4009b2 <NMatcher::match()>
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- VTBL 是否包含指向非虚函数的指针?
- 打印GDB中任何类的vtbl函数