1use {
10 crate::{elf::ElfError, memory_region::AccessType, verifier::VerifierError},
11 std::error::Error,
12};
13
14#[derive(Debug, thiserror::Error)]
16#[repr(u64)] pub enum EbpfError {
18 #[error("ELF error: {0}")]
20 ElfError(#[from] ElfError),
21 #[error("function #{0} was already registered")]
23 FunctionAlreadyRegistered(usize),
24 #[error("exceeded max BPF to BPF call depth")]
26 CallDepthExceeded,
27 #[error("attempted to exit root call frame")]
29 ExitRootCallFrame,
30 #[error("divide by zero at BPF instruction")]
32 DivideByZero,
33 #[error("division overflow at BPF instruction")]
35 DivideOverflow,
36 #[error("attempted to execute past the end of the text segment at BPF instruction")]
38 ExecutionOverrun,
39 #[error("callx attempted to call outside of the text segment")]
41 CallOutsideTextSegment,
42 #[error("exceeded CUs meter at BPF instruction")]
44 ExceededMaxInstructions,
45 #[error("program has not been JIT-compiled")]
47 JitNotCompiled,
48 #[error("invalid virtual address {0:x?}")]
50 InvalidVirtualAddress(u64),
51 #[error("Invalid memory region at index {0}")]
53 InvalidMemoryRegion(usize),
54 #[error("Access violation in {3} section at address {1:#x} of size {2:?}")]
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
80#[derive(Debug)]
82#[repr(C, u64)]
83pub enum StableResult<T, E> {
84 Ok(T),
86 Err(E),
88}
89
90impl<T: std::fmt::Debug, E: std::fmt::Debug> StableResult<T, E> {
91 pub fn is_ok(&self) -> bool {
93 match self {
94 Self::Ok(_) => true,
95 Self::Err(_) => false,
96 }
97 }
98
99 pub fn is_err(&self) -> bool {
101 match self {
102 Self::Ok(_) => false,
103 Self::Err(_) => true,
104 }
105 }
106
107 pub fn unwrap(self) -> T {
109 match self {
110 Self::Ok(value) => value,
111 Self::Err(error) => panic!("unwrap {:?}", error),
112 }
113 }
114
115 pub fn unwrap_err(self) -> E {
117 match self {
118 Self::Ok(value) => panic!("unwrap_err {:?}", value),
119 Self::Err(error) => error,
120 }
121 }
122
123 pub fn map<U, O: FnOnce(T) -> U>(self, op: O) -> StableResult<U, E> {
125 match self {
126 Self::Ok(value) => StableResult::<U, E>::Ok(op(value)),
127 Self::Err(error) => StableResult::<U, E>::Err(error),
128 }
129 }
130
131 pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> StableResult<T, F> {
133 match self {
134 Self::Ok(value) => StableResult::<T, F>::Ok(value),
135 Self::Err(error) => StableResult::<T, F>::Err(op(error)),
136 }
137 }
138
139 #[cfg_attr(
140 any(
141 not(feature = "jit"),
142 target_os = "windows",
143 not(target_arch = "x86_64")
144 ),
145 allow(dead_code)
146 )]
147 pub(crate) fn discriminant(&self) -> u64 {
148 unsafe { *std::ptr::addr_of!(*self).cast::<u64>() }
149 }
150}
151
152impl<T, E> From<StableResult<T, E>> for Result<T, E> {
153 fn from(result: StableResult<T, E>) -> Self {
154 match result {
155 StableResult::Ok(value) => Ok(value),
156 StableResult::Err(value) => Err(value),
157 }
158 }
159}
160
161impl<T, E> From<Result<T, E>> for StableResult<T, E> {
162 fn from(result: Result<T, E>) -> Self {
163 match result {
164 Ok(value) => Self::Ok(value),
165 Err(value) => Self::Err(value),
166 }
167 }
168}
169
170pub type ProgramResult = StableResult<u64, EbpfError>;
172
173#[cfg(test)]
174mod tests {
175 use super::*;
176
177 #[test]
178 fn test_program_result_is_stable() {
179 let ok = ProgramResult::Ok(42);
180 assert_eq!(ok.discriminant(), 0);
181 let err = ProgramResult::Err(EbpfError::JitNotCompiled);
182 assert_eq!(err.discriminant(), 1);
183 }
184}