深入理解计算机系统 链接

来源:互联网 发布:2017最新人生网络用语 编辑:程序博客网 时间:2024/05/24 06:58

链接的两个任务:

1.符号解析:将每个符号引用与可重定位目标文件中符号表的一个确定的符号联系起来。

2.重定位:将每个符号定义与一个存储器位置定义联系起来,并修改所有对这些符号的引用,使他们指向这个存储器位置。


目标文件:1.可重定位目标文件2.可执行目标文件3.共享目标文件

编译器和汇编器生成可重定位目标文件(包括共享目标文件),链接器生成可执行目标文件。


可重定位目标文件(.o)

ELF头.text.rodata.data.bss.symtab.rel.text.rel.data.debug.line.strtab节头部表

符号:

1.带static

2.不带static的本模块定义的

3.不带static的本模块声明在其它模块定义

typedef struct{int name;//string table offsetint value;//section offset,or VM addressint size;char type:4,//data,func,section or sre file namebinding:4;//local or globalchar reserved;char section;}ELF_Symbol//符号表


符号解析

强符号:函数和已初始化的全局变量

弱符号:未初始化的全局变量

对于多重定义的符号:

规则一:不允许有多个强符号

规则二:有一个强符号和多个弱符号,选择强符号

规则三:有多个弱符号,任选一个。


如何使用静态库来解析引用?

集合E(一个可重定位目标文件的集合),集合U(未解析的符号集合),集合D(已定义的符号集合)。初始都为空。

1.对每个输入文件f,若f是是目标文件,f添加到E,更新U和D;

2.若f是存档文件(静态库),尝试匹配U和存档文件成员定义的符号。可能会修改U和D

3所有文件扫描后若U非空,则链接返回错误。否则,合并和重定位E中的目标文件,构建可执行文件。

所以要注意库的依赖关系,存档文件顺序。


重定位:将每个符号定义与一个存储器位置定义联系起来,并修改所有对这些符号的引用,使他们指向这个存储器位置。

1.重定位节和符号定义。将所有相同类型的节合并一起,分配虚拟地址。当这一步完成时,程序中的每个指令和全局变量都有唯一的运行时存储器地址。

2.重定位节中的符号引用。修改代码节和数据节中每个符号的引用,使其指向正确的运行时地址。依赖于 重定位条目ELF32_Rel

typedef struct{int offset;//offset of the reference to the relocateint symbol:24,type:8;//包括32位相对引用,32位绝对引用等类型}ELF32_Rel

重定位伪代码

foreach section s{foreach relocation entry r{refptr = s + r.offset;if(r.type==R_386_PC32)//相对寻址{refadd = ADDR(s) + r.offset;//求出引用的运行时地址*refptr = (unsigned) (ADDR(r.symbol) + *refptr - refaddr);//运行时 符号地址与引用符号地址的差。}if(r.type==R_386_32)//绝对寻址*refptr = (unsigned) (ADDR(r.symbol) + *refptr);}}


一篇很好的文章

C编译器,链接器,加载器详解http://blog.csdn.net/zzxian/article/details/16820035

0 0