Add error types and convert most results to wasmer-runtime results

This commit is contained in:
Lachlan Sneff
2019-01-18 09:17:44 -08:00
parent f5ab605878
commit d23601a810
11 changed files with 303 additions and 80 deletions

View File

@ -11,7 +11,11 @@ use cranelift_codegen::{
settings::{self, Configurable},
};
use target_lexicon::Triple;
use wasmer_runtime::{backend::Compiler, module::ModuleInner};
use wasmer_runtime::{
backend::Compiler,
error::{CompileError, CompileResult},
module::ModuleInner,
};
use wasmparser::{self, WasmDecoder};
pub struct CraneliftCompiler {}
@ -24,7 +28,7 @@ impl CraneliftCompiler {
impl Compiler for CraneliftCompiler {
// Compiles wasm binary to a wasmer module.
fn compile(&self, wasm: &[u8]) -> Result<ModuleInner, String> {
fn compile(&self, wasm: &[u8]) -> CompileResult<ModuleInner> {
validate(wasm)?;
let isa = get_isa();
@ -53,15 +57,15 @@ fn get_isa() -> Box<isa::TargetIsa> {
isa::lookup(Triple::host()).unwrap().finish(flags)
}
fn validate(bytes: &[u8]) -> Result<(), String> {
fn validate(bytes: &[u8]) -> CompileResult<()> {
let mut parser = wasmparser::ValidatingParser::new(bytes, None);
loop {
let state = parser.read();
match *state {
wasmparser::ParserState::EndWasm => break Ok(()),
wasmparser::ParserState::Error(err) => {
return Err(format!("Validation error: {}", err.message));
}
wasmparser::ParserState::Error(err) => Err(CompileError::ValidationError {
msg: err.message.to_string(),
})?,
_ => {}
}
}

View File

@ -10,6 +10,7 @@ use std::{
use wasmer_runtime::{
backend::FuncResolver,
backend::SigRegistry,
error::CompileResult,
module::ModuleInner,
structures::{Map, TypedIndex},
types::{
@ -67,7 +68,7 @@ impl Module {
mut self,
isa: &isa::TargetIsa,
functions: Map<LocalFuncIndex, ir::Function>,
) -> Result<ModuleInner, String> {
) -> CompileResult<ModuleInner> {
// we have to deduplicate `module.func_assoc`
let func_assoc = &mut self.module.func_assoc;
let sig_registry = &self.module.sig_registry;

View File

@ -5,6 +5,7 @@ use crate::{
use cranelift_codegen::{ir, isa};
use cranelift_wasm::{self, translate_module, FuncTranslator, ModuleEnvironment};
use wasmer_runtime::{
error::{CompileError, CompileResult},
module::{DataInitializer, ExportIndex, ImportName, TableInitializer},
structures::{Map, TypedIndex},
types::{
@ -32,8 +33,9 @@ impl<'module, 'isa> ModuleEnv<'module, 'isa> {
}
}
pub fn translate(mut self, wasm: &[u8]) -> Result<Map<LocalFuncIndex, ir::Function>, String> {
translate_module(wasm, &mut self).map_err(|e| e.to_string())?;
pub fn translate(mut self, wasm: &[u8]) -> CompileResult<Map<LocalFuncIndex, ir::Function>> {
translate_module(wasm, &mut self)
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
Ok(self.func_bodies)
}
}

View File

@ -7,6 +7,7 @@ use std::ptr::{write_unaligned, NonNull};
use wasmer_runtime::{
self,
backend::{self, Mmap, Protect},
error::{CompileError, CompileResult},
structures::Map,
types::LocalFuncIndex,
vm, vmcalls,
@ -23,7 +24,7 @@ impl FuncResolverBuilder {
pub fn new(
isa: &isa::TargetIsa,
function_bodies: Map<LocalFuncIndex, ir::Function>,
) -> Result<Self, String> {
) -> CompileResult<Self> {
let mut compiled_functions: Vec<Vec<u8>> = Vec::with_capacity(function_bodies.len());
let mut relocations = Map::with_capacity(function_bodies.len());
let mut trap_sinks = Map::with_capacity(function_bodies.len());
@ -38,7 +39,7 @@ impl FuncResolverBuilder {
let mut trap_sink = TrapSink::new();
ctx.compile_and_emit(isa, &mut code_buf, &mut reloc_sink, &mut trap_sink)
.map_err(|e| format!("compile error: {}", e.to_string()))?;
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
ctx.clear();
// Round up each function's size to pointer alignment.
total_size += round_up(code_buf.len(), mem::size_of::<usize>());
@ -48,11 +49,24 @@ impl FuncResolverBuilder {
trap_sinks.push(trap_sink);
}
let mut memory = Mmap::with_size(total_size)?;
let mut memory = Mmap::with_size(total_size)
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
unsafe {
memory.protect(0..memory.size(), Protect::ReadWrite)?;
memory
.protect(0..memory.size(), Protect::ReadWrite)
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;
}
// Normally, excess memory due to alignment and page-rounding would
// be filled with null-bytes. On x86 (and x86_64),
// "\x00\x00" disassembles to "add byte ptr [eax],al".
//
// If the instruction pointer falls out of its designated area,
// it would be better if it would immediately crash instead of
// continuing on and causing non-local issues.
//
// "\xCC" disassembles to "int3", which will immediately cause
// an interrupt that we can catch if we want.
for i in unsafe { memory.as_slice_mut() } {
*i = 0xCC;
}
@ -77,7 +91,7 @@ impl FuncResolverBuilder {
})
}
pub fn finalize(mut self) -> Result<FuncResolver, String> {
pub fn finalize(mut self) -> CompileResult<FuncResolver> {
for (index, relocs) in self.relocations.iter() {
for ref reloc in relocs {
let target_func_address: isize = match reloc.target {
@ -98,11 +112,17 @@ impl FuncResolverBuilder {
ir::LibCall::NearestF64 => libcalls::nearbyintf64 as isize,
ir::LibCall::Probestack => libcalls::__rust_probestack as isize,
_ => {
panic!("unexpected libcall {}", libcall);
Err(CompileError::InternalError {
msg: format!("unexpected libcall: {}", libcall),
})?
// panic!("unexpected libcall {}", libcall);
}
},
RelocationType::Intrinsic(ref name) => {
panic!("unexpected intrinsic {}", name);
Err(CompileError::InternalError {
msg: format!("unexpected intrinsic: {}", name),
})?
// panic!("unexpected intrinsic {}", name);
}
RelocationType::VmCall(vmcall) => match vmcall {
VmCall::LocalStaticMemoryGrow => vmcalls::local_static_memory_grow as _,
@ -141,7 +161,9 @@ impl FuncResolverBuilder {
(target_func_address - reloc_address + reloc_addend) as i32;
write_unaligned(reloc_address as *mut i32, reloc_delta_i32);
},
_ => panic!("unsupported reloc kind"),
_ => Err(CompileError::InternalError {
msg: format!("unsupported reloc kind: {}", reloc.reloc),
})?,
}
}
}
@ -149,7 +171,8 @@ impl FuncResolverBuilder {
unsafe {
self.resolver
.memory
.protect(0..self.resolver.memory.size(), Protect::ReadExec)?;
.protect(0..self.resolver.memory.size(), Protect::ReadExec)
.map_err(|e| CompileError::InternalError { msg: e.to_string() })?;;
}
Ok(self.resolver)