这是一个非常简单的汇编程序,只需返回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)
由于它从文件偏移量零开始,因此它可能是一个“填充”段,旨在使 ELF 的加载更加高效。
这.text事实上,段已经在文件中对齐,因为它应该在内存中对齐。
你可以强制ldnot对齐内存中的部分和在文件中 with -n
。您还可以使用删除符号-s
.
这会将大小减少到大约 352 字节。
现在 ELF 包含:
- ELF 标头(必需)
- 程序头表(需要)
- 代码(需要)
- 字符串表(可能不需要)
- 节表(可能不需要)
字符串表可以删除,但显然strips
不能那样做。
我已经删除了.shstrtab
手动删除节数据和所有节头,将大小缩小到 144 字节。
考虑 64 个字节来自 ELF 标头,60 个字节来自单个程序标头,12 个字节来自您的代码;总共 136 字节。
额外的 8 个字节是填充,其中 4 个字节位于代码部分的末尾(易于删除),还有一个位于程序头的末尾(需要进行一些修补)。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)