1use {
10 crate::{elf::ElfError, memory_region::AccessType, verifier::VerifierError},
11 std::error::Error,
12};
13
14#[derive(Debug, thiserror::Error)]
16#[repr(u64)]
20pub enum EbpfError {
21 #[error("ELF error: {0}")]
23 ElfError(#[from] ElfError),
24 #[error("function #{0} was already registered")]
26 FunctionAlreadyRegistered(usize),
27 #[error("exceeded max BPF to BPF call depth")]
29 CallDepthExceeded,
30 #[error("attempted to exit root call frame")]
32 ExitRootCallFrame,
33 #[error("divide by zero at BPF instruction")]
35 DivideByZero,
36 #[error("division overflow at BPF instruction")]
38 DivideOverflow,
39 #[error("attempted to execute past the end of the text segment at BPF instruction")]
41 ExecutionOverrun,
42 #[error("callx attempted to call outside of the text segment")]
44 CallOutsideTextSegment,
45 #[error("exceeded CUs meter at BPF instruction")]
47 ExceededMaxInstructions,
48 #[error("program has not been JIT-compiled")]
50 JitNotCompiled,
51 #[error("Invalid memory region at index {0}")]
53 InvalidMemoryRegion(usize),
54 #[error("Access violation {0} {2} bytes at address {1:#x} (in {3} region)")]
56 AccessViolation(AccessType, u64, u64, &'static str),
57 #[error("Access violation in stack frame {3} at address {1:#x} of size {2:?}")]
59 StackAccessViolation(AccessType, u64, u64, i64),
60 #[error("invalid BPF instruction")]
62 InvalidInstruction,
63 #[error("unsupported BPF instruction")]
65 UnsupportedInstruction,
66 #[error("Compilation exhausted text segment at BPF instruction {0}")]
68 ExhaustedTextSegment(usize),
69 #[error("Libc calling {0} {1:?} returned error code {2}")]
71 LibcInvocationFailed(&'static str, Vec<String>, i32),
72 #[error("Verifier error: {0}")]
74 VerifierError(#[from] VerifierError),
75 #[error("Syscall error: {0}")]
77 SyscallError(Box<dyn Error>),
78}
79
80impl EbpfError {
81 pub fn discriminant(&self) -> u64 {
85 unsafe { *std::ptr::addr_of!(*self).cast::<u64>() }
86 }
87}
88
89#[derive(Debug)]
91#[repr(C, u64)]
92pub enum StableResult<T, E> {
93 Ok(T),
95 Err(E),
97}
98
99impl<T: std::fmt::Debug, E: std::fmt::Debug> StableResult<T, E> {
100 pub fn is_ok(&self) -> bool {
102 match self {
103 Self::Ok(_) => true,
104 Self::Err(_) => false,
105 }
106 }
107
108 pub fn is_err(&self) -> bool {
110 match self {
111 Self::Ok(_) => false,
112 Self::Err(_) => true,
113 }
114 }
115
116 pub fn unwrap(self) -> T {
118 match self {
119 Self::Ok(value) => value,
120 Self::Err(error) => panic!("unwrap {:?}", error),
121 }
122 }
123
124 pub fn unwrap_err(self) -> E {
126 match self {
127 Self::Ok(value) => panic!("unwrap_err {:?}", value),
128 Self::Err(error) => error,
129 }
130 }
131
132 pub fn map<U, O: FnOnce(T) -> U>(self, op: O) -> StableResult<U, E> {
134 match self {
135 Self::Ok(value) => StableResult::<U, E>::Ok(op(value)),
136 Self::Err(error) => StableResult::<U, E>::Err(error),
137 }
138 }
139
140 pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> StableResult<T, F> {
142 match self {
143 Self::Ok(value) => StableResult::<T, F>::Ok(value),
144 Self::Err(error) => StableResult::<T, F>::Err(op(error)),
145 }
146 }
147
148 #[cfg_attr(
149 any(
150 not(feature = "jit"),
151 target_os = "windows",
152 not(target_arch = "x86_64")
153 ),
154 allow(dead_code)
155 )]
156 pub(crate) fn discriminant(&self) -> u64 {
157 unsafe { *std::ptr::addr_of!(*self).cast::<u64>() }
158 }
159}
160
161impl<T, E> From<StableResult<T, E>> for Result<T, E> {
162 fn from(result: StableResult<T, E>) -> Self {
163 match result {
164 StableResult::Ok(value) => Ok(value),
165 StableResult::Err(value) => Err(value),
166 }
167 }
168}
169
170impl<T, E> From<Result<T, E>> for StableResult<T, E> {
171 fn from(result: Result<T, E>) -> Self {
172 match result {
173 Ok(value) => Self::Ok(value),
174 Err(value) => Self::Err(value),
175 }
176 }
177}
178
179pub type ProgramResult = StableResult<u64, EbpfError>;
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185
186 #[test]
187 fn test_program_result_is_stable() {
188 let ok = ProgramResult::Ok(42);
189 assert_eq!(ok.discriminant(), 0);
190 let err = ProgramResult::Err(EbpfError::JitNotCompiled);
191 assert_eq!(err.discriminant(), 1);
192 }
193}