From 2e9ec24c95b80b7403451e2d09ce89d5379784f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Mon, 3 Oct 2022 18:48:53 +0200 Subject: [PATCH] Reduces having one syscall context object per syscall to having one per vm instance (#387) * Reduces having one syscall context object per syscall to having one per vm instance. * Removes DynTraitVtable and DynTraitFatPointer. --- benches/elf_loader.rs | 10 +- cli/src/main.rs | 35 +-- src/elf.rs | 18 +- src/interpreter.rs | 6 +- src/jit.rs | 13 +- src/syscalls.rs | 81 ++----- src/vm.rs | 171 +++----------- tests/misc.rs | 21 +- tests/ubpf_execution.rs | 484 ++++++++++++++++++++-------------------- 9 files changed, 316 insertions(+), 523 deletions(-) diff --git a/benches/elf_loader.rs b/benches/elf_loader.rs index fa0a2d46..c926ea97 100644 --- a/benches/elf_loader.rs +++ b/benches/elf_loader.rs @@ -12,8 +12,8 @@ extern crate test_utils; use solana_rbpf::{ elf::Executable, - syscalls::{BpfSyscallContext, BpfSyscallU64}, - vm::{Config, SyscallObject, SyscallRegistry, TestInstructionMeter}, + syscalls::BpfSyscallU64, + vm::{Config, SyscallRegistry, TestInstructionMeter}, }; use std::{fs::File, io::Read}; use test::Bencher; @@ -21,11 +21,7 @@ use test::Bencher; fn syscall_registry() -> SyscallRegistry { let mut syscall_registry = SyscallRegistry::default(); syscall_registry - .register_syscall_by_name( - b"log_64", - BpfSyscallU64::init::, - BpfSyscallU64::call, - ) + .register_syscall_by_name(b"log_64", BpfSyscallU64::call) .unwrap(); syscall_registry } diff --git a/cli/src/main.rs b/cli/src/main.rs index 9e99238c..450a5cc4 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -4,39 +4,15 @@ use solana_rbpf::{ debugger, ebpf, elf::Executable, interpreter::Interpreter, - memory_region::{MemoryMapping, MemoryRegion}, + memory_region::MemoryRegion, static_analysis::Analysis, verifier::RequisiteVerifier, vm::{ - Config, DynamicAnalysis, EbpfVm, ProgramResult, SyscallObject, SyscallRegistry, - TestInstructionMeter, VerifiedExecutable, + Config, DynamicAnalysis, EbpfVm, SyscallRegistry, TestInstructionMeter, VerifiedExecutable, }, }; use std::{fs::File, io::Read, path::Path}; -#[derive(Clone)] -struct MockSyscall { - name: String, -} -impl SyscallObject for MockSyscall { - fn call( - &mut self, - arg1: u64, - arg2: u64, - arg3: u64, - arg4: u64, - arg5: u64, - _memory_mapping: &mut MemoryMapping, - result: &mut ProgramResult, - ) { - println!( - "Syscall {}: {:#x}, {:#x}, {:#x}, {:#x}, {:#x}", - self.name, arg1, arg2, arg3, arg4, arg5, - ); - *result = ProgramResult::Ok(0); - } -} - fn main() { let matches = App::new("Solana RBPF CLI") .version(crate_version!()) @@ -210,7 +186,7 @@ fn main() { _ => {} } - vm.bind_syscall_context_objects(0).unwrap(); + vm.bind_syscall_context_object(&mut ()); let result = if matches.value_of("use").unwrap() == "debugger" { let mut interpreter = Interpreter::new(&mut vm, &mut instruction_meter).unwrap(); let port = matches.value_of("port").unwrap().parse::().unwrap(); @@ -225,12 +201,13 @@ fn main() { if matches.is_present("trace") { println!("Trace:\n"); let stdout = std::io::stdout(); - vm.get_tracer() + vm.get_program_environment() + .tracer .write(&mut stdout.lock(), analysis.as_ref().unwrap()) .unwrap(); } if matches.is_present("profile") { - let tracer = &vm.get_tracer(); + let tracer = &vm.get_program_environment().tracer; let dynamic_analysis = DynamicAnalysis::new(tracer, analysis.as_ref().unwrap()); let mut file = File::create("profile.dot").unwrap(); analysis diff --git a/src/elf.rs b/src/elf.rs index d4d0cae7..abd689a7 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -1213,8 +1213,8 @@ mod test { types::{Elf64Ehdr, Elf64Shdr}, }, fuzz::fuzz, - syscalls::{BpfSyscallContext, BpfSyscallString, BpfSyscallU64}, - vm::{ProgramResult, SyscallObject, TestInstructionMeter}, + syscalls::{BpfSyscallString, BpfSyscallU64}, + vm::{ProgramResult, TestInstructionMeter}, }; use rand::{distributions::Uniform, Rng}; use std::{fs::File, io::Read}; @@ -1223,18 +1223,10 @@ mod test { fn syscall_registry() -> SyscallRegistry { let mut syscall_registry = SyscallRegistry::default(); syscall_registry - .register_syscall_by_name( - b"log", - BpfSyscallString::init::, - BpfSyscallString::call, - ) + .register_syscall_by_name(b"log", BpfSyscallString::call) .unwrap(); syscall_registry - .register_syscall_by_name( - b"log_64", - BpfSyscallU64::init::, - BpfSyscallU64::call, - ) + .register_syscall_by_name(b"log_64", BpfSyscallU64::call) .unwrap(); syscall_registry } @@ -2242,6 +2234,6 @@ mod test { Executable::jit_compile(&mut executable).unwrap(); } - assert_eq!(18656, executable.mem_size()); + assert_eq!(18464, executable.mem_size()); } } diff --git a/src/interpreter.rs b/src/interpreter.rs index 05ceff80..740b03b6 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -18,7 +18,7 @@ use crate::{ error::EbpfError, memory_region::AccessType, verifier::Verifier, - vm::{EbpfVm, InstructionMeter, ProgramResult, SyscallFunction}, + vm::{EbpfVm, InstructionMeter, ProgramResult}, }; /// Translates a vm_addr into a host_addr and sets the pc in the error if one occurs @@ -457,8 +457,8 @@ impl<'a, 'b, V: Verifier, I: InstructionMeter> Interpreter<'a, 'b, V, I> { } self.due_insn_count = 0; let mut result = ProgramResult::Ok(0); - (unsafe { std::mem::transmute::>(syscall.function) })( - self.vm.program_environment.syscall_context_objects[syscall.context_object_slot], + syscall( + self.vm.program_environment.syscall_context_object, self.reg[1], self.reg[2], self.reg[3], diff --git a/src/jit.rs b/src/jit.rs index a76416e1..d874a007 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -25,7 +25,7 @@ use rand::{rngs::SmallRng, Rng, SeedableRng}; use crate::{ elf::Executable, - vm::{Config, ProgramResult, InstructionMeter, Tracer, ProgramEnvironment}, + vm::{Config, ProgramResult, InstructionMeter, Tracer, ProgramEnvironment, SyscallFunction}, ebpf::{self, INSN_SIZE, FIRST_SCRATCH_REG, SCRATCH_REGS, FRAME_PTR_REG, MM_STACK_START, STACK_PTR_REG}, error::EbpfError, memory_region::{AccessType, MemoryMapping}, @@ -946,7 +946,7 @@ impl JitCompiler { if config.encrypt_environment_registers { ( diversification_rng.gen::() / 16, // -3 bits for 8 Byte alignment, and -1 bit to have encoding space for EnvironmentStackSlot::SlotCount - diversification_rng.gen::() / 2, // -1 bit to have encoding space for (ProgramEnvironment::SYSCALLS_OFFSET + syscall.context_object_slot) * 8 + diversification_rng.gen::() / 2, // -1 bit to have encoding space for (ProgramEnvironment::SYSCALL_CONTEXT_OBJECT + syscall.context_object_slot) * 8 ) } else { (0, 0) }; @@ -1226,8 +1226,8 @@ impl JitCompiler { if self.config.enable_instruction_meter { emit_validate_and_profile_instruction_count(self, true, Some(0)); } - emit_ins(self, X86Instruction::load_immediate(OperandSize::S64, R11, syscall.function as *const u8 as i64)); - emit_ins(self, X86Instruction::load(OperandSize::S64, R10, RAX, X86IndirectAccess::Offset(ProgramEnvironment::SYSCALLS_OFFSET as i32 + syscall.context_object_slot as i32 * 8 + self.program_argument_key))); + emit_ins(self, X86Instruction::load_immediate(OperandSize::S64, R11, syscall as *const SyscallFunction<*mut ()> as i64)); + emit_ins(self, X86Instruction::load(OperandSize::S64, R10, RAX, X86IndirectAccess::Offset(ProgramEnvironment::SYSCALL_CONTEXT_OBJECT as i32 + self.program_argument_key))); emit_ins(self, X86Instruction::call_immediate(self.relative_to_anchor(ANCHOR_SYSCALL, 5))); if self.config.enable_instruction_meter { emit_undo_profile_instruction_count(self, 0); @@ -1503,7 +1503,7 @@ impl JitCompiler { Argument { index: 3, value: Value::Register(ARGUMENT_REGISTERS[3]) }, Argument { index: 2, value: Value::Register(ARGUMENT_REGISTERS[2]) }, Argument { index: 1, value: Value::Register(ARGUMENT_REGISTERS[1]) }, - Argument { index: 0, value: Value::Register(RAX) }, // "&mut self" in the "call" method of the SyscallObject + Argument { index: 0, value: Value::Register(RAX) }, // "&mut self" in the "call" method of the syscall ], None); if self.config.enable_instruction_meter { emit_rust_call(self, Value::Constant64(I::get_remaining as *const u8 as i64, false), &[ @@ -1699,7 +1699,7 @@ impl JitCompiler { #[cfg(all(test, target_arch = "x86_64", not(target_os = "windows")))] mod tests { use super::*; - use crate::{syscalls, vm::{SyscallRegistry, SyscallObject, TestInstructionMeter}, elf::register_bpf_function}; + use crate::{syscalls, vm::{SyscallRegistry, TestInstructionMeter}, elf::register_bpf_function}; use std::collections::BTreeMap; use byteorder::{LittleEndian, ByteOrder}; @@ -1712,7 +1712,6 @@ mod tests { syscall_registry .register_syscall_by_hash( 0xFFFFFFFF, - syscalls::BpfGatherBytes::init::, syscalls::BpfGatherBytes::call, ) .unwrap(); diff --git a/src/syscalls.rs b/src/syscalls.rs index ac599ec1..4f2a715a 100644 --- a/src/syscalls.rs +++ b/src/syscalls.rs @@ -1,4 +1,5 @@ #![allow(clippy::integer_arithmetic)] +#![allow(clippy::too_many_arguments)] // Copyright 2015 Big Switch Networks, Inc // (Algorithms for uBPF syscalls, originally in C) // Copyright 2016 6WIND S.A. @@ -22,11 +23,11 @@ use crate::{ memory_region::{AccessType, MemoryMapping}, - vm::{ProgramResult, SyscallObject}, + vm::ProgramResult, }; use std::{slice::from_raw_parts, str::from_utf8}; -/// Error handling for SyscallObject::call methods +/// Error handling for syscall methods macro_rules! question_mark { ( $value:expr, $result:ident ) => {{ let value = $value; @@ -40,9 +41,6 @@ macro_rules! question_mark { }}; } -/// Test syscall context -pub type BpfSyscallContext = u64; - // bpf_trace_printk() /// Index of syscall `bpf_trace_printk()`, equivalent to `bpf_trace_printf`, in Linux kernel, see @@ -60,7 +58,7 @@ pub const BPF_TRACE_PRINTK_IDX: u32 = 6; /// ``` /// use solana_rbpf::syscalls::BpfTracePrintf; /// use solana_rbpf::memory_region::{MemoryRegion, MemoryMapping}; -/// use solana_rbpf::vm::{Config, SyscallObject, ProgramResult}; +/// use solana_rbpf::vm::{Config, ProgramResult}; /// /// let mut result = ProgramResult::Ok(0); /// let config = Config::default(); @@ -91,13 +89,8 @@ pub const BPF_TRACE_PRINTK_IDX: u32 = 6; /// program is run. pub struct BpfTracePrintf {} impl BpfTracePrintf { - /// new - pub fn init(_unused: C) -> Box { - Box::new(Self {}) - } -} -impl SyscallObject for BpfTracePrintf { - fn call( + /// Syscall handler method + pub fn call( &mut self, _arg1: u64, _arg2: u64, @@ -134,7 +127,7 @@ impl SyscallObject for BpfTracePrintf { /// ``` /// use solana_rbpf::syscalls::BpfGatherBytes; /// use solana_rbpf::memory_region::{MemoryRegion, MemoryMapping}; -/// use solana_rbpf::vm::{Config, SyscallObject, ProgramResult}; +/// use solana_rbpf::vm::{Config, ProgramResult}; /// /// let mut result = ProgramResult::Ok(0); /// let config = Config::default(); @@ -144,13 +137,8 @@ impl SyscallObject for BpfTracePrintf { /// ``` pub struct BpfGatherBytes {} impl BpfGatherBytes { - /// new - pub fn init(_unused: C) -> Box { - Box::new(Self {}) - } -} -impl SyscallObject for BpfGatherBytes { - fn call( + /// Syscall handler method + pub fn call( &mut self, arg1: u64, arg2: u64, @@ -179,7 +167,7 @@ impl SyscallObject for BpfGatherBytes { /// ``` /// use solana_rbpf::syscalls::BpfMemFrob; /// use solana_rbpf::memory_region::{MemoryRegion, MemoryMapping}; -/// use solana_rbpf::vm::{Config, SyscallObject, ProgramResult}; +/// use solana_rbpf::vm::{Config, ProgramResult}; /// /// let mut val = &mut [0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x22, 0x33]; /// let val_va = 0x100000000; @@ -194,13 +182,8 @@ impl SyscallObject for BpfGatherBytes { /// ``` pub struct BpfMemFrob {} impl BpfMemFrob { - /// new - pub fn init(_unused: C) -> Box { - Box::new(Self {}) - } -} -impl SyscallObject for BpfMemFrob { - fn call( + /// Syscall handler method + pub fn call( &mut self, vm_addr: u64, len: u64, @@ -228,7 +211,7 @@ impl SyscallObject for BpfMemFrob { /// ``` /// use solana_rbpf::syscalls::BpfStrCmp; /// use solana_rbpf::memory_region::{MemoryRegion, MemoryMapping}; -/// use solana_rbpf::vm::{Config, SyscallObject, ProgramResult}; +/// use solana_rbpf::vm::{Config, ProgramResult}; /// /// let foo = "This is a string."; /// let bar = "This is another sting."; @@ -247,13 +230,8 @@ impl SyscallObject for BpfMemFrob { /// ``` pub struct BpfStrCmp {} impl BpfStrCmp { - /// new - pub fn init(_unused: C) -> Box { - Box::new(Self {}) - } -} -impl SyscallObject for BpfStrCmp { - fn call( + /// Syscall handler method + pub fn call( &mut self, arg1: u64, arg2: u64, @@ -293,13 +271,8 @@ impl SyscallObject for BpfStrCmp { /// Prints a NULL-terminated UTF-8 string. pub struct BpfSyscallString {} impl BpfSyscallString { - /// new - pub fn init(_unused: C) -> Box { - Box::new(Self {}) - } -} -impl SyscallObject for BpfSyscallString { - fn call( + /// Syscall handler method + pub fn call( &mut self, vm_addr: u64, len: u64, @@ -329,13 +302,8 @@ impl SyscallObject for BpfSyscallString { /// Prints the five arguments formated as u64 in decimal. pub struct BpfSyscallU64 {} impl BpfSyscallU64 { - /// new - pub fn init(_unused: C) -> Box { - Box::new(Self {}) - } -} -impl SyscallObject for BpfSyscallU64 { - fn call( + /// Syscall handler method + pub fn call( &mut self, arg1: u64, arg2: u64, @@ -356,16 +324,11 @@ impl SyscallObject for BpfSyscallU64 { /// Example of a syscall with internal state. pub struct SyscallWithContext { /// Mutable state - pub context: BpfSyscallContext, + pub context: u64, } impl SyscallWithContext { - /// new - pub fn init(context: BpfSyscallContext) -> Box { - Box::new(Self { context }) - } -} -impl SyscallObject for SyscallWithContext { - fn call( + /// Syscall handler method + pub fn call( &mut self, arg1: u64, arg2: u64, diff --git a/src/vm.rs b/src/vm.rs index bbab0b22..180a4814 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -95,102 +95,34 @@ impl From> for StableResult { /// Return value of programs and syscalls pub type ProgramResult = StableResult; -/// Syscall initialization function -pub type SyscallInit<'a, C> = fn(C) -> Box<(dyn SyscallObject + 'a)>; - /// Syscall function without context pub type SyscallFunction = fn(O, u64, u64, u64, u64, u64, &mut MemoryMapping, &mut ProgramResult); -/// Syscall with context -pub trait SyscallObject { - /// Call the syscall function - #[allow(clippy::too_many_arguments)] - fn call( - &mut self, - arg1: u64, - arg2: u64, - arg3: u64, - arg4: u64, - arg5: u64, - memory_mapping: &mut MemoryMapping, - result: &mut ProgramResult, - ); -} - -/// Syscall function and binding slot for a context object -#[derive(Debug, PartialEq, Eq)] -pub struct Syscall { - /// Syscall init - pub init: u64, - /// Call the syscall function - pub function: u64, - /// Slot of context object - pub context_object_slot: usize, -} - -/// A virtual method table for dyn trait objects -pub struct DynTraitVtable { - /// Drops the dyn trait object - pub drop: fn(*const u8), - /// Size of the dyn trait object in bytes - pub size: usize, - /// Alignment of the dyn trait object in bytes - pub align: usize, - /// The methods of the trait - pub methods: [*const u8; 32], -} - -// Could be replaced by https://doc.rust-lang.org/std/raw/struct.TraitObject.html -/// A dyn trait fat pointer for SyscallObject -#[derive(Clone, Copy)] -pub struct DynTraitFatPointer { - /// Pointer to the actual object - pub data: *mut u8, - /// Pointer to the virtual method table - pub vtable: &'static DynTraitVtable, -} - /// Holds the syscall function pointers of an Executable #[derive(Debug, PartialEq, Eq, Default)] pub struct SyscallRegistry { /// Function pointers by symbol - entries: HashMap, - /// Context object slots by function pointer - context_object_slots: HashMap, + entries: HashMap, } impl SyscallRegistry { const MAX_SYSCALLS: usize = 128; /// Register a syscall function by its symbol hash - pub fn register_syscall_by_hash<'a, C, O: SyscallObject>( + pub fn register_syscall_by_hash( &mut self, hash: u32, - init: SyscallInit<'a, C>, - function: SyscallFunction<&mut O>, + function: SyscallFunction, ) -> Result<(), EbpfError> { - let init = init as *const u8 as u64; - let function = function as *const u8 as u64; let context_object_slot = self.entries.len(); if context_object_slot == SyscallRegistry::MAX_SYSCALLS { return Err(EbpfError::TooManySyscalls); } if self .entries - .insert( - hash, - Syscall { - init, - function, - context_object_slot, - }, - ) + .insert(hash, function as usize as u64) .is_some() - || self - .context_object_slots - .insert(function, context_object_slot) - .is_some() { Err(EbpfError::SyscallAlreadyRegistered(hash as usize)) } else { @@ -199,23 +131,19 @@ impl SyscallRegistry { } /// Register a syscall function by its symbol name - pub fn register_syscall_by_name<'a, C, O: SyscallObject>( + pub fn register_syscall_by_name( &mut self, name: &[u8], - init: SyscallInit<'a, C>, - function: SyscallFunction<&mut O>, + function: SyscallFunction, ) -> Result<(), EbpfError> { - self.register_syscall_by_hash::(ebpf::hash_symbol_name(name), init, function) + self.register_syscall_by_hash::(ebpf::hash_symbol_name(name), function) } - /// Get a symbol's function pointer and context object slot - pub fn lookup_syscall(&self, hash: u32) -> Option<&Syscall> { - self.entries.get(&hash) - } - - /// Get a function pointer's and context object slot - pub fn lookup_context_object_slot(&self, function_pointer: u64) -> Option { - self.context_object_slots.get(&function_pointer).copied() + /// Get a symbol's function pointer + pub fn lookup_syscall(&self, hash: u32) -> Option> { + self.entries + .get(&hash) + .map(|syscall| unsafe { std::mem::transmute(*syscall) }) } /// Get the number of registered syscalls @@ -226,8 +154,7 @@ impl SyscallRegistry { /// Calculate memory size pub fn mem_size(&self) -> usize { mem::size_of::() - + self.entries.capacity() * mem::size_of::<(u32, Syscall)>() - + self.context_object_slots.capacity() * mem::size_of::<(u64, usize)>() + + self.entries.capacity() * mem::size_of::<(u32, SyscallFunction<*mut ()>)>() } } @@ -525,7 +452,6 @@ pub struct EbpfVm<'a, V: Verifier, I: InstructionMeter> { pub(crate) program: &'a [u8], pub(crate) program_vm_addr: u64, pub(crate) program_environment: ProgramEnvironment<'a>, - syscall_context_object_pool: Vec>, pub(crate) stack: CallFrames<'a>, pub(crate) total_insn_count: u64, } @@ -569,17 +495,15 @@ impl<'a, V: Verifier, I: InstructionMeter> EbpfVm<'a, V, I> { .chain(additional_regions.into_iter()) .collect(); let (program_vm_addr, program) = executable.get_text_bytes(); - let number_of_syscalls = executable.get_syscall_registry().get_number_of_syscalls(); let vm = EbpfVm { verified_executable, program, program_vm_addr, program_environment: ProgramEnvironment { memory_mapping: MemoryMapping::new(regions, config)?, - syscall_context_objects: [ptr::null_mut(); SyscallRegistry::MAX_SYSCALLS], + syscall_context_object: ptr::null_mut(), tracer: Tracer::default(), }, - syscall_context_object_pool: Vec::with_capacity(number_of_syscalls), stack, total_insn_count: 0, }; @@ -598,8 +522,8 @@ impl<'a, V: Verifier, I: InstructionMeter> EbpfVm<'a, V, I> { } /// Returns the tracer - pub fn get_tracer(&self) -> &Tracer { - &self.program_environment.tracer + pub fn get_program_environment(&self) -> &ProgramEnvironment { + &self.program_environment } /// Initializes and binds the context object instances for all previously registered syscalls @@ -607,7 +531,7 @@ impl<'a, V: Verifier, I: InstructionMeter> EbpfVm<'a, V, I> { /// # Examples /// /// ``` - /// use solana_rbpf::{ebpf, elf::{Executable, register_bpf_function}, vm::{Config, EbpfVm, SyscallObject, SyscallRegistry, TestInstructionMeter, VerifiedExecutable}, syscalls::BpfTracePrintf, verifier::RequisiteVerifier}; + /// use solana_rbpf::{ebpf, elf::{Executable, register_bpf_function}, vm::{Config, EbpfVm, SyscallRegistry, TestInstructionMeter, VerifiedExecutable}, syscalls::BpfTracePrintf, verifier::RequisiteVerifier}; /// /// // This program was compiled with clang, from a C program containing the following single /// // instruction: `return bpf_trace_printk("foo %c %c %c\n", 10, 1, 2, 3);` @@ -628,7 +552,7 @@ impl<'a, V: Verifier, I: InstructionMeter> EbpfVm<'a, V, I> { /// // On running the program this syscall will print the content of registers r3, r4 and r5 to /// // standard output. /// let mut syscall_registry = SyscallRegistry::default(); - /// syscall_registry.register_syscall_by_hash(6, BpfTracePrintf::init::, BpfTracePrintf::call).unwrap(); + /// syscall_registry.register_syscall_by_hash(6, BpfTracePrintf::call).unwrap(); /// // Instantiate an Executable and VM /// let config = Config::default(); /// let mut bpf_functions = std::collections::BTreeMap::new(); @@ -637,47 +561,11 @@ impl<'a, V: Verifier, I: InstructionMeter> EbpfVm<'a, V, I> { /// let verified_executable = VerifiedExecutable::::from_executable(executable).unwrap(); /// let mut vm = EbpfVm::new(&verified_executable, &mut [], Vec::new()).unwrap(); /// // Bind a context object instance to the previously registered syscall - /// vm.bind_syscall_context_objects(0); + /// vm.bind_syscall_context_object(&mut ()); /// ``` - pub fn bind_syscall_context_objects( - &mut self, - syscall_context: C, - ) -> Result<(), EbpfError> { - let syscall_registry = self - .verified_executable - .get_executable() - .get_syscall_registry(); - - for syscall in syscall_registry.entries.values() { - let syscall_object_init_fn: SyscallInit = - unsafe { std::mem::transmute(syscall.init) }; - let syscall_context_object: Box = - syscall_object_init_fn(syscall_context.clone()); - let fat_ptr: DynTraitFatPointer = - unsafe { std::mem::transmute(&*syscall_context_object) }; - let slot = syscall_registry - .lookup_context_object_slot(fat_ptr.vtable.methods[0] as u64) - .ok_or(EbpfError::SyscallNotRegistered( - fat_ptr.vtable.methods[0] as usize, - ))?; - - debug_assert!(self.program_environment.syscall_context_objects[slot].is_null()); - self.program_environment.syscall_context_objects[slot] = fat_ptr.data; - // Keep the dyn trait objects so that they can be dropped properly later - self.syscall_context_object_pool - .push(syscall_context_object); - } - - Ok(()) - } - - /// Lookup a syscall context object by its function pointer. Used for testing and validation. - pub fn get_syscall_context_object(&self, syscall_function: usize) -> Option<*mut u8> { - self.verified_executable - .get_executable() - .get_syscall_registry() - .lookup_context_object_slot(syscall_function as u64) - .map(|slot| self.program_environment.syscall_context_objects[slot]) + pub fn bind_syscall_context_object(&mut self, syscall_context_object: &mut O) { + self.program_environment.syscall_context_object = + syscall_context_object as *mut O as *mut (); } /// Execute the program loaded, with the given packet data. @@ -794,8 +682,8 @@ impl<'a, V: Verifier, I: InstructionMeter> EbpfVm<'a, V, I> { pub struct ProgramEnvironment<'a> { /// The MemoryMapping describing the address space of the program pub memory_mapping: MemoryMapping<'a>, - /// Pointers to the context objects of syscalls - pub syscall_context_objects: [*mut u8; SyscallRegistry::MAX_SYSCALLS], + /// Pointer to the context object of syscalls + pub syscall_context_object: *mut (), /// The instruction tracer pub tracer: Tracer, } @@ -804,11 +692,10 @@ impl<'a> ProgramEnvironment<'a> { /// Offset to Self::memory_mapping pub const MEMORY_MAPPING_OFFSET: usize = 0; /// Offset of Self::syscalls - pub const SYSCALLS_OFFSET: usize = + pub const SYSCALL_CONTEXT_OBJECT: usize = Self::MEMORY_MAPPING_OFFSET + mem::size_of::(); /// Offset of Self::tracer - pub const TRACER_OFFSET: usize = - Self::SYSCALLS_OFFSET + mem::size_of::<[*mut u8; SyscallRegistry::MAX_SYSCALLS]>(); + pub const TRACER_OFFSET: usize = Self::SYSCALL_CONTEXT_OBJECT + mem::size_of::<*mut ()>(); } #[cfg(test)] @@ -828,7 +715,7 @@ mod tests { let config = Config::default(); let env = ProgramEnvironment { memory_mapping: MemoryMapping::new(vec![], &config).unwrap(), - syscall_context_objects: [ptr::null_mut(); SyscallRegistry::MAX_SYSCALLS], + syscall_context_object: ptr::null_mut(), tracer: Tracer::default(), }; assert_eq!( @@ -840,10 +727,10 @@ mod tests { ); assert_eq!( unsafe { - (&env.syscall_context_objects as *const _ as *const u8) + (&env.syscall_context_object as *const _ as *const u8) .offset_from(&env as *const _ as *const _) }, - ProgramEnvironment::SYSCALLS_OFFSET as isize + ProgramEnvironment::SYSCALL_CONTEXT_OBJECT as isize ); assert_eq!( unsafe { diff --git a/tests/misc.rs b/tests/misc.rs index b2deddc6..b707a63b 100644 --- a/tests/misc.rs +++ b/tests/misc.rs @@ -25,11 +25,9 @@ extern crate test_utils; use solana_rbpf::{ elf::Executable, fuzz::fuzz, - syscalls::{BpfSyscallContext, BpfSyscallString, BpfSyscallU64}, + syscalls::{BpfSyscallString, BpfSyscallU64}, verifier::RequisiteVerifier, - vm::{ - Config, EbpfVm, SyscallObject, SyscallRegistry, TestInstructionMeter, VerifiedExecutable, - }, + vm::{Config, EbpfVm, SyscallRegistry, TestInstructionMeter, VerifiedExecutable}, }; use std::{fs::File, io::Read}; @@ -116,18 +114,10 @@ fn test_fuzz_execute() { |bytes: &mut [u8]| { let mut syscall_registry = SyscallRegistry::default(); syscall_registry - .register_syscall_by_name( - b"log", - BpfSyscallString::init::, - BpfSyscallString::call, - ) + .register_syscall_by_name(b"log", BpfSyscallString::call) .unwrap(); syscall_registry - .register_syscall_by_name( - b"log_64", - BpfSyscallU64::init::, - BpfSyscallU64::call, - ) + .register_syscall_by_name(b"log_64", BpfSyscallU64::call) .unwrap(); if let Ok(executable) = Executable::::from_elf( bytes, @@ -145,8 +135,7 @@ fn test_fuzz_execute() { Vec::new(), ) .unwrap(); - vm.bind_syscall_context_objects(0).unwrap(); - vm.bind_syscall_context_objects(0).unwrap(); + vm.bind_syscall_context_object(&mut ()); let _ = vm.execute_program_interpreted(&mut TestInstructionMeter { remaining: 1_000_000, }); diff --git a/tests/ubpf_execution.rs b/tests/ubpf_execution.rs index 655cd93d..9d11ce5a 100644 --- a/tests/ubpf_execution.rs +++ b/tests/ubpf_execution.rs @@ -21,25 +21,21 @@ use solana_rbpf::{ elf::{register_bpf_function, ElfError, Executable}, error::EbpfError, memory_region::{AccessType, MemoryMapping, MemoryRegion}, - syscalls::{self, BpfSyscallContext}, + syscalls, verifier::RequisiteVerifier, vm::{ - Config, EbpfVm, ProgramResult, SyscallObject, SyscallRegistry, TestInstructionMeter, - VerifiedExecutable, + Config, EbpfVm, ProgramResult, SyscallRegistry, TestInstructionMeter, VerifiedExecutable, }, }; use std::{collections::BTreeMap, fs::File, io::Read}; use test_utils::{PROG_TCP_PORT_80, TCP_SACK_ASM, TCP_SACK_MATCH, TCP_SACK_NOMATCH}; macro_rules! test_interpreter_and_jit { - (register, $syscall_registry:expr, $location:expr => $syscall_init:expr; $syscall_function:expr) => { + (register, $syscall_registry:expr, $location:expr => $syscall_function:expr) => { $syscall_registry - .register_syscall_by_name($location, $syscall_init, $syscall_function) + .register_syscall_by_name($location, $syscall_function) .unwrap(); }; - (bind, $vm:expr, $syscall_context:expr) => { - $vm.bind_syscall_context_objects($syscall_context).unwrap(); - }; ($executable:expr, $mem:tt, $syscall_context:expr, $check:block, $expected_instruction_count:expr) => { #[allow(unused_mut)] let mut check_closure = $check; @@ -54,12 +50,15 @@ macro_rules! test_interpreter_and_jit { let mem_region = MemoryRegion::new_writable(&mut mem, ebpf::MM_INPUT_START); let mut vm = EbpfVm::new(&verified_executable, &mut [], vec![mem_region]).unwrap(); - test_interpreter_and_jit!(bind, vm, $syscall_context); + vm.bind_syscall_context_object($syscall_context); let result = vm.execute_program_interpreted(&mut TestInstructionMeter { remaining: $expected_instruction_count, }); assert!(check_closure(&vm, result)); - (vm.get_total_instruction_count(), vm.get_tracer().clone()) + ( + vm.get_total_instruction_count(), + vm.get_program_environment().tracer.clone(), + ) }; #[cfg(all(not(windows), target_arch = "x86_64"))] { @@ -72,11 +71,11 @@ macro_rules! test_interpreter_and_jit { match compilation_result { Err(err) => assert!(check_closure(&vm, ProgramResult::Err(err))), Ok(()) => { - test_interpreter_and_jit!(bind, vm, $syscall_context); + vm.bind_syscall_context_object($syscall_context); let result = vm.execute_program_jit(&mut TestInstructionMeter { remaining: $expected_instruction_count, }); - let tracer_jit = vm.get_tracer(); + let tracer_jit = &vm.get_program_environment().tracer; if !check_closure(&vm, result) || !solana_rbpf::vm::Tracer::compare(&_tracer_interpreter, tracer_jit) { @@ -113,46 +112,46 @@ macro_rules! test_interpreter_and_jit { } macro_rules! test_interpreter_and_jit_asm { - ($source:tt, $config:tt, $mem:tt, ($($location:expr => $syscall_init:expr; $syscall_function:expr),* $(,)?), $syscall_context:expr, $check:block, $expected_instruction_count:expr) => { + ($source:tt, $config:tt, $mem:tt, ($($location:expr => $syscall_function:expr),* $(,)?), $syscall_context:expr, $check:block, $expected_instruction_count:expr) => { #[allow(unused_mut)] { let mut syscall_registry = SyscallRegistry::default(); - $(test_interpreter_and_jit!(register, syscall_registry, $location => $syscall_init; $syscall_function);)* + $(test_interpreter_and_jit!(register, syscall_registry, $location => $syscall_function);)* let mut executable = assemble($source, $config, syscall_registry).unwrap(); test_interpreter_and_jit!(executable, $mem, $syscall_context, $check, $expected_instruction_count); } }; - ($source:tt, $mem:tt, ($($location:expr => $syscall_init:expr; $syscall_function:expr),* $(,)?), $syscall_context:expr, $check:block, $expected_instruction_count:expr) => { + ($source:tt, $mem:tt, ($($location:expr => $syscall_function:expr),* $(,)?), $syscall_context:expr, $check:block, $expected_instruction_count:expr) => { #[allow(unused_mut)] { let config = Config { enable_instruction_tracing: true, ..Config::default() }; - test_interpreter_and_jit_asm!($source, config, $mem, ($($location => $syscall_init; $syscall_function),*), $syscall_context, $check, $expected_instruction_count); + test_interpreter_and_jit_asm!($source, config, $mem, ($($location => $syscall_function),*), $syscall_context, $check, $expected_instruction_count); } }; } macro_rules! test_interpreter_and_jit_elf { - ($source:tt, $config:tt, $mem:tt, ($($location:expr => $syscall_init:expr; $syscall_function:expr),* $(,)?), $syscall_context:expr, $check:block, $expected_instruction_count:expr) => { + ($source:tt, $config:tt, $mem:tt, ($($location:expr => $syscall_function:expr),* $(,)?), $syscall_context:expr, $check:block, $expected_instruction_count: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 syscall_registry = SyscallRegistry::default(); - $(test_interpreter_and_jit!(register, syscall_registry, $location => $syscall_init; $syscall_function);)* + $(test_interpreter_and_jit!(register, syscall_registry, $location => $syscall_function);)* let mut executable = Executable::::from_elf(&elf, $config, syscall_registry).unwrap(); test_interpreter_and_jit!(executable, $mem, $syscall_context, $check, $expected_instruction_count); } }; - ($source:tt, $mem:tt, ($($location:expr => $syscall_init:expr; $syscall_function:expr),* $(,)?), $syscall_context:expr, $check:block, $expected_instruction_count:expr) => { + ($source:tt, $mem:tt, ($($location:expr => $syscall_function:expr),* $(,)?), $syscall_context:expr, $check:block, $expected_instruction_count:expr) => { let config = Config { enable_instruction_tracing: true, ..Config::default() }; - test_interpreter_and_jit_elf!($source, config, $mem, ($($location => $syscall_init; $syscall_function),*), $syscall_context, $check, $expected_instruction_count); + test_interpreter_and_jit_elf!($source, config, $mem, ($($location => $syscall_function),*), $syscall_context, $check, $expected_instruction_count); }; } @@ -167,7 +166,7 @@ fn test_mov() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 3 ); @@ -181,7 +180,7 @@ fn test_mov32_imm_large() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xffffffff } }, 2 ); @@ -196,7 +195,7 @@ fn test_mov_large() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xffffffff } }, 3 ); @@ -215,7 +214,7 @@ fn test_bounce() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 7 ); @@ -232,7 +231,7 @@ fn test_add32() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x3 } }, 5 ); @@ -247,7 +246,7 @@ fn test_neg32() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xfffffffe } }, 3 ); @@ -262,7 +261,7 @@ fn test_neg64() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xfffffffffffffffe } }, 3 ); @@ -293,7 +292,7 @@ fn test_alu32_arithmetic() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x2a } }, 19 ); @@ -324,7 +323,7 @@ fn test_alu64_arithmetic() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x2a } }, 19 ); @@ -378,7 +377,7 @@ fn test_mul128() { exit", [0; 16], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 600 } }, 42 ); @@ -411,7 +410,7 @@ fn test_alu32_logic() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x11 } }, 21 ); @@ -446,7 +445,7 @@ fn test_alu64_logic() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x11 } }, 23 ); @@ -462,7 +461,7 @@ fn test_arsh32_high_shift() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x4 } }, 4 ); @@ -478,7 +477,7 @@ fn test_arsh32_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xffff8000 } }, 4 ); @@ -495,7 +494,7 @@ fn test_arsh32_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xffff8000 } }, 5 ); @@ -513,7 +512,7 @@ fn test_arsh64() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xfffffffffffffff8 } }, 6 ); @@ -529,7 +528,7 @@ fn test_lsh64_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x10 } }, 4 ); @@ -545,7 +544,7 @@ fn test_rhs32_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x00ffffff } }, 4 ); @@ -561,7 +560,7 @@ fn test_rsh64_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 4 ); @@ -576,7 +575,7 @@ fn test_be16() { exit", [0x11, 0x22], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1122 } }, 3 ); @@ -591,7 +590,7 @@ fn test_be16_high() { exit", [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1122 } }, 3 ); @@ -606,7 +605,7 @@ fn test_be32() { exit", [0x11, 0x22, 0x33, 0x44], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x11223344 } }, 3 ); @@ -621,7 +620,7 @@ fn test_be32_high() { exit", [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x11223344 } }, 3 ); @@ -636,7 +635,7 @@ fn test_be64() { exit", [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1122334455667788 } }, 3 ); @@ -651,7 +650,7 @@ fn test_le16() { exit", [0x22, 0x11], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1122 } }, 3 ); @@ -666,7 +665,7 @@ fn test_le16_high() { exit", [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x2211 } }, 3 ); @@ -681,7 +680,7 @@ fn test_le32() { exit", [0x44, 0x33, 0x22, 0x11], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x11223344 } }, 3 ); @@ -696,7 +695,7 @@ fn test_le32_high() { exit", [0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x44332211 } }, 3 ); @@ -711,7 +710,7 @@ fn test_le64() { exit", [0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1122334455667788 } }, 3 ); @@ -726,7 +725,7 @@ fn test_mul32_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xc } }, 3 ); @@ -742,7 +741,7 @@ fn test_mul32_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xc } }, 4 ); @@ -758,7 +757,7 @@ fn test_mul32_reg_overflow() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x4 } }, 4 ); @@ -773,7 +772,7 @@ fn test_mul64_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x100000004 } }, 3 ); @@ -789,7 +788,7 @@ fn test_mul64_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x100000004 } }, 4 ); @@ -805,7 +804,7 @@ fn test_div32_high_divisor() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x3 } }, 4 ); @@ -820,7 +819,7 @@ fn test_div32_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x3 } }, 3 ); @@ -836,7 +835,7 @@ fn test_div32_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x3 } }, 4 ); @@ -851,7 +850,7 @@ fn test_sdiv32_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xFFFFFFFFE0000000 } }, 3 ); @@ -866,7 +865,7 @@ fn test_sdiv32_neg_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() as i64 == -0xc } }, 3 ); @@ -882,7 +881,7 @@ fn test_sdiv32_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xFFFFFFFFE0000000 } }, 4 ); @@ -898,7 +897,7 @@ fn test_sdiv32_neg_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() as i64 == -0xc } }, 4 ); @@ -914,7 +913,7 @@ fn test_div64_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x300000000 } }, 4 ); @@ -931,7 +930,7 @@ fn test_div64_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x300000000 } }, 5 ); @@ -947,7 +946,7 @@ fn test_sdiv64_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x300000000 } }, 4 ); @@ -964,7 +963,7 @@ fn test_sdiv64_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x300000000 } }, 5 ); @@ -980,7 +979,7 @@ fn test_err_div64_by_zero_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| matches!(res.unwrap_err(), EbpfError::DivideByZero(pc) if pc == 31) }, @@ -998,7 +997,7 @@ fn test_err_div32_by_zero_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| matches!(res.unwrap_err(), EbpfError::DivideByZero(pc) if pc == 31) }, @@ -1016,7 +1015,7 @@ fn test_err_sdiv64_by_zero_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| matches!(res.unwrap_err(), EbpfError::DivideByZero(pc) if pc == 31) }, @@ -1034,7 +1033,7 @@ fn test_err_sdiv32_by_zero_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| matches!(res.unwrap_err(), EbpfError::DivideByZero(pc) if pc == 31) }, @@ -1052,7 +1051,7 @@ fn test_err_sdiv64_overflow_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| matches!(res.unwrap_err(), EbpfError::DivideOverflow(pc) if pc == 31) }, @@ -1071,7 +1070,7 @@ fn test_err_sdiv64_overflow_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| matches!(res.unwrap_err(), EbpfError::DivideOverflow(pc) if pc == 32) }, @@ -1089,7 +1088,7 @@ fn test_err_sdiv32_overflow_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| matches!(res.unwrap_err(), EbpfError::DivideOverflow(pc) if pc == 31) }, @@ -1108,7 +1107,7 @@ fn test_err_sdiv32_overflow_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| matches!(res.unwrap_err(), EbpfError::DivideOverflow(pc) if pc == 32) }, @@ -1127,7 +1126,7 @@ fn test_mod32() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x5 } }, 5 ); @@ -1142,7 +1141,7 @@ fn test_mod32_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x0 } }, 3 ); @@ -1163,7 +1162,7 @@ fn test_mod64() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x30ba5a04 } }, 9 ); @@ -1179,7 +1178,7 @@ fn test_err_mod64_by_zero_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| matches!(res.unwrap_err(), EbpfError::DivideByZero(pc) if pc == 31) }, @@ -1197,7 +1196,7 @@ fn test_err_mod_by_zero_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| matches!(res.unwrap_err(), EbpfError::DivideByZero(pc) if pc == 31) }, @@ -1215,7 +1214,7 @@ fn test_ldxb() { exit", [0xaa, 0xbb, 0x11, 0xcc, 0xdd], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x11 } }, 2 ); @@ -1229,7 +1228,7 @@ fn test_ldxh() { exit", [0xaa, 0xbb, 0x11, 0x22, 0xcc, 0xdd], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x2211 } }, 2 ); @@ -1245,7 +1244,7 @@ fn test_ldxw() { 0xaa, 0xbb, 0x11, 0x22, 0x33, 0x44, 0xcc, 0xdd, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x44332211 } }, 2 ); @@ -1261,7 +1260,7 @@ fn test_ldxh_same_reg() { exit", [0xff, 0xff], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1234 } }, 4 ); @@ -1278,7 +1277,7 @@ fn test_lldxdw() { 0x77, 0x88, 0xcc, 0xdd, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x8877665544332211 } }, 2 ); @@ -1295,7 +1294,7 @@ fn test_err_ldxdw_oob() { 0x77, 0x88, 0xcc, 0xdd, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -1316,7 +1315,7 @@ fn test_err_ldxdw_nomem() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -1369,7 +1368,7 @@ fn test_ldxb_all() { 0x08, 0x09, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x9876543210 } }, 31 ); @@ -1426,7 +1425,7 @@ fn test_ldxh_all() { 0x00, 0x08, 0x00, 0x09, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x9876543210 } }, 41 ); @@ -1473,7 +1472,7 @@ fn test_ldxh_all2() { 0x01, 0x00, 0x02, 0x00, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x3ff } }, 31 ); @@ -1522,7 +1521,7 @@ fn test_ldxw_all() { 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x030f0f } }, 31 ); @@ -1536,7 +1535,7 @@ fn test_lddw() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1122334455667788 } }, 2 ); @@ -1546,7 +1545,7 @@ fn test_lddw() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x80000000 } }, 2 ); @@ -1561,7 +1560,7 @@ fn test_stb() { exit", [0xaa, 0xbb, 0xff, 0xcc, 0xdd], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x11 } }, 3 ); @@ -1578,7 +1577,7 @@ fn test_sth() { 0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x2211 } }, 3 ); @@ -1595,7 +1594,7 @@ fn test_stw() { 0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x44332211 } }, 3 ); @@ -1613,7 +1612,7 @@ fn test_stdw() { 0xff, 0xff, 0xcc, 0xdd, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x44332211 } }, 3 ); @@ -1631,7 +1630,7 @@ fn test_stxb() { 0xaa, 0xbb, 0xff, 0xcc, 0xdd, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x11 } }, 4 ); @@ -1649,7 +1648,7 @@ fn test_stxh() { 0xaa, 0xbb, 0xff, 0xff, 0xcc, 0xdd, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x2211 } }, 4 ); @@ -1667,7 +1666,7 @@ fn test_stxw() { 0xaa, 0xbb, 0xff, 0xff, 0xff, 0xff, 0xcc, 0xdd, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x44332211 } }, 4 ); @@ -1688,7 +1687,7 @@ fn test_stxdw() { 0xff, 0xff, 0xcc, 0xdd, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x8877665544332211 } }, 6 ); @@ -1721,7 +1720,7 @@ fn test_stxb_all() { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xf0f2f3f4f5f6f7f8 } }, 19 ); @@ -1741,7 +1740,7 @@ fn test_stxb_all2() { exit", [0xff, 0xff], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xf1f9 } }, 8 ); @@ -1777,7 +1776,7 @@ fn test_stxb_chain() { 0x00, 0x00, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x2a } }, 21 ); @@ -1792,7 +1791,7 @@ fn test_exit_without_value() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x0 } }, 1 ); @@ -1806,7 +1805,7 @@ fn test_exit() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x0 } }, 2 ); @@ -1822,7 +1821,7 @@ fn test_early_exit() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x3 } }, 2 ); @@ -1838,7 +1837,7 @@ fn test_ja() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 3 ); @@ -1858,7 +1857,7 @@ fn test_jeq_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 7 ); @@ -1879,7 +1878,7 @@ fn test_jeq_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 8 ); @@ -1899,7 +1898,7 @@ fn test_jge_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 7 ); @@ -1920,7 +1919,7 @@ fn test_jge_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 8 ); @@ -1941,7 +1940,7 @@ fn test_jle_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 7 ); @@ -1964,7 +1963,7 @@ fn test_jle_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 9 ); @@ -1984,7 +1983,7 @@ fn test_jgt_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 7 ); @@ -2006,7 +2005,7 @@ fn test_jgt_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 9 ); @@ -2026,7 +2025,7 @@ fn test_jlt_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 7 ); @@ -2048,7 +2047,7 @@ fn test_jlt_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 9 ); @@ -2068,7 +2067,7 @@ fn test_jne_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 7 ); @@ -2089,7 +2088,7 @@ fn test_jne_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 8 ); @@ -2109,7 +2108,7 @@ fn test_jset_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 7 ); @@ -2130,7 +2129,7 @@ fn test_jset_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 8 ); @@ -2151,7 +2150,7 @@ fn test_jsge_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 8 ); @@ -2174,7 +2173,7 @@ fn test_jsge_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 10 ); @@ -2195,7 +2194,7 @@ fn test_jsle_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 7 ); @@ -2219,7 +2218,7 @@ fn test_jsle_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 10 ); @@ -2239,7 +2238,7 @@ fn test_jsgt_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 7 ); @@ -2260,7 +2259,7 @@ fn test_jsgt_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 8 ); @@ -2280,7 +2279,7 @@ fn test_jslt_imm() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 7 ); @@ -2302,7 +2301,7 @@ fn test_jslt_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 9 ); @@ -2325,7 +2324,7 @@ fn test_stack1() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0xcd } }, 9 ); @@ -2353,10 +2352,10 @@ fn test_stack2() { exit", [], ( - b"BpfMemFrob" => syscalls::BpfMemFrob::init::; syscalls::BpfMemFrob::call, - b"BpfGatherBytes" => syscalls::BpfGatherBytes::init::; syscalls::BpfGatherBytes::call, + b"BpfMemFrob" => syscalls::BpfMemFrob::call, + b"BpfGatherBytes" => syscalls::BpfGatherBytes::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x01020304 } }, 16 ); @@ -2396,9 +2395,9 @@ fn test_string_stack() { exit", [], ( - b"BpfStrCmp" => syscalls::BpfStrCmp::init::; syscalls::BpfStrCmp::call, + b"BpfStrCmp" => syscalls::BpfStrCmp::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x0 } }, 28 ); @@ -2418,7 +2417,7 @@ fn test_err_fixed_stack_out_of_bound() { config, [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2449,7 +2448,7 @@ fn test_err_dynamic_stack_out_of_bound() { config, [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2469,7 +2468,7 @@ fn test_err_dynamic_stack_out_of_bound() { config, [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2508,7 +2507,7 @@ fn test_err_dynamic_stack_ptr_overflow() { config, [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2539,7 +2538,7 @@ fn test_dynamic_stack_frames_empty() { config, [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == ebpf::MM_STACK_START + config.stack_size() as u64 @@ -2569,7 +2568,7 @@ fn test_dynamic_frame_ptr() { config, [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == ebpf::MM_STACK_START + config.stack_size() as u64 - 8 @@ -2592,7 +2591,7 @@ fn test_dynamic_frame_ptr() { config, [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == ebpf::MM_STACK_START + config.stack_size() as u64 @@ -2630,7 +2629,7 @@ fn test_entrypoint_exit() { config, [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 42 } }, 5 ); @@ -2661,7 +2660,7 @@ fn test_stack_call_depth_tracking() { config, [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.is_ok() } }, 5 ); @@ -2681,7 +2680,7 @@ fn test_stack_call_depth_tracking() { config, [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2727,7 +2726,7 @@ fn test_err_mem_access_out_of_bound() { test_interpreter_and_jit!( executable, mem, - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2749,9 +2748,9 @@ fn test_relative_call() { "tests/elfs/relative_call.so", [1], ( - b"log" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call, + b"log" => syscalls::BpfSyscallString::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 2 } }, 14 ); @@ -2763,9 +2762,9 @@ fn test_bpf_to_bpf_scratch_registers() { "tests/elfs/scratch_registers.so", [1], ( - b"log_64" => syscalls::BpfSyscallU64::init::; syscalls::BpfSyscallU64::call, + b"log_64" => syscalls::BpfSyscallU64::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 112 } }, 41 ); @@ -2777,7 +2776,7 @@ fn test_bpf_to_bpf_pass_stack_reference() { "tests/elfs/pass_stack_reference.so", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| res.unwrap() == 42 }, 29 ); @@ -2795,9 +2794,9 @@ fn test_syscall_parameter_on_stack() { exit", [], ( - b"BpfSyscallString" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call, + b"BpfSyscallString" => syscalls::BpfSyscallString::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0 } }, 6 ); @@ -2817,7 +2816,7 @@ fn test_call_reg() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 42 } }, 8 ); @@ -2832,7 +2831,7 @@ fn test_err_callx_oob_low() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2856,7 +2855,7 @@ fn test_err_callx_oob_high() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2886,7 +2885,7 @@ fn test_err_static_jmp_lddw() { ", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x2 } }, 9 ); @@ -2900,7 +2899,7 @@ fn test_err_static_jmp_lddw() { ", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2924,7 +2923,7 @@ fn test_err_dynamic_jmp_lddw() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2947,7 +2946,7 @@ fn test_err_dynamic_jmp_lddw() { ", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2969,7 +2968,7 @@ fn test_err_dynamic_jmp_lddw() { ", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -2990,9 +2989,9 @@ fn test_bpf_to_bpf_depth() { config, [i as u8], ( - b"log" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call, + b"log" => syscalls::BpfSyscallString::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0 } }, if i == 0 { 4 } else { 3 + 10 * i as u64 } ); @@ -3007,9 +3006,9 @@ fn test_err_bpf_to_bpf_too_deep() { config, [config.max_call_depth as u8], ( - b"log" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call, + b"log" => syscalls::BpfSyscallString::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3033,7 +3032,7 @@ fn test_err_reg_stack_depth() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3083,9 +3082,9 @@ fn test_err_syscall_string() { exit", [72, 101, 108, 108, 111], ( - b"BpfSyscallString" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call, + b"BpfSyscallString" => syscalls::BpfSyscallString::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3108,9 +3107,9 @@ fn test_syscall_string() { exit", [72, 101, 108, 108, 111], ( - b"BpfSyscallString" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call, + b"BpfSyscallString" => syscalls::BpfSyscallString::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0 } }, 4 ); @@ -3130,9 +3129,9 @@ fn test_syscall() { exit", [], ( - b"BpfSyscallU64" => syscalls::BpfSyscallU64::init::; syscalls::BpfSyscallU64::call, + b"BpfSyscallU64" => syscalls::BpfSyscallU64::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0 } }, 8 ); @@ -3151,9 +3150,9 @@ fn test_call_gather_bytes() { exit", [], ( - b"BpfGatherBytes" => syscalls::BpfGatherBytes::init::; syscalls::BpfGatherBytes::call, + b"BpfGatherBytes" => syscalls::BpfGatherBytes::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x0102030405 } }, 7 ); @@ -3174,9 +3173,9 @@ fn test_call_memfrob() { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // ], ( - b"BpfMemFrob" => syscalls::BpfMemFrob::init::; syscalls::BpfMemFrob::call, + b"BpfMemFrob" => syscalls::BpfMemFrob::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x102292e2f2c0708 } }, 7 ); @@ -3196,11 +3195,11 @@ fn test_syscall_with_context() { exit", [], ( - b"SyscallWithContext" => syscalls::SyscallWithContext::init::< syscalls::BpfSyscallContext>; syscalls::SyscallWithContext::call + b"SyscallWithContext" => syscalls::SyscallWithContext::call ), - 42, + &mut syscalls::SyscallWithContext { context: 42 }, { |vm: &EbpfVm, res: ProgramResult| { - let syscall_context_object = unsafe { &*(vm.get_syscall_context_object(syscalls::SyscallWithContext::call as usize).unwrap() as *const syscalls::SyscallWithContext) }; + let syscall_context_object = unsafe { &*(vm.get_program_environment().syscall_context_object as *const syscalls::SyscallWithContext) }; assert_eq!(syscall_context_object.context, 84); res.unwrap() == 0 }}, @@ -3208,14 +3207,9 @@ fn test_syscall_with_context() { ); } -type UserContext = u64; pub struct NestedVmSyscall {} impl NestedVmSyscall { - pub fn init(_unused: C) -> Box { - Box::new(Self {}) - } -} -impl SyscallObject for NestedVmSyscall { + #[allow(clippy::too_many_arguments)] fn call( &mut self, depth: u64, @@ -3230,11 +3224,7 @@ impl SyscallObject for NestedVmSyscall { if depth > 0 { let mut syscall_registry = SyscallRegistry::default(); syscall_registry - .register_syscall_by_name( - b"NestedVmSyscall", - NestedVmSyscall::init::, - NestedVmSyscall::call, - ) + .register_syscall_by_name(b"NestedVmSyscall", NestedVmSyscall::call) .unwrap(); let mem = [depth as u8 - 1, throw as u8]; let mut executable = assemble::( @@ -3250,7 +3240,7 @@ impl SyscallObject for NestedVmSyscall { test_interpreter_and_jit!( executable, mem, - 0, + &mut (), { |_vm, res: ProgramResult| { *result = res; @@ -3293,10 +3283,10 @@ fn test_load_elf() { "tests/elfs/noop.so", [], ( - b"log" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call, - b"log_64" => syscalls::BpfSyscallU64::init::; syscalls::BpfSyscallU64::call, + b"log" => syscalls::BpfSyscallString::call, + b"log_64" => syscalls::BpfSyscallU64::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0 } }, 11 ); @@ -3308,9 +3298,9 @@ fn test_load_elf_empty_noro() { "tests/elfs/noro.so", [], ( - b"log_64" => syscalls::BpfSyscallU64::init::; syscalls::BpfSyscallU64::call, + b"log_64" => syscalls::BpfSyscallU64::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0 } }, 8 ); @@ -3322,9 +3312,9 @@ fn test_load_elf_empty_rodata() { "tests/elfs/empty_rodata.so", [], ( - b"log_64" => syscalls::BpfSyscallU64::init::; syscalls::BpfSyscallU64::call, + b"log_64" => syscalls::BpfSyscallU64::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0 } }, 8 ); @@ -3344,7 +3334,7 @@ fn test_load_elf_rodata() { config, [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 42 } }, 3 ); @@ -3357,7 +3347,7 @@ fn test_load_elf_rodata_high_vaddr() { "tests/elfs/rodata_high_vaddr.so", [1], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 42 } }, 3 ); @@ -3374,16 +3364,16 @@ fn test_custom_entrypoint() { ..Config::default() }; let mut syscall_registry = SyscallRegistry::default(); - test_interpreter_and_jit!(register, syscall_registry, b"log" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call); + test_interpreter_and_jit!(register, syscall_registry, b"log" => syscalls::BpfSyscallString::call); let mut syscall_registry = SyscallRegistry::default(); - test_interpreter_and_jit!(register, syscall_registry, b"log_64" => syscalls::BpfSyscallU64::init::; syscalls::BpfSyscallU64::call); + test_interpreter_and_jit!(register, syscall_registry, b"log_64" => syscalls::BpfSyscallU64::call); #[allow(unused_mut)] let mut executable = Executable::::from_elf(&elf, config, syscall_registry).unwrap(); test_interpreter_and_jit!( executable, [], - syscalls::BpfSyscallContext::default(), + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0 } }, 2 ); @@ -3399,7 +3389,7 @@ fn test_tight_infinite_loop_conditional() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3420,7 +3410,7 @@ fn test_tight_infinite_loop_unconditional() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3443,7 +3433,7 @@ fn test_tight_infinite_recursion() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3468,7 +3458,7 @@ fn test_tight_infinite_recursion_callx() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3491,9 +3481,9 @@ fn test_instruction_count_syscall() { exit", [72, 101, 108, 108, 111], ( - b"BpfSyscallString" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call, + b"BpfSyscallString" => syscalls::BpfSyscallString::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0 } }, 4 ); @@ -3509,9 +3499,9 @@ fn test_err_instruction_count_syscall_capped() { exit", [72, 101, 108, 108, 111], ( - b"BpfSyscallString" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call, + b"BpfSyscallString" => syscalls::BpfSyscallString::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3535,7 +3525,7 @@ fn test_err_instruction_count_lddw_capped() { ", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3564,7 +3554,7 @@ fn test_non_terminate_early() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3593,9 +3583,9 @@ fn test_err_non_terminate_capped() { exit", [], ( - b"BpfTracePrintf" => syscalls::BpfTracePrintf::init::; syscalls::BpfTracePrintf::call, + b"BpfTracePrintf" => syscalls::BpfTracePrintf::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3620,9 +3610,9 @@ fn test_err_non_terminate_capped() { exit", [], ( - b"BpfTracePrintf" => syscalls::BpfTracePrintf::init::; syscalls::BpfTracePrintf::call, + b"BpfTracePrintf" => syscalls::BpfTracePrintf::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3648,7 +3638,7 @@ fn test_err_capped_before_exception() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3670,7 +3660,7 @@ fn test_err_capped_before_exception() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3695,7 +3685,7 @@ fn test_err_exit_capped() { ", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3716,7 +3706,7 @@ fn test_err_exit_capped() { ", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3734,7 +3724,7 @@ fn test_err_exit_capped() { ", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), @@ -3760,9 +3750,9 @@ fn test_symbol_relocation() { exit", [72, 101, 108, 108, 111], ( - b"BpfSyscallString" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call + b"BpfSyscallString" => syscalls::BpfSyscallString::call ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0 } }, 6 ); @@ -3782,7 +3772,7 @@ fn test_err_call_unresolved() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| matches!(res.unwrap_err(), EbpfError::UnsupportedInstruction(pc) if pc == 34) }, @@ -3793,7 +3783,7 @@ fn test_err_call_unresolved() { #[test] fn test_err_unresolved_elf() { let mut syscall_registry = SyscallRegistry::default(); - test_interpreter_and_jit!(register, syscall_registry, b"log" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call); + test_interpreter_and_jit!(register, syscall_registry, b"log" => syscalls::BpfSyscallString::call); let mut file = File::open("tests/elfs/unresolved_syscall.so").unwrap(); let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); @@ -3812,9 +3802,9 @@ fn test_syscall_static() { "tests/elfs/syscall_static.so", [], ( - b"log" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call, + b"log" => syscalls::BpfSyscallString::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0 } }, 5 ); @@ -3830,9 +3820,9 @@ fn test_syscall_unknown_static() { "tests/elfs/syscall_static_unknown.so", [], ( - b"log" => syscalls::BpfSyscallString::init::; syscalls::BpfSyscallString::call, + b"log" => syscalls::BpfSyscallString::call, ), - 0, + &mut (), { |_vm, res: ProgramResult| { matches!(res.unwrap_err(), EbpfError::UnsupportedInstruction(29)) } }, 1 ); @@ -3847,7 +3837,7 @@ fn test_reloc_64_64() { "tests/elfs/reloc_64_64.so", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == ebpf::MM_PROGRAM_START + 0xe8 } }, 2 ); @@ -3861,7 +3851,7 @@ fn test_reloc_64_64_high_vaddr() { "tests/elfs/reloc_64_64_high_vaddr.so", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == ebpf::MM_PROGRAM_START } }, 2 ); @@ -3877,7 +3867,7 @@ fn test_reloc_64_relative() { "tests/elfs/reloc_64_relative.so", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == ebpf::MM_PROGRAM_START + 0x100 } }, 2 ); @@ -3893,7 +3883,7 @@ fn test_reloc_64_relative_high_vaddr() { "tests/elfs/reloc_64_relative_high_vaddr.so", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == ebpf::MM_PROGRAM_START + 0x18 } }, 2 ); @@ -3912,7 +3902,7 @@ fn test_reloc_64_relative_data() { "tests/elfs/reloc_64_relative_data.so", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == ebpf::MM_PROGRAM_START + 0x108 } }, 3 ); @@ -3931,7 +3921,7 @@ fn test_reloc_64_relative_data_high_vaddr() { "tests/elfs/reloc_64_relative_data_high_vaddr.so", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == ebpf::MM_PROGRAM_START + 0x20 } }, 3 ); @@ -3956,7 +3946,7 @@ fn test_reloc_64_relative_data_pre_sbfv2() { "tests/elfs/reloc_64_relative_data_pre_sbfv2.so", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == ebpf::MM_PROGRAM_START + 0x108 } }, 3 ); @@ -3980,7 +3970,7 @@ fn test_mul_loop() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x75db9c97 } }, 37 ); @@ -4008,7 +3998,7 @@ fn test_prime() { exit", [], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 655 ); @@ -4045,7 +4035,7 @@ fn test_subnet() { 0x03, 0x00, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 11 ); @@ -4071,7 +4061,7 @@ fn test_tcp_port80_match() { 0x44, 0x44, 0x44, 0x44, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x1 } }, 17 ); @@ -4097,7 +4087,7 @@ fn test_tcp_port80_nomatch() { 0x44, 0x44, 0x44, 0x44, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x0 } }, 18 ); @@ -4123,7 +4113,7 @@ fn test_tcp_port80_nomatch_ethertype() { 0x44, 0x44, 0x44, 0x44, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x0 } }, 7 ); @@ -4149,7 +4139,7 @@ fn test_tcp_port80_nomatch_proto() { 0x44, 0x44, 0x44, 0x44, // ], (), - 0, + &mut (), { |_vm, res: ProgramResult| { res.unwrap() == 0x0 } }, 9 ); @@ -4161,7 +4151,7 @@ fn test_tcp_sack_match() { TCP_SACK_ASM, TCP_SACK_MATCH, (), - 0, + &mut (), { |_vm, res: ProgramResult| res.unwrap() == 0x1 }, 79 ); @@ -4173,7 +4163,7 @@ fn test_tcp_sack_nomatch() { TCP_SACK_ASM, TCP_SACK_NOMATCH, (), - 0, + &mut (), { |_vm, res: ProgramResult| res.unwrap() == 0x0 }, 55 ); @@ -4229,7 +4219,7 @@ fn execute_generated_program(prog: &[u8]) -> bool { let result_interpreter = vm.execute_program_interpreted(&mut TestInstructionMeter { remaining: max_instruction_count, }); - let tracer_interpreter = vm.get_tracer().clone(); + let tracer_interpreter = vm.get_program_environment().tracer.clone(); ( vm.get_total_instruction_count(), tracer_interpreter, @@ -4242,7 +4232,7 @@ fn execute_generated_program(prog: &[u8]) -> bool { let result_jit = vm.execute_program_jit(&mut TestInstructionMeter { remaining: max_instruction_count, }); - let tracer_jit = vm.get_tracer(); + let tracer_jit = &vm.get_program_environment().tracer; if format!("{:?}", result_interpreter) != format!("{:?}", result_jit) || !solana_rbpf::vm::Tracer::compare(&tracer_interpreter, tracer_jit) {