位置无关代码的差异:x86 与 x86-64

发布于 2024-09-07 05:13:49 字数 386 浏览 10 评论 0原文

我最近正在构建一个针对 x86-64 架构的特定共享库 (ELF),如下所示:

g++ -o binary.so -shared --no-undefined ... -lfoo -lbar

失败并出现以下错误:

创建共享库时,不能使用针对“本地符号”的重定位 R_X86_64_32;使用-fPIC重新编译

当然,这意味着我需要将其重建为与位置无关的代码,因此它适合链接到共享库。

但这在具有完全相同的构建参数的 x86 上运行得非常好。所以问题是,x86 上的重定位与 x86-64 上的重定位有何不同?为什么我不需要在前者上使用 -fPIC 进行编译?

I was recently building a certain shared library (ELF) targeting x86-64 architecture, like this:

g++ -o binary.so -shared --no-undefined ... -lfoo -lbar

This failed with the following error:

relocation R_X86_64_32 against `a local symbol' can not be used when making a shared object; recompile with -fPIC

Of course, it means I need to rebuild it as position-independent code, so it's suitable for linking into a shared library.

But this works perfectly well on x86 with exactly the same build arguments. So the question is, how is relocation on x86 different from x86-64 and why don't I need to compile with -fPIC on the former?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

辞慾 2024-09-14 05:13:49

我找到了一个很好且详细的解释,归结为:

  1. x86 -64 使用 IP 相对偏移量来加载全局数据,x86-32 则不能,因此它取消引用全局偏移量。
  2. IP 相对偏移不适用于共享库,因为全局符号可以被覆盖,因此 x86-64 在不使用 PIC 构建时会崩溃。
  3. 如果使用 PIC 构建 x86-64,则 IP 相对偏移取消引用现在会生成指向 GOT 条目的指针,然后将其取消引用。
  4. 然而,x86-32已经使用了全局偏移量的取消引用,因此它直接变成了 GOT 条目。

I have found a nice and detailed explanation, which boils down to:

  1. x86-64 uses IP-relative offset to load global data, x86-32 cannot, so it dereferences a global offset.
  2. IP-relative offset does not work for shared libraries, because global symbols can be overridden, so x86-64 breaks down when not built with PIC.
  3. If x86-64 built with PIC, the IP-relative offset dereference now yields a pointer to GOT entry, which is then dereferenced.
  4. x86-32, however, already uses a dereference of a global offset, so it is turned into GOT entry directly.
痴梦一场 2024-09-14 05:13:49

这是一个代码模型的问题。默认情况下,构建静态代码时假设整个程序将保留在内存地址空间的较低 2G 部分。共享库的代码需要针对另一个内存模型(PIC)进行编译,或者使用 -mcmodel=large 进行编译,而无需进行该假设。

请注意,-mcmodel=large 在较旧的 gcc 版本中未实现(它在 4.4 中,不在 4.2 中,我不知道 4.3 中是否有)。

It is a code model issues. By default, static code is build assuming the whole program will stay in the lower 2G part of the memory address space. Code for shared libraries need to be compiled for another memory model, either PIC, or with -mcmodel=large which will compile without making that assumption.

Note that -mcmodel=large is not implemented in older gcc version (it is in 4.4, it isn't in 4.2, I don't know for 4.3).
.

时间海 2024-09-14 05:13:49

这纯粹是 ABI 人强加给我们的任意要求。 x86_64 上的动态链接器无法支持非 PIC 库,没有任何逻辑原因。然而,由于 x86_64 不像 x86 那样承受如此可怕的寄存器压力(并且具有更好的 PIC 功能),因此我不知道有什么重要原因不使用 PIC。

It's purely an arbitrary requirement the ABI people have imposed on us. There's no logical reason why the dynamic linker on x86_64 couldn't support non-PIC libraries. However, since x86_64 is not under such horrible register pressure as x86 (and has better features for PIC), I don't know of any significant reason not to use PIC.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文