GDB Cheatsheet
Scripting and .gdbinit
Use this GDB reference while you build software engineering projects, review code, or refresh the syntax you reach for most.
Startup Files and Load Order
gdb reads several init files. Early ones can change how gdb itself starts, ordinary ones run after the executable is loaded.
| File | When |
|---|---|
~/.config/gdb/gdbearlyinit or ~/.gdbearlyinit | first, before almost anything |
~/.config/gdb/gdbinit or ~/.gdbinit | the user init file |
./.gdbinit | the local one, only if it is on the auto-load safe path |
-x file | after the init files, in the order given |
-ex cmd | one command, after -x files, repeatable |
-ix / -iex | before the init files and before loading the inferior |
-eix / -eiex | at early-init time |
gdb -nx ./prog # ignore every init file gdb -x setup.gdb ./prog gdb -ex "b main" -ex run --args ./prog -v gdb -iex "set auto-load safe-path /" ./prog
The XDG paths ~/.config/gdb/gdbinit and ~/.config/gdb/gdbearlyinit are preferred
in current gdb, and the old dotfiles in $HOME still work. A per-project .gdbinit
is refused unless the directory is on the safe path, which is deliberate, since a
.gdbinit in a cloned repo is arbitrary code execution.
A Practical .gdbinit
set confirm off set pagination off set print pretty on set print elements 0 set history save on set history size 10000 set history filename ~/.cache/gdb_history set disassembly-flavor intel set backtrace past-main off set debuginfod enabled on add-auto-load-safe-path /home/me/src
| Setting | Why |
|---|---|
set confirm off | no "are you sure" prompts on delete, run, quit |
set pagination off | long output scrolls, no ---Type <return>--- |
set history save on | remember commands between sessions |
set print pretty on | readable structs |
set print elements 0 | never truncate an array or string with ... |
set logging file f plus set logging enabled on | tee the session to a file |
set debuginfod enabled on | fetch missing debug info by build ID |
set auto-load safe-path DIRS | where auto-loaded scripts may come from |
(gdb) add-auto-load-safe-path /home/me/src (gdb) show auto-load safe-path (gdb) info auto-load python-scripts (gdb) info auto-load local-gdbinit
If a C++ container prints as raw _M_impl internals, or gdb warned that it declined
to auto-load a script, that is the safe path. add-auto-load-safe-path on the
specific tree is the right fix. Setting the safe path to / disables the protection
entirely, so do it per project, not globally.
User-Defined Commands
define builds a command out of other gdb commands. Arguments are $arg0 through
$argN, with $argc holding the count, and they are plain text substitutions.
define plist set $n = $arg0 while $n != 0 printf "%d ", $n->key set $n = $n->next end printf "\n" end document plist Walk a singly linked list and print each key. Usage: plist HEAD end
(gdb) plist head 3 1 4 1 5 (gdb) help plist (gdb) show user plist # print the definition back (gdb) define hook-run >echo starting...\n >end
| Construct | Use |
|---|---|
define NAME ... end | a new command |
document NAME ... end | its help text, the command must exist already |
$arg0 … $argN, $argc | positional arguments and their count |
if / else / end, while / end | control flow inside a definition |
loop_break / loop_continue | break and continue inside a while |
printf "%d\n", expr | formatted output, C format strings |
echo text\n | literal text |
eval "cmd %d", n | build a command string and run it |
define hook-CMD | run before CMD every time |
define hookpost-CMD | run after it |
show user | list every user-defined command |
Arguments cannot contain spaces and quoting them is fragile, so anything past a loop and a printf belongs in Python.
Batch and Non-Interactive Use
--batch runs the commands and exits, with no prompt and no pager. This is how gdb
belongs in a script or a CI job.
# the one you actually want: a backtrace out of a core, no interaction gdb -q --batch -ex "thread apply all bt full" ./prog core.4711 gdb -q --batch -ex "bt" -ex "info registers" ./prog core.4711 > crash.txt gdb -q --batch -x triage.gdb ./prog core.4711 gdb -q --batch -p 4711 -ex "thread apply all bt" > hang.txt gdb -q --batch -ex "info functions ^http_" ./prog gdb -q --batch -ex "ptype/o struct config" ./prog gdb -q --batch -ex run -ex bt --args ./prog crash-input.bin
| Flag | Effect |
|---|---|
--batch | run the commands then exit, implies set confirm off and no pager |
--batch-silent | same, and suppress gdb's own stdout entirely |
-q / --quiet | no version banner |
-nx | ignore init files, so CI does not inherit your dotfiles |
--return-child-result | gdb exits with the inferior's exit code |
-ex / -x | the commands, inline or from a file |
--batch exits with status 0 if the commands ran, even when the program crashed.
Add --return-child-result if the exit code needs to reflect the program.
Python
A gdb built with Python gets a full API. python with no argument is a multi-line
block ended by end, and python-interactive opens a REPL.
(gdb) python print(gdb.VERSION) (gdb) python-interactive >>> gdb.execute("bt", to_string=True).count("\n") >>> gdb.parse_and_eval("cfg.port")
python import gdb class PrintList(gdb.Command): """Walk a linked list. Usage: plist HEAD""" def __init__(self): super().__init__("plist", gdb.COMMAND_DATA) def invoke(self, arg, from_tty): node = gdb.parse_and_eval(arg) while int(node) != 0: print(int(node["key"])) node = node["next"] PrintList() end
| API | Does |
|---|---|
gdb.execute(cmd, to_string=True) | run a gdb command, optionally capture the output |
gdb.parse_and_eval(expr) | evaluate a program expression into a gdb.Value |
gdb.Value indexing and int() | read struct fields and cast to Python numbers |
gdb.selected_frame() / .older() | walk the stack |
gdb.selected_inferior().read_memory(a, n) | raw memory as bytes |
gdb.breakpoints() | the breakpoint objects |
gdb.Breakpoint("f", ...) | create one from Python, subclass it for stop() |
gdb.Command | register a new gdb command |
gdb.events.stop.connect(fn) | run a callback on every stop |
gdb.write(s) / gdb.flush() | write through gdb's own output stream |
(gdb) source ~/scripts/mytools.py (gdb) set python print-stack full
set python print-stack full is the first thing to turn on when a Python script
silently misbehaves. By default gdb prints only the exception message and hides the
traceback, which makes a broken pretty-printer look like a gdb bug.