Advanced GDB Debugging: Core Concepts and Command Reference
Stack Architecture and Frame Management
When a program halts under GDB, the immediate concern involves understanding its current location and the execution path that led there. Each function invocation generates a stack frame (or activation record) containing the return address, passed arguments, and local storage. These frames collectively form the call stack—a contiguous memory region managed through hardware registers such as the Frame Pointer ($FP).
GDB assigns sequential integers to frames, with frame 0 representing the innermost (most recent) invocation. The debugger maintains a "selected frame" context; variable references and evaluations operate within this context unless explicit switched. Note that optimized builds using -fomit-frame-pointer may generate frameless functions, limiting GDB's ability to walk the stack beyond the innermost frame.
Launching and Configuring the Debugger
Invocation Patterns
gdb executable
gdb executable core_dump
gdb --args program arg1 arg2
gdb -p pid
gdb --silent # Suppress startup messages
The --args variant passes subsequent tokens directly to the inferior process, essential for debugging compilers or interpreters with complex argument lists.
Symbol and Core Management
-s file/-symbol file: Load symbol table from separate file-c file/-core file: Analyze post-mortem core dump-se file: Combined symbol and executable file-d directory: Append source search path
Session Logging
Capture output for later analysis:
set logging on
set logging file debug_session.txt
set logging overwrite on
set logging redirect on # Suppress terminal output
Shell Integration
Execute host commands with out leaving GDB:
shell make clean
!grep -n function_name src/*.c
make CFLAGS="-g -O0"
Navigating Documentation
Locate commands via keyword search when exact syntax is elusive:
apropos regexp
For precise command syntax, use:
help command_name
Execution Control
Starting and Resuming
run [args]: Launch fresh instancestart [args]: Run tomainentry point and breakcontinue [count]: Resume execution, optionally ignoring subsequent breakpoints
Selective Skipping
Exclude uninteresting code paths:
skip -function std::vector::push_back
skip -rfu ^std::.* # Regex for namespace exclusion
skip -file utils.cpp
info skip
Execution Checkpoints
Create lightweight process snapshots using fork-based bookmarks:
checkpoint # Create snapshot (displays checkpoint ID)
info checkpoints # List saved states
restart 3 # Rewind to checkpoint #3
delete checkpoint 2 # Remove specific snapshot
Checkpoints preserve memory, registers, and select system states. File descriptors and external device I/O remain unaffected by reversal. This mechanism proves invaluable when debugging elusive race conditions or when ASLR (Address Space Layout Randomization) invalidates absolute breakpoints across restarts.
Breakpoint Strategies
Placement Syntax
break function_name
break filename:line_number
break *0x7ffff7a8c2d0 # Absolute address requires asterisk
break Class::Method
break +offset # Relative to current line
break -offset
Critical distinction: break 0x4007d9 attempts to resolve a function named "0x4007d9", whereas break *0x4007d9 sets an address-based breakpoint. Verify addresses using:
info line file.cpp:42
disassemble /m function_name
Pending Breakpoints
When targeting unloaded shared libraries:
set breakpoint pending on # Auto-create pending breakpoints
# or respond 'y' to the interactive prompt
Verify library loading with info sharedlibrary and info sources.
Conditional Logic
break parse_buffer if index > 512 && buffer != NULL
condition 3 (error_code == EAGAIN) # Modify existing breakpoint
ignore 3 5 # Skip first 5 hits
Syntax requirement: Space between if and opening parenthesis is mandatory. Condisions evaluate as integer expressions (zero = false, non-zero = true).
Automated Actions
Execute GDB commands upon breakpoint hits:
commands 4
silent
printf "Debug: ptr=%p, size=%zu\n", ptr, size
dump memory dump.bin ptr ptr+size
continue
end
Replace existing commands by reissuing commands <num>. Empty command list removes automation.
User-Defined Macros
Encapsulate repetitive sequences:
define dump_vector
set $idx = 0
while $idx < $arg0.size()
print $arg0[$idx]
set $idx++
end
end
document dump_vector
Prints all elements of a vector-like structure.
Usage: dump_vector variable_name
end
Display defined macros with show user. Macros support positional parameters $arg0 through $arg9.
Specialized Breakpoint Types
tbreak location: Temporary breakpoint (removed after first hit)rbreak regex: Set breakpoints on all matching function nameshbreak location: Hardware-assisted breakpoint (limited by CPU debug registers)
Lifecycle Management
clear function_name # Delete by location
delete [range] # Remove by breakpoint number
disable [range] # Retain but deactivate
enable [range] # Reactivate
enable once [range] # Activate then delete
enable delete [range] # Equivalent to tbreak behavior
Data Examination
Expression Evaluation
The print command supports full language syntax plus GDB extensions:
print *pointer@length # Array slicing
print/x (short[2])0x12345678 # Cast raw bytes
print variable++ # Post-increment in debugger context
Memory Inspection
x/4gx &variable # 4 giant words (8 bytes), hexadecimal
x/10i $pc-0x10 # 10 instructions from current PC
x/s *0x7fffffffe400 # String at dereferenced address
Format specifiers:
- x: hexadecimal
- d: decimal
- u: unsigned
- o: octal
- t: binary
- i: instruction
- s: string
Unit sizes: b (byte), h (halfword), w (word), g (giant)
Persistent Displays
Monitor expressions automatically at every stop:
display/x current_ptr
display/t flags
disable display 2
Value History
GDB maintains a numeric history of printed values:
print buffer->length
print $1->data # $1 refers to previous result
print $$ # Second most recent value
print $$0 # Synonym for $
Convenience Variables
User-defined scratch variables:
set $counter = 0
set $buffer = (char*)malloc(256)
init-if-undefined $limit = 100
show convenience
Built-in convenience variables:
$_exitcode: Process return value (void if signal terminated)$_exitsignal: Signal number if terminated abnormally$_isvoid(expr): Returns 1 if expression evaluates to void$_streq(str1, str2): String equality (requires Python support)
Watchpoints
Monitor memory changes without knowing location:
watch -location global_counter # Write detection
rwatch buffer[64] # Read detection
awatch *0x601050 # Access detection (read or write)
Hardware watchpoints trigger immediately; software watchpoints significantly degrade performance due to single-stepping emulation. Use info break to enumerate watchpoints.
Catchpoints
Trap runtime events:
catch throw std::runtime_error # Specific C++ exceptions
catch syscall openat # Specific syscall entry/exit
catch syscall # All syscalls
catch load libvendor.so # Dynamic library loading
catch signal SIGUSR1 # Specific signal delivery
When catching C++ exceptions, GDB typically stops inside libstdc++. Use up or frame to ascend to the throwing context.
Call Stack Navigation
Backtrace Analysis
backtrace full # Include local variables
bt -5 # Innermost 5 frames
bt 10 # Outermost 10 frames
bt -10 # Relative indexing: skip outermost 10
Frame Selection
frame 3 # Select by number
frame *0x7fffffffe240 # Select by address
up 2 # Move toward outer frames
down
info frame # Detailed current frame analysis
info frame 0x4008a2 # Examine specific frame structure
Program Context Inspection
Process State
info proc all # PID, parent, working directory, open files
info proc mappings # Memory map equivalent to /proc/PID/maps
Symbol Tables
info functions ::Log # Functions matching pattern
info sources # Compilation units with debug info
info sharedlibrary # Loaded DSOs with load addresses
info files # Executable sections and entry point
Source-Level Analysis
Code Listing
list *$pc # Source at current instruction
list - # Previous lines
list func, +10 # Range specification
Line-to-Address Translation
info line main.cpp:15
info line *0x401000
disassemble /m func # Mixed source and assembly
disassemble /r # Include raw instruction bytes
Assembly Flavor
set disassembly-flavor intel
set disassembly-flavor att
set disassemble-next-line on # Auto-show asm at stops
Execution Recording
Record deterministic execution paths for deterministic replay:
record full # Start recording instruction stream
record btrace bts # Hardware Branch Trace Store (if available)
record goto start # Rewind to beginning
record goto end # Fast-forward to live execution
record save session.log
record restore session.log
Management commands:
set record full insn-number-max 50000
set record full stop-at-limit off # Auto-discard oldest
record delete # Truncate log at current position
Reverse Execution
reverse-step # Step backward by source line
reverse-next # Backward step over calls
reverse-finish # Execute backward to call site
reverse-continue # Backward until breakpoint/watchpoint
set exec-direction reverse # Flip stepping direction
Advanced Inspection
Core Dump Generation
gcore /tmp/process_snapshot.core
Register Inspection
info registers
info all-registers # Include vector and floating-point
print/x $rax
Variable Scopes
info variables ^g_ # Global/static symbols matching regex
info locals # Current frame automatic variables
info args # Current frame parameters
Search Operations
Source Search
forward-search regex
reverse-search regex
search regex # Alias for forward-search
Memory Search
Locate byte patterns in address space:
find /w100 &buffer, +1024, 0xdeadbeef
find /s &header, +sizeof(header), "MAGIC"
find /b start_addr, end_addr, 0x90, 0x90 # NOP sled detection
Results populate $_ (last address) and $numfound (match count).
Concurrent Debugging
Multi-Process Handling
Control fork behavior:
set follow-fork-mode child # Debug child process
set follow-fork-mode parent # Default: continue with parent
set detach-on-fork off # Keep both processes under GDB control
set follow-exec-mode new # Preserve pre-exec process
Use catch fork to intercept process creation events.
Threading Models
All-Stop Mode (Default): Any thread halt suspends all threads. Configure scheduler locking:
set scheduler-locking on # Only current thread runs on continue
set scheduler-locking step # Lock during single-step, unlock for continue
set schedule-multiple on # Allow all processes' threads to run
Non-Stop Mode: Target threads continue while you inspect the stopped thread:
set pagination off
set non-stop on
continue -a # Continue all threads
Verify with info threads—running threads display as "(running)" rather than "(stopped)".
C Preprocessor Support
Compile with -gdwarf-4 -g3 (or higher) to embed macro debug information:
macro expand BUFFER_SIZE + offset
info macro MAX_RETRIES
info macros src.c:45 # All active macros at location
macro define DEBUG 1 # GDB-session macro (doesn't affect inferior)
macro undef DEBUG
macro list # Show GDB-defined macros
Command-line macros (-DNAME=value) appear with line number 0 in macro listings.