静态链接:
像Unix ld程序这样的静态链接器以一组可重定位目标文件和命令行参数作为输入,生成一个完全链接的可以加载和运行的可执行目标文件作为输出。输出的可重定位目标文件由各种不同的代码和数据节(section)组成。指令在一个节中,初始化的全局变量在另一个节中,而未初始化的变量又在另一个节中。
为了构造可执行文件,链接器必须完成两个主要任务:
- 符号解析(symbol resolution):目标文件定义和引用符号。符号解析的目的是将每个符号引用刚好和一个符号定义联系起 来。
- 重定位(relocation):编译器和汇编器生成从地址0开始的代码和数据节。链接器通过把每个符号定义与一个存储器位置 联系起来,然后修改所有对这些符号的引用,使得它们指向这个存储器位置,从而重定位这些节。
目标文件:
目标文件有三种形式:
- 可重定位目标文件:包含二进制代码和数据,其形式可以在编译时与其它可重定位目标文件合并起来,创建一个可执行目标 文件。
- 可执行目标文件:包含二进制代码和数据,其形式可以被直接拷贝到存储器并执行。
- 共享目标文件:一种特殊类型的可重定位目标文件,可以在加载或运行时被动态地加载到存储器并链接。
编译器和汇编器生成可重定位目标文件(包括共享目标文件)。链接器生成可执行目标文件。
可重定位目标文件:
ELF头以一个16字节的序列开始,这个序列描述了生成该文件的系统的字的大小和字节顺序。ELF头剩下的部分包含帮助链接器语法分析和解释目标文件的信息。其中包括ELF头的大小、目标文件的类型(r如可重定位、可执行或共享)、机器类型(如IA32)、节头部表的文件偏移,以及节头部表中的条目大小和数量。不同节的位置和大小都是由节头部表描述的。其中目标文件中每个节都有一个固定大小的条目(entry)。
夹在ELF头和节头部表之间的都是节。一个典型的ELF可重定位目标文件包含以下几个节:
符号和符号表
每个可重定位目标模块都有一个符号表,它包含m所定义和引用的符号的信息。在链接器的上下文中,有三种不同的符号:
- 有m定义且能被其他模块引用的全局符号:全局链接器符号对应于非静态的C函数以及被定义为不带C static属性的全局变量
- 由其他模块定义并被模块m引用的全局符号:称之为外部符号(external),对应于定义在其他模块中的C函数和变量。
- 只被模块m定义和引用的本地符号:这些符号在m中随处可见但不能被其他模块引用。
符号表是由汇编器构造的,使用编译器输出到汇编语言.s文件中的符号。