From 75135da0f645ded0875fb292667e9b50d8fefb04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Thu, 30 Jan 2025 09:44:57 +0100 Subject: [PATCH] Removes the dense function registry from loaders. --- benches/elf_loader.rs | 17 ++---- benches/vm_execution.rs | 12 +---- cli/src/main.rs | 16 +++--- src/program.rs | 64 +++++----------------- test_utils/src/lib.rs | 70 +++++++++++------------- tests/assembler.rs | 15 ++---- tests/disassembler.rs | 7 +-- tests/elf.rs | 41 ++++++-------- tests/execution.rs | 95 +++++++++++++++----------------- tests/exercise_instructions.rs | 5 +- tests/jit.rs | 6 +-- tests/verifier.rs | 98 +++++++++++++--------------------- tests/vm.rs | 31 +++++------ 13 files changed, 177 insertions(+), 300 deletions(-) diff --git a/benches/elf_loader.rs b/benches/elf_loader.rs index a747aadb..4953b048 100644 --- a/benches/elf_loader.rs +++ b/benches/elf_loader.rs @@ -10,24 +10,17 @@ extern crate solana_sbpf; extern crate test; extern crate test_utils; -use solana_sbpf::{ - elf::Executable, - program::{BuiltinFunction, BuiltinProgram, FunctionRegistry}, - vm::Config, -}; +use solana_sbpf::{elf::Executable, program::BuiltinProgram, vm::Config}; use std::{fs::File, io::Read, sync::Arc}; use test::Bencher; use test_utils::{syscalls, TestContextObject}; fn loader() -> Arc> { - let mut function_registry = FunctionRegistry::>::default(); - function_registry - .register_function_hashed(*b"log", syscalls::SyscallString::vm) + let mut loader = BuiltinProgram::new_loader(Config::default()); + loader + .register_function("log", syscalls::SyscallString::vm) .unwrap(); - Arc::new(BuiltinProgram::new_loader( - Config::default(), - function_registry, - )) + Arc::new(loader) } #[bench] diff --git a/benches/vm_execution.rs b/benches/vm_execution.rs index 815a9140..05729528 100644 --- a/benches/vm_execution.rs +++ b/benches/vm_execution.rs @@ -10,12 +10,7 @@ extern crate solana_sbpf; extern crate test; #[cfg(all(feature = "jit", not(target_os = "windows"), target_arch = "x86_64"))] -use solana_sbpf::{ - ebpf, - memory_region::MemoryRegion, - program::{FunctionRegistry, SBPFVersion}, - vm::Config, -}; +use solana_sbpf::{ebpf, memory_region::MemoryRegion, program::SBPFVersion, vm::Config}; use solana_sbpf::{elf::Executable, program::BuiltinProgram, verifier::RequisiteVerifier}; use std::{fs::File, io::Read, sync::Arc}; use test::Bencher; @@ -83,10 +78,7 @@ fn bench_jit_vs_interpreter( ) { let mut executable = solana_sbpf::assembler::assemble::( assembly, - Arc::new(BuiltinProgram::new_loader( - config, - FunctionRegistry::default(), - )), + Arc::new(BuiltinProgram::new_loader(config)), ) .unwrap(); executable.verify::().unwrap(); diff --git a/cli/src/main.rs b/cli/src/main.rs index 6b0147e0..b550fc28 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -5,7 +5,7 @@ use solana_sbpf::{ ebpf, elf::Executable, memory_region::{MemoryMapping, MemoryRegion}, - program::{BuiltinProgram, FunctionRegistry}, + program::BuiltinProgram, static_analysis::Analysis, verifier::RequisiteVerifier, vm::{Config, DynamicAnalysis, EbpfVm}, @@ -94,15 +94,11 @@ fn main() { ) .get_matches(); - let loader = Arc::new(BuiltinProgram::new_loader( - Config { - enable_instruction_tracing: matches.is_present("trace") - || matches.is_present("profile"), - enable_symbol_and_section_labels: true, - ..Config::default() - }, - FunctionRegistry::default(), - )); + let loader = Arc::new(BuiltinProgram::new_loader(Config { + enable_instruction_tracing: matches.is_present("trace") || matches.is_present("profile"), + enable_symbol_and_section_labels: true, + ..Config::default() + })); #[allow(unused_mut)] let mut executable = match matches.value_of("assembler") { Some(asm_file_name) => { diff --git a/src/program.rs b/src/program.rs index b3df0c7e..327ca80b 100644 --- a/src/program.rs +++ b/src/program.rs @@ -134,18 +134,6 @@ impl FunctionRegistry { Ok(()) } - /// Register a symbol with an implicit key - pub fn register_function_hashed( - &mut self, - name: impl Into>, - value: T, - ) -> Result { - let name = name.into(); - let key = ebpf::hash_symbol_name(name.as_slice()); - self.register_function(key, name, value)?; - Ok(key) - } - /// Used for transitioning from SBPFv0 to SBPFv3 pub(crate) fn register_function_hashed_legacy( &mut self, @@ -246,34 +234,28 @@ pub struct BuiltinProgram { config: Option>, /// Function pointers by symbol with sparse indexing sparse_registry: FunctionRegistry>, - /// Function pointers by symbol with dense indexing - dense_registry: FunctionRegistry>, } impl PartialEq for BuiltinProgram { fn eq(&self, other: &Self) -> bool { - self.config.eq(&other.config) - && self.sparse_registry.eq(&other.sparse_registry) - && self.dense_registry.eq(&other.dense_registry) + self.config.eq(&other.config) && self.sparse_registry.eq(&other.sparse_registry) } } impl BuiltinProgram { /// Constructs a loader built-in program - pub fn new_loader(config: Config, functions: FunctionRegistry>) -> Self { + pub fn new_loader(config: Config) -> Self { Self { config: Some(Box::new(config)), - sparse_registry: functions, - dense_registry: FunctionRegistry::default(), + sparse_registry: FunctionRegistry::default(), } } /// Constructs a built-in program - pub fn new_builtin(functions: FunctionRegistry>) -> Self { + pub fn new_builtin() -> Self { Self { config: None, - sparse_registry: functions, - dense_registry: FunctionRegistry::default(), + sparse_registry: FunctionRegistry::default(), } } @@ -282,17 +264,6 @@ impl BuiltinProgram { Self { config: Some(Box::default()), sparse_registry: FunctionRegistry::default(), - dense_registry: FunctionRegistry::default(), - } - } - - /// Create a new loader with both dense and sparse function indexation - /// Use `BuiltinProgram::register_function` for registrations. - pub fn new_loader_with_dense_registration(config: Config) -> Self { - Self { - config: Some(Box::new(config)), - sparse_registry: FunctionRegistry::default(), - dense_registry: FunctionRegistry::default(), } } @@ -304,13 +275,9 @@ impl BuiltinProgram { /// Get the function registry depending on the SBPF version pub fn get_function_registry( &self, - sbpf_version: SBPFVersion, + _sbpf_version: SBPFVersion, ) -> &FunctionRegistry> { - if sbpf_version.static_syscalls() { - &self.dense_registry - } else { - &self.sparse_registry - } + &self.sparse_registry } /// Calculate memory size @@ -322,19 +289,18 @@ impl BuiltinProgram { 0 }) .saturating_add(self.sparse_registry.mem_size()) - .saturating_add(self.dense_registry.mem_size()) } /// Register a function both in the sparse and dense registries pub fn register_function( &mut self, name: &str, - dense_key: u32, value: BuiltinFunction, ) -> Result<(), ElfError> { - self.sparse_registry.register_function_hashed(name, value)?; - self.dense_registry - .register_function(dense_key, name, value) + let key = ebpf::hash_symbol_name(name.as_bytes()); + self.sparse_registry + .register_function(key, name, value) + .map(|_| ()) } } @@ -343,16 +309,12 @@ impl std::fmt::Debug for BuiltinProgram { unsafe { writeln!( f, - "sparse: {:?}\n dense: {:?}", + "registry: {:?}", // `derive(Debug)` does not know that `C: ContextObject` does not need to implement `Debug` std::mem::transmute::< &FunctionRegistry>, &FunctionRegistry, - >(&self.sparse_registry,), - std::mem::transmute::< - &FunctionRegistry>, - &FunctionRegistry, - >(&self.dense_registry,) + >(&self.sparse_registry), )?; } Ok(()) diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs index 53316c4c..e2af97b4 100644 --- a/test_utils/src/lib.rs +++ b/test_utils/src/lib.rs @@ -397,19 +397,17 @@ macro_rules! test_interpreter_and_jit { #[macro_export] macro_rules! test_interpreter_and_jit_asm { - ($source:expr, $config:expr, $mem:tt, $context_object:expr, $expected_result:expr $(,)?) => { + ($source:expr, $config:expr, $mem:expr, $context_object:expr, $expected_result:expr $(,)?) => { #[allow(unused_mut)] { let mut config = $config; config.enable_instruction_tracing = true; - let mut function_registry = - FunctionRegistry::>::default(); - let loader = Arc::new(BuiltinProgram::new_loader(config, function_registry)); + let loader = Arc::new(BuiltinProgram::new_loader(config)); let mut executable = assemble($source, loader).unwrap(); test_interpreter_and_jit!(executable, $mem, $context_object, $expected_result); } }; - ($source:expr, $mem:tt, $context_object:expr, $expected_result:expr $(,)?) => { + ($source:expr, $mem:expr, $context_object:expr, $expected_result:expr $(,)?) => { #[allow(unused_mut)] { test_interpreter_and_jit_asm!( @@ -423,27 +421,44 @@ macro_rules! test_interpreter_and_jit_asm { }; } +#[macro_export] +macro_rules! test_syscall_asm { + (register, $loader:expr, $syscall_name:expr => $syscall_function:expr) => { + let _ = $loader.register_function($syscall_name, $syscall_function).unwrap(); + }; + ($source:expr, $mem:expr, ($($syscall_name:expr => $syscall_function:expr),*$(,)?), $context_object:expr, $expected_result:expr $(,)?) => { + let mut config = Config { + enable_instruction_tracing: true, + ..Config::default() + }; + for sbpf_version in [SBPFVersion::V0, SBPFVersion::V3] { + config.enabled_sbpf_versions = sbpf_version..=sbpf_version; + let mut loader = BuiltinProgram::new_loader(config.clone()); + $(test_syscall_asm!(register, loader, $syscall_name => $syscall_function);)* + let mut executable = assemble($source, Arc::new(loader)).unwrap(); + test_interpreter_and_jit!(executable, $mem, $context_object, $expected_result); + } + }; +} + #[macro_export] macro_rules! test_interpreter_and_jit_elf { - (register, $function_registry:expr, $location:expr => $syscall_function:expr) => { - $function_registry - .register_function_hashed($location.as_bytes(), $syscall_function) - .unwrap(); + (register, $loader:expr, $location:expr => $syscall_function:expr) => { + $loader.register_function($location, $syscall_function).unwrap(); }; - ($source:tt, $config:tt, $mem:tt, ($($location:expr => $syscall_function:expr),* $(,)?), $context_object:expr, $expected_result:expr $(,)?) => { + ($source:expr, $config:expr, $mem:expr, ($($location:expr => $syscall_function:expr),* $(,)?), $context_object:expr, $expected_result:expr $(,)?) => { let mut file = File::open($source).unwrap(); let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); #[allow(unused_mut)] { - let mut function_registry = FunctionRegistry::>::default(); - $(test_interpreter_and_jit_elf!(register, function_registry, $location => $syscall_function);)* - let loader = Arc::new(BuiltinProgram::new_loader($config, function_registry)); - let mut executable = Executable::::from_elf(&elf, loader).unwrap(); + let mut loader = BuiltinProgram::new_loader($config); + $(test_interpreter_and_jit_elf!(register, loader, $location => $syscall_function);)* + let mut executable = Executable::::from_elf(&elf, Arc::new(loader)).unwrap(); test_interpreter_and_jit!(executable, $mem, $context_object, $expected_result); } }; - ($source:tt, $mem:tt, ($($location:expr => $syscall_function:expr),* $(,)?), $context_object:expr, $expected_result:expr $(,)?) => { + ($source:expr, $mem:expr, ($($location:expr => $syscall_function:expr),* $(,)?), $context_object:expr, $expected_result:expr $(,)?) => { let config = Config { enable_instruction_tracing: true, ..Config::default() @@ -451,28 +466,3 @@ macro_rules! test_interpreter_and_jit_elf { test_interpreter_and_jit_elf!($source, config, $mem, ($($location => $syscall_function),*), $context_object, $expected_result); }; } - -#[macro_export] -macro_rules! test_syscall_asm { - (register, $loader:expr, $syscall_number:literal => $syscall_name:expr => $syscall_function:expr) => { - let _ = $loader.register_function($syscall_name, $syscall_number, $syscall_function).unwrap(); - }; - ($source:tt, $mem:tt, ($($syscall_number:literal => $syscall_name:expr => $syscall_function:expr),*$(,)?), $context_object:expr, $expected_result:expr $(,)?) => { - let mut config = Config { - enable_instruction_tracing: true, - ..Config::default() - }; - for sbpf_version in [SBPFVersion::V0, SBPFVersion::V3] { - config.enabled_sbpf_versions = sbpf_version..=sbpf_version; - let src = if sbpf_version == SBPFVersion::V0 { - format!($source, $($syscall_name, )*) - } else { - format!($source, $($syscall_number, )*) - }; - let mut loader = BuiltinProgram::new_loader_with_dense_registration(config.clone()); - $(test_syscall_asm!(register, loader, $syscall_number => $syscall_name => $syscall_function);)* - let mut executable = assemble(src.as_str(), Arc::new(loader)).unwrap(); - test_interpreter_and_jit!(executable, $mem, $context_object, $expected_result); - } - }; -} diff --git a/tests/assembler.rs b/tests/assembler.rs index 70922af7..0cdf0917 100644 --- a/tests/assembler.rs +++ b/tests/assembler.rs @@ -10,7 +10,7 @@ extern crate solana_sbpf; extern crate test_utils; -use solana_sbpf::program::{FunctionRegistry, SBPFVersion}; +use solana_sbpf::program::SBPFVersion; use solana_sbpf::vm::Config; use solana_sbpf::{assembler::assemble, ebpf, program::BuiltinProgram}; use std::sync::Arc; @@ -21,7 +21,7 @@ fn asm(src: &str) -> Result, String> { } fn asm_with_config(src: &str, config: Config) -> Result, String> { - let loader = BuiltinProgram::new_loader(config, FunctionRegistry::default()); + let loader = BuiltinProgram::new_loader(config); let executable = assemble::(src, Arc::new(loader))?; let (_program_vm_addr, program) = executable.get_text_bytes(); Ok((0..program.len() / ebpf::INSN_SIZE) @@ -524,14 +524,9 @@ fn test_tcp_sack() { enabled_sbpf_versions: SBPFVersion::V3..=SBPFVersion::V3, ..Config::default() }; - let executable = assemble::( - TCP_SACK_ASM, - Arc::new(BuiltinProgram::new_loader( - config, - FunctionRegistry::default(), - )), - ) - .unwrap(); + let executable = + assemble::(TCP_SACK_ASM, Arc::new(BuiltinProgram::new_loader(config))) + .unwrap(); let (_program_vm_addr, program) = executable.get_text_bytes(); assert_eq!(program, TCP_SACK_BIN.to_vec()); } diff --git a/tests/disassembler.rs b/tests/disassembler.rs index 786b6e5e..63328c5c 100644 --- a/tests/disassembler.rs +++ b/tests/disassembler.rs @@ -11,10 +11,7 @@ extern crate solana_sbpf; use solana_sbpf::program::SBPFVersion; use solana_sbpf::{ - assembler::assemble, - program::{BuiltinProgram, FunctionRegistry}, - static_analysis::Analysis, - vm::Config, + assembler::assemble, program::BuiltinProgram, static_analysis::Analysis, vm::Config, }; use std::sync::Arc; use test_utils::TestContextObject; @@ -30,7 +27,7 @@ macro_rules! disasm { }}; ($src:expr, $config:expr) => {{ let src = $src; - let loader = BuiltinProgram::new_loader($config, FunctionRegistry::default()); + let loader = BuiltinProgram::new_loader($config); let executable = assemble::(src, Arc::new(loader)).unwrap(); let analysis = Analysis::from_executable(&executable).unwrap(); let mut reasm = Vec::new(); diff --git a/tests/elf.rs b/tests/elf.rs index 642074cb..c7cc0707 100644 --- a/tests/elf.rs +++ b/tests/elf.rs @@ -10,7 +10,7 @@ use solana_sbpf::{ Elf64, ElfParserError, SECTION_NAME_LENGTH_MAXIMUM, }, error::ProgramResult, - program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SBPFVersion}, + program::{BuiltinProgram, SBPFVersion}, vm::Config, }; use std::{fs::File, io::Read, sync::Arc}; @@ -19,17 +19,14 @@ use test_utils::{assert_error, syscalls, TestContextObject}; type ElfExecutable = Executable; fn loader() -> Arc> { - let mut function_registry = FunctionRegistry::>::default(); - function_registry - .register_function_hashed(*b"log", syscalls::SyscallString::vm) + let mut loader = BuiltinProgram::new_loader(Config::default()); + loader + .register_function("log", syscalls::SyscallString::vm) .unwrap(); - function_registry - .register_function_hashed(*b"log_64", syscalls::SyscallU64::vm) + loader + .register_function("log_64", syscalls::SyscallU64::vm) .unwrap(); - Arc::new(BuiltinProgram::new_loader( - Config::default(), - function_registry, - )) + Arc::new(loader) } #[test] @@ -39,13 +36,10 @@ fn test_strict_header() { // Check that the unmodified file can be parsed { - let loader = Arc::new(BuiltinProgram::new_loader( - Config { - enable_symbol_and_section_labels: true, - ..Config::default() - }, - FunctionRegistry::>::default(), - )); + let loader = Arc::new(BuiltinProgram::new_loader(Config { + enable_symbol_and_section_labels: true, + ..Config::default() + })); let executable = ElfExecutable::load(&elf_bytes, loader.clone()).unwrap(); let (name, _pc) = executable.get_function_registry().lookup_by_key(4).unwrap(); assert_eq!(name, b"entrypoint"); @@ -829,14 +823,11 @@ fn test_relative_call_oob_forward() { #[test] #[should_panic(expected = "validation failed: UnresolvedSymbol(\"log\", 39, 312)")] fn test_err_unresolved_syscall_reloc_64_32() { - let loader = BuiltinProgram::new_loader( - Config { - enabled_sbpf_versions: SBPFVersion::V0..=SBPFVersion::V0, - reject_broken_elfs: true, - ..Config::default() - }, - FunctionRegistry::default(), - ); + let loader = BuiltinProgram::new_loader(Config { + enabled_sbpf_versions: SBPFVersion::V0..=SBPFVersion::V0, + reject_broken_elfs: true, + ..Config::default() + }); let elf_bytes = std::fs::read("tests/elfs/syscall_reloc_64_32_sbpfv0.so").expect("failed to read elf file"); ElfExecutable::load(&elf_bytes, Arc::new(loader)).expect("validation failed"); diff --git a/tests/execution.rs b/tests/execution.rs index dc63b238..dae766d7 100644 --- a/tests/execution.rs +++ b/tests/execution.rs @@ -23,7 +23,7 @@ use solana_sbpf::{ elf::Executable, error::{EbpfError, ProgramResult}, memory_region::{AccessType, MemoryMapping, MemoryRegion}, - program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SBPFVersion}, + program::{BuiltinProgram, FunctionRegistry, SBPFVersion}, static_analysis::Analysis, verifier::RequisiteVerifier, vm::{Config, ContextObject}, @@ -1805,19 +1805,19 @@ fn test_stack2() { mov r1, r10 mov r2, 0x4 sub r1, r2 - syscall {} + syscall bpf_mem_frob mov r1, 0 ldxb r2, [r10-4] ldxb r3, [r10-3] ldxb r4, [r10-2] ldxb r5, [r10-1] - syscall {} + syscall bpf_gather_bytes xor r0, 0x2a2a2a2a exit", [], ( - 1 => "bpf_mem_frob" => syscalls::SyscallMemFrob::vm, - 2 => "bpf_gather_bytes" => syscalls::SyscallGatherBytes::vm, + "bpf_mem_frob" => syscalls::SyscallMemFrob::vm, + "bpf_gather_bytes" => syscalls::SyscallGatherBytes::vm, ), TestContextObject::new(16), ProgramResult::Ok(0x01020304), @@ -1838,7 +1838,7 @@ fn test_string_stack() { mov r1, r10 add r1, -8 mov r2, r1 - syscall {} + syscall bpf_str_cmp mov r1, r0 mov r0, 0x1 lsh r1, 0x20 @@ -1848,7 +1848,7 @@ fn test_string_stack() { add r1, -8 mov r2, r10 add r2, -16 - syscall {} + syscall bpf_str_cmp mov r1, r0 lsh r1, 0x20 rsh r1, 0x20 @@ -1858,8 +1858,7 @@ fn test_string_stack() { exit", [], ( - 3 => "bpf_str_cmp" => syscalls::SyscallStrCmp::vm, - 3 => "bpf_str_cmp" => syscalls::SyscallStrCmp::vm, + "bpf_str_cmp" => syscalls::SyscallStrCmp::vm, ), TestContextObject::new(28), ProgramResult::Ok(0x0), @@ -2173,12 +2172,12 @@ fn test_syscall_parameter_on_stack() { mov64 r1, r10 add64 r1, -0x100 mov64 r2, 0x1 - syscall {} + syscall bpf_syscall_string mov64 r0, 0x0 exit", [], ( - 1 => "bpf_syscall_string" => syscalls::SyscallString::vm, + "bpf_syscall_string" => syscalls::SyscallString::vm, ), TestContextObject::new(6), ProgramResult::Ok(0), @@ -2426,12 +2425,12 @@ fn test_err_syscall_string() { test_syscall_asm!( " mov64 r1, 0x0 - syscall {} + syscall bpf_syscall_string mov64 r0, 0x0 exit", [72, 101, 108, 108, 111], ( - 2 => "bpf_syscall_string" => syscalls::SyscallString::vm, + "bpf_syscall_string" => syscalls::SyscallString::vm, ), TestContextObject::new(2), ProgramResult::Err(EbpfError::SyscallError(Box::new(EbpfError::AccessViolation(AccessType::Load, 0, 0, "unknown")))), @@ -2443,12 +2442,12 @@ fn test_syscall_string() { test_syscall_asm!( " mov64 r2, 0x5 - syscall {} + syscall bpf_syscall_string mov64 r0, 0x0 exit", [72, 101, 108, 108, 111], ( - 1 => "bpf_syscall_string" => syscalls::SyscallString::vm, + "bpf_syscall_string" => syscalls::SyscallString::vm, ), TestContextObject::new(4), ProgramResult::Ok(0), @@ -2464,12 +2463,12 @@ fn test_syscall() { mov64 r3, 0xCC mov64 r4, 0xDD mov64 r5, 0xEE - syscall {} + syscall bpf_syscall_u64 mov64 r0, 0x0 exit", [], ( - 3 => "bpf_syscall_u64" => syscalls::SyscallU64::vm, + "bpf_syscall_u64" => syscalls::SyscallU64::vm, ), TestContextObject::new(8), ProgramResult::Ok(0), @@ -2485,11 +2484,11 @@ fn test_call_gather_bytes() { mov r3, 3 mov r4, 4 mov r5, 5 - syscall {} + syscall bpf_gather_bytes exit", [], ( - 1 => "bpf_gather_bytes" => syscalls::SyscallGatherBytes::vm, + "bpf_gather_bytes" => syscalls::SyscallGatherBytes::vm, ), TestContextObject::new(7), ProgramResult::Ok(0x0102030405), @@ -2503,7 +2502,7 @@ fn test_call_memfrob() { mov r6, r1 add r1, 2 mov r2, 4 - syscall {} + syscall bpf_mem_frob ldxdw r0, [r6] be64 r0 exit", @@ -2511,7 +2510,7 @@ fn test_call_memfrob() { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // ], ( - 2 => "bpf_mem_frob" => syscalls::SyscallMemFrob::vm, + "bpf_mem_frob" => syscalls::SyscallMemFrob::vm, ), TestContextObject::new(7), ProgramResult::Ok(0x102292e2f2c0708), @@ -2544,32 +2543,25 @@ declare_builtin_function!( #[allow(unused_mut)] if depth > 0 { let mut config = Config::default(); - let syscall_name = if version == 1 { + if version == 0 { config.enabled_sbpf_versions = SBPFVersion::V0..=SBPFVersion::V0; - "nested_vm_syscall" } else { config.enabled_sbpf_versions = SBPFVersion::V3..=SBPFVersion::V3; - "1" }; - let mut loader = BuiltinProgram::new_loader_with_dense_registration(config); - loader.register_function("nested_vm_syscall", 1, SyscallNestedVm::vm).unwrap(); - let source_code = format!( + let mut loader = BuiltinProgram::new_loader(config); + loader.register_function("nested_vm_syscall", SyscallNestedVm::vm).unwrap(); + let mut executable = assemble::( " ldxb r2, [r1+1] ldxb r1, [r1] - syscall {} + syscall nested_vm_syscall exit", - syscall_name - ); - let mem = [depth as u8 - 1, throw as u8]; - let mut executable = assemble::( - source_code.as_str(), Arc::new(loader), ) .unwrap(); test_interpreter_and_jit!( executable, - mem, + [depth as u8 - 1, throw as u8], TestContextObject::new(if throw == 0 { 4 } else { 3 }), expected_result, ); @@ -2585,15 +2577,15 @@ fn test_nested_vm_syscall() { let mut memory_mapping = MemoryMapping::new(vec![], &config, SBPFVersion::V3).unwrap(); // SBPFv0 - let result = SyscallNestedVm::rust(&mut context_object, 1, 0, 1, 0, 0, &mut memory_mapping); + let result = SyscallNestedVm::rust(&mut context_object, 1, 0, 0, 0, 0, &mut memory_mapping); assert_eq!(result.unwrap(), 42); - let result = SyscallNestedVm::rust(&mut context_object, 1, 1, 1, 0, 0, &mut memory_mapping); + let result = SyscallNestedVm::rust(&mut context_object, 1, 1, 0, 0, 0, &mut memory_mapping); assert_error!(result, "CallDepthExceeded"); // SBPFv3 - let result = SyscallNestedVm::rust(&mut context_object, 1, 0, 2, 0, 0, &mut memory_mapping); + let result = SyscallNestedVm::rust(&mut context_object, 1, 0, 3, 0, 0, &mut memory_mapping); assert_eq!(result.unwrap(), 42); - let result = SyscallNestedVm::rust(&mut context_object, 1, 1, 2, 0, 0, &mut memory_mapping); + let result = SyscallNestedVm::rust(&mut context_object, 1, 1, 3, 0, 0, &mut memory_mapping); assert_error!(result, "CallDepthExceeded"); } @@ -2659,12 +2651,12 @@ fn test_instruction_count_syscall() { test_syscall_asm!( " mov64 r2, 0x5 - syscall {} + syscall bpf_syscall_string mov64 r0, 0x0 exit", [72, 101, 108, 108, 111], ( - 1 => "bpf_syscall_string" => syscalls::SyscallString::vm, + "bpf_syscall_string" => syscalls::SyscallString::vm, ), TestContextObject::new(4), ProgramResult::Ok(0), @@ -2676,12 +2668,12 @@ fn test_err_instruction_count_syscall_capped() { test_syscall_asm!( " mov64 r2, 0x5 - syscall {} + syscall bpf_syscall_string mov64 r0, 0x0 exit", [72, 101, 108, 108, 111], ( - 1 => "bpf_syscall_string" => syscalls::SyscallString::vm, + "bpf_syscall_string" => syscalls::SyscallString::vm, ), TestContextObject::new(3), ProgramResult::Err(EbpfError::ExceededMaxInstructions), @@ -3194,13 +3186,10 @@ fn execute_generated_program(prog: &[u8]) -> bool { let mem_size = 1024 * 1024; let executable = Executable::::from_text_bytes( prog, - Arc::new(BuiltinProgram::new_loader( - Config { - enable_instruction_tracing: true, - ..Config::default() - }, - FunctionRegistry::default(), - )), + Arc::new(BuiltinProgram::new_loader(Config { + enable_instruction_tracing: true, + ..Config::default() + })), SBPFVersion::V3, FunctionRegistry::default(), ); @@ -3305,14 +3294,14 @@ fn test_call_imm_does_not_dispatch_syscalls() { " call function_foo return - syscall {} + syscall bpf_syscall_string return function_foo: mov r0, 42 return", [], ( - 3 => "bpf_syscall_string" => syscalls::SyscallString::vm, + "bpf_syscall_string" => syscalls::SyscallString::vm, ), TestContextObject::new(4), ProgramResult::Ok(42), @@ -3910,12 +3899,12 @@ fn test_symbol_relocation() { mov64 r1, r10 add64 r1, -0x1 mov64 r2, 0x1 - syscall {} + syscall bpf_syscall_string mov64 r0, 0x0 exit", [72, 101, 108, 108, 111], ( - 1 => "bpf_syscall_string" => syscalls::SyscallString::vm, + "bpf_syscall_string" => syscalls::SyscallString::vm, ), TestContextObject::new(6), ProgramResult::Ok(0), diff --git a/tests/exercise_instructions.rs b/tests/exercise_instructions.rs index 7ceb9536..451d891f 100644 --- a/tests/exercise_instructions.rs +++ b/tests/exercise_instructions.rs @@ -19,7 +19,7 @@ use solana_sbpf::{ assembler::assemble, ebpf, memory_region::MemoryRegion, - program::{BuiltinFunction, BuiltinProgram, FunctionRegistry, SBPFVersion}, + program::{BuiltinProgram, SBPFVersion}, static_analysis::Analysis, verifier::RequisiteVerifier, vm::{Config, ContextObject}, @@ -441,8 +441,7 @@ fn test_ins(v0: bool, ins: String, prng: &mut SmallRng, cu: u64) { if v0 { config.enabled_sbpf_versions = SBPFVersion::V0..=SBPFVersion::V0; } - let function_registry = FunctionRegistry::>::default(); - let loader = Arc::new(BuiltinProgram::new_loader(config, function_registry)); + let loader = Arc::new(BuiltinProgram::new_loader(config)); let mut executable = assemble(asm.as_str(), loader).unwrap(); test_interpreter_and_jit!( override_budget => true, diff --git a/tests/jit.rs b/tests/jit.rs index 1f85bcfb..18f6bb10 100644 --- a/tests/jit.rs +++ b/tests/jit.rs @@ -20,9 +20,9 @@ use test_utils::{syscalls, TestContextObject}; fn create_mockup_executable(config: Config, program: &[u8]) -> Executable { let sbpf_version = *config.enabled_sbpf_versions.end(); - let mut loader = BuiltinProgram::new_loader_with_dense_registration(config); + let mut loader = BuiltinProgram::new_loader(config); loader - .register_function("gather_bytes", 1, syscalls::SyscallGatherBytes::vm) + .register_function("gather_bytes", syscalls::SyscallGatherBytes::vm) .unwrap(); let mut function_registry = FunctionRegistry::default(); function_registry @@ -112,7 +112,7 @@ fn test_code_length_estimate() { 0x85 if !sbpf_version.static_syscalls() => (0x00, Some(8)), 0x85 if sbpf_version.static_syscalls() => (0x00, None), 0x8D => (0x88, Some(0)), - 0x95 if sbpf_version.static_syscalls() => (0x00, Some(1)), + 0x95 if sbpf_version.static_syscalls() => (0x00, Some(0x91020CDD)), 0xE5 if !sbpf_version.static_syscalls() => { // Put external function calls on a separate loop iteration opcode = 0x85; diff --git a/tests/verifier.rs b/tests/verifier.rs index 68f880ab..74a6e782 100644 --- a/tests/verifier.rs +++ b/tests/verifier.rs @@ -161,13 +161,10 @@ fn test_verifier_err_lddw_cannot_be_last() { let prog = &[0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55]; let executable = Executable::::from_text_bytes( prog, - Arc::new(BuiltinProgram::new_loader( - Config { - enabled_sbpf_versions: SBPFVersion::V0..=highest_sbpf_version, - ..Config::default() - }, - FunctionRegistry::default(), - )), + Arc::new(BuiltinProgram::new_loader(Config { + enabled_sbpf_versions: SBPFVersion::V0..=highest_sbpf_version, + ..Config::default() + })), highest_sbpf_version, FunctionRegistry::default(), ) @@ -185,13 +182,10 @@ fn test_verifier_err_invalid_reg_dst() { " mov r11, 1 exit", - Arc::new(BuiltinProgram::new_loader( - Config { - enabled_sbpf_versions: SBPFVersion::V0..=highest_sbpf_version, - ..Config::default() - }, - FunctionRegistry::default(), - )), + Arc::new(BuiltinProgram::new_loader(Config { + enabled_sbpf_versions: SBPFVersion::V0..=highest_sbpf_version, + ..Config::default() + })), ) .unwrap(); let result = executable.verify::(); @@ -208,13 +202,10 @@ fn test_verifier_err_invalid_reg_src() { " mov r0, r11 exit", - Arc::new(BuiltinProgram::new_loader( - Config { - enabled_sbpf_versions: SBPFVersion::V0..=highest_sbpf_version, - ..Config::default() - }, - FunctionRegistry::default(), - )), + Arc::new(BuiltinProgram::new_loader(Config { + enabled_sbpf_versions: SBPFVersion::V0..=highest_sbpf_version, + ..Config::default() + })), ) .unwrap(); let result = executable.verify::(); @@ -229,13 +220,10 @@ fn test_verifier_resize_stack_ptr_success() { add r10, -64 add r10, 64 exit", - Arc::new(BuiltinProgram::new_loader( - Config { - enable_stack_frame_gaps: false, - ..Config::default() - }, - FunctionRegistry::default(), - )), + Arc::new(BuiltinProgram::new_loader(Config { + enable_stack_frame_gaps: false, + ..Config::default() + })), ) .unwrap(); executable.verify::().unwrap(); @@ -304,13 +292,10 @@ fn test_verifier_err_callx_cannot_use_r10() { callx r10 exit ", - Arc::new(BuiltinProgram::new_loader( - Config { - enabled_sbpf_versions: SBPFVersion::V0..=highest_sbpf_version, - ..Config::default() - }, - FunctionRegistry::default(), - )), + Arc::new(BuiltinProgram::new_loader(Config { + enabled_sbpf_versions: SBPFVersion::V0..=highest_sbpf_version, + ..Config::default() + })), ) .unwrap(); executable.verify::().unwrap(); @@ -390,10 +375,10 @@ fn test_verifier_err_invalid_exit() { } #[test] -#[should_panic(expected = "InvalidSyscall(2)")] +#[should_panic(expected = "InvalidSyscall(2432830685)")] fn test_verifier_unknown_syscall() { let prog = &[ - 0x95, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // syscall 2 + 0x95, 0x00, 0x00, 0x00, 0xDD, 0x0C, 0x02, 0x91, // syscall gather_bytes 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // return ]; let executable = Executable::::from_text_bytes( @@ -409,13 +394,13 @@ fn test_verifier_unknown_syscall() { #[test] fn test_verifier_known_syscall() { let prog = &[ - 0x95, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, // syscall 2 + 0x95, 0x00, 0x00, 0x00, 0xDD, 0x0C, 0x02, 0x91, // syscall gather_bytes 0x9d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // return ]; - let mut loader = BuiltinProgram::new_loader_with_dense_registration(Config::default()); + let mut loader = BuiltinProgram::new_loader(Config::default()); loader - .register_function("my_syscall", 2, syscalls::SyscallString::vm) + .register_function("gather_bytes", syscalls::SyscallString::vm) .unwrap(); let executable = Executable::::from_text_bytes( prog, @@ -492,13 +477,10 @@ fn test_sdiv_disabled() { let assembly = format!("\n{instruction}\nexit"); let executable = assemble::( &assembly, - Arc::new(BuiltinProgram::new_loader( - Config { - enabled_sbpf_versions: SBPFVersion::V0..=highest_sbpf_version, - ..Config::default() - }, - FunctionRegistry::default(), - )), + Arc::new(BuiltinProgram::new_loader(Config { + enabled_sbpf_versions: SBPFVersion::V0..=highest_sbpf_version, + ..Config::default() + })), ) .unwrap(); let result = executable.verify::(); @@ -541,13 +523,10 @@ fn return_in_v2() { let executable = assemble::( "mov r0, 2 return", - Arc::new(BuiltinProgram::new_loader( - Config { - enabled_sbpf_versions: SBPFVersion::V3..=SBPFVersion::V3, - ..Config::default() - }, - FunctionRegistry::default(), - )), + Arc::new(BuiltinProgram::new_loader(Config { + enabled_sbpf_versions: SBPFVersion::V3..=SBPFVersion::V3, + ..Config::default() + })), ) .unwrap(); let result = executable.verify::(); @@ -559,13 +538,10 @@ fn function_without_return() { let executable = assemble::( "mov r0, 2 add64 r0, 5", - Arc::new(BuiltinProgram::new_loader( - Config { - enabled_sbpf_versions: SBPFVersion::V3..=SBPFVersion::V3, - ..Config::default() - }, - FunctionRegistry::default(), - )), + Arc::new(BuiltinProgram::new_loader(Config { + enabled_sbpf_versions: SBPFVersion::V3..=SBPFVersion::V3, + ..Config::default() + })), ) .unwrap(); let result = executable.verify::(); diff --git a/tests/vm.rs b/tests/vm.rs index df40b6c3..c26a723d 100644 --- a/tests/vm.rs +++ b/tests/vm.rs @@ -2,7 +2,7 @@ use solana_sbpf::{ elf::Executable, - program::{BuiltinFunction, BuiltinProgram, FunctionRegistry}, + program::BuiltinProgram, vm::{Config, RuntimeEnvironmentSlot}, }; use std::{fs::File, io::Read, sync::Arc}; @@ -54,27 +54,24 @@ fn test_runtime_environment_slots() { #[test] fn test_builtin_program_eq() { - let mut function_registry_a = FunctionRegistry::>::default(); - function_registry_a - .register_function_hashed(*b"log", syscalls::SyscallString::vm) + let mut builtin_program_a = BuiltinProgram::new_loader(Config::default()); + let mut builtin_program_b = BuiltinProgram::new_loader(Config::default()); + let mut builtin_program_c = BuiltinProgram::new_loader(Config::default()); + builtin_program_a + .register_function("log", syscalls::SyscallString::vm) .unwrap(); - function_registry_a - .register_function_hashed(*b"log_64", syscalls::SyscallU64::vm) + builtin_program_a + .register_function("log_64", syscalls::SyscallU64::vm) .unwrap(); - let mut function_registry_b = FunctionRegistry::>::default(); - function_registry_b - .register_function_hashed(*b"log_64", syscalls::SyscallU64::vm) + builtin_program_b + .register_function("log_64", syscalls::SyscallU64::vm) .unwrap(); - function_registry_b - .register_function_hashed(*b"log", syscalls::SyscallString::vm) + builtin_program_b + .register_function("log", syscalls::SyscallString::vm) .unwrap(); - let mut function_registry_c = FunctionRegistry::>::default(); - function_registry_c - .register_function_hashed(*b"log_64", syscalls::SyscallU64::vm) + builtin_program_c + .register_function("log_64", syscalls::SyscallU64::vm) .unwrap(); - let builtin_program_a = BuiltinProgram::new_loader(Config::default(), function_registry_a); - let builtin_program_b = BuiltinProgram::new_loader(Config::default(), function_registry_b); assert_eq!(builtin_program_a, builtin_program_b); - let builtin_program_c = BuiltinProgram::new_loader(Config::default(), function_registry_c); assert_ne!(builtin_program_a, builtin_program_c); }