ARMCC/C++ 空 Vtable 条目

逆向工程 反编译 C++ 手臂 虚函数
2021-06-18 12:16:50

我正在反转使用 ARMCC 编译的 3ds 应用程序。

我找到了关键类的 vtables 并且在弄清楚这些的 C++ 表示如何时遇到了问题。

第一个基类的vtable:

fBase::dtor
0                     // no dtorFree
fBase::function1
fBase::function2
...
fBase::function13

第二个基类的Vtable:

sBase::dtor
0                     // no dtorFree
sBase::function1
fBase::function2
...
sBase::function13

现在有问题的一个:

Actor类的Vtable:

Actor::dtor
0                     // no dtorFree
sBase::function1
fBase::function2
... (3-12)
sBase::function13
0                     // gap in vtable?
Actor::function14
Actor::function15
... (16-19)
Actor::function20
0                     // gap in vtable?
Actor::function21
Actor::function22
... (23-34)
Actor::function35

一开始我假设这些是纯虚函数(Actor::function20-1()=0;)但是虚表中的这些“差距”没有被任何顶级类“覆盖”,因此这些差距也最终出现在他们的虚拟表。

是什么导致这些空的 vtable 条目以及 C++ 表示是什么样的?

2个回答

想到了两种可能性:

  1. 这些是纯虚方法的插槽。在许多实现中,编译器提供类似__purecall__cxa_pure_virtual捕获意外调用的功能,但由于它们无论如何都不应该发生,因此 NULL 在资源受限的平台上也能正常工作。

  2. Itanium C++ ABI 在函数表本身之前保留了两个插槽,用于偏移到 toptypeinfo 指针

在大多数类中,到顶部的偏移量是 0,如果不使用 RTTI,typeinfo 指针也可以为零,所以通常你会在 vtables 之间看到两个零,所以我强烈怀疑你有这种情况#1。

至于为什么它们没有被覆盖,可能是源代码中的一个错误。只要它们实际上没有被称为 AFAIK,从 C++ 的角度来看,它们都是 kosher 的。

稍稍倒车后:

它不能是 __cxa_pure_virtual。我在我的二进制文件中找到了它的实现。

看起来编译器只是做了一些非常糟糕的优化:虚函数槽从未被调用,因此相应的函数被优化掉了,但它实际上并没有移动槽索引。有趣的。