20171103-程序员的自我修养

今天开始看第四章,静态链接。由于这本书中内容大多为编译器和链接器的内容,故大部分都无法用例子程序的方式记录。


对于链接器来说,输入为目标文件a.o和b.o,输出为可执行文件ab。

a,b的代码为:

20171103-程序员的自我修养20171103-程序员的自我修养

一般来说,有两种方式:

1.按序叠加,即简单的按照次序讲不通目标文件的各个段叠加起来。这样做会让内存中存在大量零散的段(每个段必须占用单独的页,x86位4096字节即4k)

20171103-程序员的自我修养

20171103-程序员的自我修养

2.相似段合并:将不通目标文件的相同的段(节)放在一起,这样做有利于节省内存空间

20171103-程序员的自我修养

20171103-程序员的自我修养

一般的编译器采用第二种方案,步骤为:

2.1:空间和地址分配:将不同目标文件的各个段的长度属性信息汇总在一起,将它们合并,并建立映射关系;

2.2:根据2.1的信息,进行符号解析与重定位,调整代码中的地址,此步骤为核心步骤


链接器链接前后各个段的属性如下:

20171103-程序员的自我修养

20171103-程序员的自我修养

由图可以看到,链接之后,.text段的size变为两者之和0x72,.data段由于a.o没有所以和b.o的数值相同。

ps:VMA为Virtual Memory Address;LMA为Load Memory Address若程序放在ROM中,两者不同,只需关注VMA即可。

链接之前所有段的VMA均为0,链接之后.text段变为0x08048094大小0x72字节,.data变为0x08049108大小4字节,那么,链接前后各段的地址关系如下:

20171103-程序员的自我修养

20171103-程序员的自我修养

在Linux下,ELF可执行文件的默认地址从0x08048000开始分配,地址0处为操作系统所占用。


综上,再根据每个符号所占用的空间,就可以推算出每个符号所在的虚拟地址位置。