Skip to content

GNU Debugger ​

The GNU Debugger (GDB) is one of the most widely used debuggers today, with numerous frontends and adapters available. GDB is freely available under the GPLv3 license.

GDB Quickstart ​

Create an executable with debug symbols ​

bash
g++ main.cpp -o program -Og -g
  • -O0 - enables no optimizations (maybe preferred)
  • -Og - enables optimizations that do not interfere with debugging
  • -g - tells GCC to emit extra information for use by a debugger
  • -ggdb - tells GCC to emit extra information for use by the GNU debugger
  • both -g and -ggdb have debug levels 0 to 3

Get hints ​

GDB is self documented.

  • $man gdb - displays manual pages
  • $gdb --help - lists all options, with brief explanations
  • $info gdb - displays detailed information and documentation
  • (gdb) help - displays help
  • (gdb) info - displays info

Launch a debugger with a file attached ​

bash
gdb program
  • GNU debugger gdb
  • Executable program you want to inspect

Layouts layout, lay ​

  • Launch TUI directly gdb program --tui (equivalent to layout src)
  • Layout source layout src - displays source code (if not available recompile with -g flag enabled)
  • Layout assembly layout asm - displays assembly
  • Layout split layout split - displays both assembly and source layout
  • Refresh layout refresh - refreshes TUI
  • Focus focus - changes focus of a window

Breakpoints ​

  • break, br, b - sets a breakpoint to pause execution at a specified location
  • watch - watchpoint stops execution of your program whenever the value of an expression changes.
  • info breakpoints - lists all breakpoints
  • delete N - deletes breakpoint with number N

Launch the program ​

  • run, r - start the program execution inside of gdb
  • start - creates a temporary breakpoint at main() and start execution

Launch the executable and step thru the program ​

  • next, n - executes the next line of code
  • nexti, ni - executes the next instruction
  • step, s - enters a function
  • finish, fin - execute until selected stack frame returns
  • continue, c - continue execution until next breakpoint

Inspect ​

  • print, inspect, p - prints a value of an expression
  • display - prints value of expression each time the program stops
  • backtrace, where, bt - prints backtrace of all stack frames

Info ​

  • info locals - print all local variables (within the current stack frame)
  • info registers - print registers and their values
  • info breakpoints - print status of all set breakpoints
  • info watchpoints - print status of all set breakpoints

Hello GDB ​

Lets start with the obligatory hello world example:

cpp
#include <iostream>
int main() {
    std::cout << "Hello, GDB!";
    return 0; /* break here */
}

Compile the source code using GCC with debug symbols enabled. Launch GDB (-q - quiet mode. GDB does not display the initial message).

g++ main.cpp -o main.out -O0 -g
gdb main.out -q
Reading symbols from main.out...

Now you should be inside of GDB. Each line should should start with (gdb) . First lets start the execution of the program start:

(gdb) start
Temporary breakpoint 1 at 0x123456: file main.cpp, line 3.
Starting program: /file/path/to/main.out

Temporary breakpoint 1, main () at main1.cpp:3
3           std::cout << "Hello, GDB!" << std::endl;

Step a line next (abbreviated n):

(gdb) n
Hello, GDB!
4           return 0;

Continue the program continue [N] (abbreviated c, optionally number of breakpoints to skip N can be specified):

(gdb) c
Continuing.
[Inferior 1 (process process_id) exited normally]

Quit GDB quit (abbreviated q).

(gdb) q

Printing ​

Inspecting the program's state at specific points in one of the core features of a debugger. The print command (abbreviated p, alias inspect) is used for displaying the value of an expression in GDB.

(gdb) print expr
(gdb) p expr

Example of printing some of the basic variables.

cpp
int main() {
    int var = 123;
    int *pvar = &var;
    const void *hello = "Hello, GDB!";
    int sum[10] = {};
    for(int i = 1; i < 10; ++i) {
        sum[i] = sum[i-1] + i;
    }
    return 0; /* break here */
}

Let's set a breakpoint break (abbreviated b) after all of the variables have been set and run the program.

(gdb) b 9
Breakpoint 1 at 0x123456: file main.cpp, line 9.
(gdb) run
Starting program: /path/to/executable.out

Breakpoint 1, main () at main.cpp:9
9           return 0;

Basic use case of the print command:

(gdb) p var
$1 = 123

Printing pointers and pointer dereferencing:

(gdb) p pvar
$2 = (int *) 0x123456789abc
(gdb) p *pvar
$3 = 123

Casting of a void pointer to a char pointer:

(gdb) p hello
$4 = (const void *) 0x123456
(gdb) p (char*) hello
$5 = 0x123456 "Hello, World!"

GDB supports printing out arrays:

(gdb) p sum
$6 = {0, 1, 3, 6, 10, 15, 21, 28, 36, 45}