【问题标题】:EXC_BAD_ACCESS when executing an arm blx rx执行 arm blx rx 时的 EXC_BAD_ACCESS
【发布时间】:2014-10-26 00:12:19
【问题描述】:

这是在 armv7 上崩溃的 c 源代码行:

ret = fnPtr (param1, param2);

在调试器中,fnPtr 的地址为 0x04216c00。当我在指向上述语句的电脑上反汇编时,这是我得到的:

0x18918e:  movw   r0, #0x73c
0x189192:  movt   r0, #0x1
0x189196:  add    r0, r2
0x189198:  ldr    r0, [r0]
0x18919a:  str    r0, [sp, #0x20]
0x18919c:  ldr    r0, [sp, #0x20]
0x18919e:  ldr    r1, [sp, #0x28]
0x1891a0:  ldr    r2, [sp, #0x2c]
0x1891a2:  str    r0, [sp, #0x14]
0x1891a4:  mov    r0, r1
0x1891a6:  mov    r1, r2
0x1891a8:  ldr    r2, [sp, #0x14]
0x1891aa:  blx    r2

现在,当我反汇编地址 $r2 (=0x4216c00) 处的内存时,我得到了看似有效的代码,应该毫无问题地执行:

(lldb) disassemble -s 0x4216c00 -C 10
   0x4216c00:  push   {r4, r5, r6, r7, lr}
   0x4216c04:  add    r7, sp, #0xc
   0x4216c08:  push   {r8, r10, r11}
   0x4216c0c:  vpush  {d8, d9, d10, d11, d12, d13, d14, d15}
   0x4216c10:  sub    r7, r7, #0x280
   0x4216c14:  mov    r6, r0
   0x4216c18:  bx     r1
   0x4216c1c:  add    r7, r7, #0x280

然而真正发生的是:

EXC_BAD_ACCESS(代码=2,地址=0x4216c00)

谁能解释什么是错的以及为什么该地址被认为是非法的?

完全披露:我不是装配专家。编译和链接的代码都是 c 代码。编译器很响。

【问题讨论】:

  • 堆栈是什么样的?快速浏览一下就会发现,由于不可能的大分配或失控的递归而耗尽堆栈可能会在看似无辜的代码中出现此错误。
  • @Notlikethat:好的;这听起来很合理。我怎样才能弄清楚这个?什么构成“快速浏览”。 '非常感谢!
  • @Notlikethat:所以,我想我会增加应用程序的内存分区,直到收到您的回复。 (≈快速检查我是否遇到了我看不到的低内存问题)。我仍然因同样的异常而崩溃。
  • 我不了解 iOS,所以我只是搜索了 EXC_BAD_ACCESS 来检查它是否相当于我假设的 SIGSEGV。堆栈耗尽的建议,例如herehere 引起了我的注意,因为在这种情况下,您最终可能会遇到各种奇怪的事情。在崩溃点转储堆栈跟踪可能会提供信息。当然,它可能仍然是其他的东西,比如尝试调用已释放的对象——仅仅因为内存仍然被映射并不意味着它仍然是可执行的。
  • 尝试在 C 中重现问题并分享它可能会很好。如果它是堆栈损坏,它可能在您被咬之前的其他地方。你在用函数指针和可变参数等做一些花哨的事情吗?

标签: c arm clang lldb thumb


【解决方案1】:

在调用执行blx指令之前检查r2的值。这可能很奇怪,告诉 cpu 地址处于 thumb 模式,但是从列表中它看起来像 arm 模式。

尝试通过 -mno-thumb 将 clang 强制设置为仅 arm 模式以进行测试。

【讨论】:

  • $r2 =0x4216c00 ; 0x4216c00 mod 2 = 0.地址是偶数
  • @user3342339 嗯.. 那是在黑暗中拍摄的 :) 然后我想接下来就是看看SP 指向的位置。你也可以添加那个吗?
  • 会的;我还将检查编译器标志并报告效果。谢谢。
  • 试过 -mno-thumb:不行。我仍然收到错误的访问错误。此外,堆栈指针是 sp = 0x00f00eb8 :偶数地址。
  • 有趣的是,只有 movbx 将其作为 ARM 提供 - 该块中的所有其他指令都是 32 位 Thumb-2 编码。无论如何,在不匹配互通的情况下,您肯定会期待未定义的指令错误而不是内存错误,不是吗?
【解决方案2】:

EXC_BAD_ACCESS异常里面有两位数据,第一位是描述访问失败的“kern_return_t”号,第二位是访问的地址。在您的情况下,代码为 2,这意味着(来自 /usr/include/mach/kern_return.h):

#define KERN_PROTECTION_FAILURE         2
                /* Specified memory is valid, but does not permit the
                 * required forms of access.
                 */

不确定为什么会发生这种情况,听起来您正在尝试执行没有设置执行权限的代码。做什么:

(lldb) image lookup -va 0x4216c00

说?

顺便说一句,异常类型在 /usr/include/mach/exception_types.h 中,如果代码具有特定于机器的含义,则它们将在,例如/usr/include/mach/i386/exception.h) 有关 ARM 信息,您可能需要查看 Xcode SDK 中的标头。

【讨论】:

  • 谢谢@Jim Ingham。这很有帮助。事实上,我正在尝试执行动态创建的代码。我会说更多,但我是 NDA 的。冲洗 icache 不起作用,我想知道是否有任何合法的解决方法。
  • 我不认为 iOS 允许您将区域的权限从可写更改为可执行,但您真的应该向 ADC 询问这是否可能以及如何实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-05
  • 2011-02-25
  • 1970-01-01
  • 2018-12-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多