位置独立可执行文件和固定入口点地址



可以从虚拟地址空间的任意地址加载和运行与位置无关的ELF可执行文件。

我试着构建下面的简单程序:

pie.c

#include <stdio.h>
void main(void)
{
printf("hello, pie!n");
}

构建命令:

gcc pie.c -o pie -pie

可执行文件的ELF头是:

:

ELF Header:
Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
Class:                             ELF64
Data:                              2's complement, little endian
Version:                           1 (current)
OS/ABI:                            UNIX - System V
ABI Version:                       0
Type:                              DYN (Shared object file)
Machine:                           Advanced Micro Devices X86-64
Version:                           0x1
Entry point address:               0x530 <================= FIXED entry point
Start of program headers:          64 (bytes into file)
Start of section headers:          6440 (bytes into file)
Flags:                             0x0
Size of this header:               64 (bytes)
Size of program headers:           56 (bytes)
Number of program headers:         9
Size of section headers:           64 (bytes)
Number of section headers:         29
Section header string table index: 28

入口地址是固定的

符号_start:

0000000000000530 T _start

这意味着_start必须放在0x530上。

这与位置无关不是矛盾的吗?

ADD 1 - 10:44 AM 8/16/2021

我尝试在没有-pie标志的情况下构建相同的程序:

gcc pie.c -o pie_not

生成的ELF头是:

pie_not:

ELF Header:
Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
Class:                             ELF64
Data:                              2's complement, little endian
Version:                           1 (current)
OS/ABI:                            UNIX - System V
ABI Version:                       0
Type:                              DYN (Shared object file)
Machine:                           Advanced Micro Devices X86-64
Version:                           0x1
Entry point address:               0x530  <============ Still the same value as with -pie flag
Start of program headers:          64 (bytes into file)
Start of section headers:          6440 (bytes into file)
Flags:                             0x0
Size of this header:               64 (bytes)
Size of program headers:           56 (bytes)
Number of program headers:         9
Size of section headers:           64 (bytes)
Number of section headers:         29
Section header string table index: 28

我进一步比较了piepie_not的构建结果。它们的二进制文件是相同的

那么操作系统如何判断哪一个应该被视为位置无关代码??

ADD 2 - 10:56 AM 8/16/2021

我想我明白了。似乎gcc默认使用-pie。为了避免它,我必须显式地添加-no-pie标志。
gcc pie.c -o pie_not -no-pie

生成的ELF头是这样的:

pie_not:

ELF Header:
Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
Class:                             ELF64
Data:                              2's complement, little endian
Version:                           1 (current)
OS/ABI:                            UNIX - System V
ABI Version:                       0
Type:                              EXEC (Executable file) <==== File type also changed!!!
Machine:                           Advanced Micro Devices X86-64
Version:                           0x1
Entry point address:               0x400400 <===== Entry point address changed!
Start of program headers:          64 (bytes into file)
Start of section headers:          6376 (bytes into file)
Flags:                             0x0
Size of this header:               64 (bytes)
Size of program headers:           56 (bytes)
Number of program headers:         9
Size of section headers:           64 (bytes)
Number of section headers:         29
Section header string table index: 28

我相信加载器依赖于ELF头文件中的Type文件来决定如何处理二进制文件。

对于位置无关的可执行文件,ELF头中的入口点地址不用作入口点的绝对地址。相反,它被用作随机选择的基址的偏移量。

所以在你的例子中,如果基址随机选择为0x567812340000,那么执行将从绝对地址0x567812340530开始。

最新更新