如何捕获调试器并在 iOS 硬件上继续?

How can I trap to the debugger and continue on iOS hardware?

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

有没有办法在 iOS 硬件上执行此操作?

An answer to an older question mentions raise(SIGINT) which as far as I can see (from examining signal.h) does not exist. Another answer mentions the trap assembly instruction, which causes a build error ("Unrecognized instruction mnemonic"). Also unrecognized is the BKPT assembly instruction mentioned in ARM documentation.

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

我正在使用 Xcode 7.3.1 为 32 位和 64 位设备构建 iOS 9。感谢您的帮助!

Apple 的 libc signal.h includes XNU's 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 上发出 "unrecognized instruction mnemonic",类似于BKPT 指令。
我也无法在 ARM 信息中心或 Apple 的文档中找到对说明的任何参考。

我在 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 可能不正确。)

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

asm ("brk #0xF000");

这也适用于 iOS 设备。