Interpreter: configurable trace hook.

This commit is contained in:
Chris Fallin 2023-04-14 23:54:44 -07:00
parent d544bf031e
commit 9f6f0cfa9e
3 changed files with 53 additions and 15 deletions

View file

@ -12,12 +12,12 @@ mod wasi;
const WASM_PAGE: usize = 0x1_0000; // 64KiB const WASM_PAGE: usize = 0x1_0000; // 64KiB
const MAX_PAGES: usize = 2048; // 2048 * 64KiB = 128MiB const MAX_PAGES: usize = 2048; // 2048 * 64KiB = 128MiB
#[derive(Debug, Clone)]
pub struct InterpContext { pub struct InterpContext {
pub memories: PerEntity<Memory, InterpMemory>, pub memories: PerEntity<Memory, InterpMemory>,
pub tables: PerEntity<Table, InterpTable>, pub tables: PerEntity<Table, InterpTable>,
pub globals: PerEntity<Global, ConstVal>, pub globals: PerEntity<Global, ConstVal>,
pub fuel: u64, pub fuel: u64,
pub trace_handler: Option<Box<dyn Fn(usize, Vec<ConstVal>) -> bool + Send>>,
} }
type MultiVal = SmallVec<[ConstVal; 2]>; type MultiVal = SmallVec<[ConstVal; 2]>;
@ -28,6 +28,7 @@ pub enum InterpResult {
Exit, Exit,
Trap, Trap,
OutOfFuel, OutOfFuel,
TraceHandlerQuit,
} }
impl InterpResult { impl InterpResult {
@ -84,6 +85,7 @@ impl InterpContext {
tables, tables,
globals, globals,
fuel: u64::MAX, fuel: u64::MAX,
trace_handler: None,
}) })
} }
@ -195,20 +197,24 @@ impl InterpContext {
smallvec![result] smallvec![result]
} }
&ValueDef::Trace(id, ref args) => { &ValueDef::Trace(id, ref args) => {
let args = args if let Some(handler) = self.trace_handler.as_ref() {
.iter() let args = args
.map(|&arg| { .iter()
let arg = body.resolve_alias(arg); .map(|&arg| {
let multivalue = frame let arg = body.resolve_alias(arg);
.values let multivalue = frame
.get(&arg) .values
.ok_or_else(|| format!("Unset SSA value: {}", arg)) .get(&arg)
.unwrap(); .ok_or_else(|| format!("Unset SSA value: {}", arg))
assert_eq!(multivalue.len(), 1); .unwrap();
multivalue[0] assert_eq!(multivalue.len(), 1);
}) multivalue[0]
.collect::<Vec<_>>(); })
eprintln!("TRACE: {}: {:?}", id, &args[..]); .collect::<Vec<ConstVal>>();
if !handler(id, args) {
return InterpResult::TraceHandlerQuit;
}
}
smallvec![] smallvec![]
} }
&ValueDef::None | &ValueDef::Placeholder(..) | &ValueDef::BlockParam(..) => { &ValueDef::None | &ValueDef::Placeholder(..) | &ValueDef::BlockParam(..) => {

View file

@ -97,6 +97,16 @@ impl<'a> FuncDecl<'a> {
FuncDecl::None => panic!("No name for FuncDecl::None"), FuncDecl::None => panic!("No name for FuncDecl::None"),
} }
} }
pub fn without_orig_bytes(self) -> FuncDecl<'static> {
match self {
FuncDecl::Body(sig, name, body) => FuncDecl::Body(sig, name, body),
FuncDecl::Import(sig, name) => FuncDecl::Import(sig, name),
FuncDecl::Compiled(sig, name, func) => FuncDecl::Compiled(sig, name, func),
FuncDecl::None => FuncDecl::None,
FuncDecl::Lazy(..) => panic!("Trying to strip lifetime from lazy decl"),
}
}
} }
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]

View file

@ -145,6 +145,28 @@ impl<'a> Module<'a> {
debug_map: DebugMap::default(), debug_map: DebugMap::default(),
} }
} }
pub fn without_orig_bytes(self) -> Module<'static> {
Module {
orig_bytes: &[],
funcs: EntityVec::from(
self.funcs
.into_vec()
.into_iter()
.map(|decl| decl.without_orig_bytes())
.collect::<Vec<_>>(),
),
signatures: self.signatures,
globals: self.globals,
tables: self.tables,
imports: self.imports,
exports: self.exports,
memories: self.memories,
start_func: self.start_func,
debug: self.debug,
debug_map: self.debug_map,
}
}
} }
impl<'a> Module<'a> { impl<'a> Module<'a> {