mirror of
https://github.com/fluencelabs/wasmer
synced 2025-04-02 07:51:03 +00:00
reorganize signal module and leave stubs in windows (#162)
This commit is contained in:
parent
9719781eee
commit
46ac4e9e1a
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +1,12 @@
|
|||||||
#[cfg(feature = "cache")]
|
#[cfg(feature = "cache")]
|
||||||
mod cache;
|
mod cache;
|
||||||
mod call;
|
|
||||||
mod func_env;
|
mod func_env;
|
||||||
mod libcalls;
|
mod libcalls;
|
||||||
mod module;
|
mod module;
|
||||||
mod module_env;
|
mod module_env;
|
||||||
mod relocation;
|
mod relocation;
|
||||||
mod resolver;
|
mod resolver;
|
||||||
|
mod signal;
|
||||||
mod trampoline;
|
mod trampoline;
|
||||||
|
|
||||||
use cranelift_codegen::{
|
use cranelift_codegen::{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#[cfg(feature = "cache")]
|
#[cfg(feature = "cache")]
|
||||||
use crate::cache::BackendCache;
|
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_codegen::{ir, isa};
|
||||||
use cranelift_entity::EntityRef;
|
use cranelift_entity::EntityRef;
|
||||||
|
@ -4,12 +4,12 @@ use crate::{
|
|||||||
trampoline::Trampolines,
|
trampoline::Trampolines,
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
call::HandlerData,
|
|
||||||
libcalls,
|
libcalls,
|
||||||
relocation::{
|
relocation::{
|
||||||
ExternalRelocation, LibCall, LocalRelocation, LocalTrapSink, Reloc, RelocSink,
|
ExternalRelocation, LibCall, LocalRelocation, LocalTrapSink, Reloc, RelocSink,
|
||||||
RelocationType, TrapSink, VmCall, VmCallKind,
|
RelocationType, TrapSink, VmCall, VmCallKind,
|
||||||
},
|
},
|
||||||
|
signal::HandlerData,
|
||||||
};
|
};
|
||||||
|
|
||||||
use byteorder::{ByteOrder, LittleEndian};
|
use byteorder::{ByteOrder, LittleEndian};
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
mod recovery;
|
use crate::relocation::{TrapData, TrapSink};
|
||||||
mod sighandler;
|
|
||||||
|
|
||||||
pub use self::recovery::{call_protected, HandlerData};
|
|
||||||
|
|
||||||
use crate::trampoline::Trampolines;
|
use crate::trampoline::Trampolines;
|
||||||
|
|
||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
|
use libc::c_void;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use wasmer_runtime_core::{
|
use wasmer_runtime_core::{
|
||||||
backend::{ProtectedCaller, Token},
|
backend::{ProtectedCaller, Token},
|
||||||
@ -16,6 +12,18 @@ use wasmer_runtime_core::{
|
|||||||
vm::{self, ImportBacking},
|
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 {
|
pub struct Caller {
|
||||||
func_export_set: HashSet<FuncIndex>,
|
func_export_set: HashSet<FuncIndex>,
|
||||||
handler_data: HandlerData,
|
handler_data: HandlerData,
|
||||||
@ -146,3 +154,38 @@ fn get_func_from_index(
|
|||||||
|
|
||||||
(func_ptr, ctx, signature, sig_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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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.
|
//! 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
|
//! 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
|
//! 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.
|
//! unless you have memory unsafety elsewhere in your code.
|
||||||
|
//!
|
||||||
use crate::call::sighandler::install_sighandler;
|
|
||||||
use crate::relocation::{TrapCode, TrapData, TrapSink};
|
use crate::relocation::{TrapCode, TrapData, TrapSink};
|
||||||
|
use crate::signal::HandlerData;
|
||||||
use libc::{c_int, c_void, siginfo_t};
|
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::cell::{Cell, UnsafeCell};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::Once;
|
use std::sync::Once;
|
||||||
@ -17,11 +24,33 @@ use wasmer_runtime_core::{
|
|||||||
types::{MemoryIndex, TableIndex},
|
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" {
|
extern "C" {
|
||||||
pub fn setjmp(env: *mut c_void) -> c_int;
|
pub fn setjmp(env: *mut c_void) -> c_int;
|
||||||
fn longjmp(env: *mut c_void, val: 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;
|
const SETJMP_BUFFER_LEN: usize = 27;
|
||||||
pub static SIGHANDLER_INIT: Once = Once::new();
|
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());
|
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> {
|
pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> RuntimeResult<T> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
6
lib/clif-backend/src/signal/windows.rs
Normal file
6
lib/clif-backend/src/signal/windows.rs
Normal 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");
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user