A minimal two-program Solana workspace for exercising and debugging sBPF programs via mollusk-svm and Gimlet.
primary makes a CPI into cpi_target. Both are written with pinocchio.
primary ─── CPI ───▶ cpi_target
The trace-emitting and debugger-attach behavior described below only works because this repo depends on:
mollusk-svm = { version = "0.13.0", features = ["sbpf-debugger"] }
mollusk-svm0.13.0or later is required — these are the builds that honorSBF_TRACE_DIRandSBF_DEBUG_PORT.- The
sbpf-debuggerfeature is what enables Gimlet integration. Without it, traces are not written and the VM will not pause for a debugger to attach.If you drop below
0.13.0or remove the feature, theRun the testandDebug a programsteps below will silently stop producing what Gimlet needs. Seeprograms/primary/Cargo.toml.
- Rust (stable, with
cargo) - Solana CLI / Agave toolchain (provides
cargo build-sbf)
Verify:
solana --version
cargo build-sbf --versioncargo-build-sbf --tools-version v1.54 --debug --arch v1Why this?
cargo build-sbfstep builds with SBPFv1 (--arch v1), debug symbols, and no optimizations — required for accurate coverage results.
Note: At the time of writing, best coverage results are achieved with SBPFv1 (dynamic stack frames), which is why we use
--arch v1. Only with dynamic stack frames can we safely disable optimizations (opt-level = 0) without hitting stack size limits. The--tools-versioncan be v1.51 or higher, and--debugis required for coverage to work. Starting withcargo-build-sbf4.0.0, the--debugflag outputs artifacts totarget/deploy/debuginstead oftarget/deploy. If you are using an older version ofcargo-build-sbf, replacetarget/deploy/debugwithtarget/deployin all the steps.
SBF_OUT_DIR=$(pwd)/target/deploy/debug \
SBF_TRACE_DIR=$(pwd)/target/sbf/trace \
cargo test -p primary --features no-entrypoint --test cpi -- --nocaptureSBF_OUT_DIRtells mollusk where to find the built.sofiles.SBF_TRACE_DIRis where the sBPF VM writes execution traces consumed by Gimlet.
This runs the mollusk CPI test and prints the program logs. Expect to see primary invoke [1] → cpi_target invoke [2] → Ping received by cpi_target! and both programs returning success.
SBF_OUT_DIR=$(pwd)/target/deploy/debug \
SBF_DEBUG_PORT=1212 \
SBF_TRACE_DIR=$(pwd)/target/sbf/trace \
cargo test -p primary --features no-entrypoint --test cpi -- --nocaptureSBF_DEBUG_PORT=1212 makes the sBPF VM open TCP port 1212 and block waiting for a debugger to attach before stepping into the program.
This blocking-on-port behavior is provided by the
sbpf-debuggerfeature ofmollusk-svm0.13.0or later. On older versions or without that feature,SBF_DEBUG_PORTis a no-op and the test will run straight through.
cargo clean
rm -rf programs/primary/targetWipes target/ and any stray nested target/ left by prior runs, if any.
.
├── Cargo.toml # workspace
└── programs/
├── cpi_target/ # callee program
│ ├── Cargo.toml
│ └── src/lib.rs
└── primary/ # caller program (does the CPI)
├── Cargo.toml
├── src/lib.rs
└── tests/cpi.rs # mollusk-svm test