Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/unwinder/src/throw.rs
1692 views
1
//! Throw action computation (handler search).
2
//!
3
//! In order to throw exceptions from within Cranelift-compiled code,
4
//! we provide a runtime function helper meant to be called by host
5
//! code that is invoked by guest code.
6
//!
7
//! The helper below must be provided a delimited range on the stack
8
//! corresponding to Cranelift frames above the current host code. It
9
//! will look for any handlers in this code, given a closure that
10
//! knows how to use an absolute PC to look up a module's exception
11
//! table and its start-of-code-segment. If a handler is found, the
12
//! helper below will return the SP, FP and PC that must be
13
//! restored. Architecture-specific helpers are provided to jump to
14
//! this new context with payload values. Otherwise, if no handler is
15
//! found, the return type indicates this, and it is the caller's
16
//! responsibility to invoke alternative behavior (e.g., abort the
17
//! program or unwind all the way to initial Cranelift-code entry).
18
19
use crate::{Frame, Unwind};
20
use core::ops::ControlFlow;
21
22
/// Description of a frame on the stack that is ready to catch an exception.
23
#[derive(Debug)]
24
pub struct Handler {
25
/// Program counter of handler return point.
26
pub pc: usize,
27
/// Stack pointer to restore before jumping to handler.
28
pub sp: usize,
29
/// Frame pointer to restore before jumping to handler.
30
pub fp: usize,
31
}
32
33
impl Handler {
34
/// Implementation of stack-walking to find a handler.
35
///
36
/// This function searches for a handler in the given range of stack
37
/// frames, starting from the throw stub and up to a specified entry
38
/// frame.
39
///
40
/// # Safety
41
///
42
/// The safety of this function is the same as [`crate::visit_frames`] where the
43
/// values passed in configuring the frame pointer walk must be correct and
44
/// Wasm-defined for this to not have UB.
45
pub unsafe fn find<F: Fn(&Frame) -> Option<(usize, usize)>>(
46
unwind: &dyn Unwind,
47
frame_handler: F,
48
exit_pc: usize,
49
exit_trampoline_frame: usize,
50
entry_frame: usize,
51
) -> Option<Handler> {
52
// SAFETY: the safety of `visit_frames` relies on the correctness of the
53
// parameters passed in which is forwarded as a contract to this function
54
// tiself.
55
let result = unsafe {
56
crate::stackwalk::visit_frames(
57
unwind,
58
exit_pc,
59
exit_trampoline_frame,
60
entry_frame,
61
|frame| {
62
log::trace!("visit_frame: frame {frame:?}");
63
if let Some((handler_pc, handler_sp)) = frame_handler(&frame) {
64
return ControlFlow::Break(Handler {
65
pc: handler_pc,
66
sp: handler_sp,
67
fp: frame.fp(),
68
});
69
}
70
ControlFlow::Continue(())
71
},
72
)
73
};
74
match result {
75
ControlFlow::Break(handler) => Some(handler),
76
ControlFlow::Continue(()) => None,
77
}
78
}
79
}
80
81