2015-07-10 122 views
15

我在PIC上看过this的帖子,似乎总是很好用PIC(无论何时它是exe /静态/共享库)。为什么不总是使用fpic(位置独立代码)?

那么有什么缺点?
有没有例子阐述何时不使用PIC?

+1

PIC通常不能在Windows中使用,因为在加载期间DLL地址是固定的。而且在x86 PIC中效率不如x86_64 –

回答

6

链接问题中接受的答案是非常简单的,只会引出PIC和非PIC代码之间不同的一个事物,即生成相对而非绝对的跳转。

制作PIC代码时,不仅是位置独立的代码,也是数据。并不是所有的代码或数据都可以简单地通过使用相对偏移量来寻址,它必须在加载时(库/程序加载到内存中)或甚至在运行时解决。另外,使用相对寻址意味着CPU必须将相对偏移量转换为绝对地址,而不是由编译器完成。

在带虚拟内存的系统上,编译器可以一劳永逸地完成这些相对地址分辨率时,通常不需要花费负载或运行时间。

+0

有没有使用-fpic的情况,或者不使用fpic程序会崩溃? (编译器是否为这两种情况生成合适的机器码?) – Azil

+0

@Azil:它确实生成了正确的代码。如果您正在构建共享库(.so,.dll),您必须*使用PIC,否则不起作用。像Amiga这样的机器的所有*代码由于它们的架构而是PIC,但是那些代码是在真正的* CPU(68k)上运行的,没有受到它的影响。 ;-) – DevSolar

+0

因此,建立如此(dll)没有PIC - 总是给编译错误? – Azil

0

在某些体系结构上,包括x86,-fPIC生成很多加载/存储数据的较差代码(即函数调用)。虽然这对图书馆来说是可以忍受的,但对于可执行文件来说这是不可取的

amd64指令集(以及最近的gnu-x32 ABI)的主要卖点之一是增加了“PC相对加载/存储”指令,从而解决了效率问题。

注意,硬化系统通常使-fPIE所有可执行文件,因为它允许地址空间布局随机。

+0

这与函数调用没有可比性,但它占用一个寄存器。 – DevSolar

+0

@DevSolar uh,它绝对需要一个函数调用(尽管它可能会在第一次显然后将其缓存在寄存器中)。它出现在反汇编中,使用'__x86.get_pc_thunk.cx'这样的名字,显然这个寄存器取决于当前使用的内容。 – o11c

+1

啊......我们的意思是一样的。 “函数调用”是将偏移表的地址存入寄存器的技巧。保持缓存需要一个寄存器(如我所说),而不是缓存它使数据访问需要一个函数调用(如你所说)。应该指出的是,这是x86体系结构的典型“丑陋点”之一;大多数(如果不是所有其他的CPU系列的话)在20世纪80年代允许适当的PC相对寻址... – DevSolar

相关问题