Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion ci/miri-provenance-test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@
# host to compile the wasm module in question to avoid needing to run Cranelift
# under MIRI. That enables much faster iteration on the test here.

# Note that this requires a nightly toolchain for the use of miri. If your
# default toolchain is not a nightly toolchain, you can run this script via
# `rustup run nightly ./ci/miri-provenance-test.sh`.

set -ex

compile() {
cargo run --no-default-features --features compile,pulley,wat,gc-drc,component-model,component-model-async \
cargo run --no-default-features --features compile,pulley,wat,gc-drc,component-model,component-model-async,debug \
compile --target pulley64 $1 \
-o ${1%.wat}.cwasm \
-O memory-reservation=$((1 << 20)) \
-O memory-guard-size=0 \
-O signals-based-traps=n \
-D guest-debug=y \
-W function-references,component-model-async,component-model-async-stackful,component-model-async-builtins,component-model-error-context
}

Expand Down
5 changes: 3 additions & 2 deletions crates/wasmtime/src/runtime/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,9 @@ impl FrameHandle {
// crates/cranelift/src/func_environ.rs in
// `update_stack_slot_vmctx()`.) The frame/activation is
// still valid because we verified this in `frame_data` above.
let vmctx: *mut VMContext =
unsafe { *(frame_data.slot_addr(self.cursor.frame().fp()) as *mut _) };
let vmctx: usize =
unsafe { *(frame_data.slot_addr(self.cursor.frame().fp()) as *mut usize) };
let vmctx: *mut VMContext = core::ptr::with_exposed_provenance_mut(vmctx);
let vmctx = NonNull::new(vmctx).expect("null vmctx in debug state slot");
// SAFETY: the stored vmctx value is a valid instance in this
// store; we only visit frames from this store in the
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmtime/src/runtime/vm/sys/unix/machports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ unsafe extern "C" fn sigbus_handler(
};
unsafe {
let faulting_addr = (*siginfo).si_addr() as usize;
let range = &info.vm_store_context.as_ref().async_guard_range;
let range = &info.vm_store_context.get().as_ref().async_guard_range;
if range.start.addr() <= faulting_addr && faulting_addr < range.end.addr() {
super::signals::abort_stack_overflow();
}
Expand Down
2 changes: 1 addition & 1 deletion crates/wasmtime/src/runtime/vm/sys/unix/signals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ unsafe extern "C" fn trap_handler(
match test {
TrapTest::NotWasm => {
if let Some(faulting_addr) = faulting_addr {
let range = unsafe { &info.vm_store_context.as_ref().async_guard_range };
let range = unsafe { &info.vm_store_context.get().as_ref().async_guard_range };
if range.start.addr() <= faulting_addr && faulting_addr < range.end.addr() {
abort_stack_overflow();
}
Expand Down
24 changes: 15 additions & 9 deletions crates/wasmtime/src/runtime/vm/traphandlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ mod call_thread_state {
#[cfg(feature = "coredump")]
pub(super) capture_coredump: bool,

pub(crate) vm_store_context: NonNull<VMStoreContext>,
pub(crate) vm_store_context: Cell<NonNull<VMStoreContext>>,
pub(crate) unwinder: &'static dyn Unwind,

pub(super) prev: Cell<tls::Ptr>,
Expand Down Expand Up @@ -582,7 +582,7 @@ mod call_thread_state {
capture_backtrace: store.engine().config().wasm_backtrace,
#[cfg(feature = "coredump")]
capture_coredump: store.engine().config().coredump_on_trap,
vm_store_context: store.vm_store_context_ptr(),
vm_store_context: Cell::new(store.vm_store_context_ptr()),
prev: Cell::new(ptr::null()),
old_state,
}
Expand Down Expand Up @@ -670,7 +670,7 @@ mod call_thread_state {
}

unsafe {
let cx = self.vm_store_context.as_ref();
let cx = self.vm_store_context.get().as_ref();
swap(
&cx.last_wasm_exit_trampoline_fp,
&mut (*self.old_state).last_wasm_exit_trampoline_fp,
Expand Down Expand Up @@ -751,6 +751,10 @@ impl CallThreadState {
let prev = self.unwind.replace(UnwindState::None);
assert!(prev.is_none());
}

// Avoid unused-variable warning in non-exceptions/GC build.
let _ = store;

let state = match reason {
#[cfg(all(feature = "std", panic = "unwind"))]
UnwindReason::Panic(err) => {
Expand Down Expand Up @@ -807,10 +811,10 @@ impl CallThreadState {
}
};

// Avoid unused-variable warning in non-exceptions/GC build.
let _ = store;

self.unwind.set(state);

// Re-derive our VMStoreContext pointer for provenance.
self.vm_store_context.set(store.vm_store_context_ptr());
}

/// Helper function to perform an actual unwinding operation.
Expand Down Expand Up @@ -948,7 +952,7 @@ impl CallThreadState {

pub(crate) fn entry_trap_handler(&self) -> Handler {
unsafe {
let vm_store_context = self.vm_store_context.as_ref();
let vm_store_context = self.vm_store_context.get().as_ref();
let fp = *vm_store_context.last_wasm_entry_fp.get();
let sp = *vm_store_context.last_wasm_entry_sp.get();
let pc = *vm_store_context.last_wasm_entry_trap_handler.get();
Expand Down Expand Up @@ -1057,8 +1061,10 @@ impl CallThreadState {
faulting_addr: Option<usize>,
trap: wasmtime_environ::Trap,
) {
let backtrace = self.capture_backtrace(self.vm_store_context.as_ptr(), Some((pc, fp)));
let coredump_stack = self.capture_coredump(self.vm_store_context.as_ptr(), Some((pc, fp)));
let backtrace =
self.capture_backtrace(self.vm_store_context.get().as_ptr(), Some((pc, fp)));
let coredump_stack =
self.capture_coredump(self.vm_store_context.get().as_ptr(), Some((pc, fp)));
self.unwind.set(UnwindState::UnwindToHost {
reason: UnwindReason::Trap(TrapReason::Jit {
pc,
Expand Down
4 changes: 2 additions & 2 deletions crates/wasmtime/src/runtime/vm/traphandlers/backtrace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ impl Backtrace {
Some((pc, fp)) => {
assert!(core::ptr::eq(
vm_store_context,
state.vm_store_context.as_ptr()
state.vm_store_context.get().as_ptr()
));
(pc, fp)
}
Expand Down Expand Up @@ -251,7 +251,7 @@ impl Backtrace {
.iter()
.flat_map(|state| state.iter())
.filter(|state| {
core::ptr::eq(vm_store_context, state.vm_store_context.as_ptr())
core::ptr::eq(vm_store_context, state.vm_store_context.get().as_ptr())
})
.map(|state| unsafe {
(
Expand Down
30 changes: 24 additions & 6 deletions tests/all/pulley.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ fn provenance_test_config() -> Config {
config.wasm_component_model_async_stackful(true);
config.wasm_component_model_threading(true);
config.wasm_component_model_error_context(true);
config.guest_debug(true);
config
}

Expand Down Expand Up @@ -133,12 +134,29 @@ fn pulley_provenance_test() -> Result<()> {
vec![],
vec![ValType::I32, ValType::I32, ValType::I32],
);
let host_new = Func::new(&mut store, host_new_ty, |_, _params, results| {
results[0] = Val::I32(1);
results[1] = Val::I32(2);
results[2] = Val::I32(3);
Ok(())
});
let module_clone = module.clone();
let host_new = Func::new(
&mut store,
host_new_ty,
move |mut caller, _params, results| {
let caller_frame = caller.debug_exit_frames().next().unwrap();
let caller_module = caller_frame.module(&mut caller).unwrap().unwrap();
assert!(Module::same(caller_module, &module_clone));
let (caller_func, pc) = caller_frame
.wasm_function_index_and_pc(&mut caller)
.unwrap()
.unwrap();
assert_eq!(caller_func.as_u32(), 3);
assert_eq!(pc, 416);
let parent_frame = caller_frame.parent(&mut caller).unwrap();
assert!(parent_frame.is_none());

results[0] = Val::I32(1);
results[1] = Val::I32(2);
results[2] = Val::I32(3);
Ok(())
},
);
let instance = Instance::new(&mut store, &module, &[host_wrap.into(), host_new.into()])?;

for func in [
Expand Down
Loading