[置顶] 泰晓 RISC-V 实验箱,配套 30+ 讲嵌入式 Linux 系统开发公开课
史上最小可执行 ELF 文件
by Falcon of TinyLab.org 2015/07/29
笔者最早在 2008 年写过一篇《如何为可执行文件“减肥”》。
该文通过各种努力,把可打印 Hello World 的 Linux ELF 可执行文件,从 6442 个字节,减少到 76 字节。
最近笔者抽空整理该文,并在重读 A Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux(史上最小 Linux ELF 文件,即 ELF Kickers 作者,不过该 ELF 只能产生一个返回值)的基础上,做了进一步突破,先后造出了 52 字节和 45 字节的 ELF 可执行文件,并且可以打印 Hello World。
而社区的早期纪录是 59 字节,也是 ELF Kickers 作者创造的,文件在 ELF Kickers 的 tiny/hello:
$ git clone https://github.com/BR903/ELFkickers
$ cd ELFkickers
$ wc -c tiny/hello
59 tiny/hello
其中 52 字节的突破主要借鉴 A Whirlwind Tutorial on Creating Really Teensy ELF Executables for Linux 关于把 ELF 程序头完全合并进 ELF 文件头的努力,而 45 字节的突破除了继承自己早期那篇文章的用参数赋值的想法外,还有些幸运的因素在(通过非法系统调用可以正常退出程序)。
最后,不仅获得了一个二进制只有 10 字节的 hello.s:
.text
.global _start # stack differ from main()
_start: # stack: argc, argv[0], argv[1], argv[2]
pop %edx # argc, number of argv[]
# 3rd arg: string length: $len
pop %ecx # argv[0], program name with path
# 2rd arg: string to write
#xor %ebx, %ebx # 1st arg: output: stdout:1, use stdin:0
# 1st arg: exit code for sys_exit
mov $4, %al # (1) write our string to stdout
# sys_write: syscall number = 4
int $0x80 # call kernel
mov $1, %al # (2) and exit
# sys_exit: syscall number = 1
int $0x80 # call kernel
最后,完全把 ELF 程序头和代码合并进了 ELF 文件头,而且可以打印字符串。
而最重要的是,通过这个过程,可以透彻地理解 C 语言的开发过程,关于 C、汇编、操作系统背后的很多奥秘。
由于最近把早期的一些文章整理成了《C 语言编程透视》一书,相关记录也更新到了该书。
如果想了解该 ELF 裁剪的细节,请移步《C 语言编程透视》GitBook 版,并阅读第 10 章。
欢迎做进一步交流,关注我们的微博@泰晓科技 或者关注我们的开源书籍项目 Github 源码仓库。也欢迎提交 Pull Request。
猜你喜欢:
- 我要投稿:发表原创技术文章,收获福利、挚友与行业影响力
- 知识星球:独家 Linux 实战经验与技巧,订阅「Linux知识星球」
- 视频频道:泰晓学院,B 站,发布各类 Linux 视频课
- 开源小店:欢迎光临泰晓科技自营店,购物支持泰晓原创
- 技术交流:Linux 用户技术交流微信群,联系微信号:tinylab
| 支付宝打赏 ¥9.68元 | 微信打赏 ¥9.68元 | |
![]() | ![]() 请作者喝杯咖啡吧 | ![]() |





