Skip to content

Commit

Permalink
reorganize signal module and leave stubs in windows (#162)
Browse files Browse the repository at this point in the history
  • Loading branch information
xmclark authored Feb 8, 2019
1 parent 9719781 commit 46ac4e9
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 78 deletions.
31 changes: 0 additions & 31 deletions lib/clif-backend/src/call/sighandler.rs

This file was deleted.

2 changes: 1 addition & 1 deletion lib/clif-backend/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand Down
2 changes: 1 addition & 1 deletion lib/clif-backend/src/module.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
2 changes: 1 addition & 1 deletion lib/clif-backend/src/resolver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down
Original file line number Diff line number Diff line change
@@ -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},
Expand All @@ -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,
Expand Down Expand Up @@ -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
}
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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();

Expand All @@ -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());
Expand Down
6 changes: 6 additions & 0 deletions lib/clif-backend/src/signal/windows.rs
Original file line number Diff line number Diff line change
@@ -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");
}

0 comments on commit 46ac4e9

Please sign in to comment.