开发者

Why does int 3 generate a SIGSEGV in 64-bit instead of stopping the debugger?

开发者 https://www.devze.com 2023-01-14 13:16 出处:网络
In 32 bits mode programming I used to employ int 3 in my programs a lot for stopping at a given location with t开发者_如何转开发he debugger (embedding the instruction in the source). Now in 64 bits it

In 32 bits mode programming I used to employ int 3 in my programs a lot for stopping at a given location with t开发者_如何转开发he debugger (embedding the instruction in the source). Now in 64 bits it seems to not be working, producing a very ordinary SIGSEGV under gdb and destroying the program beyond hope ("Program terminated with signal SIGSEGV, Segmentation fault. The program no longer exists."). I wonder if 64 bit mode has another mechanism, or if I should do some cache-flush (the int 3 is a dynamically generated opcode in this case (0xcc), is some jit-like code).


__debugbreak()

Today a colleague came by to ask about how to get "int 3" functionality on the 64bit platforms. What is "int 3"? It's the assembly instruction that is used to create a breakpoint. At least that's the instruction for the x86 processor, and as you can imagine it is very platform specific.

On the 64bit platforms there is no inline assembly, so there goes your "__asm int 3". What to do now? Well there's a lesser known construct which is actually much better to use in that it works across all platforms (x64, Itanium, and x86), which is __debugbreak(). This is a Visual C++ compiler intrinsic (defined in Visual C++ 2005 under vc\include\intrin.h, with tons of other cool intrinsics) that will effectively act "int 3" across all platforms.

DebugBreak, the Win32 function call is still around, but in general using __debugbreak() is my preference, if for no other reason than it's not a function call (it's a compiler intrinsic), and you don't need debug symbols to get a readable call stack.

If you're writing C++ you probably don't want to write non-portable assembly, and this is just one less place where you would have to.

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


The following code will work on an amd64 UNIX platform:

breakpoint.c

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

Compile it trivially: gcc -c breakpoint.c and start gdb a.out:

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

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

You see, gdb stops at the breakpoint.


Ahh, I got it, sorry. I had to unprotect the pages for execution. Int 3 is still a valid debug trap.


I recommend you never use asm int 3 as it works for all build types. You might forget a line somewhere in your code and that can mean big troubles. The alternative is to use __debugbreak which is only valid in debug mode.

0

精彩评论

暂无评论...
验证码 换一张
取 消