我正在用 C 手动构建 vtable。当从 DLL 导出时,它们会在其重定位表中生成大量条目。
示例 objdump 输出:
Virtual Address: 00002000 Chunk size 24 (0x18) Number of fixups 8
reloc 0 offset 0 [2000] HIGHLOW
reloc 1 offset 4 [2004] HIGHLOW
reloc 2 offset 8 [2008] HIGHLOW
reloc 3 offset c [200c] HIGHLOW
reloc 4 offset 10 [2010] HIGHLOW
reloc 5 offset 14 [2014] HIGHLOW
reloc 6 offset 18 [2018] HIGHLOW
reloc 7 offset 1c [201c] HIGHLOW
有什么方法可以摆脱它们,或者它们是 Windows 上的唯一方法吗?
这些是我迄今为止的发现:
- 在 Visual Studio 的
链接
中,有一个选项/FIXED
(它正是我想要的) - 有 this tuturial,但其中大部分似乎仅适用于 Linux 下的
gcc
- 我可以在不使用
-shared
的情况下构建 DLL,而是设置--image-base
最后一个确实有效(没有生成.reloc
部分),但我认为这是一个极其丑陋的黑客,因为这样它实际上就不再是DLL了。
澄清:
我的印象是这个问题被否决只是因为人们发现搬迁是一件好事。 我承认,总的来说,它们很好,但我有一个非常具体的目标。我想展示如何在 O(1) 内实现 vtable 的动态多态性,如下所示:
struct IDerived {
union {
IBaseA asBaseA;
struct {
int (*foo)(Derived this); // inherited from BaseA
...
};
};
union {
IBaseB asBaseB;
struct {
int (*bar)(Derived this); // inherited from BaseB
...
};
};
int (*baz)(Derived this);
...
};
struct Derived {
const IDerived *iface;
void *data;
};
extern void doSthWithBaseB(BaseB x);
void doSthWithDerived(Derived x) {
x.iface->foo(x);
doSthWithBaseB((BaseB){ &x.iface->asBaseB, x.data }) // high-level cast
}
由于“高级转换”仅涉及指针运算,因此时间复杂度为 O(1)(特别是,没有像 Java 那样进行线性搜索)。
现在回到重定位:无论成本有多低,它都恰好是 O(n),因为每个类中的每个方法都需要更新。叹息。
tl;博士
是否有针对 GCC 的 Microsoft /FIXED
的挂件?如果不是,要在 PE 中设置哪些标志才能实现所需的行为?
最佳答案
好吧,我自己找到了答案:
必须在 DLL 上使用 strip -R .reloc
,然后手动将 IMAGE_FILE_RELOCS_STRIPPED
(0x0001) 添加到PE header 。这样就可以了。
当然,这要与自定义基地址(-Wl,--image-base=...
)一起使用 - 否则 Windows 将无法加载 DLL。< br/>
生成的模块也可能被防病毒软件误报(因此会立即移至容器中)。
关于c - 如何使用 MinGW-gcc 删除 DLL .reloc 部分?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36988594/