c - 如何使用 MinGW-gcc 删除 DLL .reloc 部分?

标签 c gcc mingw portable-executable relocation

我正在用 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 上的唯一方法吗?
这些是我迄今为止的发现:

  1. 在 Visual Studio 的链接中,有一个选项/FIXED(它正是我想要的)
  2. this tuturial,但其中大部分似乎仅适用于 Linux 下的 gcc
  3. 我可以在不使用 -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/

相关文章:

c - 在 ShellExecute 函数中将 stderr 和 stdout 获取为字符串

c - 如何更改打印输出? (系统编程和C)

在两个大整数相乘期间捕获并计算溢出

python - 如何获取c头文件中定义的列表?

危险类型转换的 C 编译器警告

c++ - 在带有 mingw 的 Windows 上使用 openmp。找不到 -lpthread

C static main return value of 0 在使用 free(someUnrelatedPointer) 之后改变了吗?

c++ - GCC 中的表达式中间体(如果这就是它们的实际名称)

visual-studio - 如何构建支持 h264 的 FFmpeg

c - 当 x 是有符号字符时,为什么 mingw 对 printf ("%d",x) 发出警告?