20171104-程序员的自我修养

今天看4.2符号解析与重定位


这部分是接着昨天的部分,都是静态链接中的步骤。

在完成了空间地址的分配之后,链接器就进入了符号解析与重定位的步骤,也是静态链接的核心步骤。

编译完成后,静态链接完成之前,a.o的反汇编为:

20171104-程序员的自我修养

18行使用的为b.o中定义的shared变量;26行使用的为b.o中定义的函数swap()

movl对应的机器码为c7 44 24 04,后面跟的为地址信息,图中为00 00 00 00,是因为编译器暂时不知道外部变量shared的确切地址,所以暂时用0x 00 00 00 00来代替,真正的寻找地址的工作交给链接器来完成。

同理,26行为调用swap函数,call为调用的汇编语句,其机器码为0xe8,后面跟的为目的地址相对于下一条指令的偏移,0x fc ff ff ff为-4的补码形式,下一条指令的地址为0x2b,因此此处call所调用的地址为0x2b-4=0x27,这是一个假地址,和上面的shared变量类似,编译器此时并不知道swap函数的真正地址。


从昨天的笔记中可知,链接过程完成后,各个符号的虚拟地址都可以确定,因此链接器可以将上面的符号的假地址进行替换。链接完成的ab文件反汇编后如下:

20171104-程序员的自我修养

有图可以看出,movl后面的地址变为了0x08 91 04 08,call后面的地址也变为0x 09 00 00 00,即都变为了符号的真正地址。


至此,链接器就完成了符号的解析和重定位过程。

明天继续记一下常见的链接错误背后的真正原因。