为什么ARM的这个分支指令不起作用

Why this branch instruction of ARM doesn't work

本文关键字:分支指令 不起作用 ARM 为什么      更新时间:2023-10-16

现在我正在编写一个库来模拟C/c++的平凡函数。它是这样使用的:MOCK(mocked, substitute)如果调用模拟函数,则会调用替代函数。

我修改了代码页的属性,并将跳转代码注入到函数中实现。我已经为x86 CPU实现了它,我想把它移植到ARM CPU。但是我有一个问题,当我注入二进制代码。

例如,替代函数的地址为0x91f1,要模拟的函数的地址为0x91d1。所以我想注入ARM分支代码到0x91d1跳转到替代函数。

根据网上的文件,相对地址是

(0x91f1 - (0x91d1 + 8)) / 4 = 6

所以二进制指令是:

0xea000006

因为我的手臂模拟器(我使用Android手臂v7模拟器)是小端序的,所以要注入的二进制代码是:

0x060000ea

但是当我在注入分支代码后执行模拟函数时,发生了段错误。我不知道为什么分支指令是错误的。我没有学过ARM架构,所以我不知道ARM的分支指令是否有一些限制

您要分支到的地址是奇数,这意味着它们处于拇指模式。

你的方法有一个明显的问题。

如果目标处于Thumb模式,您要么需要在您的分支点处于Thumb模式,要么需要使用bx(分支和交换)指令。

您的函数处于拇指模式(目标+1),但您正在使用ARM模式分支编码(B A1编码?),因此显然您不是处于拇指模式,或者您在拇指模式下使用ARM模式指令。

ARM系列允许用值加载寄存器。其中一个寄存器是PC(程序计数器)。

其他选项:

  1. 你可以使用一个函数来加载PC寄存器目的地址(绝对).
  2. 添加带有偏移量的PC寄存器。
  3. 使用PC寄存器的乘法和加法指令。
  4. 将目标寄存器压入堆栈并弹出PC登记。

这些选择加上修改分支指令的目的地都是不同的选择,而不是"最佳"。选择一个最适合你,最容易维护的。