GDB
Setup
Build with debug symbols when you control the source:
gcc -g3 -O0 -fno-omit-frame-pointer -Wall -Wextra -o app app.c
Useful startup options:
| Command | Use |
|---|---|
gdb -q ./app | Open a binary quietly. |
gdb -q --args ./app arg1 arg2 | Open a binary with arguments. |
gdb -q ./app core | Open a binary with a core dump. |
gdb -q -p <pid> | Attach to a running process. |
gdb -q -x script.gdb ./app | Run a GDB command file on startup. |
gdb -q -ex 'set disassembly-flavor intel' ./app | Execute one GDB command on startup. |
Common interactive defaults:
set disassembly-flavor intel
set pagination off
set confirm off
set print pretty on
set print elements 0
set disassemble-next-line on
Put persistent defaults in ~/.gdbinit or load a project-local script with source.
Recommended Plugin: Pwngdb
Use vanilla GDB for the core commands in this sheet. For pwn, heap, libc, and CTF-style binary exploitation work, use Pwngdb as the recommended GDB extension.
Pwngdb adds commands that remove a lot of repeated manual address work:
| Command | Use |
|---|---|
libc | Print libc base. |
ld | Print dynamic loader base. |
codebase | Print code segment base. |
heap | Print heap base. |
got | Print Global Offset Table information. |
dyn | Print dynamic section information. |
findcall | Find calls to a function. |
bcall | Break at calls to a function. |
findsyscall | Find syscall instructions. |
fmtarg | Calculate the format-string argument index. |
heapinfo | Show arena, bin, and tcache information. |
heapinfoall | Show heap information for all threads. |
arenainfo | Show all arena information. |
chunkinfo | Show metadata for a chunk address. |
chunkptr | Show metadata for a user pointer. |
parseheap | Parse heap layout. |
tracemalloc on | Trace malloc/free activity. |
magic | Print useful glibc variables and functions. |
fp / fpchain | Inspect FILE structures. |
Install:
cd ~
git clone https://github.com/scwuaptx/Pwngdb.git
Load it from ~/.gdbinit:
source ~/Pwngdb/pwngdb.py
The upstream README also provides a .gdbinit. If an existing ~/.gdbinit already has local settings, merge the relevant lines instead of replacing the whole file.
For heapinfo and tracemalloc, install libc debug symbols. On Debian/Ubuntu:
sudo apt install libc6-dbg
sudo apt install libc6-dbg:i386
Use Pwngdb when the question is “where is libc/heap/GOT/tcache/chunk state right now?” Use raw GDB when the question is “what exact instruction, register, watchpoint, or process event controls this?”
Loading And Running
| Command | Use |
|---|---|
file ./app | Load or replace the debug target. |
set args A B C | Set program arguments. |
show args | Show current arguments. |
run / r | Start from the beginning. |
run A B | Start with one-off arguments. |
run < input.txt | Redirect stdin from a file. |
run > output.txt | Redirect stdout to a file. |
start | Run and stop at main. |
starti | Run and stop at the first machine instruction. |
kill | Kill the current inferior process. |
attach <pid> | Attach to a running process. |
detach | Detach and let the process continue. |
set environment KEY value | Set an environment variable for the inferior. |
unset environment KEY | Remove an environment variable for the inferior. |
set cwd <dir> | Set inferior working directory. |
tty /dev/pts/N | Give the inferior a separate terminal. |
ASLR can change addresses between runs:
show disable-randomization
set disable-randomization on
set disable-randomization off
Set this before run. Use show disable-randomization to confirm the current mode.
Execution Control
| Command | Use |
|---|---|
continue / c | Continue until exit, signal, or breakpoint. |
continue <n> | Ignore the current breakpoint for the next <n> hits. |
next / n | Step one source line, stepping over calls. |
step / s | Step one source line, stepping into calls with debug info. |
nexti / ni | Step one instruction, stepping over calls. |
stepi / si | Step one instruction, stepping into calls. |
finish / fin | Run until the current function returns. |
until / u | Run until execution leaves the current loop/line region. |
advance <loc> | Continue until a location is reached. |
jump *0x401000 | Set PC to an address and continue there. |
return <expr> | Force the current function to return a value. |
call func(args) | Call a function in the inferior. |
interrupt | Stop an asynchronously running inferior. |
Useful instruction stepping display:
display/i $pc
x/8i $pc
Breakpoints
| Command | Use |
|---|---|
break main / b main | Break at a symbol. |
break file.c:42 | Break at a source line. |
break *0x401156 | Break at an exact address. |
tbreak *0x401156 | Temporary breakpoint, deleted after first hit. |
hbreak *0x401156 | Hardware breakpoint when supported. |
rbreak regex | Break on functions matching a regex. |
info breakpoints / i b | List breakpoints, watchpoints, and catchpoints. |
disable <n> | Disable a breakpoint. |
enable <n> | Re-enable a breakpoint. |
delete <n> / d <n> | Delete a breakpoint. |
clear <loc> | Delete breakpoints at a location. |
Conditional and counted breakpoints:
break *0x401234 if $rax == 0
condition 3 $rdi == 0xdeadbeef
ignore 3 99
commands 3
silent
printf "hit rip=%p rdi=%p\n", $pc, $rdi
continue
end
Hit counters with convenience variables:
set $hits = 0
break *0x401234
commands
silent
set $hits = $hits + 1
continue
end
run
print $hits
Watchpoints And Catchpoints
| Command | Use |
|---|---|
watch expr | Stop when expression is written. |
rwatch expr | Stop when expression is read. |
awatch expr | Stop when expression is read or written. |
watch *(int*)0x404040 | Watch a typed memory address. |
watch -location var | Watch the storage location of a variable. |
catch syscall openat | Stop on a syscall. |
catch syscall read write | Stop on selected syscalls. |
catch throw | Stop on C++ exception throw. |
catch catch | Stop on C++ exception catch. |
catch fork | Stop on fork. |
catch vfork | Stop on vfork. |
catch exec | Stop on exec. |
catch load | Stop when a shared library is loaded. |
Watchpoints need an expression GDB can evaluate. Hardware watchpoints are fast but limited by CPU debug registers.
Registers
| Command | Use |
|---|---|
info registers / i r | Show general registers. |
info all-registers | Show general, floating-point, and vector registers. |
info registers rax rip | Show selected registers. |
print/x $rax / p/x $rax | Print register as hex. |
print/a $pc | Print as address/symbol. |
set $rax = 0 | Modify a register. |
set $pc = 0x401000 | Change the program counter. |
Common x86-64 registers:
| Register | Role |
|---|---|
$rip / $pc | Instruction pointer. |
$rsp / $sp | Stack pointer. |
$rbp / $fp | Frame/base pointer when used. |
$rax | Return value. |
$rdi, $rsi, $rdx, $rcx, $r8, $r9 | First six integer/pointer arguments on System V AMD64. |
$eflags | CPU flags. |
$fs_base | TLS base on Linux x86-64. |
Stack canary location on common Linux x86-64 builds:
info registers fs_base
x/gx $fs_base + 0x28
Memory
GDB’s x command uses x/<count><format><size> <address>.
| Format | Meaning |
|---|---|
x | Hex. |
d | Signed decimal. |
u | Unsigned decimal. |
t | Binary. |
a | Address/symbol. |
i | Instruction. |
c | Character. |
s | String. |
f | Float. |
| Size | Meaning |
|---|---|
b | Byte, 1 byte. |
h | Halfword, 2 bytes. |
w | Word, 4 bytes. |
g | Giant word, 8 bytes. |
Common memory commands:
| Command | Use |
|---|---|
x/16gx $rsp | Show 16 qwords from stack. |
x/20i $pc | Show 20 instructions from PC. |
x/s 0x404000 | Show a C string. |
x/32xb 0x404000 | Show 32 bytes. |
print *(int*)0x404040 | Print typed memory. |
set *(unsigned int*)0x404040 = 10 | Patch 4 bytes as an unsigned int. |
set {char[5]}0x404040 = "AAAA" | Patch bytes with a string literal. |
dump memory out.bin 0x401000 0x402000 | Dump a memory range. |
restore patch.bin binary 0x404000 | Restore bytes into memory. |
The $_ convenience variable often contains the last examined address, and $__ often contains the contents at that address.
Disassembly And Symbols
| Command | Use |
|---|---|
disassemble main / disass main | Disassemble a function. |
disassemble /r main | Include raw instruction bytes. |
disassemble 0x401000,0x401080 | Disassemble an address range. |
x/12i $pc | Disassemble from the current PC. |
info files | Show entry point and loaded file sections. |
info functions | List known functions. |
info variables | List known global/static variables. |
info address main | Show the address of a symbol. |
info symbol 0x401156 | Resolve address to symbol. |
info sharedlibrary | Show loaded shared libraries. |
maintenance info sections | Show detailed section mappings. |
set print asm-demangle on | Demangle C++ symbols in assembly output. |
Loading extra symbols:
symbol-file ./app.debug
add-symbol-file ./module.ko 0xffffffffc0000000
set solib-search-path ./libs
set sysroot /
Stack And Frames
| Command | Use |
|---|---|
backtrace / bt | Show call stack. |
bt full | Show call stack with locals. |
where | Alias for backtrace. |
frame <n> / f <n> | Select a stack frame. |
up / down | Move between caller/callee frames. |
info frame | Show selected frame details. |
info args | Show function arguments. |
info locals | Show local variables. |
list / l | Show source around the selected frame. |
Frame 0 is the currently executing frame. Optimized binaries can show <optimized out> for locals/arguments; rebuild with -O0 -g3 -fno-omit-frame-pointer when possible.
Mappings And Process Info
| Command | Use |
|---|---|
info proc | Show process info from /proc. |
info proc mappings | Show memory mappings. |
info proc exe | Show executable path. |
info proc cmdline | Show command line. |
info proc status | Show process status. |
info target | Show target details. |
show architecture | Show selected architecture. |
set architecture <arch> | Force architecture when needed. |
For a vanilla-GDB mapping view, use info proc mappings. For exact file-backed executable code, look for the mapping with execute permissions for the target binary.
Threads, Forks, And Inferiors
| Command | Use |
|---|---|
info threads | List threads. |
thread <n> | Select a thread. |
thread apply all bt | Backtrace every thread. |
set scheduler-locking on | Run only the current thread while stepping/running. |
set scheduler-locking step | Lock scheduler only while stepping. |
set scheduler-locking off | Resume normal scheduling. |
set follow-fork-mode parent | Follow parent after fork. |
set follow-fork-mode child | Follow child after fork. |
set detach-on-fork off | Keep both parent and child under GDB. |
info inferiors | List inferior processes. |
inferior <n> | Select an inferior. |
detach inferior <n> | Detach one inferior. |
Fork workflow:
set follow-fork-mode child
set detach-on-fork off
catch fork
run
info inferiors
inferior 2
Signals And Syscalls
| Command | Use |
|---|---|
info signals | Show signal handling table. |
handle SIGPIPE nostop noprint pass | Let SIGPIPE pass quietly. |
handle SIGSEGV stop print nopass | Stop and print on SIGSEGV. |
signal 0 | Resume without delivering current signal. |
signal SIGUSR1 | Resume and deliver a signal. |
catch syscall | Stop on every syscall. |
catch syscall openat read write | Stop on selected syscalls. |
Syscall catchpoints are useful for finding file, network, memory, or TLS setup behavior without knowing the exact code address first.
Core Dumps
Generate and inspect core dumps:
ulimit -c unlimited
./app
gdb -q ./app core
From inside GDB:
generate-core-file core.app
core-file core.app
bt full
info registers
info proc mappings
x/32gx $rsp
Crash triage order:
bt fullinfo registersx/16i $pcx/32gx $rspinfo proc mappings- Inspect arguments from registers or
info args.
Remote Debugging
Start a target with gdbserver:
gdbserver :31337 ./app arg1 arg2
Connect from GDB:
file ./app
target remote 127.0.0.1:31337
set sysroot /
set solib-search-path ./libs
continue
Attach remotely:
gdbserver --attach :31337 <pid>
Common remote commands:
| Command | Use |
|---|---|
target remote host:port | Connect to a remote stub. |
target extended-remote host:port | Keep remote connection across runs/restarts when supported. |
set sysroot <path> | Set target root for symbols/libraries. |
set solib-search-path <path> | Search path for shared library symbols. |
set substitute-path <from> <to> | Remap source paths. |
disconnect | Disconnect from target. |
Reverse Execution
Process record/replay can support reverse debugging on compatible targets.
| Command | Use |
|---|---|
record full | Start software instruction recording. |
record btrace | Start branch tracing when supported. |
record stop | Stop recording. |
reverse-continue / rc | Continue backward. |
reverse-step | Step backward by source line. |
reverse-next | Next backward by source line. |
reverse-stepi | Step backward by instruction. |
reverse-nexti | Next backward by instruction. |
Example:
start
record full
continue
reverse-continue
reverse-stepi
Recording has target and syscall limitations; use it for focused windows of execution.
TUI
| Command | Use |
|---|---|
tui enable | Enter TUI mode. |
tui disable | Leave TUI mode. |
layout src | Source view. |
layout asm | Assembly view. |
layout split | Source and assembly. |
layout regs | Register view. |
focus cmd | Focus command window. |
focus src / focus asm / focus regs | Focus a TUI pane. |
refresh | Redraw screen. |
Keyboard shortcuts:
| Shortcut | Use |
|---|---|
Ctrl-x a | Toggle TUI mode. |
Ctrl-x 1 | Single-window layout. |
Ctrl-x 2 | Two-window layout. |
Ctrl-l | Redraw terminal. |
Command Files
Run command files:
gdb -q ./app -x script.gdb
source script.gdb
Minimal command file:
set disassembly-flavor intel
set pagination off
break main
run
bt
info registers
Breakpoint command list:
break *0x401234
commands
silent
printf "rdi=%p rsi=%p rip=%p\n", $rdi, $rsi, $pc
x/4i $pc
continue
end
Custom command:
define regs
info registers rax rbx rcx rdx rsi rdi rbp rsp rip
end
document regs
Print common x86-64 registers.
end
Logging:
set logging file gdb.log
set logging overwrite on
set logging enabled on
bt full
set logging enabled off
Python In GDB
Run a Python script:
gdb -q ./app -ex 'source script.py'
Inline Python:
python
import gdb
print(gdb.parse_and_eval("$rip"))
end
Tiny command extension:
import gdb
class Pc(gdb.Command):
def __init__(self):
super().__init__("pc", gdb.COMMAND_USER)
def invoke(self, arg, from_tty):
pc = gdb.parse_and_eval("$pc")
print(pc)
Pc()
Use Python when breakpoint logic needs parsing, loops, structured output, or integration with external tooling.
Practical Flows
First Pass On A Stripped ELF
set disassembly-flavor intel
file ./app
info files
starti
x/20i $pc
info proc mappings
Use info files for the entry point and section addresses, starti for the first executed instruction, and info proc mappings for runtime layout.
Break At Main Without Symbols
starti
info files
break *0x401000
continue
For PIE binaries, compute runtime addresses from the loaded mapping base, or break after the dynamic loader transfers control.
Inspect A Function Call
break *0x401190
run
x/8i $pc
info registers rdi rsi rdx rcx r8 r9
nexti
finish
On System V AMD64, integer/pointer arguments are usually in rdi, rsi, rdx, rcx, r8, and r9.
Find Who Writes A Value
break main
run
watch *(unsigned long*)0x404080
continue
bt
x/6i $pc
Use rwatch for reads and awatch for reads or writes.
Trace Syscalls
catch syscall openat
catch syscall read
catch syscall write
run
info registers rdi rsi rdx
continue
Use the architecture syscall ABI when interpreting registers.
Patch A Branch
x/6i $pc
set $eflags |= 0x40
set $pc = 0x401250
Changing flags, registers, or $pc modifies the inferior state. Prefer temporary patches for investigation, then document the exact condition.
Dump A Runtime Region
info proc mappings
dump memory code.bin 0x401000 0x402000
dump memory heap.bin 0x555555559000 0x55555557a000
Use mapped start/end addresses from the current process, not static file offsets.
References
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Invocation.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Starting.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Continuing-and-Stepping.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Set-Breaks.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Set-Watchpoints.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Set-Catchpoints.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Registers.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Memory.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Backtrace.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Remote-Debugging.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Process-Record-and-Replay.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Command-Files.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/Python.html
- https://sourceware.org/gdb/current/onlinedocs/gdb.html/TUI.html
- https://github.com/scwuaptx/Pwngdb