20

I've been using gdb normally for 1 or 2 projects. I.e. I invoke gdb --args prog args . gdb runs in the same tty as the program I'm debugging.

However my latest project is modifying the dtach utility. This is a program like screen, so the tty's are redirected elsewhere, thus I have to use gdb's attach functionality.

The problem with gdb attach is that obviously you can't attach from the very beginning as you need to run the program first in order to get a pid to attach to.

Is there any way I can get a program to wait at a point until gdb is attached?

I can't use gdbserver as I'm on cygwin. Also I tried using pause(), but that just hung when I tried to continue.

rhlee
  • 3,857
  • 5
  • 33
  • 38
  • My bad, the message in the mailing list complaining that gdbserver doesn't work on cygwin was from 9 years ago. Compiled it last night and it works fine. For some reason the gdbserver binary is not included in the cygwin repo, probably due to the narrow use cases for it on cygwin. Also there is a potential way to hook gdb into program from the start using the gdb debugging stub. Thanks for the answers anyways. – rhlee Jun 30 '12 at 13:11
  • You may check https://github.com/scottt/debugbreak . – Jérôme Pouiller Nov 23 '22 at 14:07

3 Answers3

25

At least with LLDB making the process send SIGSTOP to itself should do the trick. Debugger continue command will then issue the SIGCONT. This should work with GDB too. Alternatively try SIGINT instead of SIGSTOP.

Include header

#include <signal.h>
#include <csignal> // or C++ style alternative

then

raise(SIGSTOP)
Peter Lamberg
  • 8,151
  • 3
  • 55
  • 69
  • The gdb command `info signals` prints the list of signals and wether or not they are passed to the program. You can then modify its behaviour with command `handle`. – Julio Guerra Aug 22 '16 at 08:55
  • The problem with this is that if the debugger actually attaches and sends the `SIGCONT` before the debugee reaches this point, the process gets stuck. – Ajay Brahmakshatriya Nov 25 '18 at 19:53
  • 2
    This worked for me while debugging C program. I included `signal.h` and inserted `raise(SIGSTOP)` at an appropriate point in the source code, ran the program with GDB, and continued execution with the GDB command `signal SIGCONT`. Much cleaner than the `sleep` method. – Jay Douglass Dec 05 '21 at 17:57
  • Improvement to @JayDouglass's answer. In case of multiple threads running, you can use `thread apply all signal SIGCONT` to resume all threads at the same time – HKTonyLee Mar 10 '23 at 01:07
16

Here is how I solve this problem. I have seen other people do this trick as well.

Pick some place you want your program to stop and wait for you to attach the debugger. For most programs, this will be the very beginning, but if there is some init work you need to do you might want to finish that up and then do this.

Put in a loop similar to this:

#ifdef DEBUG

int i = 0;

while (i == 0)
{
    usleep(100000);  // sleep for 0.1 seconds
}

#endif // DEBUG

Once you have successfully attached to the process, you can use the debugger to change the value of the variable i, which will break the loop and allow normal execution to continue.

The gdb command to change the variable to 1: set var i = 1

Another thing I do all the time: I define a short function called nop() that does nothing ("no operation"). Then I stick in a call to nop() anyplace I want to break, and put a breakpoint inside nop().

Note: if you build your debug builds with -O0 then the compiler won't optimize away the variable. If you needed this trick to work with an optimized build, I guess you would need to declare the variable as volatile.

steveha
  • 74,789
  • 21
  • 92
  • 117
  • 1
    There has to be a solution where you install a signal handler that will set the `i` variable to break out the loop? – To1ne Oct 01 '13 at 08:40
1

Some platforms may have wait-for-debugger instructions or traps.

More portably, you could make the program wait on some externally satisfied condition, such as a connection to a socket or writing some data into a fifo. You could then make the connection or send dummy data from a third terminal.

Or you could put an infinite loop in the program, testing the value of some volatile variable which you would modify with the debugger in order to allow it to continue.

If I recall you can use windows apis in cygwin programs, and some web searching seems to indicate one for detecting if the program is being debugged, so you might be able to loop until that returns to.

Chris Stratton
  • 39,853
  • 6
  • 84
  • 117