Beej's Quick Guide to GDB
Release 2 (2009 Jun 14)This is a very quick-and-dirty guide meant to get you started with the GNU Debugger,
Again, this is only a getting-started guide. There's much much MUCH more to learn about what the debugger does than is written in these few short paragraphs. Check out your "man" pages or the online resources listed below for more info.
This tutorial is meant to be read in order, up to, but not including, the "Misc" section.
Contents
- Compiling to use a debugger
- More Information
- License
- Starting
gdb and getting to main() - Breakpoints
- Stepping Around
- Examining Variables
- Misc Stuff
- Quick Reference Cheat Sheet
Compiling
You have to tell your compiler to compile your code with symbolic debugging information included. Here's how to do it with
$ gcc -g hello.c -o hello $ g++ -g hello.cpp -o hello
Once you've done that, you should be able to view program listings in the debugger.
More Information
Check out the
Also, a good GNU GDB front-end is
License

Beej's Quick Guide to GDB
Starting The Debugger
First things first: you can enter
There are several ways to start the debugger (e.g. if you were an IDE you might start it with a particular mode that's not so human-friendly) but I'll mention two of them here: vanilla console mode and curses GUI mode. The GUI is better, but let's quickly cover the simple one, and launch a program called
$ gdb hello GNU gdb 6.8 Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-slackware-linux"... (gdb) run Starting program: /home/beej/hello Hello, world! Program exited normally. (gdb)
The last line is the
To start in neato and highly-recommended GUI mode, start the debugger with
And here is a screenshot of what you'll see, approximately:

All the normal
Now, notice that we passed the name of the executable on the command line. Another option you have is to just start
Command line arguments! What if you have to get something into
$ gdb hello GNU gdb 6.8 Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-slackware-linux"... (gdb) run arg1 arg2 Starting program: /home/beej/hello arg1 arg2 Hello, world! Program exited normally. (gdb)
Notice where it says "Starting Program", above, it shows the arguments "arg1" and "arg2" being passed to "hello".
Breakpoints
Just starting the debugger to run the program straight through isn't very useful—we need to stop execution and get into stepping mode.
First, before you issue the
break main | Break at the beginning of the |
break 5 | Break at line 5 of the current file |
break hello.c:5 | Break at line 5 of |
So for this test, let's set a breakpoint at
$ gdb hello GNU gdb 6.8 Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-slackware-linux"... (gdb) b main Breakpoint 1 at 0x8048395: file hello.c, line 5. (gdb) r Starting program: /home/beej/hello Breakpoint 1, main () at hello.c:5 5 printf("Hello, world!\n"); (gdb)
As you see, we've arrived at
To list the current breakpoints, use the
(gdb) b main Breakpoint 1 at 0x8048395: file hello.c, line 5. (gdb) i b Num Type Disp Enb Address What 1 breakpoint keep y 0x08048395 in main at hello.c:5
To clear a breakpoint, use the
Additionally, you can
(gdb) i b Num Type Disp Enb Address What 1 breakpoint keep y 0x08048395 in main at hello.c:5 (gdb) disable 1 (gdb) i b Num Type Disp Enb Address What 1 breakpoint keep n 0x08048395 in main at hello.c:5 (gdb) clear main Deleted breakpoint 1 (gdb) i b No breakpoints or watchpoints.
Stepping Around
Once execution stops at a breakpoint, you can tell the debugger to do a few things. Let's start with the
(gdb) b main Breakpoint 1 at 0x8048395: file hello.c, line 5. (gdb) r Starting program: /home/beej/hello Breakpoint 1, main () at hello.c:5 5 printf("Hello, world!\n"); (gdb) next Hello, world! 7 return 0; (gdb) next 8 } (gdb) next 0xb7d6c6a5 in __libc_start_main () from /lib/libc.so.6 (gdb) next Single stepping until exit from function __libc_start_main, which has no line number information. Program exited normally. (gdb)
(That weird stuff at the end about
Now, notice that
What if you have a function you want to
Let's say you're tired of single stepping, and just want the program to run again. Use the
What if the program is running but you forgot to set breakpoints? You can hit
One final shortcut is that just hitting
Examining Variables
If you have some variables you wish to inspect over the course of the run, you can
(The following output is missing source code output between lines for clarity—it's what you'd see in GUI mode. Imagine you're seeing the highlight bar bouncing around the source code while you're running this:)
(gdb) b main Breakpoint 1 at 0x8048365: file hello.c, line 5. (gdb) r Starting program: /home/beej/hello Breakpoint 1, main () at hello.c:5 (gdb) disp i 1: i = -1207447872 (gdb) next 1: i = 1 (gdb) next 1: i = 1 (gdb) next 1: i = 2 (gdb) next 1: i = 2 (gdb) next 1: i = 4 (gdb) next 1: i = 4 (gdb) next 1: i = 4 (gdb)
The number to the left of "i", above, is the display number of the variable. Use this number to
(gdb) b main Breakpoint 1 at 0x8048365: file hello.c, line 5. (gdb) r Starting program: /home/beej/hello Breakpoint 1, main () at hello.c:5 (gdb) display i 1: i = -1207447872 (gdb) info display Auto-display expressions now in effect: Num Enb Expression 1: y i (gdb) undisplay 1 (gdb)
If you just want to one-off know the value of a variable, you can
(gdb) print i $1 = 40 (gdb)
(The "$" with the number after it means something, but it's not important for beginners.)
There's also a handy
(gdb) printf "%d\n", i 40 (gdb) printf "X\n", i 00000028 (gdb)
Misc Stuff
This is stuff that doesn't really fit in the earlier sections, but it fun enough to list somewhere.
Stack Manipulation
The command
(gdb) backtrace #0 subsubfunction () at hello.c:5 #1 0x080483a7 in subfunction () at hello.c:10 #2 0x080483cf in main () at hello.c:16 (gdb)
Type
Additional Stepping Methods
To exit the current function and return to the calling function, use the
To step for a single assembly instruction, use the
To continue to a specific location, use the
Breakpoint 1, main () at hello.c:15 15 printf("Hello, world!\n"); (gdb) advance subsubfunction Hello, world! subsubfunction () at hello.c:5 5 printf("Deepest!\n"); (gdb)
advance
Jumping to an Arbitrary Section of Code
The
If you need to stop at the jump destination, set a breakpoint there first.
Changing Variables and Values at Runtime
You can use the
Breakpoint 1, main () at hello.c:15 15 int i = 10; (gdb) print i $1 = -1208234304 (gdb) set (i = 20) (gdb) print i $2 = 20 (gdb) set variable i = 40 (gdb) print i $3 = 40 (gdb)
This, along with the
Hardware Watchpoints
Hardware watchpoints are special breakpoints that will trigger whenever an expression changes. Often you just want to know when a variable changes (is written to), and for that you can use the
Breakpoint 1, main () at hello.c:5 5 int i = 1; (gdb) watch i Hardware watchpoint 2: i (gdb) continue Continuing. Hardware watchpoint 2: i Old value = -1208361280 New value = 2 main () at hello.c:7 7 while (i < 100) { (gdb) continue Continuing. Hardware watchpoint 2: i Old value = 2 New value = 3 main () at hello.c:7 7 while (i < 100) { (gdb)
Note that
You can get a list of watch points with
Finally, you can use
Attach to a Running Process
If your program is already going and you want to stop it and debug, first you'll need the process ID (PID), which will be a number. (Get it from Unix's
For this, you can just start
In the following complete run, you'll notice a few things. First I attach to the running process, and it tells me it's in some function deep down called__nanosleep_nocancel(), which isn't too surprising since I called
$ gdb GNU gdb 6.8 Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-slackware-linux". (gdb) attach 3490 Attaching to process 3490 Reading symbols from /home/beej/hello...done. Reading symbols from /lib/libsafe.so.2...done. Loaded symbols for /lib/libsafe.so.2 Reading symbols from /lib/libc.so.6...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/libdl.so.2...done. Loaded symbols for /lib/libdl.so.2 Reading symbols from /lib/ld-linux.so.2...done. Loaded symbols for /lib/ld-linux.so.2 0xb7eab21b in __nanosleep_nocancel () from /lib/libc.so.6 (gdb) backtrace #0 0xb7eab21b in __nanosleep_nocancel () from /lib/libc.so.6 #1 0xb7eab05f in sleep () from /lib/libc.so.6 #2 0x080483ab in main () at hello.c:10 (gdb) finish Run till exit from #0 0xb7eab21b in __nanosleep_nocancel () from /lib/libc.so.6 0xb7eab05f in sleep () from /lib/libc.so.6 (gdb) finish Run till exit from #0 0xb7eab05f in sleep () from /lib/libc.so.6 0x080483ab in main () at hello.c:10 10 sleep(1); (gdb) list 5 { 6 int i = 1; 7 8 while (i < 60) { 9 i++; 10 sleep(1); 11 } 12 13 return 0; 14 } (gdb) print i $1 = 19 (gdb) quit The program is running. Quit anyway (and detach it)? (y or n) y Detaching from program: /home/beej/hello, process 3490
Notice that when I get back to
Once we've quit the debugger and detached from the program, the program returns to running normally.
Mix this with
Using Coredumps for Postmortem Analysis
Let's say you build and run a program, and it dumps core on you for some reason or another:
$ cc -g -o foo foo.c $ ./foo Segmentation fault (core dumped)
This means that a core file (with a memory snapshot from the time of the crash) has been created with the name "core". If you're not getting a core file (that is, it only says "Segmentation fault" and no core file is created), you might have your ulimit set too low; try typing
You can fire up
$ gdb -tui -c core foo
And, if in TUI mode, you'll be greeted with a screen of information, telling you why the program exited ("signal 11, Segmentation fault"), and the highlight will be on the offending line. (In dumb terminal mode, the offending line is printed out.)
In this example, I print the variable that's causing the problem. Indeed it is NULL:

Even if you don't have all the source code, it's often useful to get a
Window Functions
In TUI mode, you can get a list of existing windows with the
Note that when the SRC window has focus, the arrow keys will move the source code, but when the CMD window has focus, the arrow keys will select the previous and next commands in the command history. (For the record, the commands to move the SRC window single lines and single pages are
(gdb) info win SRC (36 lines) <has focus> CMD (18 lines) (gdb) fs next Focus set to CMD window. (gdb) info win SRC (36 lines) CMD (18 lines) <has focus> (gdb) fs SRC Focus set to SRC window. (gdb)
(Window names are case in-sensitive.)
The
Display Registers and Assembly
In TUI mode, the
layout src | Standard layout—source on top, command window on the bottom |
layout asm | Just like the "src" layout, except it's an assembly window on top |
layout split | Three windows: source on top, assembly in the middle, and command at the bottom |
layout reg | Opens the register window on top of either source or assembly, whichever was opened last |
tui | Show the general registers |
tui reg float | Show the floating point registers |
tui | Show the "system" registers |
tui reg next | Show the next page of registers—this is important because there might be pages of registers that aren't in the "general", "float", or "system" sets |
Here's a nifty screenshot to whet your appetite, showing source and assembly in "split" mode:

Assembly code comes in two flavors on Intel machines: Intel and AT&T. You can set which one appears in the disassembly window with
To display registers in dumb terminal mode, type
Writing a Front-End
You're thinking, "Wow, this is pretty cool, but I could write a killer front-end for this thing that worked so much better! How do I do it?"
GDB supports what it calls the "machine interface interpreter", or GDB/MI. The interpreter is selected on the
Basically you'll launch
See the
Quick Reference
Command parameters are in italics. Optional parameters are in square brackets. All commands can be abbreviated until they become ambiguous.
This list is very very incomplete, and only shows things talked about in this tutorial!
Help Commands | |
help | Get help on a certain command |
apropos | Search help for a particular keyword |
Starting and Quitting | |
gdb | (Unix Command) |
run | Run the currently loaded program with the given command line arguments |
quit | Exit the debugger |
file | Load an executable file by name |
Breakpoints and Watchpoints | |
break | Set a breakpoint at a location, line number, or file (e.g. "main", "5", or "hello.c:23") |
watch | Break when a variable is written to |
rwatch | Break when a variable is read from |
awatch | Break when a variable is written to or read from |
info break | Display breakpoint and watchpoint information and numbers |
info watch | Same as |
clear | Clear a breakpoint from a location |
delete | Delete a breakpoint or watchpoint by number |
Stepping and Running | |
next | Run to the next line of this function |
step | Step into the function on this line, if possible |
stepi | Step a single assembly instruction |
continue | Keep running from here |
CTRL-C | Stop running, wherever you are |
finish | Run until the end of the current function |
advance | Advance to a location, line number, or file (e.g. "somefunction", "5", or "hello.c:23") |
jump | Just like |
Examining and Modifying Variables | |
display | Display the value of a variable or expression every step of the program—the expression must make sense in the current scope |
info display | Show a list of expressions currently being displayed and their numbers |
undisplay | Stop showing an expression identified by its number (see |
print | Print the value of a variable or expression |
printf | Do some formatted output with |
set variable | Set a variable to value, e.g. |
set (expression) | Works like |
Window Commands | |
info win | Shows current window info |
focus | Set focus to a particular window bby name ("SRC", "CMD", "ASM", or "REG") or by position ("next" or "prev") |
fs | Alias for |
layout | Set the window layout ("src", "asm", "split", or "reg") |
tui reg | Set the register window layout ("general", "float", "system", or "next") |
winheight | Set the window height (either an absolute value, or a relative value prefaced with "+" or "-") |
wh | Alias for |
set | Set the look-and-feel of the disassembly. On Intel machines, valid flavors are |
Misc Commands | |
RETURN | Hit RETURN to repeat the last command |
backtrace | Show the current stack |
bt | Alias for |
attach | Attach to an already-running process by its PID |
info registers | Dump integer registers to screen |
info all-registers | Dump all registers to screen |
Copyright 2009 Brian "Beej Jorgensen" Hall <beej@beej.us>