如果要将目标文件作为共享库(.so
)加载,则编译代码到目标文件需要与位置无关,因为共享对象文件加载到的基本虚拟地址在不同的过程可能会有所不同。
现在,当我尝试加载在32位x86计算机上没有.so
GCC选项而编译和链接的-fpic
文件时,我没有遇到错误,而在64位x86计算机上失败。
我找到的随机网站说我在32位上不需要-fpic
,因为在没有-fpic
的情况下编译的代码在与位置无关的方式使用时也会根据X86 32位ABI重合。但我仍然发现软件在32位版本中附带了不同版本的库:一个用于PIC,另一个用于非PIC。例如,intel编译器附带libirc.a
和libirc_pic.a
,后者编译为与位置无关的模式(如果想要将.a
文件链接到.so
文件)。
我想知道使用-fpic
和不使用它的确切区别是32位代码,以及为什么某些软件包(如intel编译器)仍然附带了不同版本的库?
答案 0 :(得分:10)
不是非PIC代码在x86(32位)上“巧合”工作。这就是x86的动态链接器支持使其工作所需的必要“textrels”。这导致内存消耗和启动时间成本非常高,因为基本上整个代码段必须在加载时修补(因此变为不可共享的内存)。
动态链接维护者声称x86_64不支持非PIC共享库,因为架构中的基本问题(立即地址位移不能大于32位)但是这个问题可以通过只需在第一个4gb的虚拟地址空间中加载库。当然,PIC代码在x86_64上非常便宜(PIC不像32位x86那样具有性能杀手),所以它们可能是不正确的,以防止傻瓜制作非PIC库...... / p>
答案 1 :(得分:0)
共享对象文件在不同进程中加载的基本虚拟地址 可能 不同
由于共享对象通常以其首选地址加载,因此它们似乎可以正常工作。但fPIC
对所有共享代码都是一个好主意。
我认为通常没有两个版本的库的原因是许多发行版使用fPIC
作为所有代码的默认值。