COP4610: Operating Systems & Concurrent Programming up ↑

gdb - the Gnu Debugger

 

The purpose of these notes is to quickly introduce just a few useful features of gdb, the interactive debugger that goes with the Gnu C compiler (gcc). The notes are for impatient folks who have an immediate problem to solve and don't want to take the time to read more than the bare essentials. This debugger has many powerful features, and is especially convenient to call from inside the Gnu emacs text editor. If you want to learn all about gdb you should read more. See the section Learning More about gdb below for suggestions for such further reading.

The examples below were created in 2000, on a specific system with a specific version of emacs. Expect that some of the messages may be different when you try using emacs.

Finding Where your Program Dies

Suppose your program has died with a discouraging error message from the shell like "Segmentation fault" or "Bus error". These messages generally indicate that your program has tried to use an invalid pointer or array index. To fix the error you need to find out where the program was executing when it died. That is easy to do with gdb.

First make sure you compiled all your code using the "-g" option of the gcc compiler. This is necessary for you to be able to use symbolic names of subprograms, variables, etc. in gdb. Suppose the name of the program you are debugging is prog4.

Now, run gdb as follows:

gdb prog4

You will see a welcome message and prompt from gdb, something like this:

GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or 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.
This GDB was configured as "sparc-sun-solaris2.8"...
(gdb)

Now type in the the command run along with whatever command-line arguments prog4 expects, e.g. if prog4 expects a command-line argument "-nprocs=4" you would type in the following command to gdb:

run -nprocs=4

You will see whatever output prog4 produces, up to the point where it crashes, and then gdb will print out a message and prompt like the following:

Program received signal SIGSEGV, Segmentation fault.
0x11a74 in simulator_simulate () at simulator.c:161
161          next_event_time = event_queue_head->time;
(gdb)

This tells you the line where the program was executing when it died. In this case, the problem seems to be that the pointer variagle event_queue_head is null. We can verify this by printing out the value, using the following command:

print event_queue_head

This results in the following output from gdb:

$1 = 0x0
(gdb)

Sure enough, the pointer is null!

Sometimes the line of output printed by gdb is not enough to tell us exactly what went wrong. For example, if the program died inside one of s subprogram that was not compiled with the "-g" option (which is generally the case for library calls), we might get something like the following:

Program received signal SIGSEGV, Segmentation fault.
0xff2b32bc in strlen () from /usr/lib/libc.so.1
(gdb)

In this case we can ask gdb to give us more context, using the following command:

where

This results in the following output from gdb, showing the stack of procedure calls that were active when the program stopped:

#0  0xff2b32bc in strlen () from /usr/lib/libc.so.1
#1  0xff3031b0 in _doprnt () from /usr/lib/libc.so.1
#2  0xff304c58 in fprintf () from /usr/lib/libc.so.1
#3  0x12b2c in events_simulate (arg=0x24c10) at events.c:314
#4  0x11cd8 in simulator_simulate () at simulator.c:173
#5  0x112ac in main (argc=2, argv=0xffbef9bc) at prog4.c:110
(gdb)

The nearest non-library subprogram seems to be events_simulate. We can look at variables in this subprogram by asking gdb to walk up the stack, as follows:

(gdb) up
#1  0xff3031b0 in _doprnt () from /usr/lib/libc.so.1
(gdb) up
#2  0xff304c58 in fprintf () from /usr/lib/libc.so.1
(gdb) up
#3  0x12b2c in events_simulate (arg=0x24c10) at events.c:314
314           fprintf (stderr, "       %s for proc %4d at time %6d\n",

From this output, it looks as if the problem might be with a bad argument to fprintf.

That's all you need. Happy debugging!

Learning More about gdb

I learned how to use gdb just from the built-in help commands. To access these, start up gdb without any command-line arguments and then enter the command help at the gdb prompt.

(gdb) help
List of classes of commands:

aliases -- Aliases of other commands
breakpoints -- Making program stop at certain points
data -- Examining data
files -- Specifying and examining files
internals -- Maintenance commands
obscure -- Obscure features
running -- Running the program
stack -- Examining the stack
status -- Status inquiries
support -- Support facilities
tracepoints -- Tracing of program execution without stopping the program
user-defined -- User-defined commands

Type "help" followed by a class name for a list of commands in that class.
Type "help" followed by command name for full documentation.
Command name abbreviations are allowed if unambiguous.
(gdb)

Additional information is available from the following sources:

T. P. Baker. ($Id)