1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
use std::fmt;
use crate::{store::StoreOpaque, FrameInfo, Global, Instance, Memory, Module, WasmBacktrace};
/// Representation of a core dump of a WebAssembly module
///
/// When the Config::coredump_on_trap option is enabled this structure is
/// attached to the [`anyhow::Error`] returned from many Wasmtime functions that
/// execute WebAssembly such as [`Instance::new`] or [`Func::call`]. This can be
/// acquired with the [`anyhow::Error::downcast`] family of methods to
/// programmatically inspect the coredump. Otherwise since it's part of the
/// error returned this will get printed along with the rest of the error when
/// the error is logged.
///
/// Note that some state, such as Wasm locals or values on the operand stack,
/// may be optimized away by the compiler or otherwise not recovered in the
/// coredump.
///
/// Capturing of wasm coredumps can be configured through the
/// [`Config::coredump_on_trap`][crate::Config::coredump_on_trap] method.
///
/// For more information about errors in wasmtime see the documentation of the
/// [`Trap`][crate::Trap] type.
///
/// [`Func::call`]: crate::Func::call
/// [`Instance::new`]: crate::Instance::new
pub struct WasmCoreDump {
name: String,
modules: Vec<Module>,
instances: Vec<Instance>,
store_memories: Vec<Memory>,
store_globals: Vec<Global>,
backtrace: WasmBacktrace,
}
impl WasmCoreDump {
pub(crate) fn new(store: &StoreOpaque, backtrace: WasmBacktrace) -> WasmCoreDump {
let modules: Vec<_> = store.modules().all_modules().cloned().collect();
let instances: Vec<Instance> = store.all_instances().collect();
let store_memories: Vec<Memory> = store.all_memories().collect();
let store_globals: Vec<Global> = store.all_globals().collect();
WasmCoreDump {
name: String::from("store_name"),
modules,
instances,
store_memories,
store_globals,
backtrace,
}
}
/// The stack frames for the CoreDump
pub fn frames(&self) -> &[FrameInfo] {
self.backtrace.frames()
}
/// The names of the modules involved in the CoreDump
pub fn modules(&self) -> &[Module] {
self.modules.as_ref()
}
/// The instances involved in the CoreDump
pub fn instances(&self) -> &[Instance] {
self.instances.as_ref()
}
/// The imported globals that belong to the store, rather than a specific
/// instance
pub fn store_globals(&self) -> &[Global] {
self.store_globals.as_ref()
}
/// The imported memories that belong to the store, rather than a specific
/// instance.
pub fn store_memories(&self) -> &[Memory] {
self.store_memories.as_ref()
}
}
impl fmt::Display for WasmCoreDump {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "wasm coredump generated while executing {}:", self.name)?;
writeln!(f, "modules:")?;
for module in self.modules.iter() {
writeln!(f, " {}", module.name().unwrap_or("<module>"))?;
}
writeln!(f, "instances:")?;
for instance in self.instances.iter() {
writeln!(f, " {:?}", instance)?;
}
writeln!(f, "memories:")?;
for memory in self.store_memories.iter() {
writeln!(f, " {:?}", memory)?;
}
writeln!(f, "globals:")?;
for global in self.store_globals.iter() {
writeln!(f, " {:?}", global)?;
}
writeln!(f, "backtrace:")?;
write!(f, "{}", self.backtrace)?;
Ok(())
}
}
impl fmt::Debug for WasmCoreDump {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "<wasm core dump>")
}
}