Struct solana_rbpf::vm::EbpfVm
source · [−]pub struct EbpfVm<'a, E: UserDefinedError, I: InstructionMeter> { /* private fields */ }
Expand description
A virtual machine to run eBPF program.
Examples
use solana_rbpf::{ebpf, elf::{Executable, register_bpf_function}, vm::{Config, EbpfVm, TestInstructionMeter, SyscallRegistry}, user_error::UserError};
let prog = &[
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
];
let mem = &mut [
0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
];
// Instantiate a VM.
let mut bpf_functions = std::collections::BTreeMap::new();
register_bpf_function(&mut bpf_functions, 0, "entrypoint", false).unwrap();
let mut executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(prog, None, Config::default(), SyscallRegistry::default(), bpf_functions).unwrap();
let mut vm = EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], mem).unwrap();
// Provide a reference to the packet data.
let res = vm.execute_program_interpreted(&mut TestInstructionMeter { remaining: 1 }).unwrap();
assert_eq!(res, 0);
Implementations
Create a new virtual machine instance, and load an eBPF program into that instance. When attempting to load the program, it passes through a simple verifier.
Examples
use solana_rbpf::{ebpf, elf::{Executable, register_bpf_function}, vm::{Config, EbpfVm, TestInstructionMeter, SyscallRegistry}, user_error::UserError};
let prog = &[
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
];
// Instantiate a VM.
let mut bpf_functions = std::collections::BTreeMap::new();
register_bpf_function(&mut bpf_functions, 0, "entrypoint", false).unwrap();
let mut executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(prog, None, Config::default(), SyscallRegistry::default(), bpf_functions).unwrap();
let mut vm = EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], &mut []).unwrap();
Returns the number of instructions executed by the last program.
Returns the program
Returns the tracer
pub fn bind_syscall_context_object(
&mut self,
syscall_context_object: Box<dyn SyscallObject<E> + 'a>,
hash: Option<u32>
) -> Result<(), EbpfError<E>>
pub fn bind_syscall_context_object(
&mut self,
syscall_context_object: Box<dyn SyscallObject<E> + 'a>,
hash: Option<u32>
) -> Result<(), EbpfError<E>>
Bind a context object instance to a previously registered syscall
Examples
use solana_rbpf::{ebpf, elf::{Executable, register_bpf_function}, vm::{Config, EbpfVm, SyscallObject, SyscallRegistry, TestInstructionMeter}, syscalls::BpfTracePrintf, user_error::UserError};
// This program was compiled with clang, from a C program containing the following single
// instruction: `return bpf_trace_printk("foo %c %c %c\n", 10, 1, 2, 3);`
let prog = &[
0x18, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // load 0 as u64 into r1 (That would be
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // replaced by tc by the address of
// the format string, in the .map
// section of the ELF file).
0xb7, 0x02, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, // mov r2, 10
0xb7, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, // mov r3, 1
0xb7, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // mov r4, 2
0xb7, 0x05, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, // mov r5, 3
0x85, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, // call syscall with key 6
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
];
// Register a syscall.
// On running the program this syscall will print the content of registers r3, r4 and r5 to
// standard output.
let mut syscall_registry = SyscallRegistry::default();
syscall_registry.register_syscall_by_hash(6, BpfTracePrintf::call).unwrap();
// Instantiate an Executable and VM
let mut bpf_functions = std::collections::BTreeMap::new();
register_bpf_function(&mut bpf_functions, 0, "entrypoint", false).unwrap();
let mut executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(prog, None, Config::default(), syscall_registry, bpf_functions).unwrap();
let mut vm = EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], &mut []).unwrap();
// Bind a context object instance to the previously registered syscall
vm.bind_syscall_context_object(Box::new(BpfTracePrintf {}), None);
Lookup a syscall context object by its function pointer. Used for testing and validation.
Execute the program loaded, with the given packet data.
Warning: The program is executed without limiting the number of instructions that can be executed
Examples
use solana_rbpf::{ebpf, elf::{Executable, register_bpf_function}, vm::{Config, EbpfVm, TestInstructionMeter, SyscallRegistry}, user_error::UserError};
let prog = &[
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
];
let mem = &mut [
0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
];
// Instantiate a VM.
let mut bpf_functions = std::collections::BTreeMap::new();
register_bpf_function(&mut bpf_functions, 0, "entrypoint", false).unwrap();
let mut executable = Executable::<UserError, TestInstructionMeter>::from_text_bytes(prog, None, Config::default(), SyscallRegistry::default(), bpf_functions).unwrap();
let mut vm = EbpfVm::<UserError, TestInstructionMeter>::new(&executable, &mut [], mem).unwrap();
// Provide a reference to the packet data.
let res = vm.execute_program_interpreted(&mut TestInstructionMeter { remaining: 1 }).unwrap();
assert_eq!(res, 0);
Execute the previously JIT-compiled program, with the given packet data in a manner
very similar to execute_program_interpreted()
.
Safety
WARNING: JIT-compiled assembly code is not safe. It may be wise to check that the program works with the interpreter before running the JIT-compiled version of it.