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
sourceimpl<'a, E: UserDefinedError, I: InstructionMeter> EbpfVm<'a, E, I>
impl<'a, E: UserDefinedError, I: InstructionMeter> EbpfVm<'a, E, I>
sourcepub fn new(
executable: &'a Pin<Box<Executable<E, I>>>,
heap_region: &mut [u8],
input_region: &mut [u8]
) -> Result<EbpfVm<'a, E, I>, EbpfError<E>>
pub fn new(
executable: &'a Pin<Box<Executable<E, I>>>,
heap_region: &mut [u8],
input_region: &mut [u8]
) -> Result<EbpfVm<'a, E, I>, EbpfError<E>>
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();
sourcepub fn get_total_instruction_count(&self) -> u64
pub fn get_total_instruction_count(&self) -> u64
Returns the number of instructions executed by the last program.
sourcepub fn get_program(&self) -> &[u8]ⓘNotable traits for &'_ [u8]impl<'_> Read for &'_ [u8]impl<'_> Write for &'_ mut [u8]
pub fn get_program(&self) -> &[u8]ⓘNotable traits for &'_ [u8]impl<'_> Read for &'_ [u8]impl<'_> Write for &'_ mut [u8]
Returns the program
sourcepub fn get_tracer(&self) -> &Tracer
pub fn get_tracer(&self) -> &Tracer
Returns the tracer
sourcepub 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);
sourcepub fn get_syscall_context_object(
&self,
syscall_function: usize
) -> Option<*mut u8>
pub fn get_syscall_context_object(
&self,
syscall_function: usize
) -> Option<*mut u8>
Lookup a syscall context object by its function pointer. Used for testing and validation.
sourcepub fn execute_program_interpreted(
&mut self,
instruction_meter: &mut I
) -> ProgramResult<E>
pub fn execute_program_interpreted(
&mut self,
instruction_meter: &mut I
) -> ProgramResult<E>
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);
sourcepub fn execute_program_jit(
&mut self,
instruction_meter: &mut I
) -> ProgramResult<E>
pub fn execute_program_jit(
&mut self,
instruction_meter: &mut I
) -> ProgramResult<E>
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.
Auto Trait Implementations
impl<'a, E, I> !RefUnwindSafe for EbpfVm<'a, E, I>
impl<'a, E, I> !Send for EbpfVm<'a, E, I>
impl<'a, E, I> !Sync for EbpfVm<'a, E, I>
impl<'a, E, I> Unpin for EbpfVm<'a, E, I>
impl<'a, E, I> !UnwindSafe for EbpfVm<'a, E, I>
Blanket Implementations
sourceimpl<T> BorrowMut<T> for T where
T: ?Sized,
impl<T> BorrowMut<T> for T where
T: ?Sized,
const: unstable · sourcepub fn borrow_mut(&mut self) -> &mut T
pub fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more