How-To Attach GDB to a Running Process
Introduction
I’m in the position that I have to debug a program that is running alongside multiple other programs which emulate portions of the complete system so that you can run tests on a desktop PC. That means I can’t just start the program from the command line and be done with it: everything is started in proper order by a script. It’s not possible to inject a debugger into the middle of that process without disturbing it, so I have to attach the debugger after the process is already running - which I had never done before. That means I get to document something new that I’ve learned!
FYI, these steps are for Linux.
Basic Concept
At its simplest, all you need to do to use gdb on an already running program is use the -p command line option like this:
gdb -p
But there’s a difficulty: you need the PID (Process ID) which is a number. On Linux, you can get this with ps:
ps -aux
That produces output that looks something like this:
PID PPID PGID WINPID TTY UID STIME COMMAND
198 162 198 27012 pty0 197609 21:36:06 /usr/bin/ps
162 161 162 24660 pty0 197609 21:35:52 /usr/bin/bash
161 1 161 6984 ? 197609 21:35:52 /usr/bin/minttyThat’s output from ps on git bash on Windows. On Linux it will be different, but fundamentally you’re looking for the PID so that you can use it with gdb.
Of course, the program that you’re attempting to debug must be compiled with the proper switches to allow for debugging or this won’t work.
Scripting gdb
One of the nice aspects of gdb is that you can avoid having to type all the commands that you want to use by putting them in a text file and passing it to gdb on the command line. This is very useful when you’re attaching to a running process because you may want to catch some transient behavior. You can do this with the -x command line:
gdb -x gdb_cmds.txt
gdb_cmds.txt needs only be a text file that contains the commands you want to execute in gdb.
Catching Program Startup
If you want to catch some startup behavior of your program you’ll need to generate a script that’s looking for the process to start to catch the pid and then immediately start gdb. I’ve used a bash script to do this, and below is a distillation of one that I’ve used before:
# Loop until ps shows the program running and grab the pid
while [ -z "$pid" ] ; do
pid=$(ps -aux | grep -v grep | grep <program name> | tr -s ' ' | cut-d' ' -f 2)
sleep .5
done
gdb -p "$pid" -x gdb_cmds.txtObviously ‘program name’ is the name of your program. You can adjust the sleep to be more responsive if you need to catch the program doing something at startup. The big ol’ command that assigns the pid variable is processing the output of ps to find the program and massage it to return only the pid number. You can also use the gdb_cmds.txt file to immediately upon startup set a breakpoint in your desired location and then start the program executing immediately - keep in mind that gdb will halt the program when it attaches to it. This may be undesirable if your program needs to communicate with anything that isn’t halted by a debuger.