solana/docs/src/developing/on-chain-programs/debugging.md

112 lines
4.9 KiB
Markdown

---
title: "Debugging"
---
Solana programs run on-chain, so debugging them in the wild can be challenging.
To make debugging programs easier, developers can write unit tests that directly
test their program's execution via the Solana runtime, or run a local cluster
that will allow RPC clients to interact with their program.
## Running unit tests
- [Testing with Rust](developing-rust.md#how-to-test)
- [Testing with C](developing-c.md#how-to-test)
## Logging
During program execution both the runtime and the program log status and error
messages.
For information about how to log from a program see the language specific
documentation:
- [Logging from a Rust program](developing-rust.md#logging)
- [Logging from a C program](developing-c.md#logging)
When running a local cluster the logs are written to stdout as long as they are
enabled via the `RUST_LOG` log mask. From the perspective of program
development it is helpful to focus on just the runtime and program logs and not
the rest of the cluster logs. To focus in on program specific information the
following log mask is recommended:
`export RUST_LOG=solana_runtime::system_instruction_processor=trace,solana_runtime::message_processor=info,solana_bpf_loader=debug,solana_rbpf=debug`
Log messages coming directly from the program (not the runtime) will be
displayed in the form:
`Program log: <user defined message>`
## Error Handling
The amount of information that can be communicated via a transaction error is
limited but there are many points of possible failures. The following are
possible failure points and information about what errors to expect and where to
get more information:
- The BPF loader may fail to parse the program, this should not happen since the
loader has already _finalized_ the program's account data.
- `InstructionError::InvalidAccountData` will be returned as part of the
transaction error.
- The BPF loader may fail to setup the program's execution environment
- `InstructionError::Custom(0x0b9f_0001)` will be returned as part of the
transaction error. "0x0b9f_0001" is the hexadecimal representation of
[`VirtualMachineCreationFailed`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/programs/bpf_loader/src/lib.rs#L44).
- The BPF loader may have detected a fatal error during program executions
(things like panics, memory violations, system call errors, etc...)
- `InstructionError::Custom(0x0b9f_0002)` will be returned as part of the
transaction error. "0x0b9f_0002" is the hexadecimal representation of
[`VirtualMachineFailedToRunProgram`](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/programs/bpf_loader/src/lib.rs#L46).
- The program itself may return an error
- `InstructionError::Custom(<user defined value>)` will be returned. The
"user defined value" must not conflict with any of the [builtin runtime
program
errors](https://github.com/solana-labs/solana/blob/bc7133d7526a041d1aaee807b80922baa89b6f90/sdk/program/src/program_error.rs#L87).
Programs typically use enumeration types to define error codes starting at
zero so they won't conflict.
In the case of `VirtualMachineFailedToRunProgram` errors, more information about
the specifics of what failed are written to the [program's execution
logs](debugging.md#logging).
For example, an access violation involving the stack will look something like
this:
`BPF program 4uQeVj5tqViQh7yWWGStvkEG1Zmhx6uasJtWCJziofM failed: out of bounds memory store (insn #615), addr 0x200001e38/8`
## Monitoring Compute Budget Consumption
The program can log the remaining number of compute units it will be allowed
before program execution is halted. Programs can use these logs to wrap
operations they wish to profile.
- [Log the remaining compute units from a Rust
program](developing-rust.md#compute-budget)
- [Log the remaining compute units from a C
program](developing-c.md#compute-budget)
See [compute
budget](developing/programming-model/../../../programming-model/runtime.md/#compute-budget)
for more information.
## ELF Dump
The BPF shared object internals can be dumped to a text file to gain more
insight into a program's composition and what it may be doing at runtime.
- [Create a dump file of a Rust program](developing-rust.md#elf-dump)
- [Create a dump file of a C program](developing-c.md#elf-dump)
## Instruction Tracing
During execution the runtime BPF interpreter can be configured to log a trace
message for each BPF instruction executed. This can be very helpful for things
like pin-pointing the runtime context leading up to a memory access violation.
The trace logs together with the [ELF dump](#elf-dump) can provide a lot of
insight (though the traces produce a lot of information).
To turn on BPF interpreter trace messages in a local cluster configure the
`solana_rbpf` level in `RUST_LOG` to `trace`. For example:
`export RUST_LOG=solana_rbpf=trace`