[英]Does -fPIC has any effect on an executable built without -fPIE -pie?
I've seen a lot of questions at SO asking why not all code is compiled as PIC or why we can't always use -fPIC
.我在 SO 看到了很多问题,询问为什么不是所有代码都编译为 PIC或者为什么我们不能总是使用-fPIC
。
However all of the answers lack an explanation about what happens when your objects are compiled with -fPIC
but you link them to an executable that is not a PIE (position-independent executable).但是,所有答案都没有解释当您的对象使用-fPIC
编译但您将它们链接到不是PIE(位置无关的可执行文件)的可执行文件时会发生什么。
From my understanding (using a few small examples and disassembling/inspecting them with readelf
), it looks like compiling with -fPIC
does not result in a different binary when linked without -pie -fPIE
.根据我的理解(使用一些小示例并使用readelf
反汇编/检查它们),看起来使用-fPIC
进行编译在不使用-pie -fPIE
进行链接时不会产生不同的二进制文件。
My (simplistic?) explanation would be that during link time, it is known that the final executable is not intended to be relocatable, so we can resolve all addresses as in a non-PIC build and get rid of GOT and PLT completely.我(简单?)的解释是,在链接时,已知最终的可执行文件不是可重定位的,因此我们可以像在非 PIC 构建中一样解析所有地址,并完全摆脱 GOT 和 PLT。 That is also my observation: If I build a PIE, readelf
displays a GOT/PLT section.这也是我的观察:如果我构建一个 PIE, readelf
会显示一个 GOT/PLT 部分。 If I don't build a PIE, the GOT/PLT is gone, no matter if I used -fPIC
or not.如果我不构建 PIE,无论我是否使用-fPIC
,GOT/PLT 都会消失。
My question is whether this observation我的问题是这个观察是否
I found it surprisingly difficult to find a concrete answer to this simple question, that's why I'm asking here.我发现很难找到这个简单问题的具体答案,这就是我在这里问的原因。
it looks like compiling with -fPIC does not result in a different binary when linked without -pie -fPIE.看起来在没有-pie -fPIE 的情况下链接时,使用-fPIC 进行编译不会产生不同的二进制文件。
It is trivial to prove that this is not the case.证明事实并非如此是微不足道的。
#include <stdio.h>
const char *p = "Hello";
int x[1024];
int main()
{
printf("%d: %s\n", __LINE__, p);
x[1] = 42;
return x[2];
}
Using gcc (GCC) 12.3.1 20230508 (Red Hat 12.3.1-1)
and GNU ld version 2.38-27.fc37
使用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
Disassembly for x1
: 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
For x2
:对于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
That is not an identical binary -- using -fPIC
added some overhead.这不是一个完全相同的二进制文件——使用-fPIC
增加了一些开销。
The amount of overhead depends on the platform, and may also depend on the amount of linker optimizations which can be performed.开销的数量取决于平台,也可能取决于可以执行的 linker 优化的数量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.