Program Debugging
Replaying Transactions
Section titled “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
Section titled “Step 1: Build and run with debug information”To make it easier to debug programs, you should build your program with debug information.
In C and C++, you can do this with the SDK_EXTRAS environment variable:
SDK_EXTRAS=debug makeIn Rust, build the program in debug mode:
cargo buildIn 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.
Step 2: Prepare the command to run with GDB
Section titled “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:
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:
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.tafhdJHH_OVQYN4-Cimt7Y1XclSytf9Ox_iuetV8CKmz=./build/thruvm/bin/tn_token_program_rust.elf
Step 3: Run the command
Section titled “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.
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:
thru-replay --gdb \ --signature tsX2EQZzPxVgI23KmdAByeVj-yZ9JE-46q_AhjURj0vRnHdMRP3at6H_dVXDFdUtUwnW_ICnLnk0ROJWWdTIWbDh1P \ --elf tafhdJHH_OVQYN4-Cimt7Y1XclSytf9Ox_iuetV8CKmz=./build/thruvm/bin/tn_token_program_rust.elfYou should see some output like this. You’ll be in an interactive GDB session.
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 pathLog 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 transactionStarting debug server on port 9001...GDB connected!add symbol table from file "./build/thruvm/bin/tn_token_program_rust.elf" at .text_addr = 0x3000000Reading 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 = 0x30001000000Reading symbols from ./build/thruvm/bin/tn_token_program_rust.elf...Remote debugging using localhost:9001warning: No executable has been specified and target does not supportdetermining executable automatically. Try using the "file" command.0x0000030001000000 in _start ()(gdb)You can debug the program as you would normally do with GDB:
(gdb) break startBreakpoint 1 at 0x300006c: start. (2 locations)(gdb) cContinuing.
Breakpoint 1.2, token_program::start (instr_data=0x0 $core::intrinsics::cold_path, instr_data_sz=0) at examples/token_program/main.rs:2020 #[entry(stack_size = 8192)]