Rust Tooling and Code Quality

Debugging with LLDB

When compiled with debug symbols (debug = true, the default in [profile.dev] and [profile.test]), rustc embeds DWARF (on Linux and macOS) or PDB (on Windows) debug metadata directly into the binary. The Rust toolchain ships with rust-lldb and rust-gdb wrapper scripts that load custom Python pretty-printers so standard types (String, Vec<T>, HashMap<K, V>, Option<T>, slices) display their human-readable contents instead of raw pointer addresses.

Source Code (`src/main.rs`)
        |
        v  `cargo build` (generates DWARF debug info in `target/debug/my_app`)
[ Launch `rust-lldb target/debug/my_app` ]
        |
        +-- Set breakpoints (`b main`, `b src/main.rs:14`, `b rust_panic`)
        +-- Step through lines (`n` next, `s` step into, `finish` step out)
        +-- Inspect locals & expressions (`frame variable`, `p my_vec`)
        +-- Inspect call stack (`bt` backtrace, `up`, `down`)

Essential rust-lldb Commands Reference

Action rust-lldb Command Short Alias Description
Launch with args rust-lldb -- target/debug/app arg1 — Opens binary in LLDB with command-line arguments.
Start execution process launch run / r Starts the program inside the debugger.
Break on function breakpoint set --name compute b compute Pauses execution when entering compute.
Break on file:line breakpoint set --file main.rs --line 12 b main.rs:12 Pauses execution at line 12 of main.rs.
Break on any panic breakpoint set --name rust_panic b rust_panic Pauses at the exact moment a Rust panic begins unwinding!
Step over line thread step-over next / n Executes the current line without stepping into function calls.
Step into call thread step-in step / s Steps inside the function called on the current line.
Step out of fn thread step-out finish Runs until the current stack frame returns.
Continue running process continue continue / c Resumes execution until the next breakpoint or exit.
Inspect locals frame variable v Prints all local variables in the current stack frame using Rust pretty-printers.
Evaluate expression expression scores[0] p scores Evaluates an expression in the current frame context.
Stack backtrace thread backtrace bt Prints the call stack of the current thread (bt all for all threads).

Example Debugging Session on a Rust Binary

Consider a program that computes a moving average:

#[derive(Debug)]
struct WindowStats {
    count: usize,
    sum: i64,
    average: f64,
}

fn analyze_window(samples: &[i64]) -> WindowStats {
    let count = samples.len();
    let sum: i64 = samples.iter().sum();
    let average = if count > 0 {
        (sum as f64) / (count as f64)
    } else {
        0.0
    };
    WindowStats {
        count,
        sum,
        average,
    }
}

fn main() {
    let readings = vec![12, 18, 24, 30];
    let stats = analyze_window(&readings);
    println!("Stats: count={}, sum={}, avg={:.1}", stats.count, stats.sum, stats.average);
}
Stats: count=4, sum=84, avg=21.0

Running rust-lldb target/debug/app and setting a breakpoint on analyze_window displays formatted Rust slices and structs via frame variable (v):

(lldb) b analyze_window
Breakpoint 1: where = app`app::analyze_window + 24 at main.rs:9:17
(lldb) run
Process 41280 stopped
* thread #1, name = 'main', stop reason = breakpoint 1.1
    frame #0: 0x0000000100004120 app`app::analyze_window(samples=&[i64] @ 0x000000016fdff140) at main.rs:9:17
   6    }
   7
   8    fn analyze_window(samples: &[i64]) -> WindowStats {
-> 9        let count = samples.len();
   10       let sum: i64 = samples.iter().sum();
(lldb) v samples
(&[i64]) samples = size=4 {
  [0] = 12
  [1] = 18
  [2] = 24
  [3] = 30
}

Catching Panics Live in the Debugger (b rust_panic)

Whenever a Rust thread panics, the standard library invokes an internal hook function named rust_panic before unwinding the stack. Setting b rust_panic in rust-lldb pauses execution while every local variable in the panicking stack frame is still alive in memory, allowing you to run bt, up, and v to inspect the exact values that caused the panic.