我的Linux可执行程序中的段00是什么(64位)
这是一个很简单的汇编程序,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
我尝试通过阅读精灵内容来理解它:
$ 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不将内存和文件中的部分与-n
. 您还可以使用 去除符号-s
。
这会将大小减少到大约 352 字节。
现在 ELF 包含:
- ELF 标头(需要)
- 程序头表(需要)
- 代码(需要)
- 字符串表(可能不需要)
- 节表(可能不需要)
可以删除字符串表,但显然strips
不能这样做。我已经.shstrtab
手动删除了节数据和所有节标题,以将大小缩小到 144 字节。考虑到 64 个字节来自 ELF 标头,60 个来自单个程序标头,12 个来自您的代码;总共 136 个字节。
额外的 8 个字节是填充,4 个字节在代码部分的末尾(易于删除),一个在程序头的末尾(需要一点修补)。