Skip to content

Commit

Permalink
Merge #1192
Browse files Browse the repository at this point in the history
1192: Use `ExceptionCode` for error representation. r=losfair a=losfair

Extends #1129 to all backends.

Co-authored-by: losfair <[email protected]>
  • Loading branch information
bors[bot] and losfair authored Feb 10, 2020
2 parents 4a63e09 + b40edd4 commit ab059ff
Show file tree
Hide file tree
Showing 18 changed files with 167 additions and 248 deletions.
15 changes: 4 additions & 11 deletions lib/clif-backend/src/signal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use std::{any::Any, cell::Cell, ptr::NonNull, sync::Arc};
use wasmer_runtime_core::{
backend::RunnableModule,
module::ModuleInfo,
typed_func::{Trampoline, Wasm, WasmTrapInfo},
typed_func::{Trampoline, Wasm},
types::{LocalFuncIndex, SigIndex},
vm,
};
Expand All @@ -29,10 +29,7 @@ thread_local! {
pub static TRAP_EARLY_DATA: Cell<Option<Box<dyn Any + Send>>> = Cell::new(None);
}

pub enum CallProtError {
Trap(WasmTrapInfo),
Error(Box<dyn Any + Send>),
}
pub struct CallProtError(pub Box<dyn Any + Send>);

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

match res {
Err(err) => {
match err {
CallProtError::Trap(info) => *trap_info = info,
CallProtError::Error(data) => *user_error = Some(data),
}
*error_out = Some(err.0);
false
}
Ok(()) => true,
Expand Down
30 changes: 17 additions & 13 deletions lib/clif-backend/src/signal/unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use nix::sys::signal::{
use std::cell::{Cell, UnsafeCell};
use std::ptr;
use std::sync::Once;
use wasmer_runtime_core::typed_func::WasmTrapInfo;
use wasmer_runtime_core::backend::ExceptionCode;

extern "C" fn signal_trap_handler(
signum: ::nix::libc::c_int,
Expand Down Expand Up @@ -79,7 +79,7 @@ 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::Error(data))
Err(CallProtError(data))
} else {
let (faulting_addr, inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get());

Expand All @@ -88,21 +88,25 @@ pub fn call_protected<T>(
srcloc: _,
}) = handler_data.lookup(inst_ptr)
{
Err(CallProtError::Trap(match Signal::from_c_int(signum) {
Err(CallProtError(Box::new(match Signal::from_c_int(signum) {
Ok(SIGILL) => match trapcode {
TrapCode::BadSignature => WasmTrapInfo::IncorrectCallIndirectSignature,
TrapCode::IndirectCallToNull => WasmTrapInfo::CallIndirectOOB,
TrapCode::HeapOutOfBounds => WasmTrapInfo::MemoryOutOfBounds,
TrapCode::TableOutOfBounds => WasmTrapInfo::CallIndirectOOB,
_ => WasmTrapInfo::Unknown,
TrapCode::BadSignature => ExceptionCode::IncorrectCallIndirectSignature,
TrapCode::IndirectCallToNull => ExceptionCode::CallIndirectOOB,
TrapCode::HeapOutOfBounds => ExceptionCode::MemoryOutOfBounds,
TrapCode::TableOutOfBounds => ExceptionCode::CallIndirectOOB,
_ => {
return Err(CallProtError(Box::new(
"unknown clif trap code".to_string(),
)))
}
},
Ok(SIGSEGV) | Ok(SIGBUS) => WasmTrapInfo::MemoryOutOfBounds,
Ok(SIGFPE) => WasmTrapInfo::IllegalArithmetic,
Ok(SIGSEGV) | Ok(SIGBUS) => ExceptionCode::MemoryOutOfBounds,
Ok(SIGFPE) => ExceptionCode::IllegalArithmetic,
_ => unimplemented!(
"WasmTrapInfo::Unknown signal:{:?}",
"ExceptionCode::Unknown signal:{:?}",
Signal::from_c_int(signum)
),
}))
})))
} else {
let signal = match Signal::from_c_int(signum) {
Ok(SIGFPE) => "floating-point exception",
Expand All @@ -114,7 +118,7 @@ pub fn call_protected<T>(
};
// When the trap-handler is fully implemented, this will return more information.
let s = format!("unknown trap at {:p} - {}", faulting_addr, signal);
Err(CallProtError::Error(Box::new(s)))
Err(CallProtError(Box::new(s)))
}
}
} else {
Expand Down
33 changes: 19 additions & 14 deletions lib/clif-backend/src/signal/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use std::{
ptr::{self, NonNull},
};
use wasmer_runtime_core::{
typed_func::{Trampoline, WasmTrapInfo},
backend::ExceptionCode,
typed_func::Trampoline,
vm::{Ctx, Func},
};
use wasmer_win_exception_handler::CallProtectedData;
Expand Down Expand Up @@ -62,22 +63,26 @@ pub fn call_protected(
srcloc: _,
}) = handler_data.lookup(instruction_pointer as _)
{
Err(CallProtError::Trap(match code as DWORD {
EXCEPTION_ACCESS_VIOLATION => WasmTrapInfo::MemoryOutOfBounds,
Err(CallProtError(Box::new(match code as DWORD {
EXCEPTION_ACCESS_VIOLATION => ExceptionCode::MemoryOutOfBounds,
EXCEPTION_ILLEGAL_INSTRUCTION => match trapcode {
TrapCode::BadSignature => WasmTrapInfo::IncorrectCallIndirectSignature,
TrapCode::IndirectCallToNull => WasmTrapInfo::CallIndirectOOB,
TrapCode::HeapOutOfBounds => WasmTrapInfo::MemoryOutOfBounds,
TrapCode::TableOutOfBounds => WasmTrapInfo::CallIndirectOOB,
TrapCode::UnreachableCodeReached => WasmTrapInfo::Unreachable,
_ => WasmTrapInfo::Unknown,
TrapCode::BadSignature => ExceptionCode::IncorrectCallIndirectSignature,
TrapCode::IndirectCallToNull => ExceptionCode::CallIndirectOOB,
TrapCode::HeapOutOfBounds => ExceptionCode::MemoryOutOfBounds,
TrapCode::TableOutOfBounds => ExceptionCode::CallIndirectOOB,
TrapCode::UnreachableCodeReached => ExceptionCode::Unreachable,
_ => return Err(CallProtError(Box::new("unknown trap code".to_string()))),
},
EXCEPTION_STACK_OVERFLOW => WasmTrapInfo::Unknown,
EXCEPTION_STACK_OVERFLOW => ExceptionCode::MemoryOutOfBounds,
EXCEPTION_INT_DIVIDE_BY_ZERO | EXCEPTION_INT_OVERFLOW => {
WasmTrapInfo::IllegalArithmetic
ExceptionCode::IllegalArithmetic
}
_ => WasmTrapInfo::Unknown,
}))
_ => {
return Err(CallProtError(Box::new(
"unknown exception code".to_string(),
)))
}
})))
} else {
let signal = match code as DWORD {
EXCEPTION_FLT_DENORMAL_OPERAND
Expand Down Expand Up @@ -110,7 +115,7 @@ pub fn call_protected(
exception_address, code, signal,
);

Err(CallProtError::Error(Box::new(s)))
Err(CallProtError(Box::new(s)))
}
}

