Getting to Know gdb

It's worth making friends with a good C debugger.

There are many reasons you might need a debugger—the most obvious being that you're a programmer and you've written an application that doesn't work right. Beyond this, Linux depends heavily both on sharing source code and on porting code from other Unix systems. For both types of code, you may turn up problems that the original authors didn't have on their platform. So it's worth making friends with a good C debugger.

Luckily, the Free Software Foundation has come through with an excellent debugger named gdb, which works with both C and C++ code. gdb lets you stop execution within the program, examine and change variables during execution, and trace how the program executes. It also has command line editing and history features similar to those used with bash (the GNU shell) and Emacs. In fact, it now has a graphical interface. But since we've grown up using the command-line interface (and it's easier to show in print) we'll stick to that in this article.

To get full documentation on all gdb commands, read the Debugging with gdb manual on-line or order it from the Free Software Foundation.

Compilation for gdb

Before you can use gdb to debug a program, compile and link your code with the -g option. This causes the compiler to generate an augmented symbol table. For example, the command:

$ gcc -g file1.c file2.c file3.o

compiles the C source files file1.c and file2.c, generating an expanded symbol table for use with gdb. These files are linked with file3.o, an object file that has already been compiled.

The compiler's -g and -O are not incompatible; you can optimize and compile for debugging at the same time. Furthermore, unlike many other debuggers, gdb will even give you somewhat intelligible results. However, debugging optimized code is difficult since, by nature, optimization makes the machine code diverge from what the source code says to do.

Starting gdb

To debug a compiled program with gdb, use the command:

$ gdb program [ core-dump ]

where program is the filename of the executable file you want to debug, and core-dump is the name of a core dump file left from an earlier attempt to run your program. By examining the core dump with gdb, you can discover where the program failed and the reason for its failure. For example, the following command tells gdb to read the executable file qsort2 and the core dump core.2957:

$ gdb qsort2 core.2957
gdb is free software and you are welcome to
distribute copies of it under certain conditions;
type "show copying" to see the conditions.
There is absolutely no warranty for gdb;
type "show warranty" for details.
gdb 4.13 (sparc-sun-sunos4.1.3),
Copyright 1993 Free Software Foundation, Inc...
Core was generated by `qsort2'.
Program terminated with signal 7, Emulator trap.
#0  0x2734 in qsort2 (l=93643, u=93864, strat=1)
at qsort2.c:118
118           do i++; while (i <= u && x[i] < t);
(gdb) quit

The startup is fairly verbose; it tells you which version of gdb you're using. Then it tells you how the core file was generated (by the program qsort2, which received signal 7, an “emulator trap”), and what the program was doing (executing line 118). The prompt “(gdb)” tells you that gdb is ready for a command. In this case, we'll just quit.

Both the executable file and the core file arguments are optional. You can supply a core file at a later date with the core command.

Basic gdb Commands

With just a few commands, you can get most of your work done in gdb. The basic things you have to do are: look at your source code, set breakpoints, run programs, and check variables.

If you forget which command to use (or want to check for obscure features) use the built-in help facility. You can request a particular command (like help print) or on a number of special topics.

Listing a File

To see the contents of the source file from which the executable program was compiled, use the command list:

$ gdb qsort2
(gdb) list
13     void qsort2();
14     void swap();
15     void gen_and_sort();
16     void init_organ();
17     void init_random();
18     void print_array();
20     main()
21     {
22            int power=1;

To print specific lines from the file you are currently debugging, use a list command:

(gdb) list line1,line2

To list the first 10 lines from a particular function, use a list command:

(gdb) list routine-name