Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

In 32 bits mode programming I used to employ int 3 in my programs a lot for stopping at a given location with the 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).

like image 778
dsign Avatar asked Sep 03 '10 08:09

dsign


3 Answers

__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

like image 191
BarsMonster Avatar answered Nov 17 '22 17:11

BarsMonster


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.

like image 26
hek2mgl Avatar answered Nov 17 '22 17:11

hek2mgl


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

like image 38
dsign Avatar answered Nov 17 '22 18:11

dsign