在32位模式编程中,我曾经在我的程序中使用int 3
,用于使用调试器在指定位置停止(将指令嵌入到源中)。现在64位似乎不起作用,在gdb下生成一个非常普通的SIGSEGV并且破坏程序超出希望(“程序终止于信号SIGSEGV,分段错误。程序不再存在。”)。我想知道64位模式是否有另一种机制,或者我是否应该做一些缓存 - 刷新(在这种情况下int 3
是动态生成的操作码(0xcc),是一些类似jit的代码)。
以下代码适用于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在断点处停止。
__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
啊,我明白了,抱歉。我不得不取消保护页面以便执行。 Int 3仍然是有效的调试陷阱。
我建议你永远不要使用asm int 3
,因为它适用于所有构建类型。您可能会忘记代码中某处的某条线,这可能意味着很大的麻烦。另一种方法是使用仅在调试模式下有效的__debugbreak。