Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Advanced GDB Debugging: Core Concepts and Command Reference

Tech 1

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 instance
  • start [args]: Run to main entry point and break
  • continue [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 names
  • hbreak 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.

Tags: gdb

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.