Linux 使用 LD 的最小加载地址
Linux minimum Load Address with LD
在Linux理解ELF程序加载的过程中,我尝试用一个段的加载地址进行实验
将 ld 与以下 linker 脚本一起使用:
SECTIONS
{
. = 0x2000;
.text :
{
*(.text)
}
}
使用以下 link 命令:
ld -o elftest -z max-page-size=4096 -Telftest.l elftest.o
请假设 elftest.o 是一个普通的非重要 asm 代码的编译结果。
程序 link 正确地进入了 0x2000。发生的事情是程序被内核杀死,并在 shell 中输出 KILLED。
我想澄清一件事:
这不是段错误或任何其他异常,程序甚至没有到达入口点
--segments 的 readelf 输出是
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000001000 0x0000000000002000 0x0000000000002000
0x0000000000000009 0x0000000000000009 R E 1000
我的理解是这样的:
- 使用 max-page-size=4096 可以让我打破 ld 的 2MiB 对齐要求 https://lkml.org/lkml/2012/7/9/46
- 该段必须与内存页对齐,即 4KiB,因此设置为 4096 是正确的
- 基地址是任意的,通常对于x86_64是0x400000
我不明白的是:
- 当满足对齐要求时,为什么小地址不起作用(被杀死)?
- 如果有最低要求的地址记录在哪里?
- 为什么它使用更高的基地址,即 0x16000?
我在一台 64 位计算机上做这个测试,Arch Linux 内核 3.17.1 和 ld 2.24
您 运行 对用户空间应用程序可以映射页面的位置有内核限制;这些限制旨在防止某些内核漏洞发挥作用。最小可映射地址由 vm.mmap_min_addr
sysctl 值设置,通常至少为 4096(即 0x1000)。
详情参见:https://wiki.debian.org/mmap_min_addr(这种情况并非 Debian 独有;他们的文档只是我找到的第一个。)
在Linux理解ELF程序加载的过程中,我尝试用一个段的加载地址进行实验
将 ld 与以下 linker 脚本一起使用:
SECTIONS
{
. = 0x2000;
.text :
{
*(.text)
}
}
使用以下 link 命令:
ld -o elftest -z max-page-size=4096 -Telftest.l elftest.o
请假设 elftest.o 是一个普通的非重要 asm 代码的编译结果。
程序 link 正确地进入了 0x2000。发生的事情是程序被内核杀死,并在 shell 中输出 KILLED。
我想澄清一件事:
这不是段错误或任何其他异常,程序甚至没有到达入口点
--segments 的 readelf 输出是
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000001000 0x0000000000002000 0x0000000000002000
0x0000000000000009 0x0000000000000009 R E 1000
我的理解是这样的:
- 使用 max-page-size=4096 可以让我打破 ld 的 2MiB 对齐要求 https://lkml.org/lkml/2012/7/9/46
- 该段必须与内存页对齐,即 4KiB,因此设置为 4096 是正确的
- 基地址是任意的,通常对于x86_64是0x400000
我不明白的是:
- 当满足对齐要求时,为什么小地址不起作用(被杀死)?
- 如果有最低要求的地址记录在哪里?
- 为什么它使用更高的基地址,即 0x16000?
我在一台 64 位计算机上做这个测试,Arch Linux 内核 3.17.1 和 ld 2.24
您 运行 对用户空间应用程序可以映射页面的位置有内核限制;这些限制旨在防止某些内核漏洞发挥作用。最小可映射地址由 vm.mmap_min_addr
sysctl 值设置,通常至少为 4096(即 0x1000)。
详情参见:https://wiki.debian.org/mmap_min_addr(这种情况并非 Debian 独有;他们的文档只是我找到的第一个。)