前言
笔者目前所在项目的elf文件是由一个个object文件,按照link脚本规则,通过gnu ld工具生成的。“链接”在笔者的眼里好像一个魔法师一样,它在各模块程序员的眼皮子底下悄无声息地将所有目标文件解析拼接成可执行程序。对很多程序员来说,链接好像是理所当然的。但其实不然,在项目早期,已经有团队大佬将编译架构搭好了。对于一个有追求的嵌入式软件工程师,应该研究研究链接过程。但到目前为止,我们还有一个问题需要解决,否则项目的链接脚本是不可能看懂的。这个问题是object文件的格式是什么样的?
目标文件格式
ELF,Executable and Linkable Format,是一个标准的文件格式,可执行文件,目标文件,动态链接库,core dump都符合ELFwikipedia。
一个ELF有两个views:一个是链接时的view,一个是运行时view。
下图中的Program header table描述的是运行时的segements。Sectoin header描述了链接和重定位时的sections。
ELF headler
ELF头位于目标文件的开始。头包含了一些此目标文件的信息。在linux下可以使用readelf -h 目标文件名
来查看目标文件的头。这是笔者项目中某个目标文件的头信息。
ELF头的结构如下(仅供参考):
Section header table
Section header table用来定位文件中所有的section。一般来说,这个table是一个元素类型为Elf32_Shdr 的数组。Elf32_Shdr 的结构体如下(仅供参考)
特殊的Secton
各种各样的sections包含代码和控制信息。常见的section有:
- .bss 包含程序未初始化的数据
- .data 包含初始化了的数据
- .rodata 包含只读的数据
- .text 包含程序的可执行命令
- .dynamic 包含动态链接的信息
- .comment 包含注释信息
- 其他
符号表
目标文件的符号表包含了在定位和重定位时需要的程序符号的定义和引用信息。一个符号表成员的数据结构如下(仅供参考):
总结
笔者只对目标文件的格式做了一个概述,至于细节需要在以后遇到问题的时候去细究。弄懂了目标文件的结构,就可以大胆去阅读工程的链接脚本了。