mirror of
https://github.com/fluencelabs/wasmer
synced 2025-06-24 14:11:32 +00:00
Make runtime and trap errors well defined (WIP)
This commit is contained in:
@ -1,12 +1,13 @@
|
||||
use crate::{
|
||||
relocation::{TrapData, TrapSink},
|
||||
relocation::{TrapData, TrapSink, TrapCode},
|
||||
resolver::FuncResolver,
|
||||
trampoline::Trampolines,
|
||||
};
|
||||
use libc::c_void;
|
||||
use std::{any::Any, cell::Cell, ptr::NonNull, sync::Arc};
|
||||
use wasmer_runtime_core::{
|
||||
backend::RunnableModule,
|
||||
backend::{RunnableModule, ExceptionCode},
|
||||
error::{InvokeError, RuntimeError},
|
||||
module::ModuleInfo,
|
||||
typed_func::{Trampoline, Wasm},
|
||||
types::{LocalFuncIndex, SigIndex},
|
||||
@ -26,10 +27,25 @@ 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 enum CallProtError {
|
||||
UnknownTrap {
|
||||
address: usize,
|
||||
signal: &'static str,
|
||||
},
|
||||
TrapCode {
|
||||
code: ExceptionCode,
|
||||
srcloc: u32,
|
||||
},
|
||||
UnknownTrapCode {
|
||||
trap_code: TrapCode,
|
||||
srcloc: u32,
|
||||
},
|
||||
EarlyTrap(RuntimeError),
|
||||
Misc(Box<dyn Any + Send>),
|
||||
}
|
||||
|
||||
pub struct Caller {
|
||||
handler_data: HandlerData,
|
||||
@ -63,7 +79,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();
|
||||
@ -80,6 +96,9 @@ impl RunnableModule for Caller {
|
||||
|
||||
match res {
|
||||
Err(err) => {
|
||||
// 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.0);
|
||||
false
|
||||
}
|
||||
@ -101,7 +120,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()
|
||||
}
|
||||
|
@ -79,16 +79,16 @@ 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(CallProtError::EarlyTrap(data))
|
||||
} else {
|
||||
let (faulting_addr, inst_ptr) = CAUGHT_ADDRESSES.with(|cell| cell.get());
|
||||
|
||||
if let Some(TrapData {
|
||||
trapcode,
|
||||
srcloc: _,
|
||||
srcloc,
|
||||
}) = handler_data.lookup(inst_ptr)
|
||||
{
|
||||
Err(CallProtError(Box::new(match Signal::from_c_int(signum) {
|
||||
let code = match Signal::from_c_int(signum) {
|
||||
Ok(SIGILL) => match trapcode {
|
||||
TrapCode::StackOverflow => ExceptionCode::MemoryOutOfBounds,
|
||||
TrapCode::HeapOutOfBounds => ExceptionCode::MemoryOutOfBounds,
|
||||
@ -101,9 +101,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(CallProtError::UnknownTrapCode {
|
||||
trap_code: trapcode,
|
||||
srcloc,
|
||||
})
|
||||
}
|
||||
},
|
||||
Ok(SIGSEGV) | Ok(SIGBUS) => ExceptionCode::MemoryOutOfBounds,
|
||||
@ -112,7 +113,11 @@ pub fn call_protected<T>(
|
||||
"ExceptionCode::Unknown signal:{:?}",
|
||||
Signal::from_c_int(signum)
|
||||
),
|
||||
})))
|
||||
};
|
||||
Err(CallProtError::TrapCode {
|
||||
srcloc,
|
||||
code,
|
||||
})
|
||||
} else {
|
||||
let signal = match Signal::from_c_int(signum) {
|
||||
Ok(SIGFPE) => "floating-point exception",
|
||||
@ -123,8 +128,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(CallProtError::UnknownTrap {
|
||||
address: faulting_addr as usize,
|
||||
signal,
|
||||
})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user