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

View file

@ -97,6 +97,16 @@ impl<'a> FuncDecl<'a> {
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)]

View file

@ -145,6 +145,28 @@ impl<'a> Module<'a> {
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> {