//! Installing signal handlers allows us to handle traps and out-of-bounds memory //! accesses that occur when runniing WebAssembly. //! //! This code is inspired by: https://github.com/pepyakin/wasmtime/commit/625a2b6c0815b21996e111da51b9664feb174622 //! //! When a WebAssembly module triggers any traps, we perform recovery here. //! //! This module uses TLS (thread-local storage) to track recovery information. Since the four signals we're handling //! are very special, the async signal unsafety of Rust's TLS implementation generally does not affect the correctness here //! unless you have memory unsafety elsewhere in your code. //! use std::any::Any; use std::cell::{Cell, RefCell}; use std::collections::HashMap; use std::sync::Arc; use wasmer_runtime_core::alternative_stack::{ begin_unsafe_unwind, catch_unsafe_unwind, ensure_sighandler, }; use wasmer_runtime_core::codegen::BkptInfo; use wasmer_runtime_core::typed_func::WasmTrapInfo; thread_local! { pub static TRAP_EARLY_DATA: Cell>> = Cell::new(None); pub static BKPT_MAP: RefCell>>>> = RefCell::new(Vec::new()); } pub unsafe fn trigger_trap() -> ! { begin_unsafe_unwind(Box::new(())); } pub enum CallProtError { Trap(WasmTrapInfo), Error(Box), } pub fn call_protected(f: impl FnOnce() -> T) -> Result { ensure_sighandler(); unsafe { let ret = catch_unsafe_unwind(|| f()); match ret { Ok(x) => Ok(x), Err(_) => { if let Some(data) = TRAP_EARLY_DATA.with(|cell| cell.replace(None)) { Err(CallProtError::Error(data)) } else { Err(CallProtError::Trap(WasmTrapInfo::Unknown)) } } } } } pub unsafe fn throw(payload: Box) -> ! { begin_unsafe_unwind(payload); }