我看到加载到内存时与 -pie 参数链接的 ELF 文件的 .text 段位于虚拟内存地址中的某个位置,例如 linux x86_64 上的 0x00005xxxxxxxxxxx 。我检查了几个正在运行的进程,似乎 .text 段的地址all都有前缀 0x00005,例如,我找不到任何带有 0x00004 前缀的进程。
动态链接器选择这个地址范围(0x00005xxxxxxxxxxx)来定位.text段有什么原因吗?为什么它不选择一些从 4Mb+ 开始的地址,例如不带 -pie 参数链接的二进制文件?
动态链接器选择这个地址范围(0x00005xxxxxxxxxxx)来定位.text段有什么原因吗?
动态链接器与此无关。
在第一个用户空间指令执行之前,可执行文件由内核进行
mmap
编译(该指令是动态链接二进制文件的动态加载器中的 _start
)。
因此,您必须查看内核源代码以解释为什么 PIE 二进制文件最终位于
0x5...
范围内。
查看
fs/binfmt_elf.c
,你可以看到它使用了ELF_ET_DYN_BASE
,它在arch/x86/include/asm/elf.h
中定义为
#define ELF_ET_DYN_BASE (mmap_is_ia32() ? 0x000400000UL : \
(DEFAULT_MAP_WINDOW / 3 * 2))
DEFAULT_MAP_WINDOW
本身来自arch/x86/include/asm/page_64_types.h
:
define DEFAULT_MAP_WINDOW ((1UL << 47) - PAGE_SIZE)
将其放在一起:
(1UL << 47) - 4096 == 0x7ffffffff000
; 0x7ffffffff000 / 3 * 2 == 0x555555554aaa
。