Gcc中编译和链接选项 -fpic -fPIC -fpie -fPIE -pie的含义


请尊重原创版权,转载注明出处。

Gcc参数的官方的解释是:

-fpic

Generate position-independent code (PIC) suitable for use in a shared library, if supported for the target machine. Such code accesses all constant addresses through a global offset table (GOT). The dynamic loader resolves the GOT entries when the program starts (the dynamic loader is not part of GCC; it is part of the operating system). If the GOT size for the linked executable exceeds a machine-specific maximum size, you get an error message from the linker indicating that -fpic does not work; in that case, recompile with -fPIC instead. (These maximums are 8k on the SPARC and 32k on the m68k and RS/6000. The 386 has no such limit.)

Position-independent code requires special support, and therefore works only on certain machines. For the 386, GCC supports PIC for System V but not for the Sun 386i. Code generated for the IBM RS/6000 is always position-independent.

When this flag is set, the macros pic and PIC are defined to 1.

-fPIC

If supported for the target machine, emit position-independent code, suitable for dynamic linking and avoiding any limit on the size of the global offset table. This option makes a difference on the m68k, PowerPC and SPARC.

Position-independent code requires special support, and therefore works only on certain machines.

When this flag is set, the macros pic and PIC are defined to 2.

-fpie

-fPIE

These options are similar to -fpic and -fPIC, but generated position independent code can be only linked into executables. Usually these options are used when -pie GCC option will be used during linking. -fpie and -fPIE both define the macros pie and PIE. The macros have the value 1 for -fpie and 2 for -fPIE.

-fno-jump-tables

Do not use jump tables for switch statements even where it would be more efficient than other code generation strategies. This option is of use in conjunction with -fpic or -fPIC for building code which forms part of a dynamic linker and cannot reference the address of a jump table. On some targets, jump tables do not require a GOT and this option is not needed. —

另外这有也有解释:

Position-Independent-Executable是Binutils,glibc和gcc的一个功能, 能用来创建介于共享库和通常可执行代码之间的代码–能像共享库一样可重分配地址的程序, 这种程序必须连接到Scrt1.o。标准的可执行程序需要固定的地址,并且只有被装载到这个地址时, 程序才能正确执行。PIE能使程序像共享库一样在主存任何位置装载,这需要将程序编译成位置无关, 并链接为ELF共享对象。

引入PIE的原因是让程序能装载在随机的地址,通常情况下,内核都在固定的地址运行,如果能改用位置无关, 那攻击者就很难借助系统中的可执行码实施攻击了。类似缓冲区溢出之类的攻击将无法实施。而且这种安全提升的代价很小

谈到PIE就不得不说说Pax和Grsec内核。这两个东西都是为了构建坚不可摧到安全系统而准备的。 PaX是Linux内核安全增强补丁,它能在两方面保证安全性,一是ASLR(Address Space Layout Randomization, 地址空间分布随机化),这是一种将所有数据装载到内存时都随机化地址的方式,当使用PIE选项编译应用时, PaX能将应用的地址做随机加法;二是能提供不可执行的内存空间,这样就能使得攻击者放入内存中的 恶意代码不可执行。不过PaX官网上能支持的最新内核是2.6.27,已经是一年前的更新了。Grsec也时类似的内核补丁, 更新较为频繁能支持最新的2.6.32内核。这两种方式都能将内核完全位置无关,除了Grub和Glibc中无法位置无关的汇编码。

PIE最早由RedHat的人实现,他在连接起上增加了-pie选项,这样使用-fPIE编译的对象就能通过连接器 得到位置无关可执行程序。fPIE和fPIC有些不同。可以参考Gcc和Open64中的-fPIC选项.

gcc中的-fpic选项,使用于在目标机支持时,编译共享库时使用。编译出的代码将通过全局偏移表 (Global Offset Table)中的常数地址访存,动态装载器将在程序开始执行时解析GOT表项(注意, 动态装载器操作系统的一部分,连接器是GCC的一部分).而gcc中的-fPIC选项则是针对某些特殊机型做了 特殊处理,比如适合动态链接并能避免超出GOT大小限制之类的错误。而Open64仅仅支持不会导致GOT表溢出的PIC编译。 gcc中的-fpie和-fPIE选项和fpic及fPIC很相似,但不同的是,除了生成为位置无关代码外, 还能假定代码是属于本程序。通常这些选项会和GCC链接时的-pie选项一起使用。fPIE选项仅能在编译可执行码时用, 不能用于编译库。所以,如果想要PIE的程序,需要你除了在gcc增加-fPIE选项外,还需要在ld时增加-pie选项 才能产生这种代码。即gcc -fpie -pie来编译程序。单独使用哪一个都无法达到效果。

你可以使用file命令来查看当前的可执行文件是不是PIE的。

下面是本博编译helloword的显示。可以看出,可执行文件属性从executable变成了shared object.

$ gcc  helloworld.c
$ file a.out
a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), 
for GNU/Linux 2.6.9, not stripped
$ gcc -fpie -pie helloworld.c
$ file a.out
a.out: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), 
for GNU/Linux 2.6.9, not stripped

接下来,我们就能实验了,使用strace命令来查看这两个a.out执行情况了。关于strace命令,可以参考strace命令介绍 在博主电脑上,有PIE时,执行第一个brk(0)系统调用时,返回的地址一直是变化的。而无PIE时, brk(O)系统调用返回地址一直不变。内容太多,不再贴出。

注:

linux系统调用brk():

linux系统内部分配内存的系统调用,malloc()其实也是调用的brk().直接修改堆的大小,返回新内存区域的结束地址。

文档信息
--------------
* 作者:
* 版权声明:自由转载-非商用
* 转载: []

【待整理】Gcc中编译和链接选项 -fpic -fPIC -fpie -fPIE -pie的含义