该测试在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__>

在我的简单quicksort程序的汇编指令中,我没有找到任何PIC指令。

B. a_pic.out包含PIC代码,但是我没有找到任何非PIC 指令...在我的quicksort程序的指令中,所有全局数据都可以通过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 的发现。

最佳答案


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

您可以阅读有关符号插入here的信息。



很难理解您对此感到惊讶。
PIE二进制文件就像共享库一样链接,因此其默认加载地址(第一个.p_vaddr段的LOAD)为零。期望某些东西可以将该二进制文件从零页位置移开,并将其加载到某个随机地址。

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

关于c - 比较64位x86平台上的PIE,PIC代码和可执行文件有什么区别?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28119365/

10-16 03:22