[英]Does -fPIC has any effect on an executable built without -fPIE -pie?
我在 SO 看到了很多问题,询问为什么不是所有代码都编译为 PIC或者为什么我们不能总是使用-fPIC
。
但是,所有答案都没有解释当您的对象使用-fPIC
编译但您将它们链接到不是PIE(位置无关的可执行文件)的可执行文件时会发生什么。
根据我的理解(使用一些小示例并使用readelf
反汇编/检查它们),看起来使用-fPIC
进行编译在不使用-pie -fPIE
进行链接时不会产生不同的二进制文件。
我(简单?)的解释是,在链接时,已知最终的可执行文件不是可重定位的,因此我们可以像在非 PIC 构建中一样解析所有地址,并完全摆脱 GOT 和 PLT。 这也是我的观察:如果我构建一个 PIE, readelf
会显示一个 GOT/PLT 部分。 如果我不构建 PIE,无论我是否使用-fPIC
,GOT/PLT 都会消失。
我的问题是这个观察是否
我发现很难找到这个简单问题的具体答案,这就是我在这里问的原因。
看起来在没有-pie -fPIE 的情况下链接时,使用-fPIC 进行编译不会产生不同的二进制文件。
证明事实并非如此是微不足道的。
#include <stdio.h>
const char *p = "Hello";
int x[1024];
int main()
{
printf("%d: %s\n", __LINE__, p);
x[1] = 42;
return x[2];
}
使用gcc (GCC) 12.3.1 20230508 (Red Hat 12.3.1-1)
和GNU ld version 2.38-27.fc37
gcc -c -fPIC -c x.c && gcc -no-pie x.o -o x1
gcc -no-pie x.c -o x2
x1
的反汇编:
0x0000000000401126 <+0>: push %rbp
0x0000000000401127 <+1>: mov %rsp,%rbp
0x000000000040112a <+4>: mov $0x404028,%rax
0x0000000000401131 <+11>: mov (%rax),%rax
0x0000000000401134 <+14>: mov %rax,%rdx
0x0000000000401137 <+17>: mov $0x8,%esi
0x000000000040113c <+22>: lea 0xed3(%rip),%rax # 0x402016
0x0000000000401143 <+29>: mov %rax,%rdi
0x0000000000401146 <+32>: mov $0x0,%eax
0x000000000040114b <+37>: call 0x401030 <printf@plt>
0x0000000000401150 <+42>: mov $0x404060,%rax
0x0000000000401157 <+49>: movl $0x2a,0x4(%rax)
0x000000000040115e <+56>: mov $0x404060,%rax
0x0000000000401165 <+63>: mov 0x8(%rax),%eax
0x0000000000401168 <+66>: pop %rbp
0x0000000000401169 <+67>: ret
对于x2
:
0x0000000000401126 <+0>: push %rbp
0x0000000000401127 <+1>: mov %rsp,%rbp
0x000000000040112a <+4>: mov 0x2ef7(%rip),%rax # 0x404028 <p>
0x0000000000401131 <+11>: mov %rax,%rdx
0x0000000000401134 <+14>: mov $0x8,%esi
0x0000000000401139 <+19>: mov $0x402016,%edi
0x000000000040113e <+24>: mov $0x0,%eax
0x0000000000401143 <+29>: call 0x401030 <printf@plt>
0x0000000000401148 <+34>: movl $0x2a,0x2f12(%rip) # 0x404064 <x+4>
0x0000000000401152 <+44>: mov 0x2f10(%rip),%eax # 0x404068 <x+8>
0x0000000000401158 <+50>: pop %rbp
0x0000000000401159 <+51>: ret
这不是一个完全相同的二进制文件——使用-fPIC
增加了一些开销。
开销的数量取决于平台,也可能取决于可以执行的 linker 优化的数量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.