我的 Linux 可执行程序(64 位)中的段 00 是什么

what is segment 00 in my Linux executable program (64 bits)

这是一个非常简单的汇编程序,执行后return12

$ cat a.asm
        global _start

        section .text
_start: mov rax, 60    ; system call for exit
        mov rdi, 12    ; exit code 12
        syscall

可以正确构建和执行:

$ nasm -f elf64 a.asm && ld a.o && ./a.out || echo $?
12

但是a.out的大小很大,超过4k:

$ wc -c a.out
4664 a.out

我尝试通过阅读精灵内容来理解它:

$ readelf -l a.out

Elf file type is EXEC (Executable file)
Entry point 0x401000
There are 2 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000000b0 0x00000000000000b0  R      0x1000
  LOAD           0x0000000000001000 0x0000000000401000 0x0000000000401000
                 0x000000000000000c 0x000000000000000c  R E    0x1000

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .text 

很奇怪,00段是0x1000对齐的,我想这意味着这样的段至少会占用4096字节。

我的问题是这个段 00 是什么?

(nasm 版本 2.14.02, ld 版本 2.34, os 是 Ubuntu 20.04.1)

由于它从文件偏移量零开始,它可能是为了提高 ELF 的加载效率而引入的“填充”段。 .text 段实际上已经在文件中对齐,因为它应该在内存中。

您可以强制 ld not 将内存中的部分和文件 中的 部分与 -n 对齐。您还可以使用 -s.
去除符号 这会将大小减少到大约 352 字节。

现在 ELF 包含:

  • ELF header(需要)
  • 程序headertable(需要)
  • 代码(需要)
  • 字符串table(可能不需要)
  • table 部分(可能不需要)

字符串table可以删除,但显然strips不能那样做。 我已经手动删除了 .shstrtab 部分数据和所有 header 部分,以将大小缩小到 144 字节。 考虑 64 个字节来自 ELF header,60 个来自单个程序 header,12 个来自您的代码;总共 136 个字节。
额外的 8 个字节是填充,代码部分末尾有 4 个字节(易于删除),程序末尾有一个 header(这需要一点修补)。