比较64位x86平台上的PIE,PIC代码和可执行文件有什么区别?

testing是在Ubuntu 12.04 64位。 x86架构。

我对位置独立可执行(PIE)和位置独立代码(PIC)这个概念感到困惑,我想他们不是正交的。

这是我的快速实验。

gcc -fPIC -pie quickSort.c -o a_pie.out gcc -fPIC quickSort.c -o a_pic.out gcc a.out objdump -Dr -j .text a.out > a1.temp objdump -Dr -j .text a_pic.out > a2.temp objdump -Dr -j .text a_pie.out > a3.temp 

我有以下的发现。

A.a.out包含一些PIC代码,但只能在libc序言和结语函数中使用,如下所示:

 4004d0: 48 83 3d 70 09 20 00 cmpq $0x0,0x200970(%rip) # 600e48 <__JCR_END__> 

在我简单的快速sorting程序的汇编指令中,我没有find任何PIC指令。

B. a_pic.out包含PIC代码,我没有find任何非PIC指令…在我的快速sorting程序的指令中,所有的全局数据都可以通过PIC指令来访问:

  40053b: 48 8d 05 ea 02 00 00 lea 0x2ea(%rip),%rax # 40082c <_IO_stdin_used+0x4> 

C. a_pie.out包含与a_pic.out相比较的语法相同的指令。 但是,a_pie.out的.text部分的内存地址范围从0x630到0xa57,而a_pic.out的同一部分范围从0x400410到0x400817。

任何人都可以给我一些这些现象的解释吗? 特别是发现C。 再次,我真的很困惑PIE与PIC ,并不知道如何解释发现C ..

Solutions Collecting From Web of "比较64位x86平台上的PIE,PIC代码和可执行文件有什么区别?"

我对位置独立可执行(PIE)和位置独立代码(PIC)这个概念感到困惑,我想他们不是正交的。

PIEPIC之间唯一真正的区别是允许您在PIC 插入符号,但不允许在PIE 插入符号。 除此之外,它们几乎是等价的。

你可以在这里阅读关于符号设置。

C. a_pie.out包含与a_pic.out相比较的语法相同的指令。 但是,a_pie.out的.text部分的内存地址范围从0x630到0xa57,而a_pic.out的同一部分范围从0x400410到0x400817。

很难理解你对此感到惊讶。

PIE二进制就像共享库一样链接,因此其默认加载地址(第一个LOAD段的.p_vaddr )为零。 期望的是某些东西会将这个二进制文件从零页面上移开,并将其加载到某个随机地址。

另一方面,非PIE可执行文件总是加载在其链接地址。 在Linux上, x86_64二进制文件的默认地址是0x400000 ,因此.text最终不会离开那里。