wasmer/lib/clif-backend/src/signal/windows.rs

115 lines
4.5 KiB
Rust
Raw Normal View History

use crate::relocation::{TrapCode, TrapData};
use crate::signal::{CallProtError, HandlerData};
use crate::trampoline::Trampoline;
use std::cell::Cell;
use std::ffi::c_void;
2019-04-09 23:46:01 +00:00
use std::ptr::{self, NonNull};
2019-04-22 22:06:40 +00:00
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;
pub use wasmer_win_exception_handler::_call_protected;
use winapi::shared::minwindef::DWORD;
use winapi::um::minwinbase::{
EXCEPTION_ACCESS_VIOLATION, EXCEPTION_ARRAY_BOUNDS_EXCEEDED, EXCEPTION_BREAKPOINT,
EXCEPTION_DATATYPE_MISALIGNMENT, EXCEPTION_FLT_DENORMAL_OPERAND, EXCEPTION_FLT_DIVIDE_BY_ZERO,
EXCEPTION_FLT_INEXACT_RESULT, EXCEPTION_FLT_INVALID_OPERATION, EXCEPTION_FLT_OVERFLOW,
EXCEPTION_FLT_STACK_CHECK, EXCEPTION_FLT_UNDERFLOW, EXCEPTION_GUARD_PAGE,
EXCEPTION_ILLEGAL_INSTRUCTION, EXCEPTION_INT_DIVIDE_BY_ZERO, EXCEPTION_INT_OVERFLOW,
EXCEPTION_INVALID_HANDLE, EXCEPTION_IN_PAGE_ERROR, EXCEPTION_NONCONTINUABLE_EXCEPTION,
EXCEPTION_POSSIBLE_DEADLOCK, EXCEPTION_PRIV_INSTRUCTION, EXCEPTION_SINGLE_STEP,
EXCEPTION_STACK_OVERFLOW,
};
thread_local! {
pub static CURRENT_EXECUTABLE_BUFFER: Cell<*const c_void> = Cell::new(ptr::null());
}
pub fn call_protected(
handler_data: &HandlerData,
trampoline: Trampoline,
ctx: *mut Ctx,
2019-04-09 23:46:01 +00:00
func: NonNull<Func>,
param_vec: *const u64,
return_vec: *mut u64,
) -> Result<(), CallProtError> {
// TODO: trap early
// user code error
// if let Some(msg) = super::TRAP_EARLY_DATA.with(|cell| cell.replace(None)) {
// return Err(RuntimeError::User { msg });
// }
let result = _call_protected(trampoline, ctx, func, param_vec, return_vec);
if let Ok(_) = result {
return Ok(());
}
let CallProtectedData {
code,
2019-03-15 21:10:17 +00:00
exception_address,
instruction_pointer,
} = result.unwrap_err();
if let Some(TrapData {
trapcode,
srcloc: _,
}) = handler_data.lookup(instruction_pointer as _)
{
Err(CallProtError::Trap(match code as DWORD {
2019-04-22 22:06:40 +00:00
EXCEPTION_ACCESS_VIOLATION => WasmTrapInfo::MemoryOutOfBounds,
EXCEPTION_ILLEGAL_INSTRUCTION => match trapcode {
2019-04-22 22:06:40 +00:00
TrapCode::BadSignature => WasmTrapInfo::IncorrectCallIndirectSignature,
TrapCode::IndirectCallToNull => WasmTrapInfo::CallIndirectOOB,
TrapCode::HeapOutOfBounds => WasmTrapInfo::MemoryOutOfBounds,
TrapCode::TableOutOfBounds => WasmTrapInfo::CallIndirectOOB,
TrapCode::UnreachableCodeReached => WasmTrapInfo::Unreachable,
_ => WasmTrapInfo::Unknown,
},
2019-04-22 22:06:40 +00:00
EXCEPTION_STACK_OVERFLOW => WasmTrapInfo::Unknown,
EXCEPTION_INT_DIVIDE_BY_ZERO | EXCEPTION_INT_OVERFLOW => {
WasmTrapInfo::IllegalArithmetic
}
_ => WasmTrapInfo::Unknown,
}))
} else {
let signal = match code as DWORD {
EXCEPTION_FLT_DENORMAL_OPERAND
| EXCEPTION_FLT_DIVIDE_BY_ZERO
| EXCEPTION_FLT_INEXACT_RESULT
| EXCEPTION_FLT_INVALID_OPERATION
| EXCEPTION_FLT_OVERFLOW
| EXCEPTION_FLT_STACK_CHECK
| EXCEPTION_FLT_UNDERFLOW => "floating-point exception",
EXCEPTION_ILLEGAL_INSTRUCTION => "illegal instruction",
EXCEPTION_ACCESS_VIOLATION => "segmentation violation",
EXCEPTION_DATATYPE_MISALIGNMENT => "datatype misalignment",
EXCEPTION_BREAKPOINT => "breakpoint",
EXCEPTION_SINGLE_STEP => "single step",
EXCEPTION_ARRAY_BOUNDS_EXCEEDED => "array bounds exceeded",
EXCEPTION_INT_DIVIDE_BY_ZERO => "int div by zero",
EXCEPTION_INT_OVERFLOW => "int overflow",
EXCEPTION_PRIV_INSTRUCTION => "priv instruction",
EXCEPTION_IN_PAGE_ERROR => "in page error",
EXCEPTION_NONCONTINUABLE_EXCEPTION => "non continuable exception",
EXCEPTION_STACK_OVERFLOW => "stack overflow",
EXCEPTION_GUARD_PAGE => "guard page",
EXCEPTION_INVALID_HANDLE => "invalid handle",
EXCEPTION_POSSIBLE_DEADLOCK => "possible deadlock",
_ => "unknown exception code",
};
let s = format!(
"unhandled trap at {:x} - code #{:x}: {}",
exception_address, code, signal,
);
2019-04-22 22:06:40 +00:00
Err(CallProtError::Error(Box::new(s)))
}
}
pub unsafe fn trigger_trap() -> ! {
// TODO
unimplemented!();
}