【问题标题】:Does 32bit x86 code need to be specially PIC-compiled for shared library files?32 位 x86 代码是否需要针对共享库文件进行专门的 PIC 编译?
【发布时间】:2011-10-21 04:02:31
【问题描述】:

如果要将目标文件作为共享库 (.so) 加载,则将代码编译到目标文件需要与位置无关,因为共享目标文件加载到不同的虚拟基地址过程可能不同。

现在,当我尝试在 32 位 x86 计算机上加载未使用 -fpic GCC 选项编译和链接的 .so 文件时,我没有遇到错误,而在 64 位 x86 计算机上却失败了。

我发现的随机网站说我不需要在 32 位上使用 -fpic,因为没有 -fpic 编译的代码在以与位置无关的方式使用时也符合 X86 32 位 ABI 的巧合。但我仍然发现软件在 32 位版本中附带不同版本的库:一个用于 PIC,一个用于非 PIC。例如,英特尔编译器附带libirc.alibirc_pic.a,后者被编译为与位置无关的模式(如果想将.a 文件链接到.so 文件中)。

我想知道对于 32 位代码,使用 -fpic 和不使用它之间的确切区别是什么,以及为什么某些软件包(例如 intel 编译器)仍然附带不同版本的库?

【问题讨论】:

  • 您是否尝试过使用 TLS 对代码进行非-fpic 编译?或者加载几个内存范围重叠的非图片库?单独的静态库将静态链接到程序(libirc.a;没有图片更快一点)和静态链接到 .so 库(_pic.a 版本)。

标签: c linux shared-libraries elf pic


【解决方案1】:

非 PIC 代码在 x86(32 位)上运行并非“巧合”。这是 x86 的动态链接器支持使其工作所需的必要“textrels”。这会在内存消耗和启动时间方面付出非常高的代价,因为基本上整个代码段必须在加载时进行修补(因此变成不可共享的内存)。

动态链接器维护者声称,由于架构中的基本问题(立即地址位移不能大于 32 位),x86_64 上不支持非 PIC 共享库,但这个问题可以通过以下方式轻松解决只是总是在前 4gb 的虚拟地址空间中加载库。当然 PIC 代码在 x86_64 上非常便宜(PIC 不像在 32 位 x86 上那样是性能杀手),所以他们可能不支持它并防止傻瓜制作非 PIC 库是正确的......

【讨论】:

  • 谢谢,有道理。如果我在 x86 上编译 PIC 库,我怀疑它不再使用 textrels 了?那么为什么它仍然是性能杀手呢?
  • PIC 代码需要一个额外的寄存器来保存基地址。在 x86 上,您的寄存器已经太少了,因此多保留一个会使编译器更频繁地将寄存器溢出到内存中。
  • PIC 是 x86 上的性能杀手,因为加载 GOT 寄存器的成本很高。它需要一个函数调用并从堆栈中读取/保存返回地址。 x86_64 具有eip-relative 寻址,因此不需要 GOT 寄存器。
  • 还有俄罗斯雇员所说的。
  • @Alek:非 PIC 库仍然会消耗更多内存,而且它们会比 PIC 快,但不如静态链接快,因为函数调用将通过 PLT。对于性能非常重要的库(如libavcodeclibx264),我会避免生成.so 库,因此库总是以静态链接到主程序二进制文件结束。
【解决方案2】:

共享对象文件在不同进程中加载​​到的虚拟基地址可能不同

因为共享对象通常在其首选地址加载,它们可能看起来工作正常。但是fPIC 是所有共享代码的好主意。

我认为该库通常不会有两个版本的原因是许多发行版都使用 fPIC 作为所有代码的默认值。

【讨论】:

  • 共享对象通常链接到地址 0 的加载,并且它们绝对不会在那里加载。
  • @Employed Russian 所说的。此外,您可以prelink 库使它们具有首选基地址,但这是与正常链接分开的(和可选的)步骤。
  • @Employed 俄语:那是 linux 独有的吗?其他操作系统并没有傻到默认 100% 基地址冲突。
  • @Ben 这到底是什么操作系统?似乎不可能协调随机程序使用非重叠地址范围的库的所有作者。作者如何了解彼此的库?
  • @Johannes:关键字“通常”。与代码段大小相比,地址空间非常大,因此很少发生冲突。这基本上是一个生日问题,但是当你忽略 JIT 编译(可以动态选择一个未使用的地址)和操作系统供应商提供的库(可以小心打包不冲突)时,很少有程序加载超过六分之一-派对图书馆。
猜你喜欢
  • 1970-01-01
  • 2017-10-20
  • 1970-01-01
  • 2014-07-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-03
  • 1970-01-01
相关资源
最近更新 更多