推荐参考:

-fPIC, -fPIE, -fpic, -fpie 这些选项都与 位置无关代码(Position Independent Code, PIC) 相关,它们影响的是 编译器如何生成代码,从而决定可执行文件或共享库是否可以被 ASLR(Address Space Layout Randomization) 机制随机加载。

动机:之所以有这篇笔记,就是记得好像用过-no-pie 的命令行选项,在最近的面向 SPEC 17 的编译优化时又发现不用 fPIC 和 fPIE 可以提升执行效率,所以又详细回来梳理了一下。先前的理解只知道是用来实现 ASLR 技术的。

选项的影响

  • -fPIC / -fpic: 生成位置无关代码(Position Independent Code, PIC),用于共享库(.so),以最大限度减少重定位(relocation)
  • -fPIE / -fpie: 生成位置无关可执行文件(Position Independent Executable, PIE),用于可执行程序,使其支持 ASLR
  • -no-pie: 禁用 PIE,生成传统的固定地址可执行文件(通常用于低级调试)。
  • -fPIC-fpic 功能类似,但 -fpic 可能在某些架构上有大小限制
  • -fPIE-fpie 功能类似,但 -fpie 可能对代码优化策略略有不同

    -fPIC

    用于生成 共享库(.so)(动态库必须使用 fPIC),让代码可以被加载到任意地址,并且可被多个进程共享。其主要效果为代码**不使用绝对地址**,而是**依赖 GOT(Global Offset Table)和 PLT(Procedure Linkage Table)** 来间接访问全局变量和函数。
    也就是说,==程序在通常情况下是必然加速的,毕竟是间接跳转缩减为了直接跳转==

    -fpic

    与上述类似,但是生成的代码依赖更小的跳转表,但是无法支持大程序

    -fPIE

    用于生成 位置无关可执行文件(PIE),使可执行文件在 ASLR(地址空间随机化) 下运行时可被加载到随机地址。

    使用方法

  • -fno-PIE vs -fPIE
  • -pie vs -no-pie
    no-pie 的场景在于 GDB 调试时,防止地址变化导致调试困难