zoukankan      html  css  js  c++  java
  • Chap-4 Section 4.2.4 指令修正方式

    对于X86平台下的ELF文件的重定位入口所修正的指令寻址方式只有两种:绝对近址32寻址和相对近址32寻址。

    这两种指令修正方式每个被修正的位置的长度都为32位,即4个字节,而且都是近址寻址,不用考虑Intel的段间远址寻址。r_info成员的低8位表示重定位入口的类型。

    X86基本重定位类型

    宏定义                        值      重定位修正方法

    R_386_32      1     绝对寻址修正  S + A

    R_386_PC32    2     相对寻址修正  S + A - P

    A = 保存在指令中被修正位置的值

    P = 被修正的位置(相对于段开始的偏移量或者虚拟地址),该值可以通过r_offset计算得到。

    S = 符号的实际地址,即由r_info的高24位指定的符号的实际地址。

    因为a.o中shared和swap需要地址重定位,以此为例子说明重定位地址修正方法。用objdump -r a.o可以得到a.o中需要重定位的符号如图4.2.7所示:

    ***图4.2.7(同4.2.4相同)***

    从图中可知,shared的重定位类型为R_386_32,因此为绝对寻址修正方式。那么S的值怎么得到,可以从a.o,b.o链接成的可执行文件的符号表中得到,可执行文件的符号表如图4.2.8:

    ***图4.2.8***

    从图中看出shared的实际地址为0x08049158,即是S的值。从a.o反汇编指令中可知A的值,如图4.2.9所示:

    ***图4.2.9***

    从图4.2.7中得知shared相对段开始的偏移为0x15,所以A的值是0x0。那么shared重定位后的地址为S + A = 0x08049158 + 0x0 = 0x08049158。怎样验证该数值的正确性?可以通过可执行文件的反汇编代码验证,如图4.2.10所示:

    ***图4.2.10***

    注意:图中的地址为小端格式,即数值的高位存放在低地址,低位在高地址。
    而swap的重定位方式为相对寻址修正,swap的S值从图4.2.8中可知为0x080480c0,A的值为0xfffffffc,为-4的补码。P的值为符号swap的偏移量加上该段的起始地址,swap的偏移量为0x21,该段的起始地址符号main的地址,即为0x08048094。因此最终swap的地址为0x080480c0 - 0x04 - (0x08048094 + 0x21)= 0x07。从图4.2.10可以看到call指令被修正后的地址确实为0x07。而call指令的调用地址是修正后的地址加上下一条
    指令的地址,0x07 + 0x080480b9 = 0x080480c0,该地址即为swap函数的地址。

    ***图4.2.11***

  • 相关阅读:
    PHP面向对象练习
    PHP面向对象的特点
    PHP的构造函数和析构函数
    PHP面向对象
    AVL-TREE
    ReentrantLock
    treap-名次树-树堆
    细数那些我们熟悉的 排序!
    数据结构 - trie
    python 凸包(经纬度) + 面积[近似]
  • 原文地址:https://www.cnblogs.com/miaoyong/p/3505590.html
Copyright © 2011-2022 走看看