我最近收到了:
在制作共享对象时,不能使用尝试将程序编译为共享库时出现...对“本地符号”重定位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页) ]
答案 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/