Wasmtime: fix stack walking across frames from different stores (#4779)
We were previously implicitly assuming that all Wasm frames in a stack used the
same `VMRuntimeLimits` as the previous frame we walked, but this is not true
when Wasm in store A calls into the host which then calls into Wasm in store B:
| ... |
| Host | |
+-----------------+ | stack
| Wasm in store A | | grows
+-----------------+ | down
| Host | |
+-----------------+ |
| Wasm in store B | V
+-----------------+
Trying to walk this stack would previously result in a runtime panic.
The solution is to push the maintenance of our list of saved Wasm FP/SP/PC
registers that allow us to identify contiguous regions of Wasm frames on the
stack deeper into `CallThreadState`. The saved registers list is now maintained
whenever updating the `CallThreadState` linked list by making the
`CallThreadState::prev` field private and only accessible via a getter and
setter, where the setter always maintains our invariants.
This commit is contained in:
@@ -149,18 +149,18 @@ impl Backtrace {
|
||||
// trace through (since each `CallTheadState` saves the *previous*
|
||||
// call into Wasm's saved registers, and the youngest call into
|
||||
// Wasm's registers are saved in the `VMRuntimeLimits`)
|
||||
if state.prev.get().is_null() {
|
||||
debug_assert_eq!(state.old_last_wasm_exit_pc, 0);
|
||||
debug_assert_eq!(state.old_last_wasm_exit_fp, 0);
|
||||
debug_assert_eq!(state.old_last_wasm_entry_sp, 0);
|
||||
if state.prev().is_null() {
|
||||
debug_assert_eq!(state.old_last_wasm_exit_pc(), 0);
|
||||
debug_assert_eq!(state.old_last_wasm_exit_fp(), 0);
|
||||
debug_assert_eq!(state.old_last_wasm_entry_sp(), 0);
|
||||
log::trace!("====== Done Capturing Backtrace ======");
|
||||
return;
|
||||
}
|
||||
|
||||
if let ControlFlow::Break(()) = Self::trace_through_wasm(
|
||||
state.old_last_wasm_exit_pc,
|
||||
state.old_last_wasm_exit_fp,
|
||||
state.old_last_wasm_entry_sp,
|
||||
state.old_last_wasm_exit_pc(),
|
||||
state.old_last_wasm_exit_fp(),
|
||||
state.old_last_wasm_entry_sp(),
|
||||
&mut f,
|
||||
) {
|
||||
log::trace!("====== Done Capturing Backtrace ======");
|
||||
@@ -266,7 +266,7 @@ impl Backtrace {
|
||||
}
|
||||
|
||||
/// Iterate over the frames inside this backtrace.
|
||||
pub fn frames<'a>(&'a self) -> impl Iterator<Item = &'a Frame> + 'a {
|
||||
pub fn frames<'a>(&'a self) -> impl ExactSizeIterator<Item = &'a Frame> + 'a {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user