Try to return an error from call_protected when an exception occurs.

Something breaks pretty drastically sometimes, not sure why.
This commit is contained in:
Lachlan Sneff
2019-03-02 19:08:15 -08:00
parent caf2205936
commit 9cfda6800f
5 changed files with 98 additions and 30 deletions

View File

@@ -141,6 +141,7 @@ extern "C" {
}
[[noreturn]] void throw_trap(WasmTrap::Type ty) {
std::cout << "throwing trap: " << ty << std::endl;
throw WasmTrap(ty);
}
@@ -148,13 +149,30 @@ extern "C" {
delete module;
}
void invoke_trampoline(trampoline_t trampoline, void* ctx, void* func, void* params, void* results) {
bool invoke_trampoline(
trampoline_t trampoline,
void* ctx,
void* func,
void* params,
void* results,
WasmTrap::Type* trap_out
) throw() {
try {
trampoline(ctx, func, params, results);
std::cout << "Success" << std::endl;
return true;
} catch(const WasmTrap& e) {
std::cout << e.description() << std::endl;
*trap_out = e.type;
return false;
} catch(const WasmException& e) {
std::cout << e.description() << std::endl;
*trap_out = WasmTrap::Type::Unknown;
return false;
} catch (...) {
std::cout << "unknown exception" << std::endl;
std::cout << "unknown" << std::endl;
*trap_out = WasmTrap::Type::Unknown;
return false;
}
}

View File

@@ -17,11 +17,14 @@ use std::{
};
use wasmer_runtime_core::{
backend::{FuncResolver, ProtectedCaller, Token, UserTrapper},
error::RuntimeResult,
error::{RuntimeError, RuntimeResult},
export::Context,
module::{ModuleInfo, ModuleInner},
structures::TypedIndex,
types::{FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, SigIndex, Type, Value},
types::{
FuncIndex, FuncSig, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex, TableIndex, Type,
Value,
},
vm::{self, ImportBacking},
vmcalls,
};
@@ -52,6 +55,14 @@ enum LLVMResult {
OBJECT_LOAD_FAILURE,
}
#[repr(C)]
enum WasmTrapType {
Unreachable = 0,
IncorrectCallIndirectSignature = 1,
MemoryOutOfBounds = 2,
Unknown,
}
#[repr(C)]
struct Callbacks {
alloc_memory: extern "C" fn(usize, MemProtect, &mut *mut u8, &mut usize) -> LLVMResult,
@@ -80,7 +91,8 @@ extern "C" {
func_ptr: *const vm::Func,
params: *const u64,
results: *mut u64,
);
trap_out: *mut WasmTrapType,
) -> bool;
}
fn get_callbacks() -> Callbacks {
@@ -358,17 +370,21 @@ impl ProtectedCaller for LLVMProtectedCaller {
mem::transmute(symbol)
};
let mut trap_out = WasmTrapType::Unknown;
// Here we go.
unsafe {
let success = unsafe {
invoke_trampoline(
trampoline,
vmctx_ptr,
func_ptr,
param_vec.as_ptr(),
return_vec.as_mut_ptr(),
);
}
&mut trap_out,
)
};
if success {
Ok(return_vec
.iter()
.zip(signature.returns().iter())
@@ -379,6 +395,25 @@ impl ProtectedCaller for LLVMProtectedCaller {
Type::F64 => Value::F64(f64::from_bits(x as u64)),
})
.collect())
} else {
Err(match trap_out {
WasmTrapType::Unreachable => RuntimeError::User {
msg: "unreachable".into(),
},
WasmTrapType::IncorrectCallIndirectSignature => {
RuntimeError::IndirectCallSignature {
table: TableIndex::new(0),
}
}
WasmTrapType::MemoryOutOfBounds => RuntimeError::OutOfBoundsAccess {
memory: MemoryIndex::new(0),
addr: None,
},
WasmTrapType::Unknown => RuntimeError::Unknown {
msg: "unknown error".into(),
},
})
}
}
fn get_early_trapper(&self) -> Box<dyn UserTrapper> {

View File

@@ -118,8 +118,6 @@ pub fn parse_function_bodies(
})?;
}
module.print_to_stderr();
generate_trampolines(info, &signatures, &module, &context, &builder, &intrinsics);
let pass_manager = PassManager::create_for_module();

View File

@@ -46,7 +46,7 @@ extern "C" {
pub unsafe fn install_signal_handler() {
let sa = SigAction::new(
SigHandler::SigAction(signal_trap_handler),
SaFlags::SA_ONSTACK,
SaFlags::SA_ONSTACK | SaFlags::SA_SIGINFO,
SigSet::empty(),
);
sigaction(SIGFPE, &sa).unwrap();

View File

@@ -4,14 +4,31 @@ use wabt::wat2wasm;
static WAT: &'static str = r#"
(module
(memory 1)
(type (;0;) (func (param i32) (result i32)))
(func (;0;) (type 0) (param i32) (result i32)
i32.const 0x20000
i32.load
)
(export "select_trap_l" (func 0))
)
(type (;0;) (func (result i32)))
(type (;1;) (func (param i32 i32)))
(type (;2;) (func (param i32) (result i32)))
(func (;0;) (type 0) (result i32)
memory.size
i32.const 65536
i32.mul)
(func (;1;) (type 1) (param i32 i32)
call 0
local.get 0
i32.sub
local.get 1
i32.store)
(func (;2;) (type 2) (param i32) (result i32)
call 0
local.get 0
i32.add
i32.load)
(func (;3;) (type 2) (param i32) (result i32)
local.get 0
memory.grow)
(memory (;0;) 1 2)
(export "store" (func 1))
(export "load" (func 2))
(export "memory.grow" (func 3)))
"#;
fn get_wasm() -> Vec<u8> {
@@ -28,9 +45,9 @@ fn main() -> Result<(), error::Error> {
println!("instantiating");
let instance = module.instantiate(&imports)?;
let foo = instance.dyn_func("select_trap_l")?;
let foo = instance.dyn_func("store")?;
let result = foo.call(&[Value::I32(0)]);
let result = foo.call(&[Value::I32(0), Value::I32(1)]);
println!("result: {:?}", result);