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

时间:2015-01-23 21:55:59

标签: c linux assembly x86 elf

测试是在64位的Ubuntu 12.04上进行的。 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__> 

在我的简单快速排序程序的汇编说明中,我没有找到任何PIC指令。

B。 a_pic.out包含PIC代码,我没有找到任何非PIC 指令...在我的快速排序程序的说明中,所有全局数据都由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 ..

1 个答案:

答案 0 :(得分:14)

  

我对位置独立可执行(PIE)和位置无关代码(PIC)的概念感到困惑,我猜它们不是正交的。

PIEPIC之间唯一真正的区别在于,您可以在PIC插入符号,但不能在PIE中。除此之外,它们几乎相同。

您可以阅读符号插入here

  

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

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

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

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