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 ..
我对位置独立可执行(PIE)和位置独立代码(PIC)这个概念感到困惑,我想他们不是正交的。
PIE
和PIC
之间唯一真正的区别是允许您在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
最终不会离开那里。