Skip to content

Commit

Permalink
Try #1401:
Browse files Browse the repository at this point in the history
  • Loading branch information
bors[bot] authored Apr 24, 2020
2 parents ab106af + 197f2f8 commit 880a5fa
Show file tree
Hide file tree
Showing 18 changed files with 245 additions and 109 deletions.
16 changes: 9 additions & 7 deletions lib/clif-backend/src/signal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use crate::{
trampoline::Trampolines,
};
use libc::c_void;
use std::{any::Any, cell::Cell, ptr::NonNull, sync::Arc};
use std::{cell::Cell, ptr::NonNull, sync::Arc};
use wasmer_runtime_core::{
backend::RunnableModule,
error::{InvokeError, RuntimeError},
module::ModuleInfo,
typed_func::{Trampoline, Wasm},
types::{LocalFuncIndex, SigIndex},
Expand All @@ -26,11 +27,9 @@ pub use self::unix::*;
pub use self::windows::*;

thread_local! {
pub static TRAP_EARLY_DATA: Cell<Option<Box<dyn Any + Send>>> = Cell::new(None);
pub static TRAP_EARLY_DATA: Cell<Option<RuntimeError>> = Cell::new(None);
}

pub struct CallProtError(pub Box<dyn Any + Send>);

pub struct Caller {
handler_data: HandlerData,
trampolines: Arc<Trampolines>,
Expand Down Expand Up @@ -63,7 +62,7 @@ impl RunnableModule for Caller {
func: NonNull<vm::Func>,
args: *const u64,
rets: *mut u64,
error_out: *mut Option<Box<dyn Any + Send>>,
error_out: *mut Option<InvokeError>,
invoke_env: Option<NonNull<c_void>>,
) -> bool {
let handler_data = &*invoke_env.unwrap().cast().as_ptr();
Expand All @@ -80,7 +79,10 @@ impl RunnableModule for Caller {

match res {
Err(err) => {
*error_out = Some(err.0);
// probably makes the most sense to actually do a translation here to a
// a generic type defined in runtime-core
// TODO: figure out _this_ error return story
*error_out = Some(err);
false
}
Ok(()) => true,
Expand All @@ -101,7 +103,7 @@ impl RunnableModule for Caller {
})
}

unsafe fn do_early_trap(&self, data: Box<dyn Any + Send>) -> ! {
unsafe fn do_early_trap(&self, data: RuntimeError) -> ! {
TRAP_EARLY_DATA.with(|cell| cell.set(Some(data)));
trigger_trap()
}
Expand Down
31 changes: 16 additions & 15 deletions lib/clif-backend/src/signal/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//! unless you have memory unsafety elsewhere in your code.
//!
use crate::relocation::{TrapCode, TrapData};
use crate::signal::{CallProtError, HandlerData};
use crate::signal::HandlerData;
use libc::{c_int, c_void, siginfo_t};
use nix::sys::signal::{
sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
Expand All @@ -19,6 +19,7 @@ use std::cell::{Cell, UnsafeCell};
use std::ptr;
use std::sync::Once;
use wasmer_runtime_core::backend::ExceptionCode;
use wasmer_runtime_core::error::InvokeError;

extern "C" fn signal_trap_handler(
signum: ::nix::libc::c_int,
Expand Down Expand Up @@ -65,7 +66,7 @@ pub unsafe fn trigger_trap() -> ! {
pub fn call_protected<T>(
handler_data: &HandlerData,
f: impl FnOnce() -> T,
) -> Result<T, CallProtError> {
) -> Result<T, InvokeError> {
unsafe {
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
let prev_jmp_buf = *jmp_buf;
Expand All @@ -79,16 +80,12 @@ pub fn call_protected<T>(
*jmp_buf = prev_jmp_buf;

if let Some(data) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
Err(CallProtError(data))
Err(InvokeError::EarlyTrap(Box::new(data)))
} else {
let (faulting_addr, inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get());

if let Some(TrapData {
trapcode,
srcloc: _,
}) = handler_data.lookup(inst_ptr)
{
Err(CallProtError(Box::new(match Signal::from_c_int(signum) {
if let Some(TrapData { trapcode, srcloc }) = handler_data.lookup(inst_ptr) {
let code = match Signal::from_c_int(signum) {
Ok(SIGILL) => match trapcode {
TrapCode::StackOverflow => ExceptionCode::MemoryOutOfBounds,
TrapCode::HeapOutOfBounds => ExceptionCode::MemoryOutOfBounds,
Expand All @@ -101,9 +98,10 @@ pub fn call_protected<T>(
TrapCode::BadConversionToInteger => ExceptionCode::IllegalArithmetic,
TrapCode::UnreachableCodeReached => ExceptionCode::Unreachable,
_ => {
return Err(CallProtError(Box::new(
"unknown clif trap code".to_string(),
)))
return Err(InvokeError::UnknownTrapCode {
trap_code: format!("{:?}", trapcode),
srcloc,
})
}
},
Ok(SIGSEGV) | Ok(SIGBUS) => ExceptionCode::MemoryOutOfBounds,
Expand All @@ -112,7 +110,8 @@ pub fn call_protected<T>(
"ExceptionCode::Unknown signal:{:?}",
Signal::from_c_int(signum)
),
})))
};
Err(InvokeError::TrapCode { srcloc, code })
} else {
let signal = match Signal::from_c_int(signum) {
Ok(SIGFPE) => "floating-point exception",
Expand All @@ -123,8 +122,10 @@ pub fn call_protected<T>(
_ => "unknown trapped signal",
};
// When the trap-handler is fully implemented, this will return more information.
let s = format!("unknown trap at {:p} - {}", faulting_addr, signal);
Err(CallProtError(Box::new(s)))
Err(InvokeError::UnknownTrap {
address: faulting_addr as usize,
signal,
})
}
}
} else {
Expand Down
20 changes: 10 additions & 10 deletions lib/llvm-backend/cpp/object_loader.hh
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ typedef struct {
} callbacks_t;

typedef struct {
size_t data, vtable;
} box_any_t;
size_t data;
} runtime_error_t;

enum WasmTrapType {
Unreachable = 0,
Expand Down Expand Up @@ -121,7 +121,7 @@ private:

struct WasmErrorSink {
WasmTrapType *trap_out;
box_any_t *user_error;
runtime_error_t *user_error;
};

struct WasmException : std::exception {
Expand Down Expand Up @@ -149,14 +149,14 @@ public:

struct UserException : UncatchableException {
public:
UserException(size_t data, size_t vtable) : error_data({data, vtable}) {}
UserException(size_t data) : error_data({data}) {}

virtual std::string description() const noexcept override {
return "user exception";
}

// The parts of a `Box<dyn Any>`.
box_any_t error_data;
// The pointer to `RuntimeError`.
runtime_error_t error_data;

virtual void write_error(WasmErrorSink &out) const noexcept override {
*out.user_error = error_data;
Expand Down Expand Up @@ -274,10 +274,10 @@ result_t module_load(const uint8_t *mem_ptr, size_t mem_size,

void module_delete(WasmModule *module) { delete module; }

// Throw a fat pointer that's assumed to be `*mut dyn Any` on the rust
// Throw a pointer that's assumed to be `*mut RuntimeError` on the rust
// side.
[[noreturn]] void throw_any(size_t data, size_t vtable) {
unsafe_unwind(new UserException(data, vtable));
[[noreturn]] void throw_runtime_error(size_t data) {
unsafe_unwind(new UserException(data));
}

// Throw a pointer that's assumed to be codegen::BreakpointHandler on the
Expand All @@ -288,7 +288,7 @@ void module_delete(WasmModule *module) { delete module; }

bool cxx_invoke_trampoline(trampoline_t trampoline, void *ctx, void *func,
void *params, void *results, WasmTrapType *trap_out,
box_any_t *user_error, void *invoke_env) noexcept {
runtime_error_t *user_error, void *invoke_env) noexcept {
try {
catch_unwind([trampoline, ctx, func, params, results]() {
trampoline(ctx, func, params, results);
Expand Down
38 changes: 23 additions & 15 deletions lib/llvm-backend/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ use inkwell::{
};
use libc::c_char;
use std::{
any::Any,
cell::RefCell,
ffi::{c_void, CString},
mem,
Expand All @@ -27,6 +26,7 @@ use wasmer_runtime_core::{
CacheGen, ExceptionCode, RunnableModule,
},
cache::Error as CacheError,
error::{InvokeError, RuntimeError},
module::ModuleInfo,
state::ModuleStateMap,
structures::TypedIndex,
Expand Down Expand Up @@ -56,7 +56,8 @@ extern "C" {
/// but this is cleaner, I think?
#[cfg_attr(nightly, unwind(allowed))]
#[allow(improper_ctypes)]
fn throw_any(data: *mut dyn Any) -> !;
// POINTER!!!!! TODOARINO
fn throw_runtime_error(data: *mut RuntimeError) -> !;

#[allow(improper_ctypes)]
fn cxx_invoke_trampoline(
Expand All @@ -66,7 +67,7 @@ extern "C" {
params: *const u64,
results: *mut u64,
trap_out: *mut i32,
error_out: *mut Option<Box<dyn Any + Send>>,
error_out: *mut Option<InvokeError>,
invoke_env: Option<NonNull<c_void>>,
) -> bool;
}
Expand All @@ -79,7 +80,7 @@ unsafe extern "C" fn invoke_trampoline(
func_ptr: NonNull<vm::Func>,
params: *const u64,
results: *mut u64,
error_out: *mut Option<Box<dyn Any + Send>>,
error_out: *mut Option<InvokeError>,
invoke_env: Option<NonNull<c_void>>,
) -> bool {
let mut trap_out: i32 = -1;
Expand All @@ -95,15 +96,22 @@ unsafe extern "C" fn invoke_trampoline(
);
// Translate trap code if an error occurred.
if !ret && (*error_out).is_none() && trap_out != -1 {
*error_out = Some(Box::new(match trap_out {
0 => ExceptionCode::Unreachable,
1 => ExceptionCode::IncorrectCallIndirectSignature,
2 => ExceptionCode::MemoryOutOfBounds,
3 => ExceptionCode::CallIndirectOOB,
4 => ExceptionCode::IllegalArithmetic,
5 => ExceptionCode::MisalignedAtomicAccess,
_ => return ret,
}));
*error_out = {
let exception_code = match trap_out {
0 => ExceptionCode::Unreachable,
1 => ExceptionCode::IncorrectCallIndirectSignature,
2 => ExceptionCode::MemoryOutOfBounds,
3 => ExceptionCode::CallIndirectOOB,
4 => ExceptionCode::IllegalArithmetic,
5 => ExceptionCode::MisalignedAtomicAccess,
_ => return ret,
};
Some(InvokeError::TrapCode {
code: exception_code,
// TODO:
srcloc: 0,
})
};
}
ret
}
Expand Down Expand Up @@ -467,8 +475,8 @@ impl RunnableModule for LLVMBackend {
self.msm.clone()
}

unsafe fn do_early_trap(&self, data: Box<dyn Any + Send>) -> ! {
throw_any(Box::leak(data))
unsafe fn do_early_trap(&self, data: RuntimeError) -> ! {
throw_runtime_error(Box::into_raw(Box::new(data)))
}
}

Expand Down
5 changes: 3 additions & 2 deletions lib/llvm-backend/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ use std::{
use wasmer_runtime_core::{
backend::{CacheGen, CompilerConfig, Token},
cache::{Artifact, Error as CacheError},
error::RuntimeError,
codegen::*,
memory::MemoryType,
module::{ModuleInfo, ModuleInner},
Expand Down Expand Up @@ -940,11 +941,11 @@ pub struct CodegenError {
// prevents unused function elimination.
#[no_mangle]
pub unsafe extern "C" fn callback_trampoline(
b: *mut Option<Box<dyn std::any::Any>>,
b: *mut Option<RuntimeError>,
callback: *mut BreakpointHandler,
) {
let callback = Box::from_raw(callback);
let result: Result<(), Box<dyn std::any::Any + Send>> =
let result: Result<(), RuntimeError> =
callback(BreakpointInfo { fault: None });
match result {
Ok(()) => *b = None,
Expand Down
3 changes: 2 additions & 1 deletion lib/middleware-common/src/metering.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use wasmer_runtime_core::{
codegen::{Event, EventSink, FunctionMiddleware, InternalEvent},
error::RuntimeError,
module::ModuleInfo,
vm::{Ctx, InternalField},
wasmparser::{Operator, Type as WpType, TypeOrFuncType as WpTypeOrFuncType},
Expand Down Expand Up @@ -96,7 +97,7 @@ impl FunctionMiddleware for Metering {
ty: WpTypeOrFuncType::Type(WpType::EmptyBlockType),
}));
sink.push(Event::Internal(InternalEvent::Breakpoint(Box::new(|_| {
Err(Box::new(ExecutionLimitExceededError))
Err(RuntimeError::Metering(Box::new(ExecutionLimitExceededError)))
}))));
sink.push(Event::WasmOwned(Operator::End));
}
Expand Down
4 changes: 2 additions & 2 deletions lib/runtime-core/src/backend.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
error::CompileResult,
error::{CompileResult, RuntimeError},
module::ModuleInner,
state::ModuleStateMap,
typed_func::Wasm,
Expand Down Expand Up @@ -282,7 +282,7 @@ pub trait RunnableModule: Send + Sync {
fn get_trampoline(&self, info: &ModuleInfo, sig_index: SigIndex) -> Option<Wasm>;

/// Trap an error.
unsafe fn do_early_trap(&self, data: Box<dyn Any + Send>) -> !;
unsafe fn do_early_trap(&self, data: RuntimeError) -> !;

/// Returns the machine code associated with this module.
fn get_code(&self) -> Option<&[u8]> {
Expand Down
5 changes: 2 additions & 3 deletions lib/runtime-core/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,12 @@ use crate::{
backend::RunnableModule,
backend::{CacheGen, Compiler, CompilerConfig, Features, Token},
cache::{Artifact, Error as CacheError},
error::{CompileError, CompileResult},
error::{CompileError, CompileResult, RuntimeError},
module::{ModuleInfo, ModuleInner},
structures::Map,
types::{FuncIndex, FuncSig, SigIndex},
};
use smallvec::SmallVec;
use std::any::Any;
use std::collections::HashMap;
use std::fmt;
use std::fmt::Debug;
Expand All @@ -23,7 +22,7 @@ use wasmparser::{Operator, Type as WpType};

/// A type that defines a function pointer, which is called when breakpoints occur.
pub type BreakpointHandler =
Box<dyn Fn(BreakpointInfo) -> Result<(), Box<dyn Any + Send>> + Send + Sync + 'static>;
Box<dyn Fn(BreakpointInfo) -> Result<(), RuntimeError> + Send + Sync + 'static>;

/// Maps instruction pointers to their breakpoint handlers.
pub type BreakpointMap = Arc<HashMap<usize, BreakpointHandler>>;
Expand Down
Loading

0 comments on commit 880a5fa

Please sign in to comment.