构建共享库时,-fPIC是什么意思?

138

我知道'-fPIC'选项与解决地址和个别模块之间的独立性有关,但我不确定其确切含义。你能解释一下吗?


2
如果您想了解更详细的信息,这里有一篇很棒的文章(https://akkadia.org/drepper/dsohowto.pdf)。 - M-J
3个回答

81

PIC代表位置无关代码。

引用自man gcc:

如果目标机器支持,会生成适用于动态链接并避免全局偏移表大小限制的位置无关代码。这个选项在AArch64、m68k、PowerPC和SPARC上有区别。

在这些架构上构建共享对象(*.so)时,请使用该选项。


1
f并没有什么实际意义,它只是选项名称的一部分。 - Zifre
24
fpic和fPIC有区别。它们的作用相同,但fpic在可用的情况下使用较短的相对偏移量。因此,使用fpic编译可能会产生更小的文件。不幸的是,它并不总是按预期工作,所以请使用fPIC。还请注意,并非所有处理器都支持较短的偏移量,因此可能没有任何区别。 - Martin York
2
“f”是从gcc处理命令行参数的方式中遗留下来的(这是几年前的事情,他们已经改变了代码的这一部分,我最近没有查看)。但当时只有在不同条件下允许使用特定字母或组合(有一个非常复杂的语言用于定义命令行参数),因此“f”被用来作为定义命令行参数的简便方法。 - Martin York
2
如果没有使用fPIC构建*.so会发生什么? - Isa A
2
@IsaA 今天我在编译一个来自源代码的C-API MySQL函数时遇到了问题,它无法构建,我得到了/usr/bin/ld: /tmp/cc7hXILq.o: relocation R_X86_64_32 against \.rodata' can not be used when making a shared object; recompile with -fPIC`的错误提示,所以我添加了-fPIC选项,然后就成功构建了。 - chiliNUT

41

f是gcc选项的前缀,用于"控制代码生成中使用的接口约定"

PIC代表"位置无关代码",它是m68K和SPARC的fpic的一个特殊化。

编辑:阅读由0x6adb015引用的文档的第11页和coryan的评论后,我做了一些修改:

此选项仅对共享库有意义,并告诉操作系统你正在使用全局偏移表GOT。这意味着所有地址引用都相对于GOT,代码可以在多个进程之间共享。

否则,如果没有此选项,加载器必须自己修改所有偏移量。

不用说,我们几乎总是使用-fpic / PIC选项。


1
我曾认为操作系统可以自由加载库到任何虚拟地址,但是如果没有使用pic/PIC,加载器就必须修改代码并调整所有绝对跳转和间接跳转到实际例程/库的位置。有了pic/PIC,代码不会被修改,因此可以在多个进程之间共享。 - coryan
多进程很大程度上是巧合 - 关键是代码可以在任何虚拟地址加载,而最小化地址修复。 - Jonathan Leffler

20

man gcc说:

-fpic
  生成适用于共享库的位置无关代码(PIC),如果目标机器支持的话,这种代码通过全局偏移表(GOT)访问所有常量地址。动态加载器在程序启动时解析GOT条目(动态加载器不是GCC的一部分;它是操作系统的一部分)。如果链接可执行文件的GOT大小超过了机器特定的最大大小,则会从链接器显示错误消息,指示-fpic不起作用;在这种情况下,请重新编译并使用-fPIC。(这些最大值分别为SPARC上的8k和m68k以及RS / 6000上的32k。386没有此限制。)
位置无关代码需要特殊的支持,因此仅适用于某些计算机。对于386,GCC支持System V的PIC,但不支持Sun 386i。生成IBM RS / 6000的代码始终是位置无关的。
-fPIC 如果目标机器支持,发出适用于动态链接并避免全局偏移表大小限制的位置无关代码。这个选项在m68k和SPARC上有区别。
位置无关代码需要特殊的支持,因此仅适用于某些计算机。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接