1
0
mirror of https://github.com/fluencelabs/wasmer synced 2025-03-17 16:50:48 +00:00

Turns out we can just throw an exception from the signal handler

without any fancy tricks.

This has been tested on macos, hopefully it works on linux too.
This commit is contained in:
Lachlan Sneff 2019-03-03 02:15:53 -08:00
parent 9cfda6800f
commit e362b56b07

@ -61,81 +61,11 @@ extern "C" fn signal_trap_handler(
ucontext: *mut c_void, ucontext: *mut c_void,
) { ) {
unsafe { unsafe {
/// By setting the instruction pointer of the interrupted context /// Apparently, we can unwind from arbitary instructions, as long
/// to `throw_trap` and the register of the first argument /// as we don't need to catch the exception inside the function that
/// to the trap ID, we can approximate throwing an exception /// was interrupted.
/// from a signal handler. ///
set_context_to_throw(ucontext); /// This works on macos, not sure about linux.
throw_trap(2);
} }
} }
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
unsafe fn set_context_to_throw(ucontext: *mut c_void) {
use libc::{ucontext_t, RDI, RIP};
let ucontext = ucontext as *mut ucontext_t;
(*ucontext).uc_mcontext.gregs[RIP as usize] = throw_trap as u64;
(*ucontext).uc_mcontext.gregs[RDI as usize] = 2; // `MemoryOutOfBounds` variant.
}
#[cfg(all(target_os = "macos", target_arch = "x86_64"))]
unsafe fn set_context_to_throw(ucontext: *mut c_void) {
#[allow(dead_code)]
#[repr(C)]
struct ucontext_t {
uc_onstack: u32,
uc_sigmask: u32,
uc_stack: libc::stack_t,
uc_link: *const ucontext_t,
uc_mcsize: u64,
uc_mcontext: *mut mcontext_t,
}
#[repr(C)]
struct exception_state {
trapno: u16,
cpu: u16,
err: u32,
faultvaddr: u64,
}
#[repr(C)]
struct regs {
rax: u64,
rbx: u64,
rcx: u64,
rdx: u64,
rdi: u64,
rsi: u64,
rbp: u64,
rsp: u64,
r8: u64,
r9: u64,
r10: u64,
r11: u64,
r12: u64,
r13: u64,
r14: u64,
r15: u64,
rip: u64,
rflags: u64,
cs: u64,
fs: u64,
gs: u64,
}
#[allow(dead_code)]
#[repr(C)]
struct mcontext_t {
es: exception_state,
ss: regs,
// ...
}
let ucontext = ucontext as *mut ucontext_t;
(*(*ucontext).uc_mcontext).ss.rip = throw_trap as u64;
(*(*ucontext).uc_mcontext).ss.rdi = 2; // `MemoryOutOfBounds` variant.
}
#[cfg(not(any(
all(target_os = "macos", target_arch = "x86_64"),
all(target_os = "linux", target_arch = "x86_64"),
)))]
compile_error!("This crate doesn't yet support compiling on operating systems other than linux and macos and architectures other than x86_64");