为什么在64位而非32位平台上绝对需要fPIC?

时间:2011-08-27 17:45:43

标签: gcc shared-libraries 32bit-64bit dynamic-linking fpic

我最近收到了:

  在制作共享对象时,不能使用

...对“本地符号”重定位R_X86_64_32;用-fPIC重新编译

尝试将程序编译为共享库时出现

错误。

现在对此的解决方案并不太困难(使用-fPIC重新编译所有依赖项),但经过一些研究后发现此问题仅出现在x86-64平台上。在32位上,任何依赖于位置的代码仍可由动态加载程序重新定位。

我能找到的最好的answer是:

  

x86支持.text重定位(当你拥有它时会发生这种情况   位置依赖代码)。这种支持是有代价的,即每一个   包含此类重定位的页面基本上不共享,即使它也是如此   坐在一个共享的库中,从而破坏了共享的概念   库。因此我们决定在amd64上禁止这个(加上它创造了   如果值需要超过32位的问题,因为所有.text只重定位   大小'word32')

但我觉得这不够。如果重定位破坏了共享库的概念,为什么可以在32位平台上完成?另外,如果需要对ELF格式进行更改以支持64位,那么为什么并非所有字段的大小都增加以适应?

这可能是一个小问题,但它的动机是这样一个事实:a)所讨论的代码是一个科学的代码,如果不打击性能就好了,b)这个信息是不可能的找到第一个地方!

[编辑:'答案'

@awoodlands answer可能是最好的“字面答案”,@ added一些很好的信息。

在搜索中找到有关不同类型重定位的详情,我发现了this,最终发现了x86_64 ABI reference(参见第68页) ]

3 个答案:

答案 0 :(得分:11)

据我所知,问题是x86-64似乎引入了一种新的,更快的方式来引用相对于指令指针的数据,这对x86-32来说并不存在。

This article对其进行了深入的分析,并提供了以下执行摘要:

  

x86-64使用指令指针相对偏移的能力   数据地址是一个很好的优化,但在共享库中   关于数据相对位置的情况假设无效   并且不能使用。在这种情况下,访问全球数据(即   任何可能在你周围改变的东西)必须通过一层   抽象,即全局抵消表。

即。 -fPIC寻址为寻址添加了额外的抽象层,使通常寻址方式中的先前可能(以及期望的特征)仍然适用于较新的架构。

答案 1 :(得分:7)

  

但我觉得这不够。如果重定位破坏了共享库的概念,为什么可以在32位平台上完成呢?

可以做到,它不是特别有效...计算重定位具有运行时成本,重定位的可执行文件需要额外的内存,并且该机制在可执行加载器中引入了很多复杂性。此外,Linux发行版真的希望鼓励所有代码都使用-fPIC进行编译,因为更改可执行文件的基地址是一种缓解策略,这使得编写漏洞安全漏洞更加困难。

值得一提的是,-fPIC通常不会产生显着的性能成本,特别是如果您使用-fvisibility = hidden或等效。

  

为什么并非所有字段的大小都增加以容纳?

有问题的“字段”是x86-64寻址模式的直接字段,不受ELF开发人员的控制。

答案 2 :(得分:0)

您可以使用-mcmodel = large选项在x86_64上不使用-fpic构建共享库

参考:http://eli.thegreenplace.net/2012/01/03/understanding-the-x64-code-models/