Claude Code Plugins

Community-maintained marketplace

Feedback
4
0

Use when debugging the Breenix kernel at assembly or C-level using GDB - investigating CPU exceptions, page faults, triple faults, examining register state during interrupt handling, stepping through boot sequence, analyzing syscall entry/exit paths, debugging context switches, or inspecting memory layout and page tables.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name gdb-attach
description Use when debugging the Breenix kernel at assembly or C-level using GDB - investigating CPU exceptions, page faults, triple faults, examining register state during interrupt handling, stepping through boot sequence, analyzing syscall entry/exit paths, debugging context switches, or inspecting memory layout and page tables.

Breenix GDB Debugging

When to Use This Skill

Use this skill when you need to debug the Breenix kernel at the assembly or C-level using GDB. Common scenarios:

  • Investigating CPU exceptions, page faults, or triple faults
  • Examining register state during interrupt handling
  • Stepping through boot sequence or early initialization
  • Analyzing syscall entry/exit paths
  • Debugging context switches and process state transitions
  • Inspecting memory layout and page tables
  • Understanding TSC/APIC timer behavior

Quick Start

1. Launch QEMU in GDB Mode

# Set the GDB flag and run the kernel
BREENIX_GDB=1 cargo run --release --bin qemu-uefi

This will:

  • Start QEMU with -s -S (GDB server on localhost:1234, paused)
  • Wait for GDB to connect before executing any code
  • Print connection instructions

2. Connect GDB (in another terminal)

# Connect to the running QEMU instance
gdb target/x86_64-breenix/release/kernel -ex 'target remote localhost:1234'

Or use the helper command from .gdbinit:

gdb target/x86_64-breenix/release/kernel
(gdb) breenix-connect

Essential GDB Commands for Kernel Debugging

Navigation & Execution

# Continue execution
c

# Step one instruction (into calls)
si

# Step one instruction (over calls)
ni

# Step one source line
s

# Step over source line
n

# Finish current function
finish

Breakpoints

# Hardware breakpoint (works before paging is set up)
hbreak kernel_main

# Software breakpoint (requires memory to be mapped)
break rust_syscall_handler
break timer_interrupt_handler
break process::manager::spawn_process

# Conditional breakpoint
break syscall_handler if $rax == 0x1  # Only break on specific syscall

# List breakpoints
info breakpoints

# Delete breakpoint
delete 1

Registers & State

# Show all general-purpose registers
info registers

# Show specific register
print $rip
print/x $rsp
print/x $cr3

# Show segment registers
info registers cs ds ss fs gs

# Custom helper to show segments nicely
show-segments

Memory Inspection

# Examine memory (format: x/nfu addr)
# n=count, f=format (x=hex, d=decimal, s=string), u=unit (b=byte, h=halfword, w=word, g=giant/8-bytes)

x/16xg $rsp              # Show 16 8-byte values at stack pointer
x/32xb 0xffff800000000000  # Show 32 bytes at kernel base
x/s 0xsomeaddr           # Show null-terminated string
x/i $rip                 # Show instruction at program counter

# Display memory continuously as you step
display/16xg $rsp

Backtraces & Frames

# Show call stack
backtrace
bt

# Show detailed backtrace with local variables
backtrace full

# Move between stack frames
frame 0
frame 1

# Show local variables in current frame
info locals

# Show function arguments
info args

Symbols & Source

# List source code around current location
list

# Show disassembly around current instruction
disassemble

# Show disassembly of specific function
disassemble kernel_main
disassemble rust_syscall_handler

# Show type information
ptype some_variable

Common Debugging Scenarios

Scenario 1: Boot Debugging

Set breakpoint at kernel entry and step through initialization:

(gdb) hbreak kernel_main
(gdb) c
(gdb) layout asm     # Show assembly view
(gdb) si            # Step through boot sequence
(gdb) info registers

Scenario 2: Syscall Debugging

Debug a specific syscall (e.g., clock_gettime):

(gdb) break rust_syscall_handler
(gdb) c
# When syscall hits:
(gdb) print/x $rax   # Syscall number
(gdb) print/x $rdi   # First argument
(gdb) print/x $rsi   # Second argument
(gdb) s              # Step into handler

Scenario 3: Page Fault Investigation

Examine CPU state on page fault:

(gdb) break page_fault_handler
(gdb) c
# When fault occurs:
(gdb) print/x $cr2   # Faulting address
(gdb) print/x $rip   # Instruction that faulted
(gdb) x/i $rip       # Show the faulting instruction
(gdb) print error_code  # Error code (if captured)
(gdb) backtrace

Scenario 4: Timer Interrupt Debugging

Trace timer interrupt flow:

(gdb) break timer_interrupt_handler
(gdb) c
# First timer interrupt hits:
(gdb) print ticks    # Check tick counter
(gdb) s              # Step into APIC EOI
(gdb) finish         # Return from handler
(gdb) c              # Continue to next tick

Scenario 5: Context Switch Analysis

Debug process switching:

(gdb) break context_switch::switch_to
(gdb) c
# When switching:
(gdb) print from_process
(gdb) print to_process
(gdb) print/x $cr3   # Current page table
(gdb) s              # Step through switch
(gdb) print/x $cr3   # New page table

Breenix-Specific Helpers

The .gdbinit file provides custom commands:

# Connect to QEMU
breenix-connect

# Show segment registers nicely
show-segments

# Set common kernel breakpoints
breenix-breaks

Advanced Techniques

Watchpoints (Memory Access Breakpoints)

# Break when memory location is written
watch *0xffff800000010000

# Break when memory location is read
rwatch some_global_variable

# Break on read or write
awatch some_global_variable

Examining Page Tables

# Get CR3 (page table root)
print/x $cr3

# Walk page table manually (requires understanding x86_64 paging)
x/4xg ($cr3 & ~0xfff)  # PML4 entries

TSC Debugging

# Read TSC register value
print $ia32_tsc  # May not be directly accessible
# Instead, examine TSC handling code:
break tsc::read_tsc

Tips & Gotchas

  1. Use hardware breakpoints early: Before paging is fully set up, use hbreak instead of break
  2. Serial output interference: GDB traffic and serial logs both compete for terminal output
  3. Optimization can confuse stepping: Release builds may inline or reorder code
  4. No symbols for assembly: Some early boot code won't have Rust symbols
  5. Context switches reset state: Watch out for process switching changing $cr3, $rsp, etc.

Exiting GDB

# Quit GDB (QEMU will also stop)
quit

# Detach but leave QEMU running
detach

Integration with Existing Workflow

This GDB debugging flow complements the existing log-based debugging:

  • Use logs for: High-level flow, timing issues, multi-test scenarios
  • Use GDB for: Precise state inspection, assembly-level debugging, crash analysis

You can combine both: run with logs first to narrow down the issue, then use GDB to investigate the exact instruction or register state.