如何理解 objdump 的输出,关于间接 jmp?

How to understand the output of objdump, about indirect jmp?

objdump -S my_program时,通常可以看到下面的间接jmp指令,一般用于switch/case跳转table:

ffffffff802e04d3: ff 24 d5 38 2e 10 81 jmpq *-0x7eefd1c8(,%rdx,8)

如何理解地址-0x7eefd1c8?意思是table的基地址是0xffffffff802e04d3 - 0x7eefd1c8

此外,如何从 ff 24 d5 38 2e 10 81 中获取 -0x7eefd1c8

decoding issue

比你还得看看Intel Development Manuals

  • ff是JMP操作码(跳近,绝对间接)[1]
  • 24 是一个 ModR/M 字节 [2] 这意味着 SIB 字节在它之后( JMP操作码只有一个操作数,所以寄存器字段被忽略)
  • d5 是一个 SIB 字节 [2],这意味着 disp32 紧随其后,Scale = 8Index = %rdx(在 32 位模式下,索引应为 %edx),没有基数。
  • 38 2e 10 81 是一个 4 字节的 disp32 操作数。如果将其编码为双字,您将得到 0x81102e38 注意最高位设置为 1。它是一个符号位,表示值以 Two's Complement Encoding [3] 编码。

从二进制补码转换得到我们期望的数字:

>>> print hex(0x81102e38 - (1 << 32))
-0x7eefd1c8 

当处理器在 64 位模式下执行该指令时,它从 0xffffffff81102e38 + (%rdx * 8) 中读取 8 个字节(原始数字经过符号扩展)并将该四字放入 %rip [4]。

参考手册:

  1. 第 2A 卷,第 3.2 节说明 (A-M),第 3-440
  2. 第 2 卷,第 2.1.5 节 ModR/M 和 SIB 字节 的寻址模式编码,第 2-6..2-7 页
  3. 第 1 卷,第 4.2.1.2 节有符号整数 ,第 4-4
  4. 第 2 卷,第 2.2.1.3 节位移,第 2-11