【问题标题】:Why this branch instruction of ARM doesn't work为什么ARM的这个分支指令不起作用
【发布时间】:2014-06-11 00:25:11
【问题描述】:

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

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

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

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

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

所以二进制指令是:

0xea000006

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

0x060000ea

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

【问题讨论】:

  • 您确定不是注入导致了故障吗?您在哪个操作系统上运行,您如何确保您可以访问 .text 的数据?
  • 要插入的字节是0x06, 0x00, 0x00, 0xea,但是如果你将它作为一个整数插入,那么你应该保留0xea000006,因为字节序将被适当地应用到它上面。大概你的模拟器有一些调试功能,使用它。
  • 确保代码不在 Thumb 中。目前大多数 ARM 平台默认使用 Thumb。
  • ARM 没有对齐要求吗?函数的词边界可能吗? 0x91f1 看起来很可疑。
  • 哪种 ARM 架构?

标签: c++ c assembly arm


【解决方案1】:

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

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

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

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

【讨论】:

  • 这个答案看起来是对的,除了最后一句。虽然B 分支汇编程序助记符在汇编源代码中使用绝对地址,但指令操作码包含一个 26 位 PC 相对偏移量(操作码中指定的 24 位,带有两个隐式最低有效零位)。
  • @MichaelBurr 谢谢!直到某事。
【解决方案2】:

ARM 系列允许使用值加载寄存器。这些寄存器之一是 PC(程序计数器)。

一些替代方案:

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

这些选择加上修改分支指令的目的地都是不同的选项,并不是“最好的”。选择最适合您且最容易维护的一种。

【讨论】:

  • 这些都是非常好的解决方法,但是你没有回答这个问题,如果有的话,OP 使用的简单分支有什么问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-20
  • 2011-02-18
  • 1970-01-01
相关资源
最近更新 更多