Skip to main content

Vm

Struct Vm 

Source
pub struct Vm<S> {
    pub stats: Stats,
    pub optimize: bool,
    /* private fields */
}
Expand description

A machine: an owned module, a memory, and a position in the code.

Fields§

§stats: Stats

Counters and phase timings for this run.

§optimize: bool

Whether freshly lifted blocks get a cleanup round.

Lifting one machine instruction emits every side effect the specification describes, including flag computations the surrounding code never reads. Removing the ones with no users at all is sound block-locally — an instruction with no users cannot be observed — and is paid once per block instead of on every execution of it.

Implementations§

Source§

impl<S: CodeSource> Vm<S>

Source

pub fn new(ctx: Context<'static>, entry: BlockId, source: S) -> Self

Builds a machine positioned at entry.

Source

pub fn at_address( ctx: Context<'static>, addr: u64, source: S, memory: VmMemory, ) -> Result<Self, CodeError>

Builds a machine positioned at a guest address, lifting the entry block if the module does not already contain it.

Source

pub fn set_block_executor(&mut self, executor: Box<dyn BlockExecutor>)

Installs an alternative executor for block bodies, replacing any previous one. Purely an optimisation: removing it changes speed, not behaviour.

Source

pub fn clear_block_executor(&mut self)

Source

pub fn context(&self) -> &Context<'static>

Source

pub fn memory(&self) -> &VmMemory

Source

pub fn memory_mut(&mut self) -> &mut VmMemory

Source

pub fn emulator(&mut self) -> &mut StandaloneEmulator<VmMemory>

The emulator underneath, for register access and harness seeding.

Source

pub fn pc(&self) -> Option<u64>

The guest address of the block about to execute, if it has one.

Source

pub fn add_breakpoint(&mut self, addr: u64) -> bool

Source

pub fn remove_breakpoint(&mut self, addr: u64) -> bool

Source

pub fn add_injector(&mut self, injector: Box<dyn CodeInjector>)

Registers a code rewriter. It runs over every block the machine enters from now on, including blocks lifted before this call, before the block executes or is compiled.

Source

pub fn add_hook(&mut self, hook: impl Hook + 'static)

Registers a Hook: a code rewriter that picks its sites and emits through an Emitter.

Source

pub fn hook_block( &mut self, begin: u64, end: u64, callback: impl FnMut(&mut Self, u64) -> HookAction + 'static, ) -> HookId

Calls callback with the address at the entry of every block in begin..=end (anywhere when begin > end).

Source

pub fn hook_code( &mut self, begin: u64, end: u64, callback: impl FnMut(&mut Self, u64) -> HookAction + 'static, ) -> HookId

Calls callback before every guest instruction in begin..=end.

Source

pub fn hook_address( &mut self, addr: u64, callback: impl FnMut(&mut Self, u64) -> HookAction + 'static, ) -> HookId

Calls callback before the guest instruction at addr.

Source

pub fn hook_mem_write( &mut self, begin: u64, end: u64, callback: impl FnMut(&mut Self, &MemAccess) -> HookAction + 'static, ) -> HookId

Calls callback before every store to guest memory in begin..=end, with the address, width and value.

Source

pub fn hook_mem_read( &mut self, begin: u64, end: u64, callback: impl FnMut(&mut Self, &MemAccess) -> HookAction + 'static, ) -> HookId

Calls callback before every load from guest memory in begin..=end, with the address and width.

Source

pub fn hook_insn( &mut self, name: &str, callback: impl FnMut(&mut Self, &Interrupt) -> InsnAction + 'static, ) -> HookId

Calls callback when the guest reaches the user op called namesyscall, rdtsc, cpuid_basic, … — to supply its effect.

Source

pub fn hook_intr( &mut self, callback: impl FnMut(&mut Self, &Interrupt) -> InsnAction + 'static, ) -> HookId

Calls callback for every user op the interpreter cannot run, whatever its name.

Source

pub fn hook_del(&mut self, id: HookId) -> bool

Removes a hook. Interrupts it injected stay in the code and resume silently; they cost a stop and nothing more.

Source

pub fn step(&mut self) -> Option<VmExit>

Executes one instruction, lifting code on demand if control leaves the part of the module already known.

Returns None when the step was ordinary, and Some(exit) when the machine stopped for a reason worth reporting.

Source

pub fn pending_interrupt(&self) -> Option<&Interrupt>

The interrupt the machine is stopped at, if any.

Source

pub fn resume(&mut self, value: Option<u128>) -> Result<(), ResumeError>

Supplies the effect of the operation the machine is stopped at and steps past it.

value is the operation’s result, required when it declares one (Interrupt::size is non-zero) and ignored otherwise. Any other effect — a register written by a system call, memory filled by a host service — the caller applies through Vm::emulator and Vm::memory_mut before resuming. The operation’s own instruction is not run; the one after it is next.

Source

pub fn run(&mut self, budget: u64) -> VmExit

Runs until the machine stops, or until budget p-code operations have been retired.

Hooks registered through the table are called from here and the machine resumes past them, so the run only returns for an exit the caller has to see.

Auto Trait Implementations§

§

impl<S> !Freeze for Vm<S>

§

impl<S> !RefUnwindSafe for Vm<S>

§

impl<S> !Send for Vm<S>

§

impl<S> !Sync for Vm<S>

§

impl<S> !UnwindSafe for Vm<S>

§

impl<S> Unpin for Vm<S>
where S: Unpin, HookTable<S>: Unpin,

§

impl<S> UnsafeUnpin for Vm<S>
where S: UnsafeUnpin, HookTable<S>: UnsafeUnpin,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.