在gcc中编译共享库时,-fPIC选项将代码编译为与位置无关。是否有任何原因(无论是性能还是其他原因)为何您都不会独立编译所有代码位置?
在gcc中编译共享库时,-fPIC选项将代码编译为与位置无关。是否有任何原因(无论是性能还是其他原因)为何您都不会独立编译所有代码位置?
Answers:
是的,有性能原因。一些访问实际上在另一层间接访问之下,以获取内存中的绝对位置。
还有一个GOT(全局偏移量表),用于存储全局变量的偏移量。在我看来,这就像一个IAT修正表,维基百科和其他一些来源将其归类为与位置有关。
除了接受的答案。严重影响PIC代码性能的一件事是x86上缺少“ IP相对寻址”。使用“ IP相对寻址”,您可以从当前指令指针中请求X字节的数据。这将使PIC代码更加简单。
跳转和调用通常与EIP有关,因此这些并没有真正造成问题。但是,访问数据将需要一些额外的技巧。有时,寄存器将被临时保留为代码所需数据的“基本指针”。例如,一种常见的技术是滥用x86上调用的工作方式:
call label_1
.dd 0xdeadbeef
.dd 0xfeedf00d
.dd 0x11223344
label_1:
pop ebp ; now ebp holds the address of the first dataword
; this works because the call pushes the **next**
; instructions address
; real code follows
mov eax, [ebp + 4] ; for example i'm accessing the '0xfeedf00d' in a PIC way
此技术和其他技术为数据访问添加了一个间接层。例如,gcc编译器使用的GOT(全局偏移表)。
X86-64新增了“相对RIP”模式,这使得事情很多简单。
如今,操作系统和编译器默认将所有代码作为位置无关代码。尝试在不使用-fPIC标志的情况下进行编译,代码可以正常编译,但您只会得到警告。OS之类的Windows使用称为内存映射的技术来实现此目的。
该问题的日期为2009年。十年过去了,现在所有代码实际上都是与位置无关的。现在由操作系统和编译器强制执行。无法退出。所有代码都使用PIE强制编译,并且-no-pic / -no-pie标志被忽略,这是该ASLR借口的一部分。这样做的原因是,以提高安全性为幌子,放慢了以前快速运行的应用程序的速度,并出售了更新的硬件。这是完全不合理的,因为现在大容量的内存使我们完全摆脱了动态链接的麻烦,可以静态地编译所有应用程序。
以前也发生过同样的情况,人们默默地接受实模式,而其他自由正在被夺走。我想请您注意,由于上下文切换和地址转换延迟,MMU的速度大大降低。您不会在性能至关重要的系统中找到MMU,就像科学家用来采样物理实验的系统一样。
您无需抱怨,因为您甚至都不知道所有这些培训轮子都在妨碍您的代码。我能说什么 立即使用其PIC享受慢2倍的软件!甚至随着LLVM的到来,很快将强制实施JIT(托管代码),而无法访问x86内联汇编,这将进一步减慢任何C / C ++代码的速度。“为安全而牺牲自由的人不应该得到任何回报。”