“-fPIC”选项只用于共享库吗?

6

我知道-fPIC对于共享库是必需的,并且知道为什么。

然而,我不清楚这个问题:

在构建可执行文件或静态库时,是否应始终不使用-fPIC


我的印象是,编译器现在生成PIC的情况比较多,但这还有待专业人士的证实。理论上,PIC代码的效率略低于非PIC代码,但对于像ASLR(地址空间布局随机化)这样的东西,大多数情况下可能需要使用PIC。我主要考虑的是PC桌面系统和更大的系统;在“嵌入式”领域,规则可能会有所不同。(在Mac上,使用-fPIC-fpic编译或不使用这些选项都会产生相同大小的目标代码,使用GCC 7.3.0。但那不一定是ELF;对象文件是Mach-O 64位对象x86_64。) - Jonathan Leffler
1个回答

10
在构建可执行文件或静态库时,是否永远不应该使用-fPIC
“永不”是一个强烈的说法,上述陈述是错误的。
使用-fPIC构建的代码(略微)不太优化,那么为什么要将其放入除共享库之外的任何东西中呢?
让我们从静态库开始,它有一个简单的答案。
假设您想要向用户提供一个静态库,可以链接到他们自己的可执行文件或共享库中?
在这种情况下,您必须提供3个单独的存档库(一个使用-fPIC构建用于链接到共享库,一个使用-fPIE构建用于链接到PIE可执行文件,以及一个“常规”存档库),或者您可以提供一个单一的存档库(其中必须具有使用-fPIC构建的代码)。
现在,可以争论您应该改为提供共享库,但这会强制您的最终用户分发2个二进制文件,他们可能不愿意这样做。
但是,假设您要构建常规(非PIE)可执行文件。将-fPIC代码链接到这种可执行文件中的原因是什么?
嗯,假设您处于开发阶段,暂时不太关心代码优化。进一步假设您想要将代码作为共享库以及作为PIE和非PIE可执行文件的一部分进行测试。
在上述条件下,您可以将代码编译3次(使用和不使用-fPIC以及使用-fPIE),或者您可以将其编译一次(使用-fPIC)并将其链接到所有3个共享库、PIE和非PIE可执行文件中。这样做可以节省大量编译时间和某些构建系统复杂性。
简而言之:将-fPIC对象放入可执行文件和静态库中是有其位置的,您应该了解为什么要这样做(如果最终要这样做)。
更新:
对象文件中的代码始终是可重定位的。
正确。
它是否是位置无关代码?
不是:并非所有可重定位代码都是位置无关的。
位置无关代码是可重定位代码的一个子集。可重定位代码可以具有适用于任何部分的重定位。位置无关代码必须没有针对.text(和.rodata)的任何重定位。

目标文件中的代码始终是可重定位的,那么它是位置无关代码吗?静态库由目标文件组成,那么我们可以说静态库中的代码已经是位置无关的了吗? - xmllmx

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