gcc位置无关代码参数-fPIC/-fPIE/-pie的关系

2023-08-17  本文已影响0人  CodingCode
  1. -fPIC
    是一个编译选择,生成位置无关的.o文件,这些.o文件可以用来链接生成动态库(.so),也可以用来生成可执行文件(包括位置无关或者位置固定的)。

  2. -fPIE
    与-fPIC类似,差别就是生成的.o文件不能用来链接生成动态度(.so),只能用来生成可执行文件(也包括位置无关或者位置固定的),。

  3. -pie
    是一个链接选项,它要求链接器使用的所有.o文件编译是必须使用-fPIC或者-fPIE。

补充一点,如果命令行中同时使用了-fPIC和-fPIE会怎么选?回答是gcc只会选后出现的一个,把前一个覆盖掉了,且不会给出任务提示信息。即-fPIC和-fPIE不可同时有效,出现在命令行后面的那个会替换前面的那个。

所以:

  1. 生成动态库的.o文件必须使用-fPIC编译选项。
  2. 生成可执行文件的.o文件则,
    2.1 如果链接没有-pie选项,则使用的.o文件在生成时可以使用-fPIC或者-fPIE,或者什么都没有。
    2.2 如果链接包含-pie选项,则使用的.o文件在生成时必须使用-fPIC或者-fPIE选项。
  3. 那么是不是-fPIE的价值不太大呢,因为完全可以使用-fPIC替代就行了;我觉得应该是是的,如果只考虑功能,任何使用-fPIE的地方都可以使用-fPIC代替,无非就是用-fPIE代替-fPIC在某些场景下能够减少一次GOT/PLT的位移计算,提升一些性能。

我们看一个-fPIC,和-fPIE,以及标准的(即无-fPIC,也无-fPIE)的差异例子:

       int global_var = 0x10;
       int global_func(void) { return 0x11; }

static int static_var = 0x20;
static int static_func(void) { return 0x21; }

extern int extern_var;
extern int extern_func(void);

int main(void) {
    int x = 0;
    x = global_func();
    global_var = 0x12;

    x = static_func();
    static_var = 0x22;

    x = extern_func();
    extern_var = 0x32;

    return 0;
}

使用gcc -c编译后看它们main函数生成的指令码差异:

image.png
  1. 在global变量和函数(global_var/global_func)的引用上,PIE代码和STD代码是一样的,都是直接使用地址,而PIC代码则计算GOT/PLT表位移。
  2. 在extern变量和函数(extern_var/extern_func)的引用上,PIE代码和PIC代码是一样的,都是计算 GOT/PLT表位移,而STD代码则是直接使用。
  3. 对static变量和函数(static_var/static_func)的引用上,所有PIE,PIC,和STD的使用都是一样的。
上一篇下一篇

猜你喜欢

热点阅读