美文网首页
gcc位置无关代码参数-fPIC/-fPIE/-pie的关系

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

作者: CodingCode | 来源:发表于2023-08-17 00:59 被阅读0次
    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的使用都是一样的。

    相关文章

      网友评论

          本文标题:gcc位置无关代码参数-fPIC/-fPIE/-pie的关系

          本文链接:https://www.haomeiwen.com/subject/glplmdtx.html