iOS 上的可恢复断言/断点,如带有 MS 编译器的 __debugbreak() [英] Resumable assert/breakpoint on iOS like __debugbreak() with MS compiler

查看:13
本文介绍了iOS 上的可恢复断言/断点,如带有 MS 编译器的 __debugbreak()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试实现自定义资产宏(类似于 assert.h 所具有的),但我希望能够在获取和断言后继续执行.

I'm trying to implement custom asset macro (similar to what assert.h has), but I want to be able to continue execution after I get and assert.

例如,一个这样的 ASSERT 实现可以是:

For example, one such ASSERT implementation could be:

#define ASSERT(expr) ((void)( (!!(expr)) || (__debugbreak(), 0)))

__debugbreak 是 Microsoft 编译器中插入软件断点的内在函数,相当于 x86 中的 _asm int 3.对于 iOS,有不同的方法来实现 __debugbreak:

__debugbreak is an intrinsic function in Microsoft compilers that inserts software breakpoint, equivalent to _asm int 3 in x86. for iOS there are different ways to implement that __debugbreak:

  • __asm__("int $3"); 用于 x86.
  • __asm__("bkpt #0"); 用于常规手臂.
  • __asm__("brk #0"); for arm64
  • __builtin_trap()
  • raise(SIGTRAP)
  • __asm__("int $3"); for x86.
  • __asm__("bkpt #0"); for regular arm.
  • __asm__("brk #0"); for arm64
  • __builtin_trap()
  • raise(SIGTRAP)

但是对于所有这些,当我的断言命中时,我不能简单地跨过并继续我在使用 Visual Studio 时可以做的事情;当我的 iOS 构建中的某些断言卡在断言处并且我别无选择只能终止时,我什至无法手动移动指令指针并跳过断言.

but with all of them when my assert hits I cannot simply step over and continue the way I can do when working with visual studio; when something assert in my iOS builds it gets stuck at the assert and I have no choice but to terminate, I cannot even move instruction pointer manually and skip the assert.

是否有可能在 iOS 上实现断言,从而中断调试器并仍然允许我继续执行?

Is it possible to implement asserts on iOS that would break into debugger and would still allow me to continue execution?

推荐答案

事实证明我可以通过进行系统调用来实现我想要的:

Turns out I can achieve what I want by making a syscall:

#include <unistd.h>

#if defined(__APPLE__) && defined(__aarch64__)
#define __debugbreak() __asm__ __volatile__(            
    "   mov    x0, %x0;    
" /* pid                */ 
    "   mov    x1, #0x11;  
" /* SIGSTOP            */ 
    "   mov    x16, #0x25; 
" /* syscall 37 = kill  */ 
    "   svc    #0x80       
" /* software interrupt */ 
    "   mov    x0, x0      
" /* nop                */ 
    ::  "r"(getpid())                                   
    :   "x0", "x1", "x16", "memory")
#elif defined(__APPLE__) && defined(__arm__)
#define __debugbreak() __asm__ __volatile__(            
    "   mov    r0, %0;     
" /* pid                */ 
    "   mov    r1, #0x11;  
" /* SIGSTOP            */ 
    "   mov    r12, #0x25; 
" /* syscall 37 = kill  */ 
    "   svc    #0x80       
" /* software interrupt */ 
    "   mov    r0, r0      
" /* nop                */ 
    ::  "r"(getpid())                                   
    :   "r0", "r1", "r12", "memory")
#elif defined(__APPLE__) && (defined(__i386__) || defined(__x86_64__))
#define __debugbreak() __asm__ __volatile__("int $3; mov %eax, %eax")
#endif

#define MYASSERT(expr) do { if (!(expr)){ __debugbreak(); } } while(0)

有一个尾随的 NOP mov x0, x0 是有原因的:当断言中断时,调试器将准确地停在断言行而不是以下指令碰巧所在的随机行.

There is a trailing NOP mov x0, x0 for a reason: when assert breaks, debugger will stop exactly at the assert line and not some random line where the following instruction happens to be located.

如果有人正在寻找等效的 IsDebuggerPresent 在 iOS 上,您可以使用 AmIBeingDebugged.

In case if somebody is looking for equivalent of IsDebuggerPresent on iOS, you can use AmIBeingDebugged.

这篇关于iOS 上的可恢复断言/断点,如带有 MS 编译器的 __debugbreak()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