泰晓科技 -- 聚焦 Linux - 追本溯源,见微知著!
网站地址:https://tinylab.org

泰晓RISC-V实验箱,转战RISC-V,开箱即用
请稍侯

史上最小可执行 ELF 文件

Wu Zhangjin 创作于 2015/07/29

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 Kickerstiny/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。



Read Album:

Read Related:

Read Latest: