32 位 x86 代码是否需要为共享库文件专门进行 PIC 编译?
如果目标文件打算作为共享库 (.so
) 加载,则将代码编译到目标文件需要与位置无关,因为加载共享目标文件的基虚拟地址在不同的进程中进入可能会有所不同。
现在,当我尝试在 32 位 x86 计算机上加载在没有 -fpic
GCC 选项的情况下编译和链接的 .so
文件时,没有遇到错误,而在 64 位计算机上则失败x86 计算机。
我发现随机网站说我不需要 32 位上的 -fpic
,因为没有 -fpic
编译的代码在某个位置使用时也根据 X86 32 位 ABI 巧合地工作- 独立的方式。但我仍然发现软件在 32 位版本中附带了不同版本的库:一种用于 PIC,一种用于非 PIC。例如,英特尔编译器附带 libirc.a
和 libirc_pic.a
,后者被编译为位置无关模式(如果想链接该 .a)。
文件转换为 .so
文件)。
我想知道对于 32 位代码使用 -fpic
和不使用它之间的确切区别是什么,以及为什么某些软件包(例如 intel 编译器)仍然附带单独版本的库?
Compiling code to an object file needs to be done position-independent if the object file is intended to be loaded as a shared library (.so
), because the base virtual address that the shared object file is loaded into in different processes may be different.
Now I didn't encounter errors when I tried to load an .so
file compiled and linked without the -fpic
GCC option on 32bit x86 computers, while it fails on 64bit bit x86 computers.
Random websites I found say that I don't need -fpic
on 32bit because code compiled without -fpic
works by coincidence according to the X86 32bit ABI also when used in a position-independent manner. But I still found software that ship with separate versions of libraries in their 32bit versions: One for PIC, and one for non-PIC. For example, the intel compiler ships with libirc.a
and libirc_pic.a
, the latter being compiled for position-independent mode (if one wants to link that .a
file into an .so
file).
I wonder what the precise difference between using -fpic
and not using it is for 32bit code, and why some packages, like the intel compiler, still ship with separate versions of libraries?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
非 PIC 代码在 x86(32 位)上工作并不是“巧合”。 x86 的动态链接器支持使其工作所需的必要“textrel”。这会导致内存消耗和启动时间的成本非常高,因为基本上整个代码段都必须在加载时进行修补(从而成为不可共享内存)。
动态链接器维护者声称,由于架构中的基本问题(立即地址位移不能大于 32 位),x86_64 上不支持非 PIC 共享库,但这个问题可以通过始终加载来轻松解决前 4GB 虚拟地址空间中的库。当然,PIC 代码在 x86_64 上非常便宜(PIC 不像 32 位 x86 那样是性能杀手),因此他们不支持它并防止傻瓜制作非 PIC 库可能是正确的......
It's not that non-PIC code works "by coincidence" on x86 (32-bit). It's that the dynamic linker for x86 supports the necessary "textrels" needed to make it work. This comes at a very high cost in memory consumption and startup time, since basically the entire code segment must be patched up at load time (and thus becomes non-shareable memory).
The dynamic linker maintainers claim that non-PIC shared libraries can't be supported on x86_64 because of fundamental issues in the architecture (immediate address displacements can't be larger than 32-bit) but this issue could be easily solved by just always loading libraries in the first 4gb of virtual address space. Of course PIC code is very inexpensive on x86_64 (PIC isn't a performance-killer like it is on 32-bit x86) so they're probably right to keep it unsupported and prevent fools from making non-PIC libraries...
因为共享对象通常加载在其首选地址,因此它们可能看起来工作正常。但对于所有共享代码来说,fPIC 都是一个好主意。
我相信该库通常不存在两个版本的原因是许多发行版使用
fPIC
作为所有代码的默认值。Because shared objects usually load at their preferred address, they may appear to work correctly. But
fPIC
is a good idea for all shared code.I believe the reason that there aren't often two versions of the library is that many distributions use
fPIC
as the default for all code.