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

时间:2014-06-11 00:25:12

标签: c++ c assembly arm

现在我正在编写一个库来模拟C / C ++的简单函数。它的用法如下:MOCK(mocked, substitute) 如果调用mocked函数,则会调用替换函数。

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

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

根据在线文件,相对地址是

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

所以二进制指令是:

0xea000006

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

0x060000ea

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

2 个答案:

答案 0 :(得分:1)

您分支的地址是奇数编号,表示它们处于Thumb模式。

您的方法存在明显的问题。

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

您的功能处于Thumb模式(目标处为+1),但您使用的是ARM模式分支编码(B A1编码?),因此很明显要么您没有处于Thumb模式,要么您正在Thumb模式下使用ARM模式指令

答案 1 :(得分:0)

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

一些替代方案:

  1. 您可以使用一个函数来加载PC寄存器 目的地址(绝对)。
  2. 添加带有偏移量的PC寄存器。
  3. 对PC寄存器使用乘加指令。
  4. 将目标寄存器推入堆栈并弹出到PC 注册
  5. 这些选择以及修改分支指令的目的地都是不是“最佳”的不同选项。选一个最适合你的,最容易维护。