为什么入口点地址不从 0x400000 开始

Why does not entry point address start at 0x400000

在 Ubuntu 20.10 x86_64

我的示例代码:

#include <stdio.h>
#include <stdlib.h>

int main() {
    printf("helloworld\n");
    return 0;
}

建造gcc -o test test.c

显示入口地址:

readelf -h ./test

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:               0x1060
  Start of program headers:          64 (bytes into file)
  Start of section headers:          14824 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         31
  Section header string table index: 30

为什么入口点地址从 0x1060 开始?不是 0x40000 吗?

二进制文件是relocatable,段已经相互打包。 .text 段从文件中的 0x1050 开始,入口点是相对于它在文件中的位置,而不是它最终加载的位置。

对于非 relocatable 文件尝试 readelf -h /usr/lib/klibc/bin/sh。这个文件在很多方面都比较简单,包括不使用解释器,而是实际上由内核按原样加载。

我们不在 x86 了。 Relocatable 二进制文件现在是所有内容的默认设置,而不仅仅是共享库。做 relocatable 的事情不再是一件很痛苦的事,而且在某种程度上它现在比非 relocatable 便宜,因为我们无论如何都必须发出向量 table 因为处理器没有'有 64 位位移。

正如 Nate Eldredge 指出的那样,使用 -no-pie 编译会产生一个非 relocatable 二进制文件,我已经验证了预期的起始地址出现。