【问题标题】:Is -fPIC for shared libraries ONLY?-fPIC 仅适用于共享库吗?
【发布时间】:2018-03-27 02:28:11
【问题描述】:

我知道-fPIC 是共享库所必需的,并且知道原因。

但是,我不清楚这个问题:

在构建可执行文件或静态库期间,是否应该永远不要使用 -fPIC

【问题讨论】:

  • 我的印象(受知识分子的反驳)是,如今的编译器无论如何都会生成 PIC。从理论上讲,PIC 比非 PIC 代码的效率要低一些,但是对于 ASLR(地址空间布局随机化)之类的东西,大部分时间都可能需要 PIC。我主要考虑 PC 桌面系统和更大的系统; “嵌入式”空间中的规则可能会有所不同。 (在 Mac 上,使用 -fPIC-fpic 编译或两者都不使用会给出与 GCC 7.3.0 相同大小的目标代码。但这不一定是 ELF;目标文件是“Mach-O 64 位对象 x86_64”。 )

标签: c++ c gcc compilation elf


【解决方案1】:

在构建可执行文件或静态库期间,是否应该永远不要使用 -fPIC

从不是一个强词,上面的陈述是错误的。

使用-fPIC 构建的代码(稍微)不太理想,那么为什么要将其放入共享库以外的任何地方呢?

让我们从一个静态库开始,它有一个简单的答案。

假设您想为您的用户提供一个静态库,该库可以链接到或者可执行文件,链接到他们自己的共享库?

在这种情况下,您必须给他们 3 个单独的存档库(一个使用 -fPIC 构建,用于链接到共享库,一个使用 -fPIE 构建,用于链接到 PIE 可执行文件,以及一个“常规”一个),或者您可以给他们一个单一的存档库(其中必须有使用-fPIC 构建的代码)。

现在,可能有人认为您应该给他们一个共享库,但这会迫使您的最终用户分发 2 个二进制文件,他们可能更愿意不这样做。

但假设您想构建一个常规(非 PIE)可执行文件。将-fPIC 代码链接到此类可执行文件的原因可能是什么?

好吧,假设您处于开发阶段,还不太关心优化代码。进一步假设您希望将代码作为共享库、作为 PIE 和非 PIE 可执行文件的一部分进行测试。

在上述条件下,您可以编译代码 3 次(使用和不使用 -fPIC,以及使用 -fPIE),您可以编译一次(使用 -fPIC)和将其链接到所有 3 个共享库、PIE 和非 PIE 可执行文件中。这样做可以节省大量编译时间和一些构建系统的复杂性。

TL;DR:将-fPIC 对象放入可执行文件和静态库中是有其用处的,您应该了解这样做的原因(如果最终这样做的话)。

更新:

目标文件中的代码始终是可重定位的

正确。

是位置无关的代码吗?

否:并非所有可重定位代码都是位置无关的。

位置无关代码是可重定位代码的子集。可重定位代码可以具有适用于 any 部分的重定位。与位置无关的代码必须针对.text(和.rodata)进行任何重定位。

【讨论】:

  • 目标文件中的代码总是可重定位的,它是与位置无关的代码吗?静态库由目标文件组成,那么,我们可以说静态库中的代码已经是位置无关的了吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-17
  • 2014-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-10
  • 1970-01-01
相关资源
最近更新 更多