【问题标题】:How can I trap to the debugger and continue on iOS hardware?如何进入调试器并继续使用 iOS 硬件?
【发布时间】:2016-06-09 21:15:50
【问题描述】:

在 Mac OS X 和 iOS 模拟器(均为 x86)中,我们可以使用内联汇编中的 int3 指令捕获到调试器 (LLDB)。这很好,因为它会捕获到特定的代码行,但我们可以通过在调试器中点击继续来立即继续。

有没有办法在 iOS 硬件上做到这一点?

An answer to an older question 提到raise(SIGINT),据我所知(通过检查signal.h)不存在。另一个答案提到了trap 汇编指令,它会导致构建错误(“无法识别的指令助记符”)。同样无法识别的是BKPT 汇编指令mentioned in ARM documentation

我已经尝试过__builtin_trap(),它几乎,几乎可以满足我的要求,但不允许我继续。除非我使用jump +1register write pc `$pc+8\` 手动推进指令指针,否则我会一直点击它,这比点击继续方便得多。

我正在使用 Xcode 7.3.1 为 32 位和 64 位设备构建 iOS 9。任何帮助表示赞赏!

【问题讨论】:

  • 反对者,要解释一下吗?
  • 我猜他对你的问题投了反对票,因为 signal() 和 SIGINT 都是标准 C 的一部分。opensource.apple.com//source/xnu/xnu-1456.1.26/bsd/sys/signal.h
  • raise(SIGINT) 可以工作,但并不总是可靠的,有时它会稍后停止,您需要遍历线程树以查找断点在哪里。我曾经使用过此解决方案,然后将其删除。后来发现 ASSERT 应该停止而不继续,你应该面对它们而不是忽略它们,那你为什么要断言呢?
  • 这些类型的非致命断言在很多情况下都很有用,例如在代码尚未实现时。

标签: ios iphone debugging assembly breakpoints


【解决方案1】:

Apple 的 libc signal.h 包括 XNU 的 sys/signal.h确实定义了 SIGINT(在所有平台上):

// [...]

#define SIGHUP  1   /* hangup */
#define SIGINT  2   /* interrupt */
#define SIGQUIT 3   /* quit */
// [...]

因此,虽然我无法确认这种做法确实有效(由于我没有 iOS 9 设备),但阻碍您的障碍实际上应该不是问题。

对于汇编指令,BKPT 是有效的 ARM 指令,但仅适用于 A32。 A64 变体称为BRK
如果您正在构建胖二进制文件并无条件使用其中任何一个,您将始终遇到编译器错误。

另请注意,两条指令都需要立即数(传递给调试器)。省略该值也会产生编译器错误。

也就是说,您应该能够使用简单的#ifdef 插入 A32 和 A64 的调试指令:

#ifdef __aarch64__
asm volatile("BRK 0");
#else
asm volatile("BKPT 0");
#endif

您可以将0 替换为您在0255 之间选择的任何值。

关于TRAP 指令的注释:虽然Apple 的汇编程序似乎接受A32 的这条指令并将其转换为0xe7ffdefe,但它会在A64 上发出“无法识别的指令助记符”,类似于BKPT 指令。
我也无法在 ARM 信息中心或 Apple 的文档中找到该说明的任何参考。

【讨论】:

  • 这里有一些很棒的信息,谢谢!不幸的是 BRK/BKPT 和 __builtin_trap() 有同样的问题。我会再次尝试 SIGINT,看看会发生什么。
  • SIGINT 和 SIGTRAP 实际上做了我想做的事,尽管堆栈比我想要的更深一层。谢谢!
  • 很高兴我能提供帮助。 Another answer 提到 SVC,这是 BKPT/BRK 的非调试对应项 - 如果 asm("SVC 0") 的工作方式与 BKPT/BRK 不同,请尝试一下?
  • __LP64__ 可能是错误的宏。有一个 AArch64 ILP32 ABI 仍然在 64 位模式下运行,只是使用 32 位指针来节省缓存占用。 What predefined macro can I use to detect the target architecture in Clang?__aarch64__ 是您应该使用的宏。至少应该在 GCC 和 clang 中工作,希望在其他 ARM 编译器中工作。
【解决方案2】:

我在 OS X 上使用 Swift 时遇到过类似的问题: 1) raise(SIGINT) 在后台进程中对我不起作用(例如:SceneKit 的场景渲染器协议)。 (也许缺少处理程序?) 2) __builtin_trap() 之后不允许继续 3) asm(" int3 ") 需要 ObjC 和头文件,这让我一开始吓到了。但这还不错。刚刚在两个新文件中添加了三行:

---- NSObject+MachineTrap.h ----

void machineTrap(void);

---- NSObject+MachineTrap.h ----

#import "NSObject+MachineTrap.h"
void machineTrap(void) { asm (" int3 "); } /// Program has TRAPPED to DEBUGGER ///`

(我选择 int3 而不是 BRKBKPTSVC 可能不正确。)

【讨论】:

  • asm(" int3 ") 是 x86 指令。这个问题是关于 ARM 的。另外,您为什么不希望 int3 内联?在标题中将函数定义为static inline,您不需要.c
【解决方案3】:

我在使用基于 ARM 的 MacBook Pro(Apple M1 芯片)时遇到了类似的问题。这对我有用:

asm ("brk #0xF000");

这可能也适用于 iOS 设备。

【讨论】:

  • 请提供一些解释。
猜你喜欢
  • 1970-01-01
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-28
  • 1970-01-01
  • 1970-01-01
  • 2013-07-07
相关资源
最近更新 更多