> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/a16z/jolt/llms.txt
> Use this file to discover all available pages before exploring further.

# Debugging

> Debugging tools and techniques for Jolt zkVM guest programs

Jolt provides several debugging tools to help you troubleshoot issues in your zkVM guest programs.

## Backtrace Support

Tracer, Jolt's emulator, supports backtraces for panics that occur in guest programs. This is essential for debugging runtime errors.

<Note>
  By default, symbols are stripped from release guest ELFs, so backtraces won't contain detailed information. Debug/dev builds preserve symbols automatically.
</Note>

### JOLT\_BACKTRACE Environment Variable

The `JOLT_BACKTRACE` environment variable enables ad-hoc debugging by preserving symbols and enabling backtrace support.

#### Basic Backtrace

Set `JOLT_BACKTRACE=1` to enable symbol resolution (function names, file:line):

```bash theme={null}
JOLT_BACKTRACE=1 cargo run --release -p example
```

The guest program auto-rebuilds with symbols preserved. The call stack is always captured; this flag just enables symbol resolution.

<Tip>
  Use `JOLT_BACKTRACE=1` for most debugging scenarios. It provides function names and source locations without rebuilding your entire project.
</Tip>

#### Full Backtrace

For more detailed debugging information including register snapshots and cycle counts per frame, use `JOLT_BACKTRACE=full`:

```bash theme={null}
JOLT_BACKTRACE=full cargo run --release -p example
```

### Backtrace Attribute in #\[jolt::provable]

For guest programs where you always want full debug support, you can bake symbol preservation into the build using the `backtrace` attribute:

```rust theme={null}
#[jolt::provable(backtrace = "dwarf")]
fn my_function(input: u64) -> u64 {
    // Your code here
}
```

This configuration:

* Preserves symbols in the guest ELF
* Adds `-Cforce-frame-pointers=yes` to the build
* Is useful for test programs, dedicated debug builds, or when you need frame pointers for ZeroOS-level unwinding

<Note>
  The `backtrace` attribute is not needed for normal debugging — `JOLT_BACKTRACE=1` is sufficient for most cases.
</Note>

### Valid Backtrace Values

The `backtrace` attribute accepts the following values:

* `"off"` — Disable backtrace support
* `"dwarf"` — Full DWARF debug info with frame pointers
* `"frame-pointers"` — Frame pointers only

### Manual Symbol Control

You can also control symbol preservation directly via the CLI:

```bash theme={null}
jolt build --backtrace enable
```

## Printing and Tracing

Jolt supports standard `print!` and `println!` macros in guest programs for debugging output.

### Using println! in Guest Programs

#### no\_std Guests

For `no_std` guests, import the macros via:

```rust theme={null}
use jolt::println;

#[jolt::provable]
fn my_function(input: u64) -> u64 {
    println!("Input value: {}", input);
    // Your code here
}
```

#### std Guests

When std is enabled, the standard `println!` works automatically:

```rust theme={null}
#[jolt::provable]
fn my_function(input: u64) -> u64 {
    println!("Input value: {}", input);
    // Your code here
}
```

## Fast Iteration with trace\_analyze

When debugging issues with guest programs, use the corresponding `trace_analyze` function for your `#[jolt::provable]` functions. This approach:

* Skips instantiating the prover
* Allows for faster iteration during debugging
* Executes the guest program in the tracer without generating a proof

```rust theme={null}
// Instead of running the full prover
let (output, proof, io_device) = prove_fib(50);

// Use trace_analyze for faster debugging
let (output, io_device) = trace_analyze_fib(50);
```

<Tip>
  Use `trace_analyze` during development to quickly test your guest program logic without the overhead of proof generation.
</Tip>

## Debugging Workflow

1. **Add print statements** to understand program flow
2. **Use JOLT\_BACKTRACE=1** to get detailed panic information
3. **Use trace\_analyze** for fast iteration without proving
4. **Switch to full proving** once the logic is correct

<Warning>
  The tracer doesn't currently support attaching a debugger. Use print statements and backtraces for debugging instead.
</Warning>

## Common Debugging Scenarios

### Debugging Panics

```bash theme={null}
# Run with backtrace enabled
JOLT_BACKTRACE=1 cargo run --release -p my-guest

# For detailed information
JOLT_BACKTRACE=full cargo run --release -p my-guest
```

### Debugging Logic Issues

```rust theme={null}
// Add print statements in your guest code
#[jolt::provable]
fn my_function(input: u64) -> u64 {
    println!("Starting computation with input: {}", input);
    let result = complex_calculation(input);
    println!("Result: {}", result);
    result
}

// Use trace_analyze for fast testing
let (output, io_device) = trace_analyze_my_function(42);
```

### Debugging Performance Issues

Combine debugging with profiling tools:

```bash theme={null}
# Profile with debug symbols
JOLT_BACKTRACE=1 cargo run --release --features monitor -p jolt-core profile --name myprogram --format chrome
```
