Appearance
Quickstart
This quickstart guide will help you set up your environment to build and test a "Hello, World!" program implemented in both SBPF assembly and Rust, allowing you to compare the two implementations side-by-side.
🔧 Set up your environment
Install the latest version of
solana.Update your
PATHto include key SBPF tools packaged with thesolanainstall, in particular thedump.shscript called internally bycargo build-sbf--dump, and the LLVM binaries it requires. This will look something like:sh# Solana tools. export SOLANA_RELEASE="$HOME/.local/share/solana/install/active_release/bin" export SOLANA_SBPF_TOOLS="$SOLANA_RELEASE/platform-tools-sdk/sbf" export PATH="$SOLANA_RELEASE:$PATH" export PATH="$SOLANA_SBPF_TOOLS/scripts:$PATH" export PATH="$SOLANA_SBPF_TOOLS/dependencies/platform-tools/llvm/bin:$PATH"TIP
This example is from
~/.zshrcon a Mac with Oh My Zsh.Note the pinned
tools-versioninexamples/Cargo.toml, which is required (as of the time of this writing) forcargo build-sbf --arch v4to access thesbpfv4-solana-solanatarget that was removed in v1.52 of theplatform-tools.Cargo.toml
toml# cspell:word cfgs [workspace] members = ["hello-dasmac", "memo", "test-utils"] resolver = "2" [workspace.dependencies] mollusk-svm = "0.7.2" pinocchio = "0.9.2" solana-sbpf = "0.13.0" solana-sdk = "3.0.0" [workspace.lints.rust] unexpected_cfgs = {level = "warn", check-cfg = ['cfg(target_os, values("solana"))']} [workspace.metadata.solana] tools-version = "v1.51"Install
rustfilt, which is also required bydump.sh:shcargo install rustfiltInstall
sbpf.shcargo install --git https://github.com/blueshift-gg/sbpf.git(Optional) Install the VS Code SBPF Assembly extension.
⚡ Run the hello-dasmac example
Clone the Solana Opcode Guide repository.
shgit clone https://github.com/dasmac-com/solana-opcode-guide.gitNavigate to the
examples/hello-dasmacdirectory.shcd solana-opcode-guide/examples/hello-dasmacCompare the assembly and Rust program implementations:
Implementation Location Assembly src/hello-dasmac/hello-dasmac.sRust src/program.rsTIP
Other examples in the
examplesdirectory use a similar layout, since thesbpfbuildcommand expectssrc/<program-name>/<program-name>.s.asm.equ MESSAGE_LENGTH, 14 .globl entrypoint entrypoint: lddw r1, message lddw r2, MESSAGE_LENGTH call sol_log_ exit .rodata message: .ascii "Hello, DASMAC!"rsuse pinocchio::{entrypoint, msg, pubkey::Pubkey, ProgramResult}; entrypoint!(process_instruction); fn process_instruction( _program_id: &Pubkey, _accounts: &[pinocchio::account_info::AccountInfo], _instruction_data: &[u8], ) -> ProgramResult { msg!("Hello, DASMAC!"); Ok(()) }Build the assembly implementation.
shsbpf buildRun
dump.shon the assembly build ELF output atdeploy/hello-dasmac.so:shdump.sh deploy/hello-dasmac.so deploy/asm-dump.txtBuild the Rust implementation with SBPF v4 and dump the build. This operation should create the following files in
../target/deploy(solana-opcode-guide/examples/target/deploy):File Description hello_dasmac.soRust build ELF output hello_dasmac-dump.txtDump of the output shcargo build-sbf --arch v4 --dumpCompare the two dumps, in particular the below highlighted sections. Note the considerable overhead introduced by the Rust implementation:
Implementation Dump Assembly deploy/asm-dump.txtRust ../target/deploy/hello_dasmac-dump.txtOutput
txtELF Header Magic 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class ELF64 Data 2's complement, little endian Version 1 (current) OS/ABI UNIX - System V ABI Version 0 Type DYN (Shared object file) Machine EM_BPF Version 0x1 Entry point address 0xE8 Start of program headers 64 (bytes into file) Start of section headers 656 (bytes into file) Flags 0x0 Size of this header 64 (bytes) Size of program headers 56 (bytes) Number of program headers 3 Size of section headers 64 (bytes) Number of section headers 8 Section header string table index 7 There are 8 section headers, starting at offset 0x290 Section Headers [Nr] Name Type Address Off Size ES Flg Lk Inf Al [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 00000000000000e8 0000e8 000030 00 AX 0 0 4 [ 2] .rodata PROGBITS 0000000000000118 000118 00000e 00 A 0 0 1 [ 3] .dynamic DYNAMIC 0000000000000128 000128 0000b0 10 WA 5 0 8 [ 4] .dynsym DYNSYM 00000000000001d8 0001d8 000048 18 A 5 1 8 [ 5] .dynstr STRTAB 0000000000000220 000220 000018 00 A 0 0 1 [ 6] .rel.dyn REL 0000000000000238 000238 000020 10 A 4 0 8 [ 7] .s STRTAB 0000000000000000 000258 000034 00 0 0 1 Key to Flags W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), R (retain), p (processor specific) Elf file type is DYN (Shared object file) Entry point 0xe8 There are 3 program headers, starting at offset 64 Program Headers Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x0000e8 0x00000000000000e8 0x00000000000000e8 0x00003e 0x00003e R E 0x1000 LOAD 0x0001d8 0x00000000000001d8 0x00000000000001d8 0x000080 0x000080 R 0x1000 DYNAMIC 0x000128 0x0000000000000128 0x0000000000000128 0x0000b0 0x0000b0 RW 0x8 Section to Segment mapping Segment Sections... 00 .text .rodata 01 .dynsym .dynstr .rel.dyn 02 .dynamic None .s Dynamic section at offset 0x128 contains 11 entries Tag Type Name/Value 0x000000000000001e (FLAGS) TEXTREL 0x0000000000000011 (REL) 0x238 0x0000000000000012 (RELSZ) 32 (bytes) 0x0000000000000013 (RELENT) 16 (bytes) 0x000000006ffffffa (RELCOUNT) 1 0x0000000000000006 (SYMTAB) 0x1d8 0x000000000000000b (SYMENT) 24 (bytes) 0x0000000000000005 (STRTAB) 0x220 0x000000000000000a (STRSZ) 24 (bytes) 0x0000000000000016 (TEXTREL) 0x0 0x0000000000000000 (NULL) 0x0 Relocation section '.rel.dyn' at offset 0x238 contains 2 entries Offset Info Type Symbol's Value Symbol's Name 00000000000000e8 0000000000000008 Unknown 0000000000000108 000000020000000a R_BPF_64_32 0000000000000000 sol_log_ Symbol table '.dynsym' contains 3 entries Num Value Size Type Bind Vis Ndx Name 0 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1 00000000000000e8 0 NOTYPE GLOBAL DEFAULT 1 entrypoint 2 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND sol_log_ There are no section groups in this file. deploy/hello-dasmac.so file format elf64-bpf Disassembly of section .text 00000000000000e8 <entrypoint> 29 18 01 00 00 18 01 00 00 00 00 00 00 00 00 00 00 r1 = 0x118 ll 31 18 02 00 00 0e 00 00 00 00 00 00 00 00 00 00 00 r2 = 0xe ll 33 85 10 00 00 ff ff ff ff call -0x1 34 95 00 00 00 00 00 00 00 exittxtELF Header Magic 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class ELF64 Data 2's complement, little endian Version 1 (current) OS/ABI UNIX - System V ABI Version 0 Type DYN (Shared object file) Machine Solana Bytecode Format Version 0x1 Entry point address 0x18 Start of program headers 64 (bytes into file) Start of section headers 4952 (bytes into file) Flags 0x4 Size of this header 64 (bytes) Size of program headers 56 (bytes) Number of program headers 4 Size of section headers 64 (bytes) Number of section headers 8 Section header string table index 6 There are 8 section headers, starting at offset 0x1358 Section Headers [Nr] Name Type Address Off Size ES Flg Lk Inf Al [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 [ 1] .text PROGBITS 0000000000000000 000120 000828 00 AX 0 0 8 [ 2] .rodata PROGBITS 0000000100000000 000948 000020 00 A 0 0 1 [ 3] .bss.stack NOBITS 0000000200000000 000968 001000 00 A 0 0 1 [ 4] .bss.heap NOBITS 0000000300000000 000968 001000 00 A 0 0 1 [ 5] .symtab SYMTAB 0000000000000000 000968 000408 18 7 40 8 [ 6] .shstrtab STRTAB 0000000000000000 000d70 00003e 00 0 0 1 [ 7] .strtab STRTAB 0000000000000000 000dae 0005a7 00 0 0 1 Key to Flags W (write), A (alloc), X (execute), M (merge), S (strings), I (info), L (link order), O (extra OS processing required), G (group), T (TLS), C (compressed), x (unknown), o (OS specific), E (exclude), R (retain), p (processor specific) Elf file type is DYN (Shared object file) Entry point 0x18 There are 4 program headers, starting at offset 64 Program Headers Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align LOAD 0x000120 0x0000000000000000 0x0000000000000000 0x000828 0x000828 E 0x8 LOAD 0x000948 0x0000000100000000 0x0000000100000000 0x000020 0x000020 R 0x8 LOAD 0x000968 0x0000000200000000 0x0000000200000000 0x000000 0x001000 RW 0x8 LOAD 0x000968 0x0000000300000000 0x0000000300000000 0x000000 0x001000 RW 0x8 Section to Segment mapping Segment Sections... 00 .text 01 .rodata 02 .bss.stack 03 .bss.heap None .symtab .shstrtab .strtab There are no relocations in this file. Symbol table '.symtab' contains 43 entries Num Value Size Type Bind Vis Ndx Name 0 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1 0000000000000000 0 FILE LOCAL DEFAULT ABS hello_dasmac.8125ef642f86079a-cgu.0 2 0000000100000000 14 OBJECT LOCAL DEFAULT 2 .L__unnamed_1 3 000000010000000e 14 OBJECT LOCAL DEFAULT 2 .L__unnamed_2 4 0000000000000000 0 FILE LOCAL DEFAULT ABS 3rkop1sv4pggn15fe45te8a2u 5 0000000000000000 0 FILE LOCAL DEFAULT ABS std.7568b6690e93a51f-cgu.0 6 0000000000000000 0 FILE LOCAL DEFAULT ABS panic_abort.90abb13b511d24c8-cgu.0 7 0000000000000000 0 FILE LOCAL DEFAULT ABS alloc.63143c6bdd2830dc-cgu.0 8 0000000000000000 0 FILE LOCAL DEFAULT ABS core.e0b4368be1399d19-cgu.0 9 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.078 10 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.115 11 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.000 12 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.015 13 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.121 14 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.012 15 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.132 16 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.009 17 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.138 18 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.142 19 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.005 20 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.146 21 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.148 22 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.151 23 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.163 24 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.176 25 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.182 26 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.021 27 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.189 28 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.219 29 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.248 30 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.013 31 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.256 32 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.263 33 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.276 34 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.282 35 0000000000000000 0 FILE LOCAL DEFAULT ABS compiler_builtins.23e48371ed54d56c-cgu.291 36 0000000200000000 0 NOTYPE LOCAL DEFAULT 3 _stack_start 37 0000000200001000 0 NOTYPE LOCAL DEFAULT 3 _stack_end 38 0000000300000000 0 NOTYPE LOCAL DEFAULT 4 _heap_start 39 0000000300001000 0 NOTYPE LOCAL DEFAULT 4 _heap_end 40 00000000000007d8 80 FUNC GLOBAL DEFAULT 1 custom_panic 41 0000000000000018 1984 FUNC GLOBAL DEFAULT 1 entrypoint 42 0000000000000000 24 FUNC GLOBAL DEFAULT 1 abort There are no section groups in this file. Disassembly of section .text 0000000000000000 <abort> 0 07 0a 00 00 00 00 00 00 add64 r10, 0x0 8 95 00 00 00 11 1a fc b6 syscall -0x4903e5ef 10 9d 00 00 00 00 00 00 00 return 0000000000000018 <entrypoint> 18 07 0a 00 00 00 f8 ff ff add64 r10, -0x800 20 9c 13 00 00 00 00 00 00 ldxdw r3, [r1 + 0x0] 28 15 03 04 00 00 00 00 00 jeq r3, 0x0, +0x4 <entrypoint+0x38> 30 bf 12 00 00 00 00 00 00 mov64 r2, r1 38 07 02 00 00 08 00 00 00 add64 r2, 0x8 40 9f 2a 10 00 00 00 00 00 stxdw [r10 + 0x10], r2 48 35 03 06 00 03 00 00 00 jge r3, 0x3, +0x6 <entrypoint+0x68> 50 b4 01 00 00 00 00 00 00 mov32 w1, 0x0 58 f7 01 00 00 01 00 00 00 hor64 r1, 0x1 60 b7 02 00 00 0e 00 00 00 mov64 r2, 0xe 68 95 00 00 00 bd 59 75 20 syscall 0x207559bd 70 b7 00 00 00 00 00 00 00 mov64 r0, 0x0 78 9d 00 00 00 00 00 00 00 return 80 9c 12 58 00 00 00 00 00 ldxdw r2, [r1 + 0x58] 88 0f 21 00 00 00 00 00 00 add64 r1, r2 90 bf a2 00 00 00 00 00 00 mov64 r2, r10 98 07 02 00 00 10 00 00 00 add64 r2, 0x10 a0 07 01 00 00 6f 28 00 00 add64 r1, 0x286f a8 57 01 00 00 f8 ff ff ff and64 r1, -0x8 b0 a5 03 57 00 06 00 00 00 jlt r3, 0x6, +0x57 <entrypoint+0x358> b8 bf a2 00 00 00 00 00 00 mov64 r2, r10 c0 07 02 00 00 10 00 00 00 add64 r2, 0x10 c8 2c 14 00 00 00 00 00 00 ldxb w4, [r1 + 0x0] d0 55 04 25 00 ff 00 00 00 jne r4, 0xff, +0x25 <entrypoint+0x1e8> d8 9f 12 08 00 00 00 00 00 stxdw [r2 + 0x8], r1 e0 9c 14 50 00 00 00 00 00 ldxdw r4, [r1 + 0x50] e8 0f 41 00 00 00 00 00 00 add64 r1, r4 f0 07 01 00 00 67 28 00 00 add64 r1, 0x2867 f8 57 01 00 00 f8 ff ff ff and64 r1, -0x8 100 2c 14 00 00 00 00 00 00 ldxb w4, [r1 + 0x0] 108 55 04 27 00 ff 00 00 00 jne r4, 0xff, +0x27 <entrypoint+0x230> 110 9f 12 10 00 00 00 00 00 stxdw [r2 + 0x10], r1 118 9c 14 50 00 00 00 00 00 ldxdw r4, [r1 + 0x50] 120 0f 41 00 00 00 00 00 00 add64 r1, r4 128 07 01 00 00 67 28 00 00 add64 r1, 0x2867 130 57 01 00 00 f8 ff ff ff and64 r1, -0x8 138 2c 14 00 00 00 00 00 00 ldxb w4, [r1 + 0x0] 140 55 04 29 00 ff 00 00 00 jne r4, 0xff, +0x29 <entrypoint+0x278> 148 9f 12 18 00 00 00 00 00 stxdw [r2 + 0x18], r1 150 9c 14 50 00 00 00 00 00 ldxdw r4, [r1 + 0x50] 158 0f 41 00 00 00 00 00 00 add64 r1, r4 160 07 01 00 00 67 28 00 00 add64 r1, 0x2867 168 57 01 00 00 f8 ff ff ff and64 r1, -0x8 170 2c 14 00 00 00 00 00 00 ldxb w4, [r1 + 0x0] 178 55 04 2b 00 ff 00 00 00 jne r4, 0xff, +0x2b <entrypoint+0x2c0> 180 9f 12 20 00 00 00 00 00 stxdw [r2 + 0x20], r1 188 9c 14 50 00 00 00 00 00 ldxdw r4, [r1 + 0x50] 190 0f 41 00 00 00 00 00 00 add64 r1, r4 198 07 01 00 00 67 28 00 00 add64 r1, 0x2867 1a0 57 01 00 00 f8 ff ff ff and64 r1, -0x8 1a8 07 02 00 00 28 00 00 00 add64 r2, 0x28 1b0 2c 14 00 00 00 00 00 00 ldxb w4, [r1 + 0x0] 1b8 55 04 2d 00 ff 00 00 00 jne r4, 0xff, +0x2d <entrypoint+0x310> 1c0 9f 12 00 00 00 00 00 00 stxdw [r2 + 0x0], r1 1c8 9c 14 50 00 00 00 00 00 ldxdw r4, [r1 + 0x50] 1d0 0f 41 00 00 00 00 00 00 add64 r1, r4 1d8 07 01 00 00 67 28 00 00 add64 r1, 0x2867 1e0 57 01 00 00 f8 ff ff ff and64 r1, -0x8 1e8 07 03 00 00 fb ff ff ff add64 r3, -0x5 1f0 25 03 da ff 05 00 00 00 jgt r3, 0x5, -0x26 <entrypoint+0xb0> 1f8 05 00 2e 00 00 00 00 00 ja +0x2e <entrypoint+0x358> 200 67 04 00 00 03 00 00 00 lsh64 r4, 0x3 208 bf a5 00 00 00 00 00 00 mov64 r5, r10 210 07 05 00 00 10 00 00 00 add64 r5, 0x10 218 0f 45 00 00 00 00 00 00 add64 r5, r4 220 9c 54 00 00 00 00 00 00 ldxdw r4, [r5 + 0x0] 228 9f 42 08 00 00 00 00 00 stxdw [r2 + 0x8], r4 230 07 01 00 00 08 00 00 00 add64 r1, 0x8 238 2c 14 00 00 00 00 00 00 ldxb w4, [r1 + 0x0] 240 15 04 d9 ff ff 00 00 00 jeq r4, 0xff, -0x27 <entrypoint+0xf8> 248 67 04 00 00 03 00 00 00 lsh64 r4, 0x3 250 bf a5 00 00 00 00 00 00 mov64 r5, r10 258 07 05 00 00 10 00 00 00 add64 r5, 0x10 260 0f 45 00 00 00 00 00 00 add64 r5, r4 268 9c 54 00 00 00 00 00 00 ldxdw r4, [r5 + 0x0] 270 9f 42 10 00 00 00 00 00 stxdw [r2 + 0x10], r4 278 07 01 00 00 08 00 00 00 add64 r1, 0x8 280 2c 14 00 00 00 00 00 00 ldxb w4, [r1 + 0x0] 288 15 04 d7 ff ff 00 00 00 jeq r4, 0xff, -0x29 <entrypoint+0x130> 290 67 04 00 00 03 00 00 00 lsh64 r4, 0x3 298 bf a5 00 00 00 00 00 00 mov64 r5, r10 2a0 07 05 00 00 10 00 00 00 add64 r5, 0x10 2a8 0f 45 00 00 00 00 00 00 add64 r5, r4 2b0 9c 54 00 00 00 00 00 00 ldxdw r4, [r5 + 0x0] 2b8 9f 42 18 00 00 00 00 00 stxdw [r2 + 0x18], r4 2c0 07 01 00 00 08 00 00 00 add64 r1, 0x8 2c8 2c 14 00 00 00 00 00 00 ldxb w4, [r1 + 0x0] 2d0 15 04 d5 ff ff 00 00 00 jeq r4, 0xff, -0x2b <entrypoint+0x168> 2d8 67 04 00 00 03 00 00 00 lsh64 r4, 0x3 2e0 bf a5 00 00 00 00 00 00 mov64 r5, r10 2e8 07 05 00 00 10 00 00 00 add64 r5, 0x10 2f0 0f 45 00 00 00 00 00 00 add64 r5, r4 2f8 9c 54 00 00 00 00 00 00 ldxdw r4, [r5 + 0x0] 300 9f 42 20 00 00 00 00 00 stxdw [r2 + 0x20], r4 308 07 01 00 00 08 00 00 00 add64 r1, 0x8 310 07 02 00 00 28 00 00 00 add64 r2, 0x28 318 2c 14 00 00 00 00 00 00 ldxb w4, [r1 + 0x0] 320 15 04 d3 ff ff 00 00 00 jeq r4, 0xff, -0x2d <entrypoint+0x1a8> 328 67 04 00 00 03 00 00 00 lsh64 r4, 0x3 330 bf a5 00 00 00 00 00 00 mov64 r5, r10 338 07 05 00 00 10 00 00 00 add64 r5, 0x10 340 0f 45 00 00 00 00 00 00 add64 r5, r4 348 9c 54 00 00 00 00 00 00 ldxdw r4, [r5 + 0x0] 350 9f 42 00 00 00 00 00 00 stxdw [r2 + 0x0], r4 358 07 01 00 00 08 00 00 00 add64 r1, 0x8 360 07 03 00 00 fb ff ff ff add64 r3, -0x5 368 25 03 ab ff 05 00 00 00 jgt r3, 0x5, -0x55 <entrypoint+0xb0> 370 d5 03 14 00 02 00 00 00 jsle r3, 0x2, +0x14 <entrypoint+0x400> 378 15 03 18 00 03 00 00 00 jeq r3, 0x3, +0x18 <entrypoint+0x428> 380 55 03 22 00 04 00 00 00 jne r3, 0x4, +0x22 <entrypoint+0x480> 388 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 390 55 03 48 00 ff 00 00 00 jne r3, 0xff, +0x48 <entrypoint+0x5c0> 398 9f 12 08 00 00 00 00 00 stxdw [r2 + 0x8], r1 3a0 9c 13 50 00 00 00 00 00 ldxdw r3, [r1 + 0x50] 3a8 0f 31 00 00 00 00 00 00 add64 r1, r3 3b0 07 01 00 00 67 28 00 00 add64 r1, 0x2867 3b8 57 01 00 00 f8 ff ff ff and64 r1, -0x8 3c0 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 3c8 55 03 4a 00 ff 00 00 00 jne r3, 0xff, +0x4a <entrypoint+0x608> 3d0 9f 12 10 00 00 00 00 00 stxdw [r2 + 0x10], r1 3d8 9c 13 50 00 00 00 00 00 ldxdw r3, [r1 + 0x50] 3e0 0f 31 00 00 00 00 00 00 add64 r1, r3 3e8 07 01 00 00 67 28 00 00 add64 r1, 0x2867 3f0 57 01 00 00 f8 ff ff ff and64 r1, -0x8 3f8 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 400 55 03 4c 00 ff 00 00 00 jne r3, 0xff, +0x4c <entrypoint+0x650> 408 9f 12 18 00 00 00 00 00 stxdw [r2 + 0x18], r1 410 05 00 87 ff 00 00 00 00 ja -0x79 <entrypoint+0x38> 418 15 03 86 ff 01 00 00 00 jeq r3, 0x1, -0x7a <entrypoint+0x38> 420 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 428 55 03 6f 00 ff 00 00 00 jne r3, 0xff, +0x6f <entrypoint+0x790> 430 9f 12 08 00 00 00 00 00 stxdw [r2 + 0x8], r1 438 05 00 82 ff 00 00 00 00 ja -0x7e <entrypoint+0x38> 440 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 448 55 03 22 00 ff 00 00 00 jne r3, 0xff, +0x22 <entrypoint+0x548> 450 9f 12 08 00 00 00 00 00 stxdw [r2 + 0x8], r1 458 9c 13 50 00 00 00 00 00 ldxdw r3, [r1 + 0x50] 460 0f 31 00 00 00 00 00 00 add64 r1, r3 468 07 01 00 00 67 28 00 00 add64 r1, 0x2867 470 57 01 00 00 f8 ff ff ff and64 r1, -0x8 478 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 480 55 03 24 00 ff 00 00 00 jne r3, 0xff, +0x24 <entrypoint+0x590> 488 9f 12 10 00 00 00 00 00 stxdw [r2 + 0x10], r1 490 05 00 77 ff 00 00 00 00 ja -0x89 <entrypoint+0x38> 498 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 4a0 55 03 3f 00 ff 00 00 00 jne r3, 0xff, +0x3f <entrypoint+0x688> 4a8 9f 12 08 00 00 00 00 00 stxdw [r2 + 0x8], r1 4b0 9c 13 50 00 00 00 00 00 ldxdw r3, [r1 + 0x50] 4b8 0f 31 00 00 00 00 00 00 add64 r1, r3 4c0 07 01 00 00 67 28 00 00 add64 r1, 0x2867 4c8 57 01 00 00 f8 ff ff ff and64 r1, -0x8 4d0 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 4d8 55 03 41 00 ff 00 00 00 jne r3, 0xff, +0x41 <entrypoint+0x6d0> 4e0 9f 12 10 00 00 00 00 00 stxdw [r2 + 0x10], r1 4e8 9c 13 50 00 00 00 00 00 ldxdw r3, [r1 + 0x50] 4f0 0f 31 00 00 00 00 00 00 add64 r1, r3 4f8 07 01 00 00 67 28 00 00 add64 r1, 0x2867 500 57 01 00 00 f8 ff ff ff and64 r1, -0x8 508 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 510 55 03 43 00 ff 00 00 00 jne r3, 0xff, +0x43 <entrypoint+0x718> 518 9f 12 18 00 00 00 00 00 stxdw [r2 + 0x18], r1 520 9c 13 50 00 00 00 00 00 ldxdw r3, [r1 + 0x50] 528 0f 31 00 00 00 00 00 00 add64 r1, r3 530 07 01 00 00 67 28 00 00 add64 r1, 0x2867 538 57 01 00 00 f8 ff ff ff and64 r1, -0x8 540 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 548 55 03 45 00 ff 00 00 00 jne r3, 0xff, +0x45 <entrypoint+0x760> 550 9f 12 20 00 00 00 00 00 stxdw [r2 + 0x20], r1 558 05 00 5e ff 00 00 00 00 ja -0xa2 <entrypoint+0x38> 560 67 03 00 00 03 00 00 00 lsh64 r3, 0x3 568 bf a4 00 00 00 00 00 00 mov64 r4, r10 570 07 04 00 00 10 00 00 00 add64 r4, 0x10 578 0f 34 00 00 00 00 00 00 add64 r4, r3 580 9c 43 00 00 00 00 00 00 ldxdw r3, [r4 + 0x0] 588 9f 32 08 00 00 00 00 00 stxdw [r2 + 0x8], r3 590 07 01 00 00 08 00 00 00 add64 r1, 0x8 598 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 5a0 15 03 dc ff ff 00 00 00 jeq r3, 0xff, -0x24 <entrypoint+0x470> 5a8 67 03 00 00 03 00 00 00 lsh64 r3, 0x3 5b0 bf a1 00 00 00 00 00 00 mov64 r1, r10 5b8 07 01 00 00 10 00 00 00 add64 r1, 0x10 5c0 0f 31 00 00 00 00 00 00 add64 r1, r3 5c8 9c 11 00 00 00 00 00 00 ldxdw r1, [r1 + 0x0] 5d0 05 00 d6 ff 00 00 00 00 ja -0x2a <entrypoint+0x470> 5d8 67 03 00 00 03 00 00 00 lsh64 r3, 0x3 5e0 bf a4 00 00 00 00 00 00 mov64 r4, r10 5e8 07 04 00 00 10 00 00 00 add64 r4, 0x10 5f0 0f 34 00 00 00 00 00 00 add64 r4, r3 5f8 9c 43 00 00 00 00 00 00 ldxdw r3, [r4 + 0x0] 600 9f 32 08 00 00 00 00 00 stxdw [r2 + 0x8], r3 608 07 01 00 00 08 00 00 00 add64 r1, 0x8 610 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 618 15 03 b6 ff ff 00 00 00 jeq r3, 0xff, -0x4a <entrypoint+0x3b8> 620 67 03 00 00 03 00 00 00 lsh64 r3, 0x3 628 bf a4 00 00 00 00 00 00 mov64 r4, r10 630 07 04 00 00 10 00 00 00 add64 r4, 0x10 638 0f 34 00 00 00 00 00 00 add64 r4, r3 640 9c 43 00 00 00 00 00 00 ldxdw r3, [r4 + 0x0] 648 9f 32 10 00 00 00 00 00 stxdw [r2 + 0x10], r3 650 07 01 00 00 08 00 00 00 add64 r1, 0x8 658 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 660 15 03 b4 ff ff 00 00 00 jeq r3, 0xff, -0x4c <entrypoint+0x3f0> 668 67 03 00 00 03 00 00 00 lsh64 r3, 0x3 670 bf a1 00 00 00 00 00 00 mov64 r1, r10 678 07 01 00 00 10 00 00 00 add64 r1, 0x10 680 0f 31 00 00 00 00 00 00 add64 r1, r3 688 9c 11 00 00 00 00 00 00 ldxdw r1, [r1 + 0x0] 690 9f 12 18 00 00 00 00 00 stxdw [r2 + 0x18], r1 698 05 00 36 ff 00 00 00 00 ja -0xca <entrypoint+0x38> 6a0 67 03 00 00 03 00 00 00 lsh64 r3, 0x3 6a8 bf a4 00 00 00 00 00 00 mov64 r4, r10 6b0 07 04 00 00 10 00 00 00 add64 r4, 0x10 6b8 0f 34 00 00 00 00 00 00 add64 r4, r3 6c0 9c 43 00 00 00 00 00 00 ldxdw r3, [r4 + 0x0] 6c8 9f 32 08 00 00 00 00 00 stxdw [r2 + 0x8], r3 6d0 07 01 00 00 08 00 00 00 add64 r1, 0x8 6d8 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 6e0 15 03 bf ff ff 00 00 00 jeq r3, 0xff, -0x41 <entrypoint+0x4c8> 6e8 67 03 00 00 03 00 00 00 lsh64 r3, 0x3 6f0 bf a4 00 00 00 00 00 00 mov64 r4, r10 6f8 07 04 00 00 10 00 00 00 add64 r4, 0x10 700 0f 34 00 00 00 00 00 00 add64 r4, r3 708 9c 43 00 00 00 00 00 00 ldxdw r3, [r4 + 0x0] 710 9f 32 10 00 00 00 00 00 stxdw [r2 + 0x10], r3 718 07 01 00 00 08 00 00 00 add64 r1, 0x8 720 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 728 15 03 bd ff ff 00 00 00 jeq r3, 0xff, -0x43 <entrypoint+0x500> 730 67 03 00 00 03 00 00 00 lsh64 r3, 0x3 738 bf a4 00 00 00 00 00 00 mov64 r4, r10 740 07 04 00 00 10 00 00 00 add64 r4, 0x10 748 0f 34 00 00 00 00 00 00 add64 r4, r3 750 9c 43 00 00 00 00 00 00 ldxdw r3, [r4 + 0x0] 758 9f 32 18 00 00 00 00 00 stxdw [r2 + 0x18], r3 760 07 01 00 00 08 00 00 00 add64 r1, 0x8 768 2c 13 00 00 00 00 00 00 ldxb w3, [r1 + 0x0] 770 15 03 bb ff ff 00 00 00 jeq r3, 0xff, -0x45 <entrypoint+0x538> 778 67 03 00 00 03 00 00 00 lsh64 r3, 0x3 780 bf a1 00 00 00 00 00 00 mov64 r1, r10 788 07 01 00 00 10 00 00 00 add64 r1, 0x10 790 0f 31 00 00 00 00 00 00 add64 r1, r3 798 9c 11 00 00 00 00 00 00 ldxdw r1, [r1 + 0x0] 7a0 05 00 b5 ff 00 00 00 00 ja -0x4b <entrypoint+0x538> 7a8 67 03 00 00 03 00 00 00 lsh64 r3, 0x3 7b0 bf a1 00 00 00 00 00 00 mov64 r1, r10 7b8 07 01 00 00 10 00 00 00 add64 r1, 0x10 7c0 0f 31 00 00 00 00 00 00 add64 r1, r3 7c8 9c 11 00 00 00 00 00 00 ldxdw r1, [r1 + 0x0] 7d0 05 00 8b ff 00 00 00 00 ja -0x75 <entrypoint+0x418> 00000000000007d8 <custom_panic> 7d8 07 0a 00 00 00 00 00 00 add64 r10, 0x0 7e0 9c 11 08 00 00 00 00 00 ldxdw r1, [r1 + 0x8] 7e8 9c 12 08 00 00 00 00 00 ldxdw r2, [r1 + 0x8] 7f0 9c 11 00 00 00 00 00 00 ldxdw r1, [r1 + 0x0] 7f8 95 00 00 00 bd 59 75 20 syscall 0x207559bd 800 b4 01 00 00 0e 00 00 00 mov32 w1, 0xe 808 f7 01 00 00 01 00 00 00 hor64 r1, 0x1 810 b7 02 00 00 0e 00 00 00 mov64 r2, 0xe 818 95 00 00 00 bd 59 75 20 syscall 0x207559bd 820 9d 00 00 00 00 00 00 00 returnTIP
You can generate a similar output using the
sbpfdisassemblecommand:shsbpf disassemble deploy/hello-dasmac.so > deploy/asm-disassembly.jsonOutput
json{ "elf_header": { "ei_magic": "ELF", "ei_class": 2, "ei_data": 1, "ei_version": 1, "ei_osabi": 0, "ei_abiversion": 0, "ei_pad": [ 0, 0, 0, 0, 0, 0, 0 ], "e_type": 3, "e_machine": 247, "e_version": 1, "e_entry": 232, "e_phoff": 64, "e_shoff": 656, "e_flags": 0, "e_ehsize": 64, "e_phentsize": 56, "e_phnum": 3, "e_shentsize": 64, "e_shnum": 8, "e_shstrndx": 7 }, "program_headers": [ { "p_type": "PT_LOAD", "p_flags": 5, "p_offset": 232, "p_vaddr": 232, "p_paddr": 232, "p_filesz": 62, "p_memsz": 62, "p_align": 4096 }, { "p_type": "PT_LOAD", "p_flags": 4, "p_offset": 472, "p_vaddr": 472, "p_paddr": 472, "p_filesz": 128, "p_memsz": 128, "p_align": 4096 }, { "p_type": "PT_DYNAMIC", "p_flags": 6, "p_offset": 296, "p_vaddr": 296, "p_paddr": 296, "p_filesz": 176, "p_memsz": 176, "p_align": 8 } ], "section_headers": [ { "sh_name": 0, "sh_type": "SHT_NULL", "sh_flags": 0, "sh_addr": 0, "sh_offset": 0, "sh_size": 0, "sh_link": 0, "sh_info": 0, "sh_addralign": 0, "sh_entsize": 0 }, { "sh_name": 1, "sh_type": "SHT_PROGBITS", "sh_flags": 6, "sh_addr": 232, "sh_offset": 232, "sh_size": 48, "sh_link": 0, "sh_info": 0, "sh_addralign": 4, "sh_entsize": 0 }, { "sh_name": 7, "sh_type": "SHT_PROGBITS", "sh_flags": 2, "sh_addr": 280, "sh_offset": 280, "sh_size": 14, "sh_link": 0, "sh_info": 0, "sh_addralign": 1, "sh_entsize": 0 }, { "sh_name": 15, "sh_type": "SHT_DYNAMIC", "sh_flags": 3, "sh_addr": 296, "sh_offset": 296, "sh_size": 176, "sh_link": 5, "sh_info": 0, "sh_addralign": 8, "sh_entsize": 16 }, { "sh_name": 24, "sh_type": "SHT_DYNSYM", "sh_flags": 2, "sh_addr": 472, "sh_offset": 472, "sh_size": 72, "sh_link": 5, "sh_info": 1, "sh_addralign": 8, "sh_entsize": 24 }, { "sh_name": 32, "sh_type": "SHT_STRTAB", "sh_flags": 2, "sh_addr": 544, "sh_offset": 544, "sh_size": 24, "sh_link": 0, "sh_info": 0, "sh_addralign": 1, "sh_entsize": 0 }, { "sh_name": 40, "sh_type": "SHT_REL", "sh_flags": 2, "sh_addr": 568, "sh_offset": 568, "sh_size": 32, "sh_link": 4, "sh_info": 0, "sh_addralign": 8, "sh_entsize": 16 }, { "sh_name": 49, "sh_type": "SHT_STRTAB", "sh_flags": 0, "sh_addr": 0, "sh_offset": 600, "sh_size": 52, "sh_link": 0, "sh_info": 0, "sh_addralign": 1, "sh_entsize": 0 } ], "section_header_entries": [ { "label": "\u0000", "offset": 0, "data": [] }, { "label": ".text\u0000", "offset": 232, "data": [ 24, 1, 0, 0, 24, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 2, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 133, 16, 0, 0, 255, 255, 255, 255, 149, 0, 0, 0, 0, 0, 0, 0 ] }, { "label": ".rodata\u0000", "offset": 280, "data": [ 72, 101, 108, 108, 111, 44, 32, 68, 65, 83, 77, 65, 67, 33 ], "utf8": "Hello, DASMAC!" }, { "label": ".dynamic\u0000", "offset": 296, "data": [ 30, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 56, 2, 0, 0, 0, 0, 0, 0, 18, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 19, 0, 0, 0, 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 250, 255, 255, 111, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 216, 1, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 32, 2, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 24, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] }, { "label": ".dynsym\u0000", "offset": 472, "data": [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 16, 0, 1, 0, 232, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] }, { "label": ".dynstr\u0000", "offset": 544, "data": [ 0, 101, 110, 116, 114, 121, 112, 111, 105, 110, 116, 0, 115, 111, 108, 95, 108, 111, 103, 95, 0, 0, 0, 0 ], "utf8": "\u0000entrypoint\u0000sol_log_\u0000\u0000\u0000\u0000" }, { "label": ".rel.dyn\u0000", "offset": 568, "data": [ 232, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 0, 0, 10, 0, 0, 0, 2, 0, 0, 0 ] }, { "label": ".s\u0000", "offset": 600, "data": [ 0, 46, 116, 101, 120, 116, 0, 46, 114, 111, 100, 97, 116, 97, 0, 46, 100, 121, 110, 97, 109, 105, 99, 0, 46, 100, 121, 110, 115, 121, 109, 0, 46, 100, 121, 110, 115, 116, 114, 0, 46, 114, 101, 108, 46, 100, 121, 110, 0, 46, 115, 0 ], "utf8": "\u0000.text\u0000.rodata\u0000.dynamic\u0000.dynsym\u0000.dynstr\u0000.rel.dyn\u0000.s\u0000" } ] }Run the assembly implementation test.
shcargo test -- --test test_asmTIP
If you get errors, you might need to clear your
solanainstallation cache and re-installsolana(this is a known issue with the Solana toolchain).shrm -rf ~/.cache/solanaRebuild the Rust implementation and run its test.
shcargo build-sbf --arch v3 && cargo test -- --test test_rsNOTE
As of the time of this writing, although SBPF v4 compilation is supported, the runtime only supports loading up to SBPF v3.
Compare the two outputs, noting in particular the compute unit overhead introduced by the Rust implementation (despite its use of the
pinocchiooptimization framework):sh[... DEBUG ...] Program DASMAC... invoke [1] [... DEBUG ...] Program log: Hello, DASMAC! [... DEBUG ...] Program DASMAC... consumed 104 of 1400000 compute units [... DEBUG ...] Program DASMAC... success test tests::test_asm ... oksh[... DEBUG ...] Program DASMAC... invoke [1] [... DEBUG ...] Program log: Hello, DASMAC! [... DEBUG ...] Program DASMAC... consumed 109 of 1400000 compute units [... DEBUG ...] Program DASMAC... success test tests::test_rs ... ok
🎉 Congratulations 🎉
You have successfully assembled, disassembled, and tested your first SBPF program!
NOTE
The assembly file and testing framework in this example were adapted from the sbpf init command.