Skip to main content
Effective debugging is essential when working on an emulator. This page covers the debugging tools and techniques available in oboromi.

GUI Debugger

Oboromi includes an eframe/egui-based GUI that provides visual debugging capabilities.

Launching the GUI

cargo run
The GUI opens with a splash screen showing the oboromi logo and project status, then transitions to the main debugging interface. Reference: gui/src/gui/gui.rs:26

Features

The splash screen displays:
  • Animated oboromi logo with fade-in/fade-out effects
  • “Experimental” warning badge
  • Project status information
  • Automatic transition after ~1.6 seconds
Reference: gui/src/gui/gui.rs:41
The main interface provides:
  • “Run CPU Tests” button - Executes ARM64 instruction tests in background thread
  • Results panel - Scrollable view of test output with color-coded results:
    • 🟢 Green for passing tests
    • 🔴 Red for failing tests
    • ⚪ Gray for status messages
  • Menu bar - File and About menus
Reference: gui/src/gui/gui.rs:157

GUI Architecture

The GUI is built with:
  • eframe 0.33 - Application framework
  • egui 0.33 - Immediate mode GUI library
  • Thread-based test execution - Tests run in background to keep UI responsive
if ui.button("Run CPU Tests").clicked() {
    let ctx = ctx.clone();
    self.test_thread = Some(std::thread::spawn(move || {
        ctx.request_repaint();
        run_tests()
    }));
}
Reference: gui/src/gui/gui.rs:157
The GUI automatically requests repaints when tests are running to ensure the interface stays responsive.

Logging System

Oboromi uses fern and log for flexible, structured logging.

Log Configuration

The logging system is configured in gui/src/main.rs:5 with:
fn setup_logger() -> Result<(), fern::InitError> {
    fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "[{}][{}] {}",
                record.level(),
                record.target(),
                message
            ))
        })
        .level(log::LevelFilter::Debug)
        .chain(std::io::stdout())
        .chain(fern::log_file("oboromi.log")?)
        .apply()?;
    Ok()
}

Log Output

Logs are written to two destinations:
  • stdout - Console output for immediate feedback
  • oboromi.log - Persistent log file in the current directory

Log Format

Each log entry includes:
[LEVEL][target] message
Example:
[INFO][oboromi_core::cpu] Initializing CPU core 0
[DEBUG][oboromi_core::cpu] Register X1 = 0x0000000000000007
[ERROR][oboromi_core::cpu] Invalid memory access at 0xDEADBEEF

Log Levels

The logger is set to Debug level by default, showing:
  • Error - Critical failures
  • Warn - Potential issues
  • Info - General information
  • Debug - Detailed debugging information
  • Trace - Extremely verbose output (requires feature flag)
Reference: gui/src/main.rs:15

Trace Feature Flag

For extremely verbose debugging, enable the trace feature:
cargo run --features trace
This enables:
  • Trace-level logging throughout the codebase
  • Detailed instruction execution logging
  • Memory access tracing
Trace logging significantly impacts performance. Only use it when you need to debug specific instruction-level behavior.

Trace in Code

When the trace feature is enabled, the application logs a startup message:
#[cfg(feature = "trace")]
log::info!("-- TRACING ENABLED --");
Reference: gui/src/main.rs:42

Feature Configuration

The trace feature is defined in gui/Cargo.toml:19 and propagates to the core library:
[features]
default = []
trace = ["oboromi-core/trace"]

Debugging Techniques

1

Test-Driven Debugging

When investigating a bug:
  1. Write a test that reproduces the issue
  2. Run the test with cargo test -- --nocapture
  3. Add log statements to trace execution
  4. Fix the bug
  5. Verify the test passes
2

GUI-Based Debugging

For visual inspection:
  1. Launch the GUI with cargo run
  2. Click “Run CPU Tests”
  3. Examine color-coded results
  4. Check oboromi.log for detailed output
3

Trace Debugging

For instruction-level issues:
  1. Enable trace: cargo run --features trace
  2. Reproduce the issue
  3. Examine oboromi.log for detailed execution trace
  4. Identify the failing instruction or memory access

Platform-Specific Debugging

macOS

macOS (especially Apple Silicon) may have JIT-related timing issues during initial test runs. This is normal and usually resolves on subsequent runs.
If you encounter issues:
  1. Check that Rosetta 2 is not interfering (for x86_64 builds)
  2. Verify CMake and Ninja are properly installed
  3. Rebuild with cargo clean && cargo build

Windows

Ensure you have:
  • MSVC Build Tools installed
  • CMake and Ninja in PATH
  • Proper Visual Studio environment variables set

Linux

Most issues on Linux relate to:
  • Missing Clang or C++ compiler
  • CMake version too old (need 3.16+)
  • Vulkan development libraries (for GPU code)

Debugging Memory Issues

For memory-related bugs:
  1. Check shared memory initialization
    cargo test test_multicore_initialization -- --nocapture
    
  2. Verify memory access patterns
    cargo test test_shared_memory_access -- --nocapture
    
  3. Enable address sanitizer (Linux/macOS)
    RUSTFLAGS="-Z sanitizer=address" cargo run
    
The address sanitizer requires nightly Rust: rustup default nightly

Useful Debugging Commands

# Run tests with full output
cargo test -- --nocapture

# Run specific test
cargo test test_multicore_initialization -- --nocapture

# Run with trace logging
cargo run --features trace

# Check for common errors
cargo clippy

# Build in release mode for performance testing
cargo build --release

# Clean and rebuild (helps with dependency issues)
cargo clean && cargo build

Reading Log Files

The oboromi.log file contains chronological entries. Use standard tools to analyze:
# View recent logs
tail -f oboromi.log

# Search for errors
grep ERROR oboromi.log

# Filter by component
grep "oboromi_core::cpu" oboromi.log

# View trace-level logs (when trace feature enabled)
grep TRACE oboromi.log
For more information on the test suite structure, see the Testing page.