reorganize signal module and leave stubs in windows (#162)

This commit is contained in:
Mackenzie Clark 2019-02-07 17:08:42 -08:00 committed by GitHub
parent 9719781eee
commit 46ac4e9e1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 90 additions and 78 deletions

View File

@ -1,31 +0,0 @@
//! 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
use crate::call::recovery;
use nix::libc::{c_void, siginfo_t};
use nix::sys::signal::{
sigaction, SaFlags, SigAction, SigHandler, SigSet, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
};
pub unsafe fn install_sighandler() {
let sa = SigAction::new(
SigHandler::SigAction(signal_trap_handler),
SaFlags::SA_ONSTACK,
SigSet::empty(),
);
sigaction(SIGFPE, &sa).unwrap();
sigaction(SIGILL, &sa).unwrap();
sigaction(SIGSEGV, &sa).unwrap();
sigaction(SIGBUS, &sa).unwrap();
}
extern "C" fn signal_trap_handler(
signum: ::nix::libc::c_int,
siginfo: *mut siginfo_t,
ucontext: *mut c_void,
) {
unsafe {
recovery::do_unwind(signum, siginfo as _, ucontext);
}
}

View File

@ -1,12 +1,12 @@
#[cfg(feature = "cache")]
mod cache;
mod call;
mod func_env;
mod libcalls;
mod module;
mod module_env;
mod relocation;
mod resolver;
mod signal;
mod trampoline;
use cranelift_codegen::{

View File

@ -1,6 +1,6 @@
#[cfg(feature = "cache")]
use crate::cache::BackendCache;
use crate::{call::Caller, resolver::FuncResolverBuilder, trampoline::Trampolines};
use crate::{resolver::FuncResolverBuilder, signal::Caller, trampoline::Trampolines};
use cranelift_codegen::{ir, isa};
use cranelift_entity::EntityRef;

View File

@ -4,12 +4,12 @@ use crate::{
trampoline::Trampolines,
};
use crate::{
call::HandlerData,
libcalls,
relocation::{
ExternalRelocation, LibCall, LocalRelocation, LocalTrapSink, Reloc, RelocSink,
RelocationType, TrapSink, VmCall, VmCallKind,
},
signal::HandlerData,
};
use byteorder::{ByteOrder, LittleEndian};

View File

@ -1,11 +1,7 @@
mod recovery;
mod sighandler;
pub use self::recovery::{call_protected, HandlerData};
use crate::relocation::{TrapData, TrapSink};
use crate::trampoline::Trampolines;
use hashbrown::HashSet;
use libc::c_void;
use std::sync::Arc;
use wasmer_runtime_core::{
backend::{ProtectedCaller, Token},
@ -16,6 +12,18 @@ use wasmer_runtime_core::{
vm::{self, ImportBacking},
};
#[cfg(unix)]
mod unix;
#[cfg(windows)]
mod windows;
#[cfg(unix)]
pub use self::unix::*;
#[cfg(windows)]
pub use self::windows::*;
pub struct Caller {
func_export_set: HashSet<FuncIndex>,
handler_data: HandlerData,
@ -146,3 +154,38 @@ fn get_func_from_index(
(func_ptr, ctx, signature, sig_index)
}
unsafe impl Send for HandlerData {}
unsafe impl Sync for HandlerData {}
pub struct HandlerData {
pub trap_data: TrapSink,
exec_buffer_ptr: *const c_void,
exec_buffer_size: usize,
}
impl HandlerData {
pub fn new(
trap_data: TrapSink,
exec_buffer_ptr: *const c_void,
exec_buffer_size: usize,
) -> Self {
Self {
trap_data,
exec_buffer_ptr,
exec_buffer_size,
}
}
pub fn lookup(&self, ip: *const c_void) -> Option<TrapData> {
let ip = ip as usize;
let buffer_ptr = self.exec_buffer_ptr as usize;
if buffer_ptr <= ip && ip < buffer_ptr + self.exec_buffer_size {
let offset = ip - buffer_ptr;
self.trap_data.lookup(offset)
} else {
None
}
}
}

View File

@ -1,13 +1,20 @@
//! 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 crate::call::sighandler::install_sighandler;
//!
use crate::relocation::{TrapCode, TrapData, TrapSink};
use crate::signal::HandlerData;
use libc::{c_int, c_void, siginfo_t};
use nix::sys::signal::{Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV};
use nix::sys::signal::{
sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
};
use std::cell::{Cell, UnsafeCell};
use std::ptr;
use std::sync::Once;
@ -17,11 +24,33 @@ use wasmer_runtime_core::{
types::{MemoryIndex, TableIndex},
};
extern "C" fn signal_trap_handler(
signum: ::nix::libc::c_int,
siginfo: *mut siginfo_t,
ucontext: *mut c_void,
) {
unsafe {
do_unwind(signum, siginfo as _, ucontext);
}
}
extern "C" {
pub fn setjmp(env: *mut c_void) -> c_int;
fn longjmp(env: *mut c_void, val: c_int) -> !;
}
pub unsafe fn install_sighandler() {
let sa = SigAction::new(
SigHandler::SigAction(signal_trap_handler),
SaFlags::SA_ONSTACK,
SigSet::empty(),
);
sigaction(SIGFPE, &sa).unwrap();
sigaction(SIGILL, &sa).unwrap();
sigaction(SIGSEGV, &sa).unwrap();
sigaction(SIGBUS, &sa).unwrap();
}
const SETJMP_BUFFER_LEN: usize = 27;
pub static SIGHANDLER_INIT: Once = Once::new();
@ -31,41 +60,6 @@ thread_local! {
pub static CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null());
}
unsafe impl Send for HandlerData {}
unsafe impl Sync for HandlerData {}
pub struct HandlerData {
pub trap_data: TrapSink,
exec_buffer_ptr: *const c_void,
exec_buffer_size: usize,
}
impl HandlerData {
pub fn new(
trap_data: TrapSink,
exec_buffer_ptr: *const c_void,
exec_buffer_size: usize,
) -> Self {
Self {
trap_data,
exec_buffer_ptr,
exec_buffer_size,
}
}
pub fn lookup(&self, ip: *const c_void) -> Option<TrapData> {
let ip = ip as usize;
let buffer_ptr = self.exec_buffer_ptr as usize;
if buffer_ptr <= ip && ip < buffer_ptr + self.exec_buffer_size {
let offset = ip - buffer_ptr;
self.trap_data.lookup(offset)
} else {
None
}
}
}
pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> RuntimeResult<T> {
unsafe {
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());

View File

@ -0,0 +1,6 @@
use crate::signal::HandlerData;
use wasmer_runtime_core::error::RuntimeResult;
pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> RuntimeResult<T> {
unimplemented!("TODO");
}