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

3
这是一个非常简单的汇编程序,执行后只需返回12
$ 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

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

$ 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,操作系统为Ubuntu 20.04.1)

1个回答

9

由于从文件偏移量0开始,它很可能是引入的“填充”段,以使ELF的加载更加高效。 实际上,.text段已经按应该在内存中的方式对齐在文件中。

你可以使用-n强制ld不要对内存和文件中的节进行对齐。你也可以使用-s去掉符号。
这将把大小减少到约352字节。

现在ELF包含:

  • ELF头(必需)
  • 程序头表(必需)
  • 代码(必需)
  • 字符串表(可能不需要)
  • 节表(可能不需要)

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


我认为这是为了在您取消引用空指针时创建段错误而存在的。(包括在结构体内部某个适度偏移处的成员“member”时,当“p”为空时,包括“p->member”)。 - Nemo
1
你是否在考虑零页?ELF文件并未加载到虚拟地址0,而该段在内存中存在。 - Margaret Bloom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接