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:

CommandUse
gdb -q ./appOpen a binary quietly.
gdb -q --args ./app arg1 arg2Open a binary with arguments.
gdb -q ./app coreOpen a binary with a core dump.
gdb -q -p <pid>Attach to a running process.
gdb -q -x script.gdb ./appRun a GDB command file on startup.
gdb -q -ex 'set disassembly-flavor intel' ./appExecute 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.

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:

CommandUse
libcPrint libc base.
ldPrint dynamic loader base.
codebasePrint code segment base.
heapPrint heap base.
gotPrint Global Offset Table information.
dynPrint dynamic section information.
findcallFind calls to a function.
bcallBreak at calls to a function.
findsyscallFind syscall instructions.
fmtargCalculate the format-string argument index.
heapinfoShow arena, bin, and tcache information.
heapinfoallShow heap information for all threads.
arenainfoShow all arena information.
chunkinfoShow metadata for a chunk address.
chunkptrShow metadata for a user pointer.
parseheapParse heap layout.
tracemalloc onTrace malloc/free activity.
magicPrint useful glibc variables and functions.
fp / fpchainInspect 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

CommandUse
file ./appLoad or replace the debug target.
set args A B CSet program arguments.
show argsShow current arguments.
run / rStart from the beginning.
run A BStart with one-off arguments.
run < input.txtRedirect stdin from a file.
run > output.txtRedirect stdout to a file.
startRun and stop at main.
startiRun and stop at the first machine instruction.
killKill the current inferior process.
attach <pid>Attach to a running process.
detachDetach and let the process continue.
set environment KEY valueSet an environment variable for the inferior.
unset environment KEYRemove an environment variable for the inferior.
set cwd <dir>Set inferior working directory.
tty /dev/pts/NGive 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

CommandUse
continue / cContinue until exit, signal, or breakpoint.
continue <n>Ignore the current breakpoint for the next <n> hits.
next / nStep one source line, stepping over calls.
step / sStep one source line, stepping into calls with debug info.
nexti / niStep one instruction, stepping over calls.
stepi / siStep one instruction, stepping into calls.
finish / finRun until the current function returns.
until / uRun until execution leaves the current loop/line region.
advance <loc>Continue until a location is reached.
jump *0x401000Set 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.
interruptStop an asynchronously running inferior.

Useful instruction stepping display:

display/i $pc
x/8i $pc

Breakpoints

CommandUse
break main / b mainBreak at a symbol.
break file.c:42Break at a source line.
break *0x401156Break at an exact address.
tbreak *0x401156Temporary breakpoint, deleted after first hit.
hbreak *0x401156Hardware breakpoint when supported.
rbreak regexBreak on functions matching a regex.
info breakpoints / i bList 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

CommandUse
watch exprStop when expression is written.
rwatch exprStop when expression is read.
awatch exprStop when expression is read or written.
watch *(int*)0x404040Watch a typed memory address.
watch -location varWatch the storage location of a variable.
catch syscall openatStop on a syscall.
catch syscall read writeStop on selected syscalls.
catch throwStop on C++ exception throw.
catch catchStop on C++ exception catch.
catch forkStop on fork.
catch vforkStop on vfork.
catch execStop on exec.
catch loadStop when a shared library is loaded.

Watchpoints need an expression GDB can evaluate. Hardware watchpoints are fast but limited by CPU debug registers.

Registers

CommandUse
info registers / i rShow general registers.
info all-registersShow general, floating-point, and vector registers.
info registers rax ripShow selected registers.
print/x $rax / p/x $raxPrint register as hex.
print/a $pcPrint as address/symbol.
set $rax = 0Modify a register.
set $pc = 0x401000Change the program counter.

Common x86-64 registers:

RegisterRole
$rip / $pcInstruction pointer.
$rsp / $spStack pointer.
$rbp / $fpFrame/base pointer when used.
$raxReturn value.
$rdi, $rsi, $rdx, $rcx, $r8, $r9First six integer/pointer arguments on System V AMD64.
$eflagsCPU flags.
$fs_baseTLS 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>.

