Is There a Portable Equivalent to Debugbreak()/_Debugbreak

Is there a portable equivalent to DebugBreak()/__debugbreak?

What about defining a conditional macro based on #ifdef that expands to different constructs based on the current architecture or platform.

Something like:

#ifdef _MSC_VER
#define DEBUG_BREAK __debugbreak()
#else
...
#endif

This would be expanded by the preprocessor the correct debugger break instruction based on the platform where the code is compiled. This way you always use DEBUG_BREAK in your code.

Xcode equivalent of ' __asm int 3 / DebugBreak() / Halt?

http://developer.apple.com/documentation/DeveloperTools/Conceptual/XcodeProjectManagement/090_Running_Programs/chapter_11_section_3.html

asm {trap}            ; Halts a program running on PPC32 or PPC64.

__asm {int 3} ; Halts a program running on IA-32.

__debugbreak and int3 instruction

int3 is a single-byte instruction (and so is the push in this case). call isn't. You jmp will jump into the "middle" of call if you overwrite your push with call instead of int3.
But unless there's a way to reach the push (I see no label before it to jump/call to), putting a breakpoint on push is useless, isn't it?

Resumable assert/breakpoint on iOS like __debugbreak() with MS compiler

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; \n" /* pid */ \
" mov x1, #0x11; \n" /* SIGSTOP */ \
" mov x16, #0x25; \n" /* syscall 37 = kill */ \
" svc #0x80 \n" /* software interrupt */ \
" mov x0, x0 \n" /* nop */ \
:: "r"(getpid()) \
: "x0", "x1", "x16", "memory")
#elif defined(__APPLE__) && defined(__arm__)
#define __debugbreak() __asm__ __volatile__( \
" mov r0, %0; \n" /* pid */ \
" mov r1, #0x11; \n" /* SIGSTOP */ \
" mov r12, #0x25; \n" /* syscall 37 = kill */ \
" svc #0x80 \n" /* software interrupt */ \
" mov r0, r0 \n" /* 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)

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.

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

What is the difference between int3 instruction and call __debugbreak?

int3 is an x86 instruction.

__debugbreak() is an intrinsic supported by MSVC that will get the compiler to emit that instruction when compiling for x86, or whatever software-breakpoint instruction is appropriate for the target ISA (e.g. ARM, AArch64, etc.)

ICC also supports it, but other compilers (like gcc) don't..

You wouldn't do call __debugbreak in asm, you'd just write int3. e.g. if you compile a function that uses it, like

void foo() {
__debugbreak();
}

MSVC on the Godbolt compiler explorer produces this asm:

void foo(void) PROC                                        ; foo
npad 2
int 3
ret 0

Notice the lack of a call instruction anywhere. It's an intrinsic that "inlines" even with optimization disabled. It's not "just" a function.


This is the same as how _mm_mfence() is an intrinsic for the mfence instruction, or _mm_popcnt_u64 for 64-bit operand-size popcnt.


Related: Is there a portable equivalent to DebugBreak()/__debugbreak?

says clang has a __builtin_debugtrap().

Another answer there says the more widely available GNU C __builtin_trap() is assumed to stop / abort the program, not act like a breakpoint. (So gcc won't emit any code after an unconditional __builtin_trap.)


update: apparently MSVC does let you take its address, so I guess there is a library version of it somewhere. So you could write call __debugbreak in asm, but you still wouldn't because it's pointless.

GCC does not let you take the address of builtins, for example trying to compile:

int (*getbuiltin(void))(unsigned) {    return &__builtin_popcount;  }

gives you this error:

error: built-in function '__builtin_popcount' must be directly called

But MSVC and ICC compile void (*getFunc(void))(void) { return &__debugbreak; } into this (on Godbolt)

void (__cdecl*getFunc(void))(void) PROC                         ; getFunc
lea rax, OFFSET FLAT:__debugbreak
ret 0


Related Topics



Leave a reply



Submit