大学那会儿我闲得慌,开始研究ELF文件格式。说实话,之前学链接器那套理论,什么重定位、符号解析,听着就头大。后来想着直接动手,拿二进制编辑器打开一个可执行文件,一行一行看结构。那种感觉就是:哦,原来底层长这样,比啃书爽多了。
![]()
我甚至干过一件蠢事:用ld脚本去处理a.out,但中间文件还是ELF。然后才发现,原来链接器再怎么折腾,最后装东西的容器还是ELF。那一刻我就觉得,设计这套规则的人真牛逼,他们怎么做到三十多年前就把事情想得这么清楚的。
今天聊聊这个被吹了很多年的文件格式。它1988年就定下来了,到现在Linux、各种Unix系统还在用。不是没有别的格式出来,但就是没人能把它挤掉。你说它完美吗?肯定也不是。但就是找不到很多能挑毛病的地方。
在ELF出现之前,可执行文件格式一片混乱。a.out最简单,但缺点太多:不支持动态链接,内存加载效率低,连个像样的段权限都没有。COFF稍微好一点,引入了节(Section)的概念,但扩展性差,而且不同操作系统对它的解释不一样,没法统一。
后来System V Release 4搞出了ELF。它最聪明的一手,就是把“链接视图”和“执行视图”彻底分开。啥意思呢?就是给链接器看的东西和给操作系统加载器看的东西,是两套不同的表。链接器只管合并节、做重定位,操作系统只管把权限相同的节打包成段,按需加载到内存。各干各的,谁也不耽误谁。
我自己逆向的时候,最先看的就是ELF头。这个头本身很薄,就记了几个偏移量和大小。但它神奇的地方在于:你只要读懂了这几十个字节,就能找到程序头表和节头表的位置、数量。这种自描述的设计,在1988年简直就是超前。
再往下看,程序头表是给操作系统用的。操作系统根本不关心你的代码叫什么名字,它只关心哪些内存区域要读,哪些要写,哪些要执行。所以程序头表把多个同权限的节合并成一个段,加载的时候一次性映射。而节头表是给链接器和调试器用的,每个节的名字、属性、对齐方式都很清楚。比如`.text`放代码,`.data`放全局变量,`.rodata`放只读数据。
这些节里的东西更讲究。`.interp`告诉加载器动态链接器的路径;`.dynamic`记录了动态链接需要的所有信息;`.hash`是哈希表,用来快速查找符号,对性能影响很大;`.debug_*`系列节专门放调试信息,发布时可以直接剥离,不影响运行。这种模块化设计,让ELF可以灵活扩展,而不需要改动核心结构。
ELF之所以能成为ABI(应用二进制接口)的基础,是因为它定义了一套通用的“游戏规则”。不管是GCC编译C代码,还是Rust编译Rust代码,最后生成的都是同一个ELF格式。不同架构的CPU(x86、ARM、RISC-V)也只是在ELF的框架里规定了各自的调用约定和数据类型大小。这就像TCP/IP协议一样,底层怎么实现不管,但上层通信的格式大家统一。
我觉得ELP设计最厉害的地方,是它的“克制”。设计者没有把所有可能用到的特性都塞进标准里,而是只搭好了基础框架——头、程序头表、节头表。剩下的所有东西,比如动态链接、位置无关代码、弱符号,都是在已有框架里通过标准扩展实现的。这样既保证了兼容性,又给未来留足了空间。
当然它也不是完美的。对嵌入式系统来说,ELF太复杂了。一个简单的单片机程序,可能就用几个字节的数据,但ELF头就要占好几十。而且动态链接器的复杂性,比如符号冲突、延迟绑定,这些虽然不是ELF本身的问题,但确实是使用了ELF之后才引入的麻烦。
但回到最开始的问题,为什么三十多年了还没人做出更好的替代品?我觉得是因为ELF的抽象层级太高了。它不只是个文件格式,更像是操作系统和程序之间的一份“契约”。想打破这份契约,就得重新定义整个工具链、加载器、动态链接器,这个成本太大了。
我想起自己那次用ld脚本偷换概念的实验。我想着能不能绕过ELF,直接用a.out的流程。结果链接器虽然假装生成了a.out,但中间那一层还是ELF。就像你换了一层皮,但骨子里还是那套结构。这说明什么?说明ELF已经渗到工具链的每个毛细血管里了,想绕都绕不开。
最后说回“设计规则的人真牛逼”这件事。逆向学习的好处,就是能让你直接触摸到这些规则的本意。不是背书,而是亲手拆开它,看看里面到底怎么工作的。当你看到那些偏移量、标志位、段权限是如何被精确控制的时候,你就会明白:一个好的设计,不是把所有事情做满,而是把基础框架做到位,剩下的让后人去填。
下一个十年,内存安全、异构计算这些新东西出来,说不定会有新的容器格式。但要像ELF这样,用一个设计撑住三十多年的生态,我觉得很难。至少到目前为止,它依然是那个“不可挑剔”的容器。
特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.