Expand Down
5 changes: 2 additions & 3 deletions lib/llvm-backend/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ use wasmer_runtime_core::{
module::ModuleInfo,
state::ModuleStateMap,
structures::TypedIndex,
typed_func::{Trampoline, Wasm, WasmTrapInfo},
typed_func::{Trampoline, Wasm},
types::{LocalFuncIndex, SigIndex},
vm, vmcalls,
};
Expand Down Expand Up @@ -65,8 +65,7 @@ extern "C" {
func_ptr: NonNull<vm::Func>,
params: *const u64,
results: *mut u64,
trap_out: *mut WasmTrapInfo,
user_error: *mut Option<Box<dyn Any + Send>>,
error_out: *mut Option<Box<dyn Any + Send>>,
invoke_env: Option<NonNull<c_void>>,
) -> bool;
}
Expand Down
10 changes: 4 additions & 6 deletions lib/middleware-common-tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,12 +165,10 @@ mod tests {
}

let err = result.unwrap_err();
match err {
RuntimeError::Error { data } => {
assert!(data.downcast_ref::<ExecutionLimitExceededError>().is_some());
}
_ => unreachable!(),
}
assert!(err
.0
.downcast_ref::<ExecutionLimitExceededError>()
.is_some());

// verify it used the correct number of points
assert_eq!(get_points_used(&instance), 109); // Used points will be slightly more than `limit` because of the way we do gas checking.
Expand Down
27 changes: 6 additions & 21 deletions lib/runtime-core-tests/tests/imports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,7 @@ macro_rules! call_and_assert {
expected_value,
concat!("Expected right when calling `", stringify!($function), "`.")
),
(
Err(RuntimeError::Error { data }),
Err(RuntimeError::Error {
data: expected_data,
}),
) => {
(Err(RuntimeError(data)), Err(RuntimeError(expected_data))) => {
if let (Some(data), Some(expected_data)) = (
data.downcast_ref::<&str>(),
expected_data.downcast_ref::<&str>(),
Expand Down Expand Up @@ -260,35 +255,25 @@ test!(
test!(
test_fn_trap,
function_fn_trap,
Err(RuntimeError::Error {
data: Box::new(format!("foo {}", 2))
})
Err(RuntimeError(Box::new(format!("foo {}", 2))))
);
test!(
test_closure_trap,
function_closure_trap,
Err(RuntimeError::Error {
data: Box::new(format!("bar {}", 2))
})
Err(RuntimeError(Box::new(format!("bar {}", 2))))
);
test!(
test_fn_trap_with_vmctx,
function_fn_trap_with_vmctx,
Err(RuntimeError::Error {
data: Box::new(format!("baz {}", 2 + SHIFT))
})
Err(RuntimeError(Box::new(format!("baz {}", 2 + SHIFT))))
);
test!(
test_closure_trap_with_vmctx,
function_closure_trap_with_vmctx,
Err(RuntimeError::Error {
data: Box::new(format!("qux {}", 2 + SHIFT))
})
Err(RuntimeError(Box::new(format!("qux {}", 2 + SHIFT))))
);
test!(
test_closure_trap_with_vmctx_and_env,
function_closure_trap_with_vmctx_and_env,
Err(RuntimeError::Error {
data: Box::new(format!("! {}", 2 + shift + SHIFT))
})
Err(RuntimeError(Box::new(format!("! {}", 2 + shift + SHIFT))))
);
34 changes: 29 additions & 5 deletions lib/runtime-core/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::{
module::ModuleInfo,
sys::Memory,
};
use std::fmt;
use std::{any::Any, ptr::NonNull};

use std::collections::HashMap;
Expand Down Expand Up @@ -158,13 +159,36 @@ impl ExceptionTable {
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
pub enum ExceptionCode {
/// An `unreachable` opcode was executed.
Unreachable,

Unreachable = 0,
/// Call indirect incorrect signature trap.
IncorrectCallIndirectSignature = 1,
/// Memory out of bounds trap.
MemoryOutOfBounds = 2,
/// Call indirect out of bounds trap.
CallIndirectOOB = 3,
/// An arithmetic exception, e.g. divided by zero.
Arithmetic,
IllegalArithmetic = 4,
/// Misaligned atomic access trap.
MisalignedAtomicAccess = 5,
}

/// Memory access exception, e.g. misaligned/out-of-bound read/write.
Memory,
impl fmt::Display for ExceptionCode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"{}",
match self {
ExceptionCode::Unreachable => "unreachable",
ExceptionCode::IncorrectCallIndirectSignature => {
"incorrect `call_indirect` signature"
}
ExceptionCode::MemoryOutOfBounds => "memory out-of-bounds access",
ExceptionCode::CallIndirectOOB => "`call_indirect` out-of-bounds",
ExceptionCode::IllegalArithmetic => "illegal arithmetic operation",
ExceptionCode::MisalignedAtomicAccess => "misaligned atomic access",
}
)
}
}

pub trait Compiler {
Expand Down
37 changes: 10 additions & 27 deletions lib/runtime-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,18 +179,7 @@ impl std::error::Error for LinkError {}
/// The main way to do this is `Instance.call`.
///
/// Comparing two `RuntimeError`s always evaluates to false.
pub enum RuntimeError {
/// Trap.
Trap {
/// Trap message.
msg: Box<str>,
},
/// Error.
Error {
/// Error data.
data: Box<dyn Any + Send>,
},
}
pub struct RuntimeError(pub Box<dyn Any + Send>);

impl PartialEq for RuntimeError {
fn eq(&self, _other: &RuntimeError) -> bool {
Expand All @@ -200,21 +189,15 @@ impl PartialEq for RuntimeError {

impl std::fmt::Display for RuntimeError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
RuntimeError::Trap { ref msg } => {
write!(f, "WebAssembly trap occurred during runtime: {}", msg)
}
RuntimeError::Error { data } => {
if let Some(s) = data.downcast_ref::<String>() {
write!(f, "\"{}\"", s)
} else if let Some(s) = data.downcast_ref::<&str>() {
write!(f, "\"{}\"", s)
} else if let Some(exc_code) = data.downcast_ref::<ExceptionCode>() {
write!(f, "Caught exception of type \"{:?}\".", exc_code)
} else {
write!(f, "unknown error")
}
}
let data = &*self.0;
if let Some(s) = data.downcast_ref::<String>() {
write!(f, "\"{}\"", s)
} else if let Some(s) = data.downcast_ref::<&str>() {
write!(f, "\"{}\"", s)
} else if let Some(exc_code) = data.downcast_ref::<ExceptionCode>() {
write!(f, "Caught exception of type \"{:?}\".", exc_code)
} else {
write!(f, "unknown error")
}
}
}
Expand Down
Loading

0 comments on commit ab059ff

Please sign in to comment.