首页 文章

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

提问于
浏览
25

我最近收到了:

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

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

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

我能找到的最好的answer是:

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

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

这可能是一个小问题,但它的动机是这样一个事实:a)所讨论的代码是一个科学的代码,如果不必受到性能影响就很好b)这个信息很难在第一名!

[编辑:'答案'

@awoodlands answer可能是最好的'literal answer',@ regn added一些不错的信息 .

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

3 回答

  • 11

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

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

    x86-64使用指令指针相对偏移到数据地址的能力是一个很好的优化,但在共享库情况下,关于数据相对位置的假设是无效的,不能使用 . 在这种情况下,访问全局数据(即可能在您周围更改的任何内容)必须经过一个抽象层,即全局偏移表 .

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

  • 0

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

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

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

    为什么不是所有的场地都增加了以容纳?

    所讨论的“字段”是x86-64寻址模式的直接领域,它不受ELF开发人员的控制 .

  • 7

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

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

相关问题