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