#[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 u64
Needed to exit from the guest back into the host
call_depth: u64
The 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: u64
Guest 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 C
Pointer to ContextObject
previous_instruction_meter: u64
Last return value of instruction_meter.get_remaining()
due_insn_count: u64
Outstanding value to instruction_meter.consume()
stopwatch_numerator: u64
CPU cycles accumulated by the stop watch
stopwatch_denominator: u64
Number 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