为什么我的 ELF 二进制文件中 LOAD 段的 VirtAddr 显示为 0x0000000000000000?

Why does the VirtAddr of the LOAD segment in my ELF binary show as 0x0000000000000000?

我编译了一个 hello world C 程序,这是 file 信息:

hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, BuildID[sha1]=3c4fc3bc82d53281357312935790846333a3c7bc, with debug_info, not stripped

当我检查段头信息时,我看到 LOAD 段的 VirtAddr 指向地址 0x0000000000000000,它被定义为 NULL。入口地址为 0x540,表示它位于两者的第一个 LOAD 段中。 E(执行)标志和 .text 部分也映射到第一个 LOAD 段。

当我使用 gdb 并在 main 设置断点时,我看到地址发生了变化,这意味着地址已经移动了一定的偏移量。为什么会这样?我尝试多次加载程序,但偏移量保持不变,这意味着没有地址随机化发生。我在 SO 上看到 other questions 正在获取与我相反的加载地址。为什么?当我用 -m32 编译时,同样的事情发生了。在过去的几年里,我从链接的问题中得到不同的输出,是否有什么变化 w.r.t linux?

您看到 0 表示 LOAD,因为您的 ELF 与位置无关。

现代版本的 GCC 默认生成 Position Independent Executables(除非另外配置)。如果可执行文件是 PIE,则 ELF headers 中的基虚拟地址设置为 0。当您 运行 您的程序在 GDB 下时,它会暂时禁用地址随机化并在默认地址 0x0000555555554000.

加载您的程序

如果要编译 non-PIE 可执行文件,可以使用 -no-pie -fno-pie 编译标志。