2011-08-27 40 views
25

我最近收到了:创建共享目标时为什么fPIC绝对需要64位而不是32位平台?

...对`局部符号”搬迁R_X86_64_32不能使用;使用-fPIC重新编译

尝试将程序编译为共享库时发生错误。

现在解决这个问题并不困难(用-fPIC重新编译所有依赖关系),但经过一番研究后发现,这个问题只存在于x86-64平台上。在32位上,任何依赖于位置的代码仍然可以通过动态加载程序进行重定位。

最好answer我能找到的是:

86具有的.text迁移的支持(这是当你有 位置dependend代码会发生什么)。这种支持是有代价的,即每个包含这种重定位的页面都基本上是不共享的,即使它位于共享库中,从而破坏了共享库的概念。因此,我们决定禁止这种基于AMD64(加上它创建 问题如果该值比需要32位以上,因为所有的.text relocs只有 有大小“word32”)

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

这可能是一个小问题,但它的动机是这样的事实:a)有问题的代码是一个科学代码,它不会有必要采取性能打击和b)这个信息是不可能的首先找到!

[编辑: '答案'

@awoodlands answer可能是最好的 '的字面解释',@servn added一些有用的信息。

在搜索中找到更多有关不同类型的搬迁,我发现this,最终的x86_64 ABI reference(见68页) ]

+1

我不知道回答你的问题,但你应该知道了'在x86-64(相对于x86-32)中,-fPIC性能降低,因为它具有更多的寄存器,PC相对寻址以及考虑PIC设计的ABI。我不会说它已经消失了,但是测量一下,你可能会感到惊喜。 – zwol

+0

这似乎是共识,对于无可否认的极大便利的表现来说是一个小小的惩罚。我将不得不亲自尝试。 –

+0

主要问题当然是为什么编译器有一个“强制选项”。 “你没有说这个魔术字”是一个相当幼稚的游戏。 – MSalters

回答

10

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

This article有它一个很好的深入分析,并给出了下面的执行摘要:

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

I.e. -fPIC寻址为寻址增加了一个额外的抽象层,以使通常寻址风格中以前可能的(以及所希望的功能)仍然适用于较新的体系结构。

+0

这是一篇很棒的文章,谢谢! –

7

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

这是可以做到的,它只是是不是特别有效......计算迁移具有运行成本,重新定位的可执行文件需要额外的内存,并且该机制引入了大量的复杂性到可执行文件加载器。另外,Linux发行版确实希望鼓励所有代码使用-fPIC进行编译,因为更改可执行文件的基址是一种缓解策略,可以使攻击安全漏洞的攻击变得更加困难。

还值得一提的是-fPIC通常不是一个重要的性能成本,尤其是如果您使用-fvisibility = hidden或等效的话。

为什么不是所有的领域的大小都增加以适应?

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

+0

感谢您的回答,它确实增加了@awoodland提供的链接 - 尤其是承认它可以完成,但在某一点变得愚蠢。 澄清:fvisibility = hidden意味着所有未显式导出的函数不会通过PLT调用,因此间接级别被删除? –

+0

是的,fvisibility = hidden删除PLT间接。 – servn

相关问题