目标文件格式
复习
- 生成汇编代码:汇编之后还要经汇编器
- 程序在内存里的样子:代码区、数据区等
- 从源代码到可执行文件:编译、汇编、链接的流水线
TL;DR
- 目标文件是汇编器产出的中间产物,还不是可执行文件
- 它包含机器码,还包含符号、分段和其他元数据
- 常见内容:代码段、数据段、符号表、重定位信息
- 多个目标文件要靠链接合成为可执行文件
正文
汇编代码经汇编器翻译,得到的不直接是可执行文件,而是一个目标文件(object file)。为什么还要一个中间的“目标文件”,而不是一步生成可执行文件?
因为它还不知道“最终在哪”
根本原因在于:编译一个文件时,编译器还不知道整个程序最终会怎么摆放。
比如你的代码里调用了另一个文件里的函数、或者用了一个外部变量。这个函数最终会被放在内存的哪个地址?此刻谁也说不准——那要等所有文件合在一起、统一分配地址之后才知道。
既然地址未知,目标文件里就要做两件事:
- 先留个“空位”:那个地址暂时空着
- 顺便记一笔:这里将来需要填上一个地址
这笔“哪里需要填地址”的记录,就是重定位信息,是下一章的主角。
目标文件里有什么
一个典型的目标文件,大致包含:
- 机器码(代码段)
- 已初始化的数据(数据段)、未初始化的数据(可简记为一个大小)
- 符号表:这个文件对外提供了哪些名字,又引用了哪些外部的名字
- 重定位信息:哪些位置需要链接时填地址
你会发现,它和我们讲程序在内存里的样子时说的“代码区、数据区”,是能对上的:目标文件其实就是这些内容在磁盘上的“打包形态”。
它是砖,不是房子
目标文件像是盖房子用的一块砖:它自身完整,却还不是一座房子。多个目标文件(以及库)要由链接器拼在一起,才成为可执行文件。
所以,从源码到能运行的程序,路径是:
源代码 →(编译)→ 汇编 →(汇编)→ 目标文件 →(链接)→ 可执行文件
前面讲编程基础时,我们把“编译、汇编、链接”当成黑箱;现在,我们正站在“汇编之后、链接之前”。下一组,就正式进入链接。
思考题 1
目标文件里除了机器码,还需要哪些信息?为什么?
思考题 2
为什么汇编器不直接生成可执行文件,而要先生成目标文件?
小结
知识点
- 目标文件是汇编器产出的中间产物
- 它含代码段、数据段、符号表与重定位信息
- 因为外部地址未知,需要先留空并记录
- 多个目标文件由链接器合成可执行文件
参考资料
- Wikipedia(zh):目标文件:汇编器生成的、等待链接的中间文件
- Wikipedia(zh):符号表:目标文件中记录名字与引用的表
思考题答案(仅供参考)
思考题 1
还需要符号表(记录本文件提供和引用的名字)和重定位信息(记录哪些位置将来需要填入地址),以及各段的内容与布局。因为编译单个文件时外部符号的最终地址未知,必须留待链接时确定。
思考题 2
因为单个文件编译时还不知道外部符号的地址,也无法与其它文件合并。先生成目标文件、记录好符号与重定位信息,再由链接器统一分配地址、合并各段,才能得到可执行文件。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