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

时间:2019-02-05 17:36:54

标签: debugging assembly x86 gdb interrupt

什么是__debugbreak?它用于触发SIGTRAP吗? int3和__debugbreak有什么区别?

1 个答案:

答案 0 :(得分:2)

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指令。即使禁用优化,它也是“内联”的内在函数。这不是“仅仅”一个功能。


这与_mm_mfence()内在mfence指令或_mm_popcnt_u64对于64位操作数大小popcnt的内在方式相同。


相关:Is there a portable equivalent to DebugBreak()/__debugbreak?
说c有一个__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