#[repr(C)]pub struct EbpfVm<'a, C>where
C: ContextObject,{Show 13 fields
pub host_stack_pointer: *mut u64,
pub call_depth: u64,
pub stack_pointer: u64,
pub context_object_pointer: &'a mut C,
pub previous_instruction_meter: u64,
pub due_insn_count: u64,
pub stopwatch_numerator: u64,
pub stopwatch_denominator: u64,
pub registers: [u64; 12],
pub program_result: StableResult<u64, EbpfError>,
pub memory_mapping: MemoryMapping<'a>,
pub call_frames: Vec<CallFrame>,
pub loader: Arc<BuiltinProgram<C>>,
}Expand description
A virtual machine to run eBPF programs.
§Examples
use solana_rbpf::{
aligned_memory::AlignedMemory,
ebpf,
elf::Executable,
memory_region::{MemoryMapping, MemoryRegion},
program::{BuiltinProgram, FunctionRegistry, SBPFVersion},
verifier::RequisiteVerifier,
vm::{Config, EbpfVm, TestContextObject},
};
let prog = &[
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // exit
];
let mem = &mut [
0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd
];
let loader = std::sync::Arc::new(BuiltinProgram::new_mock());
let function_registry = FunctionRegistry::default();
let mut executable = Executable::<TestContextObject>::from_text_bytes(prog, loader.clone(), SBPFVersion::V2, function_registry).unwrap();
executable.verify::<RequisiteVerifier>().unwrap();
let mut context_object = TestContextObject::new(1);
let sbpf_version = executable.get_sbpf_version();
let mut stack = AlignedMemory::<{ebpf::HOST_ALIGN}>::zero_filled(executable.get_config().stack_size());
let stack_len = stack.len();
let mut heap = AlignedMemory::<{ebpf::HOST_ALIGN}>::with_capacity(0);
let regions: Vec<MemoryRegion> = vec![
executable.get_ro_region(),
MemoryRegion::new_writable(
stack.as_slice_mut(),
ebpf::MM_STACK_START,
),
MemoryRegion::new_writable(heap.as_slice_mut(), ebpf::MM_HEAP_START),
MemoryRegion::new_writable(mem, ebpf::MM_INPUT_START),
];
let memory_mapping = MemoryMapping::new(regions, executable.get_config(), sbpf_version).unwrap();
let mut vm = EbpfVm::new(loader, sbpf_version, &mut context_object, memory_mapping, stack_len);
let (instruction_count, result) = vm.execute_program(&executable, true);
assert_eq!(instruction_count, 1);
assert_eq!(result.unwrap(), 0);Fields§
§host_stack_pointer: *mut u64Needed to exit from the guest back into the host
call_depth: u64The current call depth.
Incremented on calls and decremented on exits. It’s used to enforce config.max_call_depth and to know when to terminate execution.
stack_pointer: u64Guest stack pointer (r11).
The stack pointer isn’t exposed as an actual register. Only sub and add instructions (typically generated by the LLVM backend) are allowed to access it when sbpf_version.dynamic_stack_frames()=true. Its value is only stored here and therefore the register is not tracked in REGISTER_MAP.
context_object_pointer: &'a mut CPointer to ContextObject
previous_instruction_meter: u64Last return value of instruction_meter.get_remaining()
due_insn_count: u64Outstanding value to instruction_meter.consume()
stopwatch_numerator: u64CPU cycles accumulated by the stop watch
stopwatch_denominator: u64Number of times the stop watch was used
registers: [u64; 12]Registers inlined
program_result: StableResult<u64, EbpfError>ProgramResult inlined
memory_mapping: MemoryMapping<'a>MemoryMapping inlined
call_frames: Vec<CallFrame>Stack of CallFrames used by the Interpreter
loader: Arc<BuiltinProgram<C>>Loader built-in program
Implementations§
Source§impl<'a, C> EbpfVm<'a, C>where
C: ContextObject,
impl<'a, C> EbpfVm<'a, C>where
C: ContextObject,
Sourcepub fn new(
loader: Arc<BuiltinProgram<C>>,
sbpf_version: &SBPFVersion,
context_object: &'a mut C,
memory_mapping: MemoryMapping<'a>,
stack_len: usize,
) -> EbpfVm<'a, C>
pub fn new( loader: Arc<BuiltinProgram<C>>, sbpf_version: &SBPFVersion, context_object: &'a mut C, memory_mapping: MemoryMapping<'a>, stack_len: usize, ) -> EbpfVm<'a, C>
Creates a new virtual machine instance.
Sourcepub fn execute_program(
&mut self,
executable: &Executable<C>,
interpreted: bool,
) -> (u64, StableResult<u64, EbpfError>)
pub fn execute_program( &mut self, executable: &Executable<C>, interpreted: bool, ) -> (u64, StableResult<u64, EbpfError>)
Execute the program
If interpreted = false then the JIT compiled executable is used.
Auto Trait Implementations§
impl<'a, C> !Freeze for EbpfVm<'a, C>
impl<'a, C> !RefUnwindSafe for EbpfVm<'a, C>
impl<'a, C> !Send for EbpfVm<'a, C>
impl<'a, C> !Sync for EbpfVm<'a, C>
impl<'a, C> Unpin for EbpfVm<'a, C>
impl<'a, C> !UnwindSafe for EbpfVm<'a, C>
Blanket Implementations§
Source§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
Source§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more