在Linux中,.o可重定位文件,可执行文件/bin/bash,共享目标文件.so,核心存储文件,都可以称为目标文件,采用Elf格式存储。
一般来说,生成的.o文件都包括重定位表和符号表,这两个表都以段的形式表现。
重定位表:rel.text;rel.data等,如果引用了其余目标中间中的函数或全局变量,就会在这两个段中标明出来,通过指明段类型为SHT_REL,来标明该段是重定位段。
符号表:段名一般叫.symtab,每个符号都由如下结构体来表现:
typedef struct{
Elf32_Word st_name;//符号名字
Elf32_Addr st_value;//符号直,可能是绝对值,也可能是一个地址
Elf32_Word st_size;//符号大小
unsigned char st_info;//符号绑定信息以及符号类型
unsigned char st_other;
Elf32_Half st_shndx;
}Elf32_Sym;
熟悉单个目标文件的格式以后,就能更好的理解链接过程了。
编译器和汇编器生成从地址零开始的代码和数据段,连接器通过把每个符号定义与一个存储器位置联系起来,然后修改所有对这些符号的引用,使得它们指向这个存储器位置,从而重定位这些指令。
链接器在链接多个.o文件时,首先会合并各个.o文件的重定位表段以及符号表段,链接时先确定目标文件的虚拟地址,随后就能知道各个符号的绝对的虚拟地址。得知此地址后再去更新新的符号表段中各个符号的地址;符号确定后,再按照重定位表段,去更新指令中需要重定位的地址或数值。