int3指令和调用__debugbreak有什么区别?

What is the difference between int3 instruction and call __debugbreak?

什么是__debugbreak?是用来触发SIGTRAP的吗? int3 和 __debugbreak 有什么区别?

int3 is an x86 instruction.

__debugbreak() is an intrinsic supported by MSVC 这将使编译器在为 x86 编译时发出该指令,或任何适用于目标 ISA(例如 ARM、AArch64 等)的软件断点指令

ICC 也支持它,但其他编译器(如 gcc)不支持..

不会在asm中做call __debugbreak,你只需要写int3。例如如果你编译一个使用它的函数,比如

void foo() {
    __debugbreak();
}

Godbolt 编译器资源管理器上的 MSVC 生成此 asm:

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

注意在任何地方都缺少 call 指令。即使禁用优化,它也是 "inlines" 的固有特性。这不是 "just" 函数。


这与 _mm_mfence() 对于 mfence 指令或 _mm_popcnt_u64 对于 64 位操作数大小 popcnt.


相关:Is there a portable equivalent to DebugBreak()/__debugbreak?
说 clang 有一个 __builtin_debugtrap().

那里的另一个答案说更广泛使用的 GNU C __builtin_trap() 被假定为停止/中止程序,而不是像断点一样。 (因此 gcc 在无条件 __builtin_trap 后不会发出任何代码。)


更新:显然 MSVC 确实 让你获取它的地址,所以我猜某处有它的库版本。 所以你可以用 asm 编写 call __debugbreak,但您仍然不会,因为它毫无意义。

GCC 不会 让你获取内置函数的地址,例如尝试编译:

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

给你这个错误:

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

但是 MSVC 和 ICC 将 void (*getFunc(void))(void) { return &__debugbreak; } 编译成这个 (on Godbolt)

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