1 use crate::instance::{FaultDetails, TerminationDetails}; 2 use failure::Fail; 3 4 /// Lucet runtime errors. 5 #[derive(Debug, Fail)] 6 pub enum Error { 7 #[fail(display = "Invalid argument: {}", _0)] 8 InvalidArgument(&'static str), 9 10 /// A [`Region`](trait.Region.html) cannot currently accommodate additional instances. 11 #[fail(display = "Region capacity reached: {} instances", _0)] 12 RegionFull(usize), 13 14 /// A module error occurred. 15 #[fail(display = "Module error: {}", _0)] 16 ModuleError(ModuleError), 17 18 /// A method call or module specification would exceed an instance's 19 /// [`Limit`s](struct.Limits.html). 20 #[fail(display = "Instance limits exceeded: {}", _0)] 21 LimitsExceeded(String), 22 23 /// A method call attempted to modify linear memory for an instance that 24 /// does not have linear memory 25 #[fail(display = "No linear memory available: {}", _0)] 26 NoLinearMemory(String), 27 28 /// An attempt to look up a WebAssembly function by its symbol name failed. 29 #[fail(display = "Symbol not found: {}", _0)] 30 SymbolNotFound(String), 31 32 /// An attempt to look up a WebAssembly function by its table index failed. 33 #[fail(display = "Function not found: (table {}, func {})", _0, _1)] 34 FuncNotFound(u32, u32), 35 36 /// An instance aborted due to a runtime fault. 37 #[fail(display = "Runtime fault: {:?}", _0)] 38 RuntimeFault(FaultDetails), 39 40 /// An instance terminated, potentially with extra information about the termination. 41 /// 42 /// This condition can arise from a hostcall explicitly calling 43 /// [`Vmctx::terminate()`](vmctx/struct.Vmctx.html#method.terminate), or via a custom signal handler 44 /// that returns [`SignalBehavior::Terminate`](enum.SignalBehavior.html#variant.Terminate). 45 #[fail(display = "Runtime terminated")] 46 RuntimeTerminated(TerminationDetails), 47 48 /// IO errors arising during dynamic loading with [`DlModule`](struct.DlModule.html). 49 #[fail(display = "Dynamic loading error: {}", _0)] 50 DlError(#[cause] std::io::Error), 51 52 #[fail(display = "Instance not returned")] 53 InstanceNotReturned, 54 55 #[fail(display = "Instance not yielded")] 56 InstanceNotYielded, 57 58 #[fail(display = "Start function yielded")] 59 StartYielded, 60 61 /// A catch-all for internal errors that are likely unrecoverable by the runtime user. 62 /// 63 /// As the API matures, these will likely become rarer, replaced by new variants of this enum, 64 /// or by panics for truly unrecoverable situations. 65 #[fail(display = "Internal error: {}", _0)] 66 InternalError(#[cause] failure::Error), 67 68 /// An unsupported feature was used. 69 #[fail(display = "Unsupported feature: {}", _0)] 70 Unsupported(String), 71 } 72 73 impl From<failure::Error> for Error { from(e: failure::Error) -> Error74 fn from(e: failure::Error) -> Error { 75 Error::InternalError(e) 76 } 77 } 78 79 impl From<crate::context::Error> for Error { from(e: crate::context::Error) -> Error80 fn from(e: crate::context::Error) -> Error { 81 Error::InternalError(e.into()) 82 } 83 } 84 85 impl From<nix::Error> for Error { from(e: nix::Error) -> Error86 fn from(e: nix::Error) -> Error { 87 Error::InternalError(e.into()) 88 } 89 } 90 91 impl From<std::ffi::IntoStringError> for Error { from(e: std::ffi::IntoStringError) -> Error92 fn from(e: std::ffi::IntoStringError) -> Error { 93 Error::InternalError(e.into()) 94 } 95 } 96 97 impl From<lucet_module::Error> for Error { from(e: lucet_module::Error) -> Error98 fn from(e: lucet_module::Error) -> Error { 99 Error::ModuleError(ModuleError::ModuleDataError(e)) 100 } 101 } 102 103 /// Lucet module errors. 104 #[derive(Debug, Fail)] 105 pub enum ModuleError { 106 /// An error was found in the definition of a Lucet module. 107 #[fail(display = "Incorrect module definition: {}", _0)] 108 IncorrectModule(String), 109 110 /// An error occurred with the module data section, likely during deserialization. 111 #[fail(display = "Module data error: {}", _0)] 112 ModuleDataError(#[cause] lucet_module::Error), 113 } 114 115 #[macro_export] 116 macro_rules! lucet_bail { 117 ($e:expr) => { 118 return Err(lucet_format_err!($e)); 119 }; 120 ($fmt:expr, $($arg:tt)*) => { 121 return Err(lucet_format_err!($fmt, $($arg)*)); 122 }; 123 } 124 125 #[macro_export(local_inner_macros)] 126 macro_rules! lucet_ensure { 127 ($cond:expr, $e:expr) => { 128 if !($cond) { 129 lucet_bail!($e); 130 } 131 }; 132 ($cond:expr, $fmt:expr, $($arg:tt)*) => { 133 if !($cond) { 134 lucet_bail!($fmt, $($arg)*); 135 } 136 }; 137 } 138 139 #[macro_export] 140 macro_rules! lucet_format_err { 141 ($($arg:tt)*) => { $crate::error::Error::InternalError(failure::format_err!($($arg)*)) } 142 } 143 144 #[macro_export] 145 macro_rules! lucet_incorrect_module { 146 ($($arg:tt)*) => { 147 $crate::error::Error::ModuleError( 148 $crate::error::ModuleError::IncorrectModule(format!($($arg)*)) 149 ) 150 } 151 } 152 153 #[macro_export] 154 macro_rules! bail_limits_exceeded { 155 ($($arg:tt)*) => { return Err($crate::error::Error::LimitsExceeded(format!($($arg)*))); } 156 } 157