位置无关的可执行文件和固定的入口点地址
Position independent executable and fixed entry point address
可以从虚拟地址 space.
中的任意地址加载和 运行 位置无关的 ELF 可执行文件
我尝试构建以下简单程序:
pie.c
#include <stdio.h>
void main(void)
{
printf("hello, pie!\n");
}
构建命令:
gcc pie.c -o pie -pie
可执行文件的 ELF header 是:
饼图:
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
。
这不是与位置无关自相矛盾吗?
添加 1 - 10:44 2021 年 8 月 16 日上午
我试图在没有 -pie
标志的情况下构建相同的程序:
gcc pie.c -o pie_not
生成的ELFheader为:
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
并且我进一步比较了构建结果pie
和pie_not
。它们的二进制文件是相同的。
那么操作系统如何判断哪一个应该被视为位置无关代码?
添加 2 - 10:56 2021 年 8 月 16 日上午
我想我明白了。
似乎 gcc 默认使用 -pie
。为避免这种情况,我必须明确添加 -no-pie
标志。
gcc pie.c -o pie_not -no-pie
而生成的ELFheader是这样的:
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 header 中提交的类型来决定如何处理二进制文件。
对于position-independent 可执行文件,ELF header 中的入口点地址不用作入口点的绝对地址。相反,它用作随机选择的基地址的偏移量。
因此在您的示例中,如果基地址随机选择为 0x567812340000
,则执行将从绝对地址 0x567812340530
.
开始
可以从虚拟地址 space.
中的任意地址加载和 运行 位置无关的 ELF 可执行文件我尝试构建以下简单程序:
pie.c
#include <stdio.h>
void main(void)
{
printf("hello, pie!\n");
}
构建命令:
gcc pie.c -o pie -pie
可执行文件的 ELF header 是:
饼图:
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
。
这不是与位置无关自相矛盾吗?
添加 1 - 10:44 2021 年 8 月 16 日上午
我试图在没有 -pie
标志的情况下构建相同的程序:
gcc pie.c -o pie_not
生成的ELFheader为:
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
并且我进一步比较了构建结果pie
和pie_not
。它们的二进制文件是相同的。
那么操作系统如何判断哪一个应该被视为位置无关代码?
添加 2 - 10:56 2021 年 8 月 16 日上午
我想我明白了。
似乎 gcc 默认使用 -pie
。为避免这种情况,我必须明确添加 -no-pie
标志。
gcc pie.c -o pie_not -no-pie
而生成的ELFheader是这样的:
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 header 中提交的类型来决定如何处理二进制文件。
对于position-independent 可执行文件,ELF header 中的入口点地址不用作入口点的绝对地址。相反,它用作随机选择的基地址的偏移量。
因此在您的示例中,如果基地址随机选择为 0x567812340000
,则执行将从绝对地址 0x567812340530
.