Add Program loader/environment instruction errors (#14120)
This commit is contained in:
		| @@ -13,7 +13,6 @@ use crate::{ | ||||
|     serialization::{deserialize_parameters, serialize_parameters}, | ||||
|     syscalls::SyscallError, | ||||
| }; | ||||
| use num_derive::{FromPrimitive, ToPrimitive}; | ||||
| use solana_rbpf::{ | ||||
|     ebpf::MM_HEAP_START, | ||||
|     error::{EbpfError, UserDefinedError}, | ||||
| @@ -26,7 +25,6 @@ use solana_sdk::{ | ||||
|     bpf_loader, bpf_loader_deprecated, | ||||
|     bpf_loader_upgradeable::{self, UpgradeableLoaderState}, | ||||
|     clock::Clock, | ||||
|     decode_error::DecodeError, | ||||
|     entrypoint::SUCCESS, | ||||
|     feature_set::bpf_compute_budget_balancing, | ||||
|     instruction::InstructionError, | ||||
| @@ -48,22 +46,6 @@ solana_sdk::declare_builtin!( | ||||
|     solana_bpf_loader_program::process_instruction | ||||
| ); | ||||
|  | ||||
| /// Errors returned by the BPFLoader if the VM fails to run the program | ||||
| #[derive(Error, Debug, Clone, PartialEq, FromPrimitive, ToPrimitive)] | ||||
| pub enum BPFLoaderError { | ||||
|     #[error("failed to create virtual machine")] | ||||
|     VirtualMachineCreationFailed = 0x0b9f_0001, | ||||
|     #[error("virtual machine failed to run the program to completion")] | ||||
|     VirtualMachineFailedToRunProgram = 0x0b9f_0002, | ||||
|     #[error("failed to compile program")] | ||||
|     JustInTimeCompilationFailed = 0x0b9f_0003, | ||||
| } | ||||
| impl<E> DecodeError<E> for BPFLoaderError { | ||||
|     fn type_of() -> &'static str { | ||||
|         "BPFLoaderError" | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// Errors returned by functions the BPF Loader registers with the VM | ||||
| #[derive(Debug, Error, PartialEq)] | ||||
| pub enum BPFError { | ||||
| @@ -107,6 +89,8 @@ pub fn create_and_cache_executor( | ||||
|     invoke_context: &mut dyn InvokeContext, | ||||
|     use_jit: bool, | ||||
| ) -> Result<Arc<BPFExecutor>, InstructionError> { | ||||
|     let logger = invoke_context.get_logger(); | ||||
|  | ||||
|     let bpf_compute_budget = invoke_context.get_bpf_compute_budget(); | ||||
|     let mut program = Executable::<BPFError, ThisInstructionMeter>::from_elf( | ||||
|         data, | ||||
| @@ -127,11 +111,16 @@ pub fn create_and_cache_executor( | ||||
|         !invoke_context.is_feature_active(&bpf_compute_budget_balancing::id()), | ||||
|     ) | ||||
|     .map_err(|e| map_ebpf_error(invoke_context, EbpfError::UserError(e)))?; | ||||
|     let syscall_registry = syscalls::register_syscalls(invoke_context) | ||||
|         .map_err(|e| map_ebpf_error(invoke_context, e))?; | ||||
|     let syscall_registry = syscalls::register_syscalls(invoke_context).map_err(|e| { | ||||
|         log!(logger, "Failed to register syscalls: {}", e); | ||||
|         InstructionError::ProgramEnvironmentSetupFailure | ||||
|     })?; | ||||
|     program.set_syscall_registry(syscall_registry); | ||||
|     if use_jit && program.jit_compile().is_err() { | ||||
|         return Err(BPFLoaderError::JustInTimeCompilationFailed.into()); | ||||
|     if use_jit { | ||||
|         if let Err(err) = program.jit_compile() { | ||||
|             log!(logger, "Failed to compile program {:?}", err); | ||||
|             return Err(InstructionError::ProgramFailedToCompile); | ||||
|         } | ||||
|     } | ||||
|     let executor = Arc::new(BPFExecutor { program }); | ||||
|     invoke_context.add_executor(key, executor.clone()); | ||||
| @@ -682,7 +671,7 @@ impl Executor for BPFExecutor { | ||||
|                 Ok(info) => info, | ||||
|                 Err(e) => { | ||||
|                     log!(logger, "Failed to create BPF VM: {}", e); | ||||
|                     return Err(BPFLoaderError::VirtualMachineCreationFailed.into()); | ||||
|                     return Err(InstructionError::ProgramEnvironmentSetupFailure); | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
| @@ -721,7 +710,10 @@ impl Executor for BPFExecutor { | ||||
|                         EbpfError::UserError(BPFError::SyscallError( | ||||
|                             SyscallError::InstructionError(error), | ||||
|                         )) => error, | ||||
|                         _ => BPFLoaderError::VirtualMachineFailedToRunProgram.into(), | ||||
|                         err => { | ||||
|                             log!(logger, "Program failed to complete: {:?}", err); | ||||
|                             InstructionError::ProgramFailedToComplete | ||||
|                         } | ||||
|                     }; | ||||
|  | ||||
|                     stable_log::program_failure(&logger, program.unsigned_key(), &error); | ||||
| @@ -1010,7 +1002,7 @@ mod tests { | ||||
|             Arc::new(FeatureSet::default()), | ||||
|         ); | ||||
|         assert_eq!( | ||||
|             Err(InstructionError::Custom(194969602)), | ||||
|             Err(InstructionError::ProgramFailedToComplete), | ||||
|             process_instruction(&bpf_loader::id(), &keyed_accounts, &[], &mut invoke_context) | ||||
|         ); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user