-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add core dump support to the runtime
This adds the machinery to capture a core dump when a trap occurs and attach it to the resulting anyhow::Error that gets bubbled up to the caller. I've created a CoreDumpStack structure in the runtime, which is currently just a backtrace until we design a way to recover the locals stack values when a trap occurs. When that CoreDumpStack gets converted to a wasmtime::WasmCoreDump, we add additional information from the Store such as globals, memories, and instance information. A lot of this is mechanistically similar to how backtraces are captured and attached to errors. Given that they both are attached as context to anyhow::Errors, setting coredump_on_trap to true will supercede any setting for wasm_backtrace.
- Loading branch information
Showing
16 changed files
with
618 additions
and
430 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
use wasm_encoder::CoreDumpValue; | ||
|
||
use crate::{Backtrace, VMRuntimeLimits}; | ||
|
||
use super::CallThreadState; | ||
|
||
/// A WebAssembly Coredump | ||
#[derive(Debug)] | ||
pub struct CoreDumpStack { | ||
/// The backtrace containing the stack frames for the CoreDump | ||
pub bt: Backtrace, | ||
|
||
/// Unimplemented | ||
/// The indices of the locals and operand_stack all map to each other (ie. | ||
/// index 0 is the locals for the first frame in the backtrace, etc) | ||
pub locals: Vec<Vec<CoreDumpValue>>, | ||
|
||
/// Unimplemented | ||
/// The operands for each stack frame | ||
pub operand_stack: Vec<Vec<CoreDumpValue>>, | ||
} | ||
|
||
impl CoreDumpStack { | ||
/// Capture a core dump of the current wasm state | ||
pub fn new( | ||
cts: &CallThreadState, | ||
limits: *const VMRuntimeLimits, | ||
trap_pc_and_fp: Option<(usize, usize)>, | ||
) -> Self { | ||
let bt = unsafe { Backtrace::new_with_trap_state(limits, cts, trap_pc_and_fp) }; | ||
|
||
Self { | ||
bt, | ||
locals: vec![], | ||
operand_stack: vec![], | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
use std::fmt; | ||
|
||
use crate::{store::StoreOpaque, Global, Instance, Memory, Module, WasmBacktrace}; | ||
|
||
/// Representation of a core dump of a WebAssembly module | ||
/// | ||
/// 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. | ||
/// | ||
/// TODO: Notably absent from this structure at the moment are any locals or | ||
/// operand values for the stack frames. More work is needed to be able to | ||
/// recover those when a trap occurs, at which point they will be added here. | ||
/// | ||
/// 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`] type. | ||
/// | ||
/// [`Func::call`]: crate::Func::call | ||
/// [`Instance::new`]: crate::Instance::new | ||
pub struct WasmCoreDump { | ||
name: String, | ||
modules: Vec<Module>, | ||
instances: Vec<Instance>, | ||
memories: Vec<Memory>, | ||
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 memories: Vec<Memory> = store.all_memories().collect(); | ||
let globals: Vec<Global> = store.all_globals().collect(); | ||
WasmCoreDump { | ||
name: String::from("store_name"), | ||
modules, | ||
instances, | ||
memories, | ||
globals, | ||
backtrace, | ||
} | ||
} | ||
} | ||
|
||
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_default())?; | ||
} | ||
|
||
writeln!(f, "instances:")?; | ||
for instance in self.instances.iter() { | ||
writeln!(f, " {:?}", instance)?; | ||
} | ||
|
||
writeln!(f, "memories:")?; | ||
for memory in self.memories.iter() { | ||
writeln!(f, " {:?}", memory)?; | ||
} | ||
|
||
writeln!(f, "globals:")?; | ||
for global in self.globals.iter() { | ||
writeln!(f, " {:?}", global)?; | ||
} | ||
|
||
writeln!(f, "backtrace:")?; | ||
write!(f, "{}", self.backtrace)?; | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -395,6 +395,7 @@ mod compiler; | |
|
||
mod code; | ||
mod config; | ||
mod coredump; | ||
mod engine; | ||
mod externals; | ||
mod instance; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.