1

What is __debugbreak? Is it used for triggering SIGTRAP? What is the difference between int3 and __debugbreak?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
anandthegreat
  • 61
  • 1
  • 9

1 Answers1

4

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
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • __debugbreak is a function. Can you elaborate on why can't we call this in asm? – anandthegreat Feb 06 '19 at 09:19
  • 1
    @anandthegreat: Updated. It's not *just* a function, there's never a reason not to inline it as `int3` in asm, unless you're taking the address as a function pointer. I'm surprised MSVC even has a non-inline version of it in the library. GCC doesn't let you take the address of built-in functions. – Peter Cordes Feb 06 '19 at 10:04
  • @PeterCordes ["Some intrinsics are available only as intrinsics, and some are available both in function and intrinsic implementations."](https://docs.microsoft.com/en-us/cpp/intrinsics/compiler-intrinsics?view=vs-2019) However, ["This routine is only available as an intrinsic."](https://docs.microsoft.com/en-us/cpp/intrinsics/debugbreak?view=vs-2019) (and even as far back as VS2015), so IDK. That being said, there is the [`DebugBreak()` Windows API call](https://msdn.microsoft.com/library/windows/desktop/ms679297.aspx) in `kernel32.dll`, so it's possible there's a stub somewhere in the vcrt… – andlabs May 13 '19 at 03:49