Skip to content

Commit

Permalink
Merge #1129
Browse files Browse the repository at this point in the history
1129: Standard exception types for singlepass backend. r=losfair a=losfair



Co-authored-by: losfair <[email protected]>
  • Loading branch information
bors[bot] and losfair authored Jan 20, 2020
2 parents 328d538 + 1b5d9f2 commit d73d837
Show file tree
Hide file tree
Showing 9 changed files with 491 additions and 522 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## **[Unreleased]**

- [#1129](https://github.com/wasmerio/wasmer/pull/1129) Standard exception types for singlepass backend.

## 0.13.1 - 2020-01-16
- Fix bug in wapm related to the `package.wasmer_extra_flags` entry in the manifest

Expand Down
30 changes: 30 additions & 0 deletions lib/runtime-core/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,32 @@ pub struct CompilerConfig {
pub backend_specific_config: Option<BackendCompilerConfig>,
}

/// An exception table for a `RunnableModule`.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct ExceptionTable {
/// Mappings from offsets in generated machine code to the corresponding exception code.
pub offset_to_code: HashMap<usize, ExceptionCode>,
}

impl ExceptionTable {
pub fn new() -> Self {
Self::default()
}
}

/// The code of an exception.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
pub enum ExceptionCode {
/// An `unreachable` opcode was executed.
Unreachable,

/// An arithmetic exception, e.g. divided by zero.
Arithmetic,

/// Memory access exception, e.g. misaligned/out-of-bound read/write.
Memory,
}

pub trait Compiler {
/// Compiles a `Module` from WebAssembly binary format.
/// The `CompileToken` parameter ensures that this can only
Expand Down Expand Up @@ -153,6 +179,10 @@ pub trait RunnableModule: Send + Sync {
None
}

fn get_exception_table(&self) -> Option<&ExceptionTable> {
None
}

unsafe fn patch_local_function(&self, _idx: usize, _target_address: usize) -> bool {
false
}
Expand Down
3 changes: 3 additions & 0 deletions lib/runtime-core/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! The error module contains the data structures and helper functions used to implement errors that
//! are produced and returned from the wasmer runtime core.
use crate::backend::ExceptionCode;
use crate::types::{FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor, Type};
use core::borrow::Borrow;
use std::any::Any;
Expand Down Expand Up @@ -208,6 +209,8 @@ impl std::fmt::Display for RuntimeError {
write!(f, "\"{}\"", s)
} else if let Some(s) = data.downcast_ref::<&str>() {
write!(f, "\"{}\"", s)
} else if let Some(exc_code) = data.downcast_ref::<ExceptionCode>() {
write!(f, "Caught exception of type \"{:?}\".", exc_code)
} else {
write!(f, "unknown error")
}
Expand Down
29 changes: 28 additions & 1 deletion lib/runtime-core/src/fault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,23 +375,50 @@ extern "C" fn signal_trap_handler(
_ => {}
}

// Now we have looked up all possible handler tables but failed to find a handler
// for this exception that allows a normal return.
//
// So here we check whether this exception is caused by a suspend signal, return the
// state image if so, or throw the exception out otherwise.

let ctx: &mut vm::Ctx = &mut **CURRENT_CTX.with(|x| x.get());
let es_image = fault
.read_stack(None)
.expect("fault.read_stack() failed. Broken invariants?");

if is_suspend_signal {
// If this is a suspend signal, we parse the runtime state and return the resulting image.
let image = build_instance_image(ctx, es_image);
unwind_result = Box::new(image);
} else {
// Otherwise, this is a real exception and we just throw it to the caller.
if es_image.frames.len() > 0 {
eprintln!(
"\n{}",
"Wasmer encountered an error while running your WebAssembly program."
);
es_image.print_backtrace_if_needed();
}
// Just let the error propagate otherwise

// Look up the exception tables and try to find an exception code.
let exc_code = CURRENT_CODE_VERSIONS.with(|versions| {
let versions = versions.borrow();
for v in versions.iter() {
if let Some(table) = v.runnable_module.get_exception_table() {
let ip = fault.ip.get();
let end = v.base + v.msm.total_size;
if ip >= v.base && ip < end {
if let Some(exc_code) = table.offset_to_code.get(&(ip - v.base)) {
return Some(*exc_code);
}
}
}
}
None
});
if let Some(code) = exc_code {
unwind_result = Box::new(code);
}
}

true
Expand Down
8 changes: 7 additions & 1 deletion lib/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
#[macro_use]
extern crate serde_derive;

pub use wasmer_runtime_core::backend::Features;
pub use wasmer_runtime_core::backend::{ExceptionCode, Features};
pub use wasmer_runtime_core::codegen::{MiddlewareChain, StreamingCompiler};
pub use wasmer_runtime_core::export::Export;
pub use wasmer_runtime_core::global::Global;
Expand All @@ -111,6 +111,12 @@ pub use wasmer_runtime_core::Func;
pub use wasmer_runtime_core::{compile_with, validate};
pub use wasmer_runtime_core::{func, imports};

#[cfg(unix)]
pub use wasmer_runtime_core::{
fault::{pop_code_version, push_code_version},
state::CodeVersion,
};

pub mod memory {
//! The memory module contains the implementation data structures and helper functions used to
//! manipulate and access wasm memory.
Expand Down
Loading

0 comments on commit d73d837

Please sign in to comment.