为什么int 3以64位生成SIGSEGV而不是停止调试器?

问题描述 投票:18回答:4

在32位模式编程中,我曾经在我的程序中使用int 3,用于使用调试器在指定位置停止(将指令嵌入到源中)。现在64位似乎不起作用,在gdb下生成一个非常普通的SIGSEGV并且破坏程序超出希望(“程序终止于信号SIGSEGV,分段错误。程序不再存在。”)。我想知道64位模式是否有另一种机制,或者我是否应该做一些缓存 - 刷新(在这种情况下int 3是动态生成的操作码(0xcc),是一些类似jit的代码)。

debugging assembly signals x86-64
4个回答
13
投票

以下代码适用于amd64 UNIX平台:

breakpoint.c

int main() {
    int i;     
    for(i=0; i<3;i++) {
        __asm__("int3");
    }
}

简单地编译它:gcc -c breakpoint.c并启动gdb a.out

(gdb) run
Starting program: /tmp/a.out 

Program received signal SIGTRAP, Trace/breakpoint trap.
0x00000000004004fb in main ()

你看,gdb在断点处停止。


20
投票

__debugbreak()

今天,一位同事过来询问如何在64位平台上获得“int 3”功能。什么是“int 3”?它是用于创建断点的汇编指令。至少那是x86处理器的指令,你可以想象它是非常特定于平台的。

在64位平台上没有内联汇编,所以有你的“__asm int 3”。现在做什么?好吧,有一个鲜为人知的结构实际上更好用,它适用于所有平台(x64,Itanium和x86),即__debugbreak()。这是一个Visual C ++编译器内在函数(在vc \ include \ intrin.h下的Visual C ++ 2005中定义,具有大量其他很酷的内在函数),它将在所有平台上有效地扮演“int 3”。

DebugBreak,Win32函数调用仍然存在,但通常使用__debugbreak()是我的首选,如果没有其他原因,它不是一个函数调用(它是一个编译器内在的),你不需要调试符号来获得可读的调用堆栈。

如果你正在编写C ++,你可能不想编写非可移植的程序集,而这只是你需要的地方。

http://blogs.msdn.com/b/kangsu/archive/2005/09/07/462232.aspx


12
投票

啊,我明白了,抱歉。我不得不取消保护页面以便执行。 Int 3仍然是有效的调试陷阱。


0
投票

我建议你永远不要使用asm int 3,因为它适用于所有构建类型。您可能会忘记代码中某处的某条线,这可能意味着很大的麻烦。另一种方法是使用仅在调试模式下有效的__debugbreak

© www.soinside.com 2019 - 2024. All rights reserved.