FormatMeaning
xHex.
dSigned decimal.
uUnsigned decimal.
tBinary.
aAddress/symbol.
iInstruction.
cCharacter.
sString.
fFloat.
SizeMeaning
bByte, 1 byte.
hHalfword, 2 bytes.
wWord, 4 bytes.
gGiant word, 8 bytes.

Common memory commands:

CommandUse
x/16gx $rspShow 16 qwords from stack.
x/20i $pcShow 20 instructions from PC.
x/s 0x404000Show a C string.
x/32xb 0x404000Show 32 bytes.
print *(int*)0x404040Print typed memory.
set *(unsigned int*)0x404040 = 10Patch 4 bytes as an unsigned int.
set {char[5]}0x404040 = "AAAA"Patch bytes with a string literal.
dump memory out.bin 0x401000 0x402000Dump a memory range.
restore patch.bin binary 0x404000Restore bytes into memory.

The $_ convenience variable often contains the last examined address, and $__ often contains the contents at that address.

Disassembly And Symbols

CommandUse
disassemble main / disass mainDisassemble a function.
disassemble /r mainInclude raw instruction bytes.
disassemble 0x401000,0x401080Disassemble an address range.
x/12i $pcDisassemble from the current PC.
info filesShow entry point and loaded file sections.
info functionsList known functions.
info variablesList known global/static variables.
info address mainShow the address of a symbol.
info symbol 0x401156Resolve address to symbol.
info sharedlibraryShow loaded shared libraries.
maintenance info sectionsShow detailed section mappings.
set print asm-demangle onDemangle 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

CommandUse
backtrace / btShow call stack.
bt fullShow call stack with locals.
whereAlias for backtrace.
frame <n> / f <n>Select a stack frame.
up / downMove between caller/callee frames.
info frameShow selected frame details.
info argsShow function arguments.
info localsShow local variables.
list / lShow 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

CommandUse
info procShow process info from /proc.
info proc mappingsShow memory mappings.
info proc exeShow executable path.
info proc cmdlineShow command line.
info proc statusShow process status.
info targetShow target details.
show architectureShow 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

CommandUse
info threadsList threads.
thread <n>Select a thread.
thread apply all btBacktrace every thread.
set scheduler-locking onRun only the current thread while stepping/running.
set scheduler-locking stepLock scheduler only while stepping.
set scheduler-locking offResume normal scheduling.
set follow-fork-mode parentFollow parent after fork.
set follow-fork-mode childFollow child after fork.
set detach-on-fork offKeep both parent and child under GDB.
info inferiorsList 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

CommandUse
info signalsShow signal handling table.
handle SIGPIPE nostop noprint passLet SIGPIPE pass quietly.
handle SIGSEGV stop print nopassStop and print on SIGSEGV.
signal 0Resume without delivering current signal.
signal SIGUSR1Resume and deliver a signal.
catch syscallStop on every syscall.
catch syscall openat read writeStop 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:

  1. bt full
  2. info registers
  3. x/16i $pc
  4. x/32gx $rsp
  5. info proc mappings
  6. 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:

CommandUse
target remote host:portConnect to a remote stub.
target extended-remote host:portKeep 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.
disconnectDisconnect from target.

Reverse Execution

Process record/replay can support reverse debugging on compatible targets.

CommandUse
record fullStart software instruction recording.
record btraceStart branch tracing when supported.
record stopStop recording.
reverse-continue / rcContinue backward.
reverse-stepStep backward by source line.
reverse-nextNext backward by source line.
reverse-stepiStep backward by instruction.
reverse-nextiNext 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

CommandUse
tui enableEnter TUI mode.
tui disableLeave TUI mode.
layout srcSource view.
layout asmAssembly view.
layout splitSource and assembly.
layout regsRegister view.
focus cmdFocus command window.
focus src / focus asm / focus regsFocus a TUI pane.
refreshRedraw screen.

Keyboard shortcuts:

ShortcutUse
Ctrl-x aToggle TUI mode.
Ctrl-x 1Single-window layout.
Ctrl-x 2Two-window layout.
Ctrl-lRedraw 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