mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-25 14:41:32 +00:00
Hook up error propagation
This commit is contained in:
@ -27,6 +27,11 @@ thread_local! {
|
||||
pub static TRAP_EARLY_DATA: Cell<Option<Box<dyn Any>>> = Cell::new(None);
|
||||
}
|
||||
|
||||
pub enum RunErr {
|
||||
Trap(WasmTrapInfo),
|
||||
Error(Box<dyn Any>),
|
||||
}
|
||||
|
||||
pub struct Caller {
|
||||
handler_data: HandlerData,
|
||||
trampolines: Arc<Trampolines>,
|
||||
@ -59,7 +64,8 @@ impl RunnableModule for Caller {
|
||||
func: NonNull<vm::Func>,
|
||||
args: *const u64,
|
||||
rets: *mut u64,
|
||||
_trap_info: *mut WasmTrapInfo,
|
||||
trap_info: *mut WasmTrapInfo,
|
||||
user_error: *mut Option<Box<dyn Any>>,
|
||||
invoke_env: Option<NonNull<c_void>>,
|
||||
) -> bool {
|
||||
let handler_data = &*invoke_env.unwrap().cast().as_ptr();
|
||||
@ -68,14 +74,22 @@ impl RunnableModule for Caller {
|
||||
let res = call_protected(handler_data, || {
|
||||
// Leap of faith.
|
||||
trampoline(ctx, func, args, rets);
|
||||
})
|
||||
.is_ok();
|
||||
});
|
||||
|
||||
// the trampoline is called from C on windows
|
||||
#[cfg(target_os = "windows")]
|
||||
let res = call_protected(handler_data, trampoline, ctx, func, args, rets).is_ok();
|
||||
let res = call_protected(handler_data, trampoline, ctx, func, args, rets);
|
||||
|
||||
res
|
||||
match res {
|
||||
Err(err) => {
|
||||
match err {
|
||||
RunErr::Trap(info) => *trap_info = info,
|
||||
RunErr::Error(data) => *user_error = Some(data),
|
||||
}
|
||||
false
|
||||
}
|
||||
Ok(()) => true,
|
||||
}
|
||||
}
|
||||
|
||||
let trampoline = self
|
||||
|
@ -10,7 +10,7 @@
|
||||
//! unless you have memory unsafety elsewhere in your code.
|
||||
//!
|
||||
use crate::relocation::{TrapCode, TrapData};
|
||||
use crate::signal::HandlerData;
|
||||
use crate::signal::{HandlerData, RunErr};
|
||||
use libc::{c_int, c_void, siginfo_t};
|
||||
use nix::sys::signal::{
|
||||
sigaction, SaFlags, SigAction, SigHandler, SigSet, Signal, SIGBUS, SIGFPE, SIGILL, SIGSEGV,
|
||||
@ -18,7 +18,7 @@ use nix::sys::signal::{
|
||||
use std::cell::{Cell, UnsafeCell};
|
||||
use std::ptr;
|
||||
use std::sync::Once;
|
||||
use wasmer_runtime_core::error::{RuntimeError, RuntimeResult};
|
||||
use wasmer_runtime_core::typed_func::WasmTrapInfo;
|
||||
|
||||
extern "C" fn signal_trap_handler(
|
||||
signum: ::nix::libc::c_int,
|
||||
@ -62,7 +62,7 @@ pub unsafe fn trigger_trap() -> ! {
|
||||
longjmp(jmp_buf as *mut c_void, 0)
|
||||
}
|
||||
|
||||
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) -> Result<T, RunErr> {
|
||||
unsafe {
|
||||
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
|
||||
let prev_jmp_buf = *jmp_buf;
|
||||
@ -76,7 +76,7 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
|
||||
*jmp_buf = prev_jmp_buf;
|
||||
|
||||
if let Some(data) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
|
||||
Err(RuntimeError::Error { data })
|
||||
Err(RunErr::Error(data))
|
||||
} else {
|
||||
let (faulting_addr, inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get());
|
||||
|
||||
@ -85,33 +85,18 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
|
||||
srcloc: _,
|
||||
}) = handler_data.lookup(inst_ptr)
|
||||
{
|
||||
Err(match Signal::from_c_int(signum) {
|
||||
Err(RunErr::Trap(match Signal::from_c_int(signum) {
|
||||
Ok(SIGILL) => match trapcode {
|
||||
TrapCode::BadSignature => RuntimeError::Trap {
|
||||
msg: "incorrect call_indirect signature".into(),
|
||||
},
|
||||
TrapCode::IndirectCallToNull => RuntimeError::Trap {
|
||||
msg: "indirect call to null".into(),
|
||||
},
|
||||
TrapCode::HeapOutOfBounds => RuntimeError::Trap {
|
||||
msg: "memory out-of-bounds access".into(),
|
||||
},
|
||||
TrapCode::TableOutOfBounds => RuntimeError::Trap {
|
||||
msg: "table out-of-bounds access".into(),
|
||||
},
|
||||
_ => RuntimeError::Trap {
|
||||
msg: "unknown trap".into(),
|
||||
},
|
||||
},
|
||||
Ok(SIGSEGV) | Ok(SIGBUS) => RuntimeError::Trap {
|
||||
msg: "memory out-of-bounds access".into(),
|
||||
},
|
||||
Ok(SIGFPE) => RuntimeError::Trap {
|
||||
msg: "illegal arithmetic operation".into(),
|
||||
TrapCode::BadSignature => WasmTrapInfo::IncorrectCallIndirectSignature,
|
||||
TrapCode::IndirectCallToNull => WasmTrapInfo::CallIndirectOOB,
|
||||
TrapCode::HeapOutOfBounds => WasmTrapInfo::MemoryOutOfBounds,
|
||||
TrapCode::TableOutOfBounds => WasmTrapInfo::CallIndirectOOB,
|
||||
_ => WasmTrapInfo::Unknown,
|
||||
},
|
||||
Ok(SIGSEGV) | Ok(SIGBUS) => WasmTrapInfo::MemoryOutOfBounds,
|
||||
Ok(SIGFPE) => WasmTrapInfo::IllegalArithmetic,
|
||||
_ => unimplemented!(),
|
||||
}
|
||||
.into())
|
||||
}))
|
||||
} else {
|
||||
let signal = match Signal::from_c_int(signum) {
|
||||
Ok(SIGFPE) => "floating-point exception",
|
||||
@ -122,10 +107,8 @@ pub fn call_protected<T>(handler_data: &HandlerData, f: impl FnOnce() -> T) -> R
|
||||
_ => "unkown trapped signal",
|
||||
};
|
||||
// When the trap-handler is fully implemented, this will return more information.
|
||||
Err(RuntimeError::Trap {
|
||||
msg: format!("unknown trap at {:p} - {}", faulting_addr, signal).into(),
|
||||
}
|
||||
.into())
|
||||
let s = format!("unknown trap at {:p} - {}", faulting_addr, signal);
|
||||
Err(RunErr::Error(Box::new(s)))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1,10 +1,11 @@
|
||||
use crate::relocation::{TrapCode, TrapData};
|
||||
use crate::signal::HandlerData;
|
||||
use crate::signal::{HandlerData, RunErr};
|
||||
use crate::trampoline::Trampoline;
|
||||
use std::cell::Cell;
|
||||
use std::ffi::c_void;
|
||||
use std::ptr::{self, NonNull};
|
||||
use wasmer_runtime_core::error::{RuntimeError, RuntimeResult};
|
||||
use wasmer_runtime_core::typed_func::WasmTrapInfo;
|
||||
use wasmer_runtime_core::vm::Ctx;
|
||||
use wasmer_runtime_core::vm::Func;
|
||||
use wasmer_win_exception_handler::CallProtectedData;
|
||||
@ -28,7 +29,7 @@ pub fn call_protected(
|
||||
func: NonNull<Func>,
|
||||
param_vec: *const u64,
|
||||
return_vec: *mut u64,
|
||||
) -> RuntimeResult<()> {
|
||||
) -> Result<(), RunErr> {
|
||||
// TODO: trap early
|
||||
// user code error
|
||||
// if let Some(msg) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
|
||||
@ -52,38 +53,22 @@ pub fn call_protected(
|
||||
srcloc: _,
|
||||
}) = handler_data.lookup(instruction_pointer as _)
|
||||
{
|
||||
Err(match signum as DWORD {
|
||||
EXCEPTION_ACCESS_VIOLATION => RuntimeError::Trap {
|
||||
msg: "memory out-of-bounds access".into(),
|
||||
},
|
||||
Err(RunErr::Trap(match signum as DWORD {
|
||||
EXCEPTION_ACCESS_VIOLATION => WasmTrapInfo::MemoryOutOfBounds,
|
||||
EXCEPTION_ILLEGAL_INSTRUCTION => match trapcode {
|
||||
TrapCode::BadSignature => RuntimeError::Trap {
|
||||
msg: "incorrect call_indirect signature".into(),
|
||||
},
|
||||
TrapCode::IndirectCallToNull => RuntimeError::Trap {
|
||||
msg: "indirect call to null".into(),
|
||||
},
|
||||
TrapCode::HeapOutOfBounds => RuntimeError::Trap {
|
||||
msg: "memory out-of-bounds access".into(),
|
||||
},
|
||||
TrapCode::TableOutOfBounds => RuntimeError::Trap {
|
||||
msg: "table out-of-bounds access".into(),
|
||||
},
|
||||
_ => RuntimeError::Trap {
|
||||
msg: "unknown trap".into(),
|
||||
},
|
||||
TrapCode::BadSignature => WasmTrapInfo::IncorrectCallIndirectSignature,
|
||||
TrapCode::IndirectCallToNull => WasmTrapInfo::CallIndirectOOB,
|
||||
TrapCode::HeapOutOfBounds => WasmTrapInfo::MemoryOutOfBounds,
|
||||
TrapCode::TableOutOfBounds => WasmTrapInfo::CallIndirectOOB,
|
||||
TrapCode::UnreachableCodeReached => WasmTrapInfo::Unreachable,
|
||||
_ => WasmTrapInfo::Unknown,
|
||||
},
|
||||
EXCEPTION_STACK_OVERFLOW => RuntimeError::Trap {
|
||||
msg: "stack overflow trap".into(),
|
||||
},
|
||||
EXCEPTION_INT_DIVIDE_BY_ZERO | EXCEPTION_INT_OVERFLOW => RuntimeError::Trap {
|
||||
msg: "illegal arithmetic operation".into(),
|
||||
},
|
||||
_ => RuntimeError::Trap {
|
||||
msg: "unknown trap".into(),
|
||||
},
|
||||
}
|
||||
.into())
|
||||
EXCEPTION_STACK_OVERFLOW => WasmTrapInfo::Unknown,
|
||||
EXCEPTION_INT_DIVIDE_BY_ZERO | EXCEPTION_INT_OVERFLOW => {
|
||||
WasmTrapInfo::IllegalArithmetic
|
||||
}
|
||||
_ => WasmTrapInfo::Unknown,
|
||||
}))
|
||||
} else {
|
||||
let signal = match signum as DWORD {
|
||||
EXCEPTION_FLT_DENORMAL_OPERAND
|
||||
@ -98,10 +83,9 @@ pub fn call_protected(
|
||||
_ => "unkown trapped signal",
|
||||
};
|
||||
|
||||
Err(RuntimeError::Trap {
|
||||
msg: format!("unknown trap at {} - {}", exception_address, signal).into(),
|
||||
}
|
||||
.into())
|
||||
let s = format!("unknown trap at {} - {}", exception_address, signal);
|
||||
|
||||
Err(RunErr::Error(Box::new(s)))
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user