Skip to content

Commit 00591bd

Browse files
committed
wasmtime-unwinder: factor out visit_frames inner loop to an iterator.
This will be desirable to allow a lazy stack-walk for our guest debugging API. It provides a `frame_iterator()` function that produces an iterator over frames in one Wasm activation, factoring out the heart of `visit_frames`; `visit_frames` is now a thin wrapper around this iterator. No functional change expected.
1 parent 3e14d77 commit 00591bd

File tree

1 file changed

+43
-10
lines changed

1 file changed

+43
-10
lines changed

crates/unwinder/src/stackwalk.rs

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ impl Frame {
9797
}
9898
}
9999

100-
/// Walk through a contiguous sequence of Wasm frames starting with
101-
/// the frame at the given PC and FP and ending at
102-
/// `trampoline_fp`. This FP should correspond to that of a trampoline
103-
/// that was used to enter the Wasm code.
100+
/// Provide an iterator that walks through a contiguous sequence of
101+
/// Wasm frames starting with the frame at the given PC and FP and
102+
/// ending at `trampoline_fp`. This FP should correspond to that of a
103+
/// trampoline that was used to enter the Wasm code.
104104
///
105105
/// We require that the initial PC, FP, and `trampoline_fp` values are
106106
/// non-null (non-zero).
@@ -112,13 +112,12 @@ impl Frame {
112112
/// then this method may segfault. These values must point to valid Wasmtime
113113
/// compiled code which respects the frame pointers that Wasmtime currently
114114
/// requires.
115-
pub unsafe fn visit_frames<R>(
115+
pub unsafe fn frame_iterator(
116116
unwind: &dyn Unwind,
117117
mut pc: usize,
118118
mut fp: usize,
119119
trampoline_fp: usize,
120-
mut f: impl FnMut(Frame) -> ControlFlow<R>,
121-
) -> ControlFlow<R> {
120+
) -> impl Iterator<Item = Frame> {
122121
log::trace!("=== Tracing through contiguous sequence of Wasm frames ===");
123122
log::trace!("trampoline_fp = 0x{trampoline_fp:016x}");
124123
log::trace!(" initial pc = 0x{pc:016x}");
@@ -170,7 +169,12 @@ pub unsafe fn visit_frames<R>(
170169
// which `return_call`'d an exit trampoline, then `fp ==
171170
// trampoline_fp` on the entry of this function, meaning the loop
172171
// won't actually execute anything.
173-
while fp != trampoline_fp {
172+
core::iter::from_fn(move || {
173+
if fp == trampoline_fp {
174+
log::trace!("=== Done tracing contiguous sequence of Wasm frames ===");
175+
return None;
176+
}
177+
174178
// At the start of each iteration of the loop, we know that
175179
// `fp` is a frame pointer from Wasm code. Therefore, we know
176180
// it is not being used as an extra general-purpose register,
@@ -188,7 +192,7 @@ pub unsafe fn visit_frames<R>(
188192
log::trace!("pc = {:p}", pc as *const ());
189193
log::trace!("fp = {:p}", fp as *const ());
190194

191-
f(Frame { pc, fp })?;
195+
let frame = Frame { pc, fp };
192196

193197
// SAFETY: this unsafe traversal of the linked list on the stack is
194198
// reflected in the contract of this function where `pc`, `fp`,
@@ -212,8 +216,37 @@ pub unsafe fn visit_frames<R>(
212216
assert!(next_older_fp > fp, "{next_older_fp:#x} > {fp:#x}");
213217
fp = next_older_fp;
214218
}
219+
220+
Some(frame)
221+
})
222+
}
223+
224+
/// Walk through a contiguous sequence of Wasm frames starting with
225+
/// the frame at the given PC and FP and ending at
226+
/// `trampoline_fp`. This FP should correspond to that of a trampoline
227+
/// that was used to enter the Wasm code.
228+
///
229+
/// We require that the initial PC, FP, and `trampoline_fp` values are
230+
/// non-null (non-zero).
231+
///
232+
/// # Safety
233+
///
234+
/// This function is not safe as `unwind`, `pc`, `fp`, and `trampoline_fp` must
235+
/// all be "correct" in that if they're wrong or mistakenly have the wrong value
236+
/// then this method may segfault. These values must point to valid Wasmtime
237+
/// compiled code which respects the frame pointers that Wasmtime currently
238+
/// requires.
239+
pub unsafe fn visit_frames<R>(
240+
unwind: &dyn Unwind,
241+
pc: usize,
242+
fp: usize,
243+
trampoline_fp: usize,
244+
mut f: impl FnMut(Frame) -> ControlFlow<R>,
245+
) -> ControlFlow<R> {
246+
let iter = unsafe { frame_iterator(unwind, pc, fp, trampoline_fp) };
247+
for frame in iter {
248+
f(frame)?;
215249
}
216250

217-
log::trace!("=== Done tracing contiguous sequence of Wasm frames ===");
218251
ControlFlow::Continue(())
219252
}

0 commit comments

Comments
 (0)