Skip to content

xiaoniaoyouhuajiang/Ferrumpy

Repository files navigation

FerrumPy

A powerful debugging REPL for Rust, built on LLDB. Debug Rust with the ease of an interactive Python session.

Features

  • 🎯 Interactive REPL: Full-featured Rust REPL powered by evcxr
  • 📸 Snapshot Variables: Capture debugged process variables and use them in REPL
  • 🎨 Pretty Printers: Human-readable display of Rust types (String, Vec, Option, Result, etc.)
  • 🔍 Path Navigation: Access nested data with a.b[0].c syntax
  • ⚡ Smart Type Restoration: Automatic type inference with manual restore! macro for complex types

Installation

One-Line Installer (Recommended)

curl -sSL https://raw.githubusercontent.com/xiaoniaoyouhuajiang/Ferrumpy/main/scripts/install.sh | bash

This automatically:

  • Downloads the correct wheel for your platform (macOS/Linux, arm64/x86_64)
  • Installs to ~/.local/lib/ferrumpy
  • Configures ~/.lldbinit to load FerrumPy
  • Sets up the REPL worker environment variable

Via pip/pipx

# Using pipx (isolated environment)
pipx install ferrumpy

# Or using pip
pip install ferrumpy

After pip install, manually add to ~/.lldbinit:

echo 'command script import <path-to-ferrumpy-package>/ferrumpy' >> ~/.lldbinit

From Source (for development)

git clone https://github.com/xiaoniaoyouhuajiang/Ferrumpy.git
cd Ferrumpy
maturin develop --release
echo "command script import $(pwd)/python/ferrumpy" >> ~/.lldbinit

Requirements: Python 3.9+, uses Stable ABI (abi3)

Quick Start

// your_program.rs
fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    let message = "Hello, FerrumPy!";
    println!("Set breakpoint here");  // <-- breakpoint
}
# In LLDB
(lldb) b main.rs:4
(lldb) run
(lldb) ferrumpy repl  # Start interactive REPL

>> numbers().iter().sum::<i32>()
15
>> message().to_uppercase()
"HELLO, FERRUMPY!"
>> let doubled: Vec<i32> = numbers().iter().map(|x| x * 2).collect();
>> doubled
[2, 4, 6, 8, 10]

Usage

Pretty Printing

(lldb) ferrumpy locals           # Pretty print all local variables
(lldb) ferrumpy pp user          # Pretty print specific variable
(lldb) ferrumpy pp user.name[0]  # Navigate nested structures
(lldb) ferrumpy type user        # Show type information

REPL Mode

(lldb) ferrumpy repl

# Variables accessed as functions
>> simple_string()
"Hello, FerrumPy!"

# Full Rust expressions supported
>> numbers().iter().filter(|x| x % 2 == 0).collect::<Vec<_>>()
[2, 4]

# Define new functions and types
>> fn double(x: i32) -> i32 { x * 2 }
>> double(21)
42

Type Restoration (Advanced)

For complex types that can't be automatically restored, use the restore! macro:

>> tuple()  // Returns JSON representation
{"__elements__": ["first", 2, 3.14], ...}

>> let t = restore!(tuple, (&str, i32, f64));
>> t.0
"first"

Supported Types

Type Category Examples Support
Primitives i32, f64, bool, char ✅ Full
Strings String, &str ✅ Full
Collections Vec<T>, Arrays ✅ Full
Smart Pointers Box, Rc, Arc ✅ Full
Options/Results Option<T>, Result<T, E> ✅ Full
Tuples (T1, T2, ...) ✅ Full
Enums All variants ✅ Full
Structs User-defined ✅ Full
HashMap HashMap<K, V> ⚠️ Limited*

* HashMap serialization is not supported in REPL snapshots. Create them manually in REPL if needed.

⚠️ Important Limitations

Snapshot REPL Requirements

The REPL snapshot feature captures variables via serde serialization. This means:

  1. User-defined types: Automatically work (FerrumPy adds Serialize/Deserialize derives)

  2. Third-party types: The crate must enable serde feature. For example:

    # ✅ Works - serde feature enabled
    compact_str = { version = "0.9", features = ["serde"] }
    
    # ❌ Won't work - no serde support
    compact_str = "0.9"
  3. Types without serde support: If a third-party type doesn't offer a serde feature, the REPL cannot restore those variables

Workspace Projects

FerrumPy fully supports Cargo workspaces with:

  • { workspace = true } dependency resolution
  • Path dependencies between workspace members
  • Automatic type re-exports for path dependencies

Just ensure all third-party dependencies have serde features enabled when needed.

Project Structure

ferrumpy/
├── python/ferrumpy/        # LLDB Python integration
│   ├── commands.py         # LLDB commands (pp, repl, etc.)
│   ├── serializer.py       # Variable serialization with memory reading
│   └── providers/          # Pretty printer providers
├── ferrumpy-core/          # Rust core library
│   ├── src/repl/          # REPL session management
│   ├── src/expr/          # Expression parsing
│   └── src/libgen/        # Snapshot library generation
├── tests/                  # Test suite
│   ├── run_tests.sh       # Test runner
│   ├── test_repl.exp      # REPL integration tests
│   └── rust_sample/       # Test Rust project
└── docs/                   # Documentation

Requirements

  • macOS: 11.0+ (arm64 or x86_64)
  • Linux: x86_64 (LLDB required)
  • Python: 3.9+
  • Rust: 1.70+ (for building from source)
  • LLDB: System LLDB (ships with Xcode on macOS)

Contributing

Contributions welcome! See CONTRIBUTING.md for guidelines.

Documentation

License

MIT License - see LICENSE for details.

Acknowledgments

Built on top of:

  • evcxr - Rust REPL engine
  • PyO3 - Rust-Python bindings
  • LLDB Python API

About

debug rust like python

Resources

Stars

Watchers

Forks

Packages

No packages published