How to make GDB stop at SIGTRAP only at breakpoints?

I am trying to debug a program that often causes GDB to stop and display SIGTRAP when it is not at a breakpoint. This happens when loading dynamic libraries and other common things. There are about 1000 of these events before my breakpoint finally hits, so I was not able to manually continue all these irrelevant SIGTRAPs. But if I use the handle SIGTRAP nostop noprint , then GDB will not stop at my breakpoint.

There seems to be a way to train GDB so that it understands which SIGTRAP is good for stopping and which is not good for stopping. It’s clear that GDB knows if it is at a breakpoint because the output is very reliable: at the breakpoint it mentions a “breakpoint” and shows the number of the breakpoint, but in any other SIGTRAP it just says “SIGTRAP”. So instead of printing a message about SIGTRAP, I would really like GDB to just say to itself: “Wow, this is SIGTRAP, and there is no breakpoint. Look at me, I'm going to stop and print a useless SIGTRAP message that completely destroys the session debugging! How about I just keep calm? " Please let me know if anyone has a way to do this.

+4
source share
1 answer

You can set catchpoints to catch the SIGTRAP signal and add commands to decide whether to continue or stop. In this handler, you can check for handy variables like $_siginfo because of the signal.

Of particular interest is $_siginfo.si_code , its value depends on the transmitted signal. sigaction (2) The Linux manual page describes the exact relationship. You can find the numerical values ​​for these codes SI_USER , SI_KERNEL , etc. SI_KERNEL program or looking at the headers (my system uses the /usr/include/bits/siginfo.h header). Some of the values ​​I came across are as follows:

  • 0x00 (0): SI_USER
  • 0x80 (128): SI_KERNEL
  • 0x02 (2): TRAP_TRACE

With this information in hand, here is an example that catches SIGTRAP and prints the reason, and then continues:

 catch signal SIGTRAP commands p $_siginfo.si_code c end # Set another breakpoint for testing break sleep 

Now consider this test program, which sleeps 5 seconds, then runs the debug trap on x86 (-64):

 #include <unistd.h> int main(void) { for (;;) { sleep(5); asm("int3"); } return 0; } 

This program continues to stop gdb on the int3 line because the signal is caught ( si_code is 0x80, SI_KERNEL ), but then the command is repeated again. Therefore, to skip this instruction, the program counter ( $pc ) must be increased. After that, I found out this information about SIGTRAP and si_code :

  • Breakpoints start SIGTRAP with code 128 ( SI_KERNEL ).
  • After continuing the U-turn, SIGTRAP with code 2 ( TRAP_TRACE ) is TRAP_TRACE (due to the catch point for SIGTRAP ).
  • The int3 instruction starts SIGTRAP with the code 128. Thus, you need to distinguish something from the instructions.

Here are the final GDB commands that skip int3 traps and still retain interrupt functionality:

 catch signal SIGTRAP commands silent # do not print catchpoint hits # ignore the int3 instruction (this address was looked up at # the tracepoint using print $pc) if $pc == 0x400568 set $pc++ # skip int3 c end # Ignore TRAP_TRACE that is used for breakpoints if $_siginfo.si_code == 2 c end end 

One final note: SIGTRAP is used internally by the debugger, it is possible that the above catches too much. This has been tested with GDB 7.10 on Arch Linux.

+2
source

All Articles