7.1
链接是将各种代码和数据片段收集并组合成为一个单一文件的过程。
驱动程序首先运行C预处理器(cpp),它将C的源程序main.c翻译成一个ASCII码的中间文件main.i,接下来驱动程序运行C编译器,它将main.i翻译成一个ASCII汇编语言文件main.s,然后驱动程序运行汇编器,它将main.s翻译成一个可重定位目标文件main.o,最后链接器把所有.o文件以及一些必要的系统目标文件组合起来,创建一个可执行目标文件。
7.2
首先整体介绍了一下静态链接的概念,以及静态链接的工作是什么。
静态链接:以一组可重定位目标文件和命令行参数作为输入,生成一个完全链接的、可以加载和运行的可执行目标文件作为输出。
一共有两个主要任务:
符号解析:目标文件定义和引用的符号,每个符号对应于一个函数、一个全局变量或一个静态变量(注意,没有局部变量)。符号解析的目的是将每个符号引用正好和一个符号定义关联起来。
重定位:在完成符号解析后,就可以重定位这些节,修改所有对这些符号的引用,使得他们指向这个内存位置。
7.3
然后交代了目标文件的概念。
有三种形式,
可重定位目标文件:包含二进制代码和数据,在编译时与其他可重定位目标文件合并起来,创建一个可执行目标文件。
可执行目标文件:包含二进制代码和数据,其形式可以被直接复制到内存并执行。
共享目标文件:特殊的可重定位目标文件,可被动态地加载进内存并链接。
然后开始说目标文件的格式:ELF。
目标文件都是按照特定的文件格式来组织的,Linux 和 Windows使用 可执行可链接格式(ELF)。
7.4
可重定位目标文件的ELF格式中,比较重要的部分是
.text(函数的机器代码), .data(已初始化的全局和静态C变量), .bss(未初始化的全局和静态C变量),注意:局部C变量在运行时被保存在栈中。
.symtab,符号表,接下来还介绍。
7.5
符号表里包含m定义和应用的符号信息,一共有三种不同的符号:
1. 由模块m定义并能被其他模块引用的全局符号。 非静态的C函数和全局变量。
2. 由其他模块定义并被模块m引用的全局符号,称为外部符号。其他模块定义的非静态C函数和全局变量。
3. 只被模块m定义和引用的局部符号。 带static属性的C函数和全局变量。这些符号在模块m中任何位置可见,但不能被其他模块引用,类似类定义中的private变量。、
符号表不包含任何局部非静态变量,它们在栈中被管理。
所以说,只有全局变量,全局函数,静态变量,静态函数有符号的概念!
COMMON 未初始化的全局变量
.bss 未初始化的静态变量和初始化为0的全局或静态变量
7.6.1
符号解析的过程中,可能会遇到多重定义的全局符号。
全局符号有强弱之分:
函数和已初始化的全局变量是强符号。
未初始化的全局变量是弱符号。
7.6.2
与静态库链接。静态库以一种称为存档的特殊文件格式存放在磁盘中,存档文件名由后缀.a标识。
在符号解析阶段,链接器从左到右按照它们在编译器驱动程序命令行上出现的是顺序来扫描可重定位目标文件和存档文件,在命令行中,如果定义一个符号的库出现在引用这个符号的目标文件之前,那么引用就不能被解析。