This section presents advanced GDB features, some of which may make sense only after reading the Operating Systems chapter.
GDB accepts the
make command to rebuild an executable during a debugging
session, and if the build is successful, it will run the newly built program
(when issued the
run command to run it from the beginning).
(gdb) make (gdb) run
Building from within GDB is convenient to a user who has set many breakpoints
and has fixed one bug but wants to continue the debugging session. In this
case, rather than quitting GDB, recompiling, re-starting GDB with the new
executable, and resetting all the breakpoints, a GDB user can run
start debugging the new version of the program with all the breakpoints still
set. Keep in mind, however, that modifying C source and recompiling by running
make from within GDB may result in breakpoints not being at the same logical
location in the new version of the program as in the old version; adding or
removing lines of C source code can result in breakpoints no longer being at
the same logical part of the program in the new version of the source code.
When this problem occurs, either exit GDB and restart the GDB session on the
new executable, or use
delete to disable or delete old
breakpoints and then
break to set new breakpoints at the correct location in
the newly compiled version of the program.
GDB supports debugging a program that is already running (vs. starting a program to run from within a GDB session), by attaching GDB to a running process. To do this, the user needs to get the process ID (PID) value.
Get the process’s PID using the ps command in a bash shell:
# ps to get process's PID (lists all processes started in current shell): $ ps # list all processes pipe through grep for just those named a.out: $ ps -A | grep a.out PID TTY TIME CMD 12345 pts/3 00:00:00 a.out
Start GDB and attach it to the specific running process (with PID 12345):
# gdb <executable> <pid> $ gdb a.out 12345 (gdb) # OR alternative syntax: gdb attach <pid> <executable> $ gdb attach 12345 a.out (gdb)
Attaching GDB to a process pauses it, and the user can issue GDB commands before continuing its execution.
Alternatively, a program can explicitly pause itself to wait for debugging by
kill(getpid(), SIGSTOP) (as in the
attach_example.c example). When the
program pauses at this point, a programmer can attach GDB to the process to
Regardless of how a program pauses, after GDB attaches and the user enters some
GDB commands, the program’s execution continues from its attach point using
cont doesn’t work, GDB may need to explicitly send the process a
SIGCONT signal in order to continue its execution:
(gdb) signal SIGCONT
When GDB debugs a program that calls the
fork() function to create a
new child process, GDB can be set to follow (to debug) either the parent
process or the child process, leaving the execution of the other
process unaffected by GDB. By default, GDB follows the parent after
a call to
fork(). To set GDB to follow the child process after a call
fork(), use the
set follow-fork-mode command:
(gdb) set follow-fork-mode child Set gdb to follow child on fork (gdb) set follow-fork-mode parent Set gdb to follow parent on fork (gdb) show follow-fork-mode Display gdb's follow mode
Setting breakpoints at
fork() calls in the program is
useful when the user wants to change this behavior during a GDB
The attach_example.c example shows one
way to "follow" both processes on fork: GDB follows the parent process after
the fork, and the child sends itself a
SIGSTOP signal to explicitly pause
after the fork, allowing the programmer to attach a second GDB process to the
child before it continues.
The GDB process can send signals to the target process it is debugging and can handle signals received by the target process.
GDB can send signals to the process it debugs using the
(gdb) signal SIGCONT (gdb) signal SIGALARM ...
Sometimes a user would like GDB to perform some action when a signal is receive
by the debugged process. For example, if a program tries to access memory with
a misaligned memory address for the type it is accessing, it receives a
SIGBUS signal and usually exits. The default behavior of GDB on a
also to let the process exit. If, however, you want GDB to examine program
state when it receives a
SIGBUS, you can specify that GDB handle the
signal differently using the
handle command (the
info command shows
additional information about how GDB handles signals received by the process
(gdb) handle SIGBUS stop # if program gets a SIGBUS, gdb gets control (gdb) info signal # list info on all signals (gdb) info SIGALRM # list info just for the SIGALRM signal
Running DDD creates a
.ddd directory in your home directory, which it uses to
store its settings so that users don’t need to reset all their preferences
from scratch on each invocation. Some examples of saved settings include sizes
of sub-windows, menu display options, and enabling windows to view register
values and assembly code.
Sometimes DDD hangs on start-up with a "Waiting until GDB ready" message.
This often indicates an error in its saved settings files. The easiest
way to fix this is remove the
.ddd directory (you will lose all your saved
settings and need to reset them when it starts up again):
$ rm -rf ~/.ddd # Be careful when entering this command! $ ddd ./a.out