当我们又两个目标文件时,如何将他们链接起来形成一个可执行文件?这个过程发生了
什么?这基本上就是链接的核心:静态链接。在本章中,将会用一下两个源文件a.c和
b.c做为例子说明:
//a.c
extern int shared;
int main() {
int a = 100;
swap(&a, &shared);
return 0;
}
//b.c
int shared = 1;
void swap(int* a, int* b) {
*a ^= *b ^= *a ^= *b;
}
4.1 空间与地址分配
对于多个输入目标文件,链接器如何将它们的各个段合并到输出文件?或者说,输出文件
中的空间如何分配给输入文件?
4.1.1 按序叠加
即将输入的目标文件按照次序叠加起来。
4.1.2 相似段合并
一个更为实际的方案是将相同性质的段合并到一起,使用这种方法的链接器一般都采用一种
叫做两步链接(Two-Pass Linking)的方法,整个链接过程分为两步:
1.空间与地址分配。链接器获得所有输入目标文件的段长度,将它们合并,计算出输出文件
中各个段合并后的长度和位置,并建立映射关系。同时,将输入目标文件中的符号表所有符
号的定义和引用收集起来,同一放到一个全局的符号表中。
2.符号解析和重定位。使用第一步收集到的信息,读取输入文件中段的数据、重定位信息,
并且进行符号解析和重定位、调整代码中的地址等。
***图4.1.2.1***
***图4.1.2.2***
***图4.1.2.3***
链接后的可执行文件中的地址已经是进程执行时所用到的虚拟地址,即图4.1.2.3各个段中
的VMA(Virtual Memory Address)。在链接之前,如图4.1.2.1和图4.1.2.2所示,目标文件
中所有段的VMA都是0,因为虚拟空间还没又被分配,所以默认为0.在Linux下,ELF可执行
文件默认从地址0x08048000开始分配。