• Chap-4 Section 4.2 符号解析和重定位


    在完成空间和地址的分配步骤后,链接器进入了符号解析与重定位的步骤,这也是静态链接
    的核心内容。
    首先看一下目标文件a.o中怎么使用两个外部符号shared和swap的。用objdump -d a.o查看
    反汇编后的结果,如图4.2.1:


    ***图4.2.1***
    可以很清楚的看到a.o的反汇编结果中,a.o共定义了一个函数main,这个函数占用0x2b个字节,
    共12条指令,最左边那列是每条指令的偏移量,每行代表一条指令,有的指令很长,例如偏移
    量为0x09和0x11的两条指令,对于变量shared引用的是偏移为0x11的movl指令,
    这条指令共计8个字节,作用是将shared的地址赋值给esp寄存器+4的偏移地址中,前面4个字节
    是指令码,后面4个字节是变量shared的地址。
    当源代码a.c在被编译成目标文件时,编译器不知道shared和swap的地址,因为他们定义在其他
    目标文件中,所以编译器就暂时把地址0看作是shared的地址,在偏移量为0x11的movl指令中,
    关于shared的地址部分是0x00000000。
    另外一条偏移量为0x20的指令是对函数swap的调用,这条指令共5个字节,前面的0xe8是操作码,
    该条指令是一条近址相对位移调用指令,后面四个字节就是调用函数相对于调用指令下一条指令
    的偏移量,在没有重定位之前,相对偏移位置为0xFFFFFFFC(小端),它是常量-4的补码形式。
    紧跟在call指令后面的那条指令为mov指令,mov指令的实际地址是0x25,而相对于mov指令偏移
    量为-4的地址即是0x25-4=0x21,所以这条call指令的实际调用地址是0x21。而0x21存放的不是
    swap的地址。在编译的时候,编译器并不知道swap的真正地址。
    链接器在完成地址和空间分配之后,就可以确定所有符号的虚拟地址,那么链接器根据符号的
    地址就能对需要重定位的指令进行地址修正,用objdump来反汇编输出可执行文件ab的汇编指令,


    ***图4.2.2***


    ***图4.2.3***
    从图4.2.2可以看出在main函数中,两个需要重定位的部分地址已经被修正。

  • 相关阅读:
    UVA11825 Hackers' Crackdown
    UVA 11346 Probability
    Codeforces 12 D Ball
    bzoj 4766: 文艺计算姬
    Codeforces 757 F Team Rocket Rises Again
    [HAOI2011] problem C
    Atcoder 3857 Median Sum
    bzoj4399 魔法少女LJJ
    bzoj2638 黑白染色
    bzoj4197 [Noi2015]寿司晚宴
  • 原文地址:https://www.cnblogs.com/miaoyong/p/3502884.html
Copyright © 2020-2023  润新知