【问题标题】:Why not always use fpic (Position Independent Code)? [duplicate]为什么不总是使用 fpic(位置无关代码)? [复制]
【发布时间】:2015-09-28 16:52:13
【问题描述】:

我在 PIC 上阅读了this 的帖子,似乎使用 PIC 总是好的(只要它是 exe / static / share llibrary)。

那么有什么缺点呢?
是否有详细说明何时不使用 PIC 的示例?

【问题讨论】:

  • PIC 通常不能在 Windows 中使用,因为 DLL 地址在加载期间是固定的。此外,在 x86 PIC 中的效率不如 x86_64

标签: c++ gcc fpic


【解决方案1】:

链接问题中接受的答案非常简单,只提出了 PIC 和非 PIC 代码之间的不同之处,即生成相对而非绝对的跳转。

当您制作 PIC 代码时,不仅代码与位置无关,数据也是如此。并不是所有的代码或数据都可以简单地通过使用相对偏移来解决,它必须在加载时(当库/程序加载到内存中时)甚至在运行时解决。

此外,使用相对寻址意味着 CPU 必须将相对偏移量转换为绝对地址,而不是由编译器完成。

在具有虚拟内存的系统上,当编译器可以一劳永逸地完成时,通常不需要在这些相对地址解析上花费加载或运行时间。

【讨论】:

  • 有没有使用-fpic,或者不使用fpic会导致程序崩溃的情况? (编译器是否为这两种情况生成合适的机器代码?)
  • @Azil:它确实会生成正确的代码。如果您正在构建一个共享库(.so、.dll),您必须使用 PIC,否则它不起作用。例如,像 Amiga 这样的机器,由于其架构的原因,其 all 代码都是 PIC,但是那些运行在不受其影响的 real CPU (68k) 上。 ;-)
  • 那么,在没有 PIC 的情况下构建 so (dll) - 总是给出编译错误?
  • @Azil 可能不是编译器错误,因为编译器实际上并不知道您正在构建 DLL,但是您很可能会遇到链接器错误。
  • @JoachimPileborg:嗯,MSVC 得到<ConfigurationType>DynamicLibrary<...> 作为提示,GCC 得到-shared,至少如果你做得对的话。 ;-)
【解决方案2】:

在包括 x86 在内的某些架构上,-fPIC 会为数据的加载/存储生成很多 更糟糕的代码(即函数调用)。虽然这对于库来说是可以容忍的,但对于可执行文件来说却是不可取的。

amd64 指令集(以及最近的 gnu-x32 ABI)的主要卖点之一是添加了“PC-relative load/store”指令,它解决了效率问题。

请注意,强化系统通常确实为所有可执行文件启用-fPIE,因为它允许地址空间布局随机性。

【讨论】:

  • 和函数调用比不上,但是占用了一个寄存器。
  • @DevSolar 呃,它肯定需要一个函数调用(尽管它可能会在第一次之后将它缓存在一个寄存器中)。它以__x86.get_pc_thunk.cx 之类的名称显示在反汇编中,显然寄存器根据当前使用的内容而有所不同。
  • 啊...我们的意思是一样的。 “函数调用”是将偏移表的地址放入寄存器的技巧。保持缓存占用一个寄存器(如我所说),不缓存它会使数据访问需要函数调用(如你所说)。需要注意的是,这是 x86 架构的典型“丑陋位”之一;早在 1980 年代,大多数(如果不是所有)其他 CPU 系列都允许正确的 PC 相关寻址......
猜你喜欢
  • 1970-01-01
  • 2016-11-06
  • 2021-11-27
  • 1970-01-01
  • 1970-01-01
  • 2017-03-28
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
相关资源
最近更新 更多