OpenHarmony 啃论文计划 -elf 文件格式介绍
1.elf 格式的由来可执行程序也是一个文件,它像图片,文本,mp3,zip 压缩等一样,有自己的固有格式,只不过打开它的软件是操作系统而已。不同操作系统平台对自己可以运行的可执行程序有不同的规范要求。目前主流的有三种格式:linux&Unix : ELF (Executable and Linking Format)Mac (MacOS / iOS) : mach-O (mach-object)Windows : PE (Portable Executable)其中 ELF 和 PE 都是 COFF(Common Object File Format)的变种。COFF 是在 Unix System V Release 3 时由 UNIX 系统实验室(UNIX System Laboratories, USL)⾸先提出并且使⽤的⽂件规范,后来微软公司基于 COFF 格式,制定了 PE 格式标准,并将其⽤于当时的 Windows NT 系统。在 System V Release 4 时,UNIX 系统实验室在 COFF 的基础上,开发和发布了 ELF 格式,作为应⽤程序⼆进制接⼝(Application Binary Interface,ABI)。后来工具接口标准委员会(TIS)选择了正在发展中的 ELF 标准作为工作在 32 位 INTEL 体系上不同操作系统之间可移植的二进制文件格式。可执行和链接格式 (ELF) 规范描述了广泛使用的可执行文件格式,应用程序二进制接口 (ABI) 规范定义了为应用程序构建执行环境所必需的操作系统和应用程序接口。相关文档请查看 linux 基金会链接,也可以下载本文资源英文版和中文版的 elf 规范。ELF 是 Executable and Linkable Format 的缩写,定义了二进制文件、库和核心文件的结构。正式规范允许操作系统正确解释其底层机器指令。ELF 文件通常是编译器或链接器的输出,并且是二进制格式。2 elf 格式介绍 elf 文件是 linux 操作系统加载的可执行文件,操作系统运行程序如下图所示:
我们需要从两方面来理解 elf,一是编译链接的时候生成 elf,二是系统加载 elf 运行时,所以 elf 文件有两种视图。
有三种类型的 elf 文件 1) 可重定位的对象文件(Relocatable object file)这是由源文件在编译阶段生成的 .o 文件,或由.o 组成的静态链接库文件。后面的链接器(link editor)拿一个或一些 .o 文件作为输入,经链接处理后,生成一个可执行的对象文件 (Executable file) 或者一个可被共享的对象文件(Shared object file)。2) 可执行的对象文件(Executable file)这个是可以直接运行的程序,是由源文件编译成.o 文件,然后与共享库链接而成的可执行文件。3) 可被共享的对象文件(Shared object file)这些就是所谓的动态库文件,也即 .so 文件。如果拿静态库来生成可执行程序,那每个生成的可执行程序中都会有一份库代码的拷贝,而动态库整个操作系统只有一份文件,可执行文件加载时会把 so 加载到内存。下边这张图可以很直观的看到这三种类型 elf 文件是怎么生成的:
在静态链接和多个.o 目标文件合并阶段:链接器会扫描所有输入的目标文件,然后把所有符号表里的信息收集起来,构成一个全局的符号表。然后再遍历 elf 重定位表,把所有不确定的跳转地址,根据全局符号表各个符号的实际地址,进行一次修正。最后,把所有的目标文件的对应段进行一次合并,变成了最终的可执行代码(CPU 可执行)。在链接器把程序变成可执行文件之后,要装载器去执行程序就容易多了。装载器不再需要考虑地址跳转的问题,只需要解析 ELF 文件,把对应的指令和数据,加载到内存里面供 CPU 执行就可以了。动态链接的时候由于链接阶段无法把动态库函数地址确定,所以动态链接是在加载阶段确定动态库地址的:在连接器把程序变成可执行文件之后,elf 文件的重定位段中还保存着未知地址的符号,这些符号位于动态链接库。在这种情况下,装载器需要考虑地址跳转的问题,并且需要装载器将该可执行文件引用的动态链接库加载到内存,按照上图中静态链接的方法合并多个 elf 文件的各个段,变成了最终的可执行代码(CPU 可执行)。本文以可执行 elf 文件为例,ELF 文件格式把各种信息,分成一个一个的 Section 保存起来。ELF 有一个基本的文件头(File Header),用来表示这个文件的基本属性,比如是否是可执行文件,对应的 CPU、操作系统等等。除了这些基本属性之外,大部分程序还有这么一些 Section:
首先是.text Section,也叫作代码段或者指令段(Code Section),用来保存程序的代码和指令;接着是.data Section,也叫作数据段(Data Section),用来保存程序里面设置好的初始化数据信息;然后就是.rel.text Secion,叫作重定位表(Relocation Table)。重定位表里,保留的是当前的文件里面,哪些跳转地址其实是我们不知道的。最后是.symtab Section,叫作符号表(Symbol Table)。符号表保留了我们所说的当前文件里面定义的函数名称和对应地址的地址簿。
评论