Skip to content

Commit

Permalink
Rename BacktraceContext to WasmBacktrace
Browse files Browse the repository at this point in the history
This feels like a better name given how this has turned out, and
additionally this commit removes having both `WasmBacktrace` and
`BacktraceContext`.
  • Loading branch information
alexcrichton committed Nov 1, 2022
1 parent 5819d25 commit 9b0275e
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 55 deletions.
2 changes: 1 addition & 1 deletion crates/fuzzing/src/oracles/stacks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pub fn check_stacks(stacks: Stacks) -> usize {
.get_memory(&mut store, "memory")
.expect("should have `memory` export");

let host_trace = trap.downcast_ref::<BacktraceContext>().unwrap().frames();
let host_trace = trap.downcast_ref::<WasmBacktrace>().unwrap().frames();
let trap = trap.downcast_ref::<Trap>().unwrap();
max_stack_depth = max_stack_depth.max(host_trace.len());
assert_stack_matches(&mut store, memory, ptr, len, host_trace, *trap);
Expand Down
58 changes: 23 additions & 35 deletions crates/wasmtime/src/trap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,23 +71,15 @@ pub enum Trap {
OutOfFuel,
}

#[derive(Debug)]
pub(crate) struct TrapBacktrace {
wasm_trace: Vec<FrameInfo>,
#[allow(dead_code)]
runtime_trace: wasmtime_runtime::Backtrace,
hint_wasm_backtrace_details_env: bool,
}

impl Trap {
// Same safety requirements and caveats as
// `wasmtime_runtime::raise_user_trap`.
pub(crate) unsafe fn raise(error: anyhow::Error) -> ! {
let needs_backtrace = error.downcast_ref::<BacktraceContext>().is_none();
let needs_backtrace = error.downcast_ref::<WasmBacktrace>().is_none();
wasmtime_runtime::raise_user_trap(error, needs_backtrace)
}

#[cold] // see Trap::new
#[cold] // traps are exceptional, this helps move handling off the main path
pub(crate) fn from_runtime_box(
store: &StoreOpaque,
runtime_trap: Box<wasmtime_runtime::Trap>,
Expand Down Expand Up @@ -127,11 +119,11 @@ impl Trap {
};
match backtrace {
Some(bt) => {
let bt = TrapBacktrace::new(store, bt, pc);
let bt = WasmBacktrace::new(store, bt, pc);
if bt.wasm_trace.is_empty() {
error
} else {
error.context(BacktraceContext(bt))
error.context(bt)
}
}
None => error,
Expand Down Expand Up @@ -182,8 +174,17 @@ impl fmt::Display for Trap {

impl std::error::Error for Trap {}

impl TrapBacktrace {
pub fn new(
/// todo
#[derive(Debug)]
pub struct WasmBacktrace {
wasm_trace: Vec<FrameInfo>,
#[allow(dead_code)]
runtime_trace: wasmtime_runtime::Backtrace,
hint_wasm_backtrace_details_env: bool,
}

impl WasmBacktrace {
fn new(
store: &StoreOpaque,
runtime_trace: wasmtime_runtime::Backtrace,
trap_pc: Option<usize>,
Expand Down Expand Up @@ -258,11 +259,17 @@ impl TrapBacktrace {
hint_wasm_backtrace_details_env,
}
}

/// Returns a list of function frames in WebAssembly this backtrace
/// represents.
pub fn frames(&self) -> &[FrameInfo] {
self.wasm_trace.as_slice()
}
}

impl fmt::Display for TrapBacktrace {
impl fmt::Display for WasmBacktrace {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "wasm backtrace:")?;
writeln!(f, "error while executing at wasm backtrace:")?;

let mut needs_newline = false;
for (i, frame) in self.wasm_trace.iter().enumerate() {
Expand Down Expand Up @@ -317,25 +324,6 @@ impl fmt::Display for TrapBacktrace {
}
}

/// Describes the context (backtrace) at which a user's error terminated (trapped)
/// WebAssembly execution
#[derive(Debug)]
pub struct BacktraceContext(TrapBacktrace);

impl fmt::Display for BacktraceContext {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "error while executing at {}", self.0)
}
}

impl BacktraceContext {
/// Returns a list of function frames in WebAssembly code that led to this
/// trap happening.
pub fn frames(&self) -> &[FrameInfo] {
self.0.wasm_trace.as_slice()
}
}

/// Description of a frame in a backtrace for a [`Trap`] or [`BacktraceContext`].
///
/// Whenever a WebAssembly trap occurs an instance of [`Trap`] is created. Each
Expand Down
4 changes: 2 additions & 2 deletions tests/all/component_model/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use super::REALLOC_AND_FREE;
use anyhow::Result;
use std::ops::Deref;
use wasmtime::component::*;
use wasmtime::{BacktraceContext, Store, StoreContextMut};
use wasmtime::{Store, StoreContextMut, WasmBacktrace};

#[test]
fn can_compile() -> Result<()> {
Expand Down Expand Up @@ -262,7 +262,7 @@ fn attempt_to_leave_during_malloc() -> Result<()> {
"bad trap: {trap:?}",
);

let trace = trap.downcast_ref::<BacktraceContext>().unwrap().frames();
let trace = trap.downcast_ref::<WasmBacktrace>().unwrap().frames();
assert_eq!(trace.len(), 4);

// This was our entry point...
Expand Down
34 changes: 17 additions & 17 deletions tests/all/traps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ fn test_trap_return() -> Result<()> {
assert!(format!("{e:?}").contains("test 123"));

assert!(
e.downcast_ref::<BacktraceContext>().is_some(),
"error should contain a BacktraceContext"
e.downcast_ref::<WasmBacktrace>().is_some(),
"error should contain a WasmBacktrace"
);

Ok(())
Expand Down Expand Up @@ -55,7 +55,7 @@ fn test_anyhow_error_return() -> Result<()> {
assert!(format!("{:?}", e).contains("Caused by:\n test 1234"));

assert!(e.downcast_ref::<Trap>().is_none());
assert!(e.downcast_ref::<BacktraceContext>().is_some());
assert!(e.downcast_ref::<WasmBacktrace>().is_some());

Ok(())
}
Expand Down Expand Up @@ -101,8 +101,8 @@ fn test_trap_return_downcast() -> Result<()> {
e.downcast_ref::<MyTrap>()
.expect("error downcasts to MyTrap");
let bt = e
.downcast_ref::<BacktraceContext>()
.expect("error downcasts to BacktraceContext");
.downcast_ref::<WasmBacktrace>()
.expect("error downcasts to WasmBacktrace");
assert_eq!(bt.frames().len(), 1);
println!("{:?}", bt);

Expand All @@ -125,7 +125,7 @@ fn test_trap_trace() -> Result<()> {

let e = run_func.call(&mut store, ()).unwrap_err();

let trace = e.downcast_ref::<BacktraceContext>().unwrap().frames();
let trace = e.downcast_ref::<WasmBacktrace>().unwrap().frames();
assert_eq!(trace.len(), 2);
assert_eq!(trace[0].module_name().unwrap(), "hello_mod");
assert_eq!(trace[0].func_index(), 1);
Expand Down Expand Up @@ -198,7 +198,7 @@ fn test_trap_through_host() -> Result<()> {
)?;
let a = instance.get_typed_func::<(), (), _>(&mut store, "a")?;
let err = a.call(&mut store, ()).unwrap_err();
let trace = err.downcast_ref::<BacktraceContext>().unwrap().frames();
let trace = err.downcast_ref::<WasmBacktrace>().unwrap().frames();
assert_eq!(trace.len(), 3);
assert_eq!(trace[0].func_name(), Some("c"));
assert_eq!(trace[1].func_name(), Some("b"));
Expand All @@ -225,7 +225,7 @@ fn test_trap_backtrace_disabled() -> Result<()> {
let run_func = instance.get_typed_func::<(), (), _>(&mut store, "run")?;

let e = run_func.call(&mut store, ()).unwrap_err();
assert!(e.downcast_ref::<BacktraceContext>().is_none());
assert!(e.downcast_ref::<WasmBacktrace>().is_none());
Ok(())
}

Expand All @@ -249,7 +249,7 @@ fn test_trap_trace_cb() -> Result<()> {

let e = run_func.call(&mut store, ()).unwrap_err();

let trace = e.downcast_ref::<BacktraceContext>().unwrap().frames();
let trace = e.downcast_ref::<WasmBacktrace>().unwrap().frames();
assert_eq!(trace.len(), 2);
assert_eq!(trace[0].module_name().unwrap(), "hello_mod");
assert_eq!(trace[0].func_index(), 2);
Expand All @@ -275,7 +275,7 @@ fn test_trap_stack_overflow() -> Result<()> {

let e = run_func.call(&mut store, ()).unwrap_err();

let trace = e.downcast_ref::<BacktraceContext>().unwrap().frames();
let trace = e.downcast_ref::<WasmBacktrace>().unwrap().frames();
assert!(trace.len() >= 32);
for i in 0..trace.len() {
assert_eq!(trace[i].module_name().unwrap(), "rec_mod");
Expand Down Expand Up @@ -470,7 +470,7 @@ fn rust_catch_panic_import() -> Result<()> {
let instance = Instance::new(&mut store, &module, &[panic.into(), catch_panic.into()])?;
let run = instance.get_typed_func::<(), (), _>(&mut store, "run")?;
let trap = run.call(&mut store, ()).unwrap_err();
let trace = trap.downcast_ref::<BacktraceContext>().unwrap().frames();
let trace = trap.downcast_ref::<WasmBacktrace>().unwrap().frames();
assert_eq!(trace.len(), 1);
assert_eq!(trace[0].func_index(), 3);
assert_eq!(num_panics.load(std::sync::atomic::Ordering::SeqCst), 2);
Expand Down Expand Up @@ -625,7 +625,7 @@ fn present_after_module_drop() -> Result<()> {

fn assert_trap(t: Error) {
println!("{:?}", t);
let trace = t.downcast_ref::<BacktraceContext>().unwrap().frames();
let trace = t.downcast_ref::<WasmBacktrace>().unwrap().frames();
assert_eq!(trace.len(), 1);
assert_eq!(trace[0].func_index(), 0);
}
Expand Down Expand Up @@ -718,7 +718,7 @@ fn parse_dwarf_info() -> Result<()> {
let trap = run.call(&mut store, &[], &mut []).unwrap_err();

let mut found = false;
let frames = trap.downcast_ref::<BacktraceContext>().unwrap().frames();
let frames = trap.downcast_ref::<WasmBacktrace>().unwrap().frames();
for frame in frames {
for symbol in frame.symbols() {
if let Some(file) = symbol.file() {
Expand Down Expand Up @@ -847,7 +847,7 @@ fn traps_without_address_map() -> Result<()> {

let e = run_func.call(&mut store, ()).unwrap_err();

let trace = e.downcast_ref::<BacktraceContext>().unwrap().frames();
let trace = e.downcast_ref::<WasmBacktrace>().unwrap().frames();
assert_eq!(trace.len(), 2);
assert_eq!(trace[0].func_name(), Some("hello"));
assert_eq!(trace[0].func_index(), 1);
Expand Down Expand Up @@ -900,7 +900,7 @@ fn catch_trap_calling_across_stores() -> Result<()> {
"trap should contain 'unreachable', got: {trap:?}"
);

let trace = trap.downcast_ref::<BacktraceContext>().unwrap().frames();
let trace = trap.downcast_ref::<WasmBacktrace>().unwrap().frames();

assert_eq!(trace.len(), 1);
assert_eq!(trace[0].func_name(), Some("trap"));
Expand Down Expand Up @@ -1010,7 +1010,7 @@ async fn async_then_sync_trap() -> Result<()> {
.unwrap();
let trap = a.call_async(&mut async_store, ()).await.unwrap_err();

let trace = trap.downcast_ref::<BacktraceContext>().unwrap().frames();
let trace = trap.downcast_ref::<WasmBacktrace>().unwrap().frames();
// We don't support cross-store or cross-engine symbolication currently, so
// the other frames are ignored.
assert_eq!(trace.len(), 1);
Expand Down Expand Up @@ -1091,7 +1091,7 @@ async fn sync_then_async_trap() -> Result<()> {
.unwrap();
let trap = a.call(&mut sync_store, ()).unwrap_err();

let trace = trap.downcast_ref::<BacktraceContext>().unwrap().frames();
let trace = trap.downcast_ref::<WasmBacktrace>().unwrap().frames();
// We don't support cross-store or cross-engine symbolication currently, so
// the other frames are ignored.
assert_eq!(trace.len(), 1);
Expand Down

0 comments on commit 9b0275e

Please sign in to comment.