---
title: Program Debugging
description: Learn how to debug Thru programs
source_url:
  html: https://thru.org/docs/program-development/debugging/
  md: https://thru.org/docs/program-development/debugging.md
---

# Program Debugging

## Replaying Transactions

The `thru-replay` tool can be used to replay transactions run on Thru, and supports debugging with GDB. This can help you debug crashes and other issues in your program.

### Step 1: Build and run with debug information

To make it easier to debug programs, you should build your program with debug information.

**C/C++:**

In C and C++, you can do this with the `SDK_EXTRAS` environment variable:

```bash
SDK_EXTRAS=debug make
```

**Rust:**

In Rust, build the program in debug mode:

```bash
cargo build
```

In addition to the `.bin` file, you’ll find a file at `target/thruvm/bin/<program-name>.elf` that contains the program’s debug information. Make a note of this file for later use.

After this, upload your program in debug mode to the network, and run a transaction.

> **Note:**
>
> Note that this step is optional, and may not be possible if you are debugging a transaction that has already been run. However, it makes it significantly easier to debug your program.

### Step 2: Prepare the command to run with GDB

Next, you’ll need to gather all the information to replay your program. You’ll need:

- The transaction signature. It will look something like this:
  ```plaintext
  tsX2EQZzPxVgI23KmdAByeVj-yZ9JE-46q_AhjURj0vRnHdMRP3at6H_dVXDFdUtUwnW_ICnLnk0ROJWWdTIWbDh1P
  ```
- For each program in your transaction, you’ll need the program’s address as well as the path to the program’s debug information. For instance:
  ```plaintext
  tafhdJHH_OVQYN4-Cimt7Y1XclSytf9Ox_iuetV8CKmz=./build/thruvm/bin/tn_token_program_rust.elf
  ```
  If you don’t have the debug information for a program, you can skip it. However, you won’t be able to view the source information for that program.

### Step 3: Run the command

Now you can run the command to replay the transaction with GDB. You’ll need to pass the transaction signature, and for each program in your transaction, you’ll need to pass the program’s address and the path to the program’s debug information.

```bash
thru-replay --gdb \
  --signature $transaction-signature \
  --elf $program-address-1=$program-debug-info-path-1 \
  --elf $program-address-2=$program-debug-info-path-2 ...
```

For example:

```bash
thru-replay --gdb \
  --signature tsX2EQZzPxVgI23KmdAByeVj-yZ9JE-46q_AhjURj0vRnHdMRP3at6H_dVXDFdUtUwnW_ICnLnk0ROJWWdTIWbDh1P \
  --elf tafhdJHH_OVQYN4-Cimt7Y1XclSytf9Ox_iuetV8CKmz=./build/thruvm/bin/tn_token_program_rust.elf
```

You should see some output like this. You’ll be in an interactive GDB session.

```bash
Fetching transaction tsCRsKwMAupg5jUbus7GSeN8XgUS_lafAIo6YPUCfJW_zIYTgNJ5xCufxghWfiL1LGAPBWsCWHFHa0srws70WEAx38...
Fetching 3 account states at slot 66 (pre-transaction)...
Fetching state roots ending at slot 66...
--log-path not specified; using autogenerated path
Log at "/tmp/fd-0.0.0_3872496_user_machine-1_2025_12_16_17_38_45_883488412_GMT+00"
Note: RW account ta1kDh1kmoJuRkoBChLLRk-ZOvzAHFNWNrK1iDCBJToaxR not in pre-tx state - will be created by transaction
Starting debug server on port 9001...
GDB connected!
add symbol table from file "./build/thruvm/bin/tn_token_program_rust.elf" at
        .text_addr = 0x3000000
Reading symbols from ./build/thruvm/bin/tn_token_program_rust.elf...
add symbol table from file "./build/thruvm/bin/tn_token_program_rust.elf" at
        .text_addr = 0x30001000000
Reading symbols from ./build/thruvm/bin/tn_token_program_rust.elf...
Remote debugging using localhost:9001
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file" command.
0x0000030001000000 in _start ()
(gdb)
```

You can debug the program as you would normally do with GDB:

```bash
(gdb) break start
Breakpoint 1 at 0x300006c: start. (2 locations)
(gdb) c
Continuing.

Breakpoint 1.2, token_program::start (instr_data=0x0 $core::intrinsics::cold_path, instr_data_sz=0)
    at examples/token_program/main.rs:20
20      #[entry(stack_size = 8192)]
```
