关于重定位的一些笔记

  • 润物细无声
  • 2024-04-28 14:11

    关于 x86_32 的两种重定位修正方式

    宏定义 重定位修正方式
    R_386_32 1 绝对寻址修正 S + A
    R_386_PC32 2 相对寻址修正 S + A - P

    关于 S A P 说明:

    更多重定位类型 点这里

    绝对寻址修正

    符号地址直接计算,直接存放在修正位置。比如,mov 指令获取全局变量的值。

    0300: 
        gval dw 0x12345678
    
    1011: c7 45 f8 64 00 00 00     movl  $0x64, 0xfffffff8(%esp)
    1018: c7 44 24 04 00 00 00 00  movl  $0, 0x4(%esp) # movl gval, 0x(%esp)
    1020: 8d 45 f8                 lea   0xfffffff8(%ebp), %eax
    

    这段代码中,1018 有一个 R_386_32 类型的重定位,它的信息如下:

    信息 说明
    修正位置 101D = 1018 + 5
    修正位置的长度 4 个字节
    S 300
    A 0,一般就是 0
    P 101D
    最终修正为 300 = 300 + 0
    1018: c7 44 24 04 00 03 00 00  movl  $300, 0x4(%esp) # movl gval, 0x(%esp)
    

    相对寻址修正

    修正位置上的符号地址,是符号相对于 PC 的偏移。比如:call 指令调用子程序。

    1023: 8d 45 f8        lea   0xfffffff8(%ebp), %eax
    1026: e8 fc ff ff ff  call  -4 # call foo
    102b: 89 04 24        mov   %eax, (%esp)
    
    1234:
        foo:
            ...
            ...
            ...
            ret
    

    这段代码中,1026 有一个 R_386_PC32 类型的重定位,它的信息如下:

    信息 说明
    修正位置 1027 = 1026 + 1
    修正位置的长度 4 个字节
    S 1234
    A -4,一般就是 0xfffffffc(即 -4)
    P 1027
    最终修正为 209 = 1234 + (-4) - 1027
    1026: e8 09 02 00 00  call  -4 # call foo
    

    这里 call 指令是一个偏移值,符号相对于修正位置的偏移,那为什么需要减 4 呢。因为,当 CPU 执行 call 指令时,PC 值已经是下一条指令地址了,即:当 CPU 执行 1026 时,PC 寄存器是 102b,需要 PC - 4 调整为修正位置的地址,再加上 call 指令后的偏移 209,就将 PC 调整到 foo 函数处了。

    © 2022-2024 留校察看 liuxocakn 保留所有权利 All Rights Reserved
    蜀ICP证2022022862号-1 川公网安备51010702003077号

    自 2024-04-23 22:54 之后访问量: 66182