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: StatsCounters and phase timings for this run.
optimize: boolWhether 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>
impl<S: CodeSource> Vm<S>
Sourcepub fn new(ctx: Context<'static>, entry: BlockId, source: S) -> Self
pub fn new(ctx: Context<'static>, entry: BlockId, source: S) -> Self
Builds a machine positioned at entry.
Sourcepub fn at_address(
ctx: Context<'static>,
addr: u64,
source: S,
memory: VmMemory,
) -> Result<Self, CodeError>
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.
Sourcepub fn set_block_executor(&mut self, executor: Box<dyn BlockExecutor>)
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.
pub fn clear_block_executor(&mut self)
pub fn context(&self) -> &Context<'static>
pub fn memory(&self) -> &VmMemory
pub fn memory_mut(&mut self) -> &mut VmMemory
Sourcepub fn emulator(&mut self) -> &mut StandaloneEmulator<VmMemory>
pub fn emulator(&mut self) -> &mut StandaloneEmulator<VmMemory>
The emulator underneath, for register access and harness seeding.
Sourcepub fn pc(&self) -> Option<u64>
pub fn pc(&self) -> Option<u64>
The guest address of the block about to execute, if it has one.
pub fn add_breakpoint(&mut self, addr: u64) -> bool
pub fn remove_breakpoint(&mut self, addr: u64) -> bool
Sourcepub fn add_injector(&mut self, injector: Box<dyn CodeInjector>)
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.
Sourcepub fn hook_block(
&mut self,
begin: u64,
end: u64,
callback: impl FnMut(&mut Self, u64) -> HookAction + 'static,
) -> HookId
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).
Sourcepub fn hook_code(
&mut self,
begin: u64,
end: u64,
callback: impl FnMut(&mut Self, u64) -> HookAction + 'static,
) -> HookId
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.
Sourcepub fn hook_address(
&mut self,
addr: u64,
callback: impl FnMut(&mut Self, u64) -> HookAction + 'static,
) -> HookId
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.
Sourcepub fn hook_mem_write(
&mut self,
begin: u64,
end: u64,
callback: impl FnMut(&mut Self, &MemAccess) -> HookAction + 'static,
) -> HookId
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.
Sourcepub fn hook_mem_read(
&mut self,
begin: u64,
end: u64,
callback: impl FnMut(&mut Self, &MemAccess) -> HookAction + 'static,
) -> HookId
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.
Sourcepub fn hook_insn(
&mut self,
name: &str,
callback: impl FnMut(&mut Self, &Interrupt) -> InsnAction + 'static,
) -> HookId
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 name —
syscall, rdtsc, cpuid_basic, … — to supply its effect.
Sourcepub fn hook_intr(
&mut self,
callback: impl FnMut(&mut Self, &Interrupt) -> InsnAction + 'static,
) -> HookId
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.
Sourcepub fn hook_del(&mut self, id: HookId) -> bool
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.
Sourcepub fn step(&mut self) -> Option<VmExit>
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.
Sourcepub fn pending_interrupt(&self) -> Option<&Interrupt>
pub fn pending_interrupt(&self) -> Option<&Interrupt>
The interrupt the machine is stopped at, if any.
Sourcepub fn resume(&mut self, value: Option<u128>) -> Result<(), ResumeError>
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.