[置顶] 泰晓 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元 | |
请作者喝杯咖啡吧 |