我正在用C手工构建vtables。从DLL导出时,它们会在其重定位表中生成大量条目。
示例$mdBottomSheet
输出:
z-index
有没有办法摆脱它们,还是它们是Windows的唯一途径? 以上是我的发现:
md-bottom-sheet{
z-index: 81;
}
中,有一个选项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
link
的情况下构建DLL,而是设置/FIXED
最后一个确实起作用(没有生成gcc
部分),但我认为这是一个极端丑陋的黑客,因为它实际上不再是DLL了。
澄清:
我觉得这个问题只是因为人们发现重新安置是一件好事而被低估了。 我承认,他们一般都很好,但我有一个非常具体的目标。我想展示如何在O(1)中实现与vtable的动态多态,如下所示:
-shared
由于“高级演员”仅涉及指针算术,因此这是O(1)(特别是,没有像Java那样进行线性搜索)。
现在回到重新定位:无论成本有多低,它恰好是O(n),因为每个类中的每个方法都需要更新。叹息。
TL;博士
GCC的微软--image-base
有挂件吗?如果没有,在PE中设置哪些标志以实现所需的行为?
答案 0 :(得分:2)
好的,我自己找到了答案:
必须在DLL上使用strip -R .reloc
,然后手动将IMAGE_FILE_RELOCS_STRIPPED
(0x0001)添加到PE头中的Characteristics
字段。那样做。
当然,这与自定义基地址(-Wl,--image-base=...
)一起使用 - 否则Windows无法加载DLL。
生成的模块也可能是防病毒软件的误报(因此可以立即移动到容器中)。
答案 1 :(得分:1)
你可以让运行时链接器完成它的工作并在你的代码加载时修复你的vtable,或者你可以在运行时填充vtable,如果编译器不能优化这样的代码并给你rdata vtable返回。无论哪种方式,你都在做同样的事情而你却无法摆脱它。
而不是带有函数指针的vtable,你可以明确地发送thunk并希望交换机不会用编译器生成的vtable实现。然后C_foo(&c, ...)
thunk调用将替换c->vtable->foo(...)
调用。
typedef enum { C_type, D_type } type_t;
typedef struct {
type_t type;
} C;
typedef struct {
type_t type;
} D;
// Replaces the vtable
void C_foo_impl(int);
void D_foo_impl(int);
void C_foo(C * self, int i) {
switch (self->type) {
case C_type: return C_foo_impl(i);
case D_type: return D_foo_impl(i);
default: return;
}
}
void C_init(C * self) {
self->type = C_type;
}
void D_init(D * self) {
C_init((C*)self);
self->type = D_type;
}
void test(void) {
C c;
C_init(&c);
D d;
D_init(&d);
C_foo(&c, 10); // calls c_foo_impl
C_foo((C*)&d, 10); // calls d_foo_impl
}