了解用于反转 MIPS 的分支延迟槽

逆向工程 雷达2 米普
2021-07-05 21:15:13

我正在使用radare2静态反转为Atheros AR7161编译的一些软件。这个处理器实现了 MIPS,我记得 MIPS 有一个分支延迟槽。这在反汇编中确实很明显,因为我可以看到应该在分支放置在它们之后的逻辑之前执行的指令。

然而,在分析一段代码时,我遇到了一条 beqz 指令,假设它应该首先执行之后的指令在程序上下文中没有意义。我必须承认我的分析可能是错误的,这并非不可能;但是,我有一些疑问,我也想澄清一下:

  • 是否所有分支/跳转指令总是使用分支延迟槽,以便紧随其后的指令在逻辑上首先执行?如果不是,在哪些情况下不会?

  • 有没有办法让radare2显示逻辑执行顺序而不是二进制编码的顺序?

编辑:具体来说,我正在处理以下序列:

beqz v0, <some address>
lb v0, 0x40(sp)

关于这些进入管道的指令,我脑子里有一个非常分散的画面。我可以想象在解码第一条指令时正在提取第二条指令;因此,分支延迟槽的执行实际上应该开始。但是,分支指令依赖于被分支延迟槽中的指令修改的同一个寄存器,那么会发生什么呢?分支指令是使用旧的寄存器值还是由 lb 更新的新值来评估条件?

谢谢

2个回答

在分支(或跳转)指令之后评估分支延迟槽中的指令。分支延迟槽中指令的执行不影响分支条件的评估。

我观察到分支延迟槽用于一些事情:

  • 指向分支指令的基本块的最后一条指令
    • 分支测试将不依赖于分支延迟槽指令计算的输出
    • 常见于无条件跳转/分支,例如bjal
  • fall through 块的第一条指令。
    • 如果采用分支,则不应存在副作用。
    • 分析将表明,如果采用分支,则不需要任何受影响的寄存器
  • 如果分支被采用,则块的第一条指令
    • 如果分支目标有多条路径,这条指令很可能会在不同的分支中多次看到
  • 条件值的加载,通常用于返回值

本文详细介绍了分支延迟槽。

正如 Igor 所指出的,分支指令的“可能”版本仅在实际采用指令时才将指令的效果保持在分支延迟槽中。

  1. 有条件分支的变体,称为“可能的分支[条件]”,例如
    • bgezl - 分支可能大于或等于零
    • beql - 等概率分支

这些指令有一个延迟槽,但延迟槽中的指令只有在进行分支时才会执行如果不采取分支,则延迟槽中的指令执行(无效)。

注意:这些指令已在 MIPS 架构的第 6 版中删除。它还添加了没有延迟槽的分支的紧凑变体

至于你的代码片段,我强烈怀疑分支使用了旧的寄存器值,但你可能只能通过在实际处理器上运行它来确认它。