在 64 位 x86 平台上比较 PIE、PIC 代码和可执行文件有什么区别?
What are the differences comparing PIE, PIC code and executable on 64-bit x86 platform?
测试是在 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 prologue和epilogue函数中,如图在下面:
4004d0: 48 83 3d 70 09 20 00 cmpq [=11=]x0,0x200970(%rip) # 600e48 <__JCR_END__>
在我的简单快速排序程序的汇编指令中,我没有找到任何 PIC 指令。
B. a_pic.out 包含 PIC 代码,我没有找到任何 non-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..
I am confused about the concept Position Independent Executable (PIE) and Position Independent code (PIC), and I guess they are not orthogonal.
PIE
和 PIC
之间唯一真正的区别是您可以 在 PIC
中插入 符号,但不能在 PIE
。除此之外,它们几乎是等价的。
您可以阅读有关符号插入的内容 here。
C. a_pie.out contains syntax-identical instructions comparing with a_pic.out. However, the memory addresses of a_pie.out's .text section range from 0x630 to 0xa57, while the same section of a_pic.out ranges from 0x400410 to 0x400817.
很难理解您对此感到惊讶的地方。
PIE
二进制文件被链接为共享库,因此它的默认加载地址(第一个 LOAD
段的 .p_vaddr
)为零。期望某些东西会将此二进制文件从零页重新定位,并将其加载到某个随机地址。
另一方面,非PIE
可执行文件总是 加载到其链接地址。在 Linux 上,x86_64
二进制文件的默认地址是 0x400000
,因此 .text
离那里不远。
测试是在 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 prologue和epilogue函数中,如图在下面:
4004d0: 48 83 3d 70 09 20 00 cmpq [=11=]x0,0x200970(%rip) # 600e48 <__JCR_END__>
在我的简单快速排序程序的汇编指令中,我没有找到任何 PIC 指令。
B. a_pic.out 包含 PIC 代码,我没有找到任何 non-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..
I am confused about the concept Position Independent Executable (PIE) and Position Independent code (PIC), and I guess they are not orthogonal.
PIE
和 PIC
之间唯一真正的区别是您可以 在 PIC
中插入 符号,但不能在 PIE
。除此之外,它们几乎是等价的。
您可以阅读有关符号插入的内容 here。
C. a_pie.out contains syntax-identical instructions comparing with a_pic.out. However, the memory addresses of a_pie.out's .text section range from 0x630 to 0xa57, while the same section of a_pic.out ranges from 0x400410 to 0x400817.
很难理解您对此感到惊讶的地方。
PIE
二进制文件被链接为共享库,因此它的默认加载地址(第一个 LOAD
段的 .p_vaddr
)为零。期望某些东西会将此二进制文件从零页重新定位,并将其加载到某个随机地址。
另一方面,非PIE
可执行文件总是 加载到其链接地址。在 Linux 上,x86_64
二进制文件的默认地址是 0x400000
,因此 .text
离那里不远。