diff --git a/src/debugger.rs b/src/debugger.rs index 432cf8b7..81cfbe0b 100644 --- a/src/debugger.rs +++ b/src/debugger.rs @@ -23,10 +23,10 @@ use gdbstub::target::ext::section_offsets::Offsets; use crate::{ ebpf, - error::EbpfError, + error::{EbpfError, ProgramResult}, interpreter::{DebugState, Interpreter}, memory_region::AccessType, - vm::{ContextObject, ProgramResult}, + vm::ContextObject, }; type DynResult = Result>; diff --git a/src/elf.rs b/src/elf.rs index d47fcc73..fd76235a 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -1189,10 +1189,11 @@ mod test { consts::{ELFCLASS32, ELFDATA2MSB, ET_REL}, types::{Elf64Ehdr, Elf64Shdr}, }, + error::ProgramResult, fuzz::fuzz, program::BuiltinFunction, syscalls, - vm::{ProgramResult, TestContextObject}, + vm::TestContextObject, }; use rand::{distributions::Uniform, Rng}; use std::{fs::File, io::Read}; diff --git a/src/error.rs b/src/error.rs index 411db985..5761b147 100644 --- a/src/error.rs +++ b/src/error.rs @@ -87,3 +87,96 @@ pub enum EbpfError { #[error("Syscall error: {0}")] SyscallError(Box), } + +/// Same as `Result` but provides a stable memory layout +#[derive(Debug)] +#[repr(C, u64)] +pub enum StableResult { + /// Success + Ok(T), + /// Failure + Err(E), +} + +impl StableResult { + /// `true` if `Ok` + pub fn is_ok(&self) -> bool { + match self { + Self::Ok(_) => true, + Self::Err(_) => false, + } + } + + /// `true` if `Err` + pub fn is_err(&self) -> bool { + match self { + Self::Ok(_) => false, + Self::Err(_) => true, + } + } + + /// Returns the inner value if `Ok`, panics otherwise + pub fn unwrap(self) -> T { + match self { + Self::Ok(value) => value, + Self::Err(error) => panic!("unwrap {:?}", error), + } + } + + /// Returns the inner error if `Err`, panics otherwise + pub fn unwrap_err(self) -> E { + match self { + Self::Ok(value) => panic!("unwrap_err {:?}", value), + Self::Err(error) => error, + } + } + + /// Maps ok values, leaving error values untouched + pub fn map U>(self, op: O) -> StableResult { + match self { + Self::Ok(value) => StableResult::::Ok(op(value)), + Self::Err(error) => StableResult::::Err(error), + } + } + + /// Maps error values, leaving ok values untouched + pub fn map_err F>(self, op: O) -> StableResult { + match self { + Self::Ok(value) => StableResult::::Ok(value), + Self::Err(error) => StableResult::::Err(op(error)), + } + } + + #[cfg_attr( + any( + not(feature = "jit"), + target_os = "windows", + not(target_arch = "x86_64") + ), + allow(dead_code) + )] + pub(crate) fn discriminant(&self) -> u64 { + unsafe { *(self as *const _ as *const u64) } + } +} + +impl From> for Result { + fn from(result: StableResult) -> Self { + match result { + StableResult::Ok(value) => Ok(value), + StableResult::Err(value) => Err(value), + } + } +} + +impl From> for StableResult { + fn from(result: Result) -> Self { + match result { + Ok(value) => Self::Ok(value), + Err(value) => Self::Err(value), + } + } +} + +/// Return value of programs and syscalls +pub type ProgramResult = StableResult; diff --git a/src/interpreter.rs b/src/interpreter.rs index 2d485ba0..9c489e7a 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -15,8 +15,8 @@ use crate::{ ebpf::{self, STACK_PTR_REG}, elf::Executable, - error::EbpfError, - vm::{get_runtime_environment_key, Config, ContextObject, EbpfVm, ProgramResult}, + error::{EbpfError, ProgramResult}, + vm::{get_runtime_environment_key, Config, ContextObject, EbpfVm}, }; /// Virtual memory operation helper. diff --git a/src/jit.rs b/src/jit.rs index 76d11646..c68bb8b6 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -16,12 +16,12 @@ use std::{fmt::Debug, mem, ptr}; use crate::{ ebpf::{self, FIRST_SCRATCH_REG, FRAME_PTR_REG, INSN_SIZE, SCRATCH_REGS, STACK_PTR_REG}, elf::Executable, - error::EbpfError, + error::{EbpfError, ProgramResult}, memory_management::{ allocate_pages, free_pages, get_system_page_size, protect_pages, round_to_page_size, }, memory_region::{AccessType, MemoryMapping}, - vm::{get_runtime_environment_key, Config, ContextObject, EbpfVm, ProgramResult}, + vm::{get_runtime_environment_key, Config, ContextObject, EbpfVm}, x86::*, }; diff --git a/src/memory_region.rs b/src/memory_region.rs index 9f519f2d..260596cc 100644 --- a/src/memory_region.rs +++ b/src/memory_region.rs @@ -3,9 +3,9 @@ use crate::{ aligned_memory::Pod, ebpf, - error::EbpfError, + error::{EbpfError, ProgramResult}, program::SBPFVersion, - vm::{Config, ProgramResult}, + vm::Config, }; use std::{ array, diff --git a/src/program.rs b/src/program.rs index 05bc0a68..279d4ea2 100644 --- a/src/program.rs +++ b/src/program.rs @@ -330,7 +330,7 @@ macro_rules! declare_builtin_function { if config.enable_instruction_meter { vm.context_object_pointer.consume(vm.previous_instruction_meter - vm.due_insn_count); } - let converted_result: $crate::vm::ProgramResult = Self::rust( + let converted_result: $crate::error::ProgramResult = Self::rust( vm.context_object_pointer, $arg_a, $arg_b, $arg_c, $arg_d, $arg_e, &mut vm.memory_mapping, ).into(); vm.program_result = converted_result; diff --git a/src/vm.rs b/src/vm.rs index 069347a5..eba59184 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -15,7 +15,7 @@ use crate::{ ebpf, elf::Executable, - error::EbpfError, + error::{EbpfError, ProgramResult}, interpreter::Interpreter, memory_region::MemoryMapping, program::{BuiltinProgram, FunctionRegistry, SBPFVersion}, @@ -36,99 +36,6 @@ pub fn get_runtime_environment_key() -> i32 { .get_or_init(|| rand::thread_rng().gen::() >> PROGRAM_ENVIRONMENT_KEY_SHIFT) } -/// Same as `Result` but provides a stable memory layout -#[derive(Debug)] -#[repr(C, u64)] -pub enum StableResult { - /// Success - Ok(T), - /// Failure - Err(E), -} - -impl StableResult { - /// `true` if `Ok` - pub fn is_ok(&self) -> bool { - match self { - Self::Ok(_) => true, - Self::Err(_) => false, - } - } - - /// `true` if `Err` - pub fn is_err(&self) -> bool { - match self { - Self::Ok(_) => false, - Self::Err(_) => true, - } - } - - /// Returns the inner value if `Ok`, panics otherwise - pub fn unwrap(self) -> T { - match self { - Self::Ok(value) => value, - Self::Err(error) => panic!("unwrap {:?}", error), - } - } - - /// Returns the inner error if `Err`, panics otherwise - pub fn unwrap_err(self) -> E { - match self { - Self::Ok(value) => panic!("unwrap_err {:?}", value), - Self::Err(error) => error, - } - } - - /// Maps ok values, leaving error values untouched - pub fn map U>(self, op: O) -> StableResult { - match self { - Self::Ok(value) => StableResult::::Ok(op(value)), - Self::Err(error) => StableResult::::Err(error), - } - } - - /// Maps error values, leaving ok values untouched - pub fn map_err F>(self, op: O) -> StableResult { - match self { - Self::Ok(value) => StableResult::::Ok(value), - Self::Err(error) => StableResult::::Err(op(error)), - } - } - - #[cfg_attr( - any( - not(feature = "jit"), - target_os = "windows", - not(target_arch = "x86_64") - ), - allow(dead_code) - )] - pub(crate) fn discriminant(&self) -> u64 { - unsafe { *(self as *const _ as *const u64) } - } -} - -impl From> for Result { - fn from(result: StableResult) -> Self { - match result { - StableResult::Ok(value) => Ok(value), - StableResult::Err(value) => Err(value), - } - } -} - -impl From> for StableResult { - fn from(result: Result) -> Self { - match result { - Ok(value) => Self::Ok(value), - Err(value) => Self::Err(value), - } - } -} - -/// Return value of programs and syscalls -pub type ProgramResult = StableResult; - /// VM configuration settings #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Config { diff --git a/tests/execution.rs b/tests/execution.rs index 92cb0762..769b111f 100644 --- a/tests/execution.rs +++ b/tests/execution.rs @@ -19,13 +19,13 @@ use solana_rbpf::{ assembler::assemble, declare_builtin_function, ebpf, elf::Executable, - error::EbpfError, + error::{EbpfError, ProgramResult}, memory_region::{AccessType, MemoryMapping, MemoryRegion}, program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SBPFVersion}, static_analysis::Analysis, syscalls, verifier::RequisiteVerifier, - vm::{Config, ContextObject, ProgramResult, TestContextObject}, + vm::{Config, ContextObject, TestContextObject}, }; use std::{fs::File, io::Read, sync::Arc}; use test_utils::{