From 6ae9e4b4e9e674ed1681f73e73bfd33088bf2aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20Mei=C3=9Fner?= Date: Tue, 22 Aug 2023 13:39:23 +0200 Subject: [PATCH] Refactor - Remove generic parameter `Verifier` from `Executable` (#500) * Removes the generic parameter "V: Verifier" from Executable. * Removes TautologyVerifier from public interface. * Turns Executable::verified() into executable.verify() --- benches/elf_loader.rs | 9 +-- benches/jit_compile.rs | 28 +++---- benches/vm_execution.rs | 49 +++++------- cli/src/main.rs | 31 ++++---- examples/disassemble.rs | 3 +- examples/to_json.rs | 3 +- fuzz/fuzz_targets/dumb.rs | 4 +- fuzz/fuzz_targets/smart.rs | 4 +- fuzz/fuzz_targets/smart_jit_diff.rs | 4 +- fuzz/fuzz_targets/smarter_jit_diff.rs | 8 +- src/assembler.rs | 12 +-- src/debugger.rs | 39 ++++------ src/elf.rs | 35 ++++----- src/interpreter.rs | 9 +-- src/jit.rs | 22 ++---- src/static_analysis.rs | 7 +- src/verifier.rs | 14 ---- src/vm.rs | 21 +++-- src/x86.rs | 3 +- test_utils/src/lib.rs | 5 +- tests/execution.rs | 53 +++++-------- tests/verifier.rs | 107 +++++++++++--------------- 22 files changed, 184 insertions(+), 286 deletions(-) diff --git a/benches/elf_loader.rs b/benches/elf_loader.rs index deecd307..0ff3c84f 100644 --- a/benches/elf_loader.rs +++ b/benches/elf_loader.rs @@ -13,7 +13,6 @@ extern crate test_utils; use solana_rbpf::{ elf::{Executable, FunctionRegistry}, syscalls, - verifier::TautologyVerifier, vm::{BuiltinFunction, BuiltinProgram, Config, TestContextObject}, }; use std::{fs::File, io::Read, sync::Arc}; @@ -36,9 +35,7 @@ fn bench_load_sbpfv1(bencher: &mut Bencher) { let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); let loader = loader(); - bencher.iter(|| { - Executable::::from_elf(&elf, loader.clone()).unwrap() - }); + bencher.iter(|| Executable::::from_elf(&elf, loader.clone()).unwrap()); } #[bench] @@ -47,7 +44,5 @@ fn bench_load_sbpfv2(bencher: &mut Bencher) { let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); let loader = loader(); - bencher.iter(|| { - Executable::::from_elf(&elf, loader.clone()).unwrap() - }); + bencher.iter(|| Executable::::from_elf(&elf, loader.clone()).unwrap()); } diff --git a/benches/jit_compile.rs b/benches/jit_compile.rs index ccdb4be9..f4e572fb 100644 --- a/benches/jit_compile.rs +++ b/benches/jit_compile.rs @@ -11,7 +11,7 @@ extern crate test; use solana_rbpf::{ elf::Executable, - verifier::{RequisiteVerifier, TautologyVerifier}, + verifier::RequisiteVerifier, vm::{BuiltinProgram, TestContextObject}, }; use std::{fs::File, io::Read, sync::Arc}; @@ -23,18 +23,15 @@ fn bench_init_vm(bencher: &mut Bencher) { let mut file = File::open("tests/elfs/relative_call.so").unwrap(); let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); - let executable = Executable::::from_elf( - &elf, - Arc::new(BuiltinProgram::new_mock()), - ) - .unwrap(); - let verified_executable = - Executable::::verified(executable).unwrap(); + let executable = + Executable::::from_elf(&elf, Arc::new(BuiltinProgram::new_mock())) + .unwrap(); + executable.verify::().unwrap(); bencher.iter(|| { let mut context_object = TestContextObject::default(); create_vm!( _vm, - &verified_executable, + &executable, &mut context_object, stack, heap, @@ -50,12 +47,9 @@ fn bench_jit_compile(bencher: &mut Bencher) { let mut file = File::open("tests/elfs/relative_call.so").unwrap(); let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); - let executable = Executable::::from_elf( - &elf, - Arc::new(BuiltinProgram::new_mock()), - ) - .unwrap(); - let mut verified_executable = - Executable::::verified(executable).unwrap(); - bencher.iter(|| verified_executable.jit_compile().unwrap()); + let mut executable = + Executable::::from_elf(&elf, Arc::new(BuiltinProgram::new_mock())) + .unwrap(); + executable.verify::().unwrap(); + bencher.iter(|| executable.jit_compile().unwrap()); } diff --git a/benches/vm_execution.rs b/benches/vm_execution.rs index 505f927f..965a7ef6 100644 --- a/benches/vm_execution.rs +++ b/benches/vm_execution.rs @@ -13,7 +13,7 @@ use solana_rbpf::{ ebpf, elf::{Executable, FunctionRegistry}, memory_region::MemoryRegion, - verifier::{RequisiteVerifier, TautologyVerifier}, + verifier::RequisiteVerifier, vm::{BuiltinProgram, Config, TestContextObject}, }; use std::{fs::File, io::Read, sync::Arc}; @@ -25,17 +25,14 @@ fn bench_init_interpreter_start(bencher: &mut Bencher) { let mut file = File::open("tests/elfs/rodata_section.so").unwrap(); let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); - let executable = Executable::::from_elf( - &elf, - Arc::new(BuiltinProgram::new_mock()), - ) - .unwrap(); - let verified_executable = - Executable::::verified(executable).unwrap(); + let executable = + Executable::::from_elf(&elf, Arc::new(BuiltinProgram::new_mock())) + .unwrap(); + executable.verify::().unwrap(); let mut context_object = TestContextObject::default(); create_vm!( vm, - &verified_executable, + &executable, &mut context_object, stack, heap, @@ -44,7 +41,7 @@ fn bench_init_interpreter_start(bencher: &mut Bencher) { ); bencher.iter(|| { vm.context_object_pointer.remaining = 37; - vm.execute_program(&verified_executable, true).1.unwrap() + vm.execute_program(&executable, true).1.unwrap() }); } @@ -54,18 +51,15 @@ fn bench_init_jit_start(bencher: &mut Bencher) { let mut file = File::open("tests/elfs/rodata_section.so").unwrap(); let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); - let executable = Executable::::from_elf( - &elf, - Arc::new(BuiltinProgram::new_mock()), - ) - .unwrap(); - let mut verified_executable = - Executable::::verified(executable).unwrap(); - verified_executable.jit_compile().unwrap(); + let mut executable = + Executable::::from_elf(&elf, Arc::new(BuiltinProgram::new_mock())) + .unwrap(); + executable.verify::().unwrap(); + executable.jit_compile().unwrap(); let mut context_object = TestContextObject::default(); create_vm!( vm, - &verified_executable, + &executable, &mut context_object, stack, heap, @@ -74,7 +68,7 @@ fn bench_init_jit_start(bencher: &mut Bencher) { ); bencher.iter(|| { vm.context_object_pointer.remaining = 37; - vm.execute_program(&verified_executable, false).1.unwrap() + vm.execute_program(&executable, false).1.unwrap() }); } @@ -86,7 +80,7 @@ fn bench_jit_vs_interpreter( instruction_meter: u64, mem: &mut [u8], ) { - let executable = solana_rbpf::assembler::assemble::( + let mut executable = solana_rbpf::assembler::assemble::( assembly, Arc::new(BuiltinProgram::new_loader( config, @@ -94,14 +88,13 @@ fn bench_jit_vs_interpreter( )), ) .unwrap(); - let mut verified_executable = - Executable::::verified(executable).unwrap(); - verified_executable.jit_compile().unwrap(); + executable.verify::().unwrap(); + executable.jit_compile().unwrap(); let mut context_object = TestContextObject::default(); let mem_region = MemoryRegion::new_writable(mem, ebpf::MM_INPUT_START); create_vm!( vm, - &verified_executable, + &executable, &mut context_object, stack, heap, @@ -112,8 +105,7 @@ fn bench_jit_vs_interpreter( .bench(|bencher| { bencher.iter(|| { vm.context_object_pointer.remaining = instruction_meter; - let (instruction_count_interpreter, result) = - vm.execute_program(&verified_executable, true); + let (instruction_count_interpreter, result) = vm.execute_program(&executable, true); assert!(result.is_ok(), "{:?}", result); assert_eq!(instruction_count_interpreter, instruction_meter); }); @@ -125,8 +117,7 @@ fn bench_jit_vs_interpreter( .bench(|bencher| { bencher.iter(|| { vm.context_object_pointer.remaining = instruction_meter; - let (instruction_count_jit, result) = - vm.execute_program(&verified_executable, false); + let (instruction_count_jit, result) = vm.execute_program(&executable, false); assert!(result.is_ok(), "{:?}", result); assert_eq!(instruction_count_jit, instruction_meter); }); diff --git a/cli/src/main.rs b/cli/src/main.rs index c11521c7..2de9c782 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -6,7 +6,7 @@ use solana_rbpf::{ elf::{Executable, FunctionRegistry}, memory_region::{MemoryMapping, MemoryRegion}, static_analysis::Analysis, - verifier::{RequisiteVerifier, TautologyVerifier}, + verifier::RequisiteVerifier, vm::{BuiltinProgram, Config, DynamicAnalysis, EbpfVm, TestContextObject}, }; use std::{fs::File, io::Read, path::Path, sync::Arc}; @@ -101,7 +101,8 @@ fn main() { }, FunctionRegistry::default(), )); - let executable = match matches.value_of("assembler") { + #[allow(unused_mut)] + let mut executable = match matches.value_of("assembler") { Some(asm_file_name) => { let mut file = File::open(Path::new(asm_file_name)).unwrap(); let mut source = Vec::new(); @@ -112,15 +113,13 @@ fn main() { let mut file = File::open(Path::new(matches.value_of("elf").unwrap())).unwrap(); let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); - Executable::::from_elf(&elf, loader) + Executable::::from_elf(&elf, loader) .map_err(|err| format!("Executable constructor failed: {err:?}")) } } .unwrap(); - #[allow(unused_mut)] - let verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); let mut mem = match matches.value_of("input").unwrap().parse::() { Ok(allocate) => vec![0u8; allocate], @@ -133,7 +132,7 @@ fn main() { }; #[cfg(all(feature = "jit", not(target_os = "windows"), target_arch = "x86_64"))] if matches.value_of("use") == Some("jit") { - verified_executable.jit_compile().unwrap(); + executable.jit_compile().unwrap(); } let mut context_object = TestContextObject::new( matches @@ -142,8 +141,8 @@ fn main() { .parse::() .unwrap(), ); - let config = verified_executable.get_config(); - let sbpf_version = verified_executable.get_sbpf_version(); + let config = executable.get_config(); + let sbpf_version = executable.get_sbpf_version(); let mut stack = AlignedMemory::<{ ebpf::HOST_ALIGN }>::zero_filled(config.stack_size()); let stack_len = stack.len(); let mut heap = AlignedMemory::<{ ebpf::HOST_ALIGN }>::zero_filled( @@ -154,7 +153,7 @@ fn main() { .unwrap(), ); let regions: Vec = vec![ - verified_executable.get_ro_region(), + executable.get_ro_region(), MemoryRegion::new_writable_gapped( stack.as_slice_mut(), ebpf::MM_STACK_START, @@ -171,8 +170,8 @@ fn main() { let memory_mapping = MemoryMapping::new(regions, config, sbpf_version).unwrap(); let mut vm = EbpfVm::new( - verified_executable.get_config(), - verified_executable.get_sbpf_version(), + executable.get_config(), + executable.get_sbpf_version(), &mut context_object, memory_mapping, stack_len, @@ -183,7 +182,7 @@ fn main() { || matches.is_present("trace") || matches.is_present("profile") { - Some(Analysis::from_executable(&verified_executable).unwrap()) + Some(Analysis::from_executable(&executable).unwrap()) } else { None }; @@ -212,10 +211,8 @@ fn main() { if matches.value_of("use").unwrap() == "debugger" { vm.debug_port = Some(matches.value_of("port").unwrap().parse::().unwrap()); } - let (instruction_count, result) = vm.execute_program( - &verified_executable, - matches.value_of("use").unwrap() != "jit", - ); + let (instruction_count, result) = + vm.execute_program(&executable, matches.value_of("use").unwrap() != "jit"); println!("Result: {result:?}"); println!("Instruction Count: {instruction_count}"); if matches.is_present("trace") { diff --git a/examples/disassemble.rs b/examples/disassemble.rs index eab69b94..4417af4a 100644 --- a/examples/disassemble.rs +++ b/examples/disassemble.rs @@ -8,7 +8,6 @@ extern crate solana_rbpf; use solana_rbpf::{ elf::{Executable, FunctionRegistry, SBPFVersion}, static_analysis::Analysis, - verifier::TautologyVerifier, vm::{BuiltinProgram, TestContextObject}, }; use std::sync::Arc; @@ -32,7 +31,7 @@ fn main() { 0x00, 0x00, 0x00, 0x00, 0x00, ]; let loader = Arc::new(BuiltinProgram::new_mock()); - let executable = Executable::::from_text_bytes( + let executable = Executable::::from_text_bytes( program, loader, SBPFVersion::V2, diff --git a/examples/to_json.rs b/examples/to_json.rs index dc3974bf..89e9ec9d 100644 --- a/examples/to_json.rs +++ b/examples/to_json.rs @@ -14,7 +14,6 @@ extern crate solana_rbpf; use solana_rbpf::{ elf::{Executable, FunctionRegistry, SBPFVersion}, static_analysis::Analysis, - verifier::TautologyVerifier, vm::{BuiltinProgram, TestContextObject}, }; use std::sync::Arc; @@ -28,7 +27,7 @@ use std::sync::Arc; // * Print integers as integers, and not as strings containing their hexadecimal representation // (just replace the relevant `format!()` calls by the commented values. fn to_json(program: &[u8]) -> String { - let executable = Executable::::from_text_bytes( + let executable = Executable::::from_text_bytes( program, Arc::new(BuiltinProgram::new_mock()), SBPFVersion::V2, diff --git a/fuzz/fuzz_targets/dumb.rs b/fuzz/fuzz_targets/dumb.rs index ab8ace34..b0dab4e9 100644 --- a/fuzz/fuzz_targets/dumb.rs +++ b/fuzz/fuzz_targets/dumb.rs @@ -8,7 +8,7 @@ use solana_rbpf::{ ebpf, elf::{Executable, FunctionRegistry, SBPFVersion}, memory_region::MemoryRegion, - verifier::{RequisiteVerifier, TautologyVerifier, Verifier}, + verifier::{RequisiteVerifier, Verifier}, vm::{BuiltinProgram, TestContextObject}, }; use test_utils::create_vm; @@ -33,7 +33,7 @@ fuzz_target!(|data: DumbFuzzData| { return; } let mut mem = data.mem; - let executable = Executable::::from_text_bytes( + let executable = Executable::::from_text_bytes( &prog, std::sync::Arc::new(BuiltinProgram::new_loader(config, FunctionRegistry::default())), SBPFVersion::V2, diff --git a/fuzz/fuzz_targets/smart.rs b/fuzz/fuzz_targets/smart.rs index 92d82889..d1a91a98 100644 --- a/fuzz/fuzz_targets/smart.rs +++ b/fuzz/fuzz_targets/smart.rs @@ -10,7 +10,7 @@ use solana_rbpf::{ elf::{Executable, FunctionRegistry, SBPFVersion}, insn_builder::{Arch, IntoBytes}, memory_region::MemoryRegion, - verifier::{RequisiteVerifier, TautologyVerifier, Verifier}, + verifier::{RequisiteVerifier, Verifier}, vm::{BuiltinProgram, TestContextObject}, }; use test_utils::create_vm; @@ -37,7 +37,7 @@ fuzz_target!(|data: FuzzData| { return; } let mut mem = data.mem; - let executable = Executable::::from_text_bytes( + let executable = Executable::::from_text_bytes( prog.into_bytes(), std::sync::Arc::new(BuiltinProgram::new_loader(config, FunctionRegistry::default())), SBPFVersion::V2, diff --git a/fuzz/fuzz_targets/smart_jit_diff.rs b/fuzz/fuzz_targets/smart_jit_diff.rs index a6c2e99e..a6fc1e79 100644 --- a/fuzz/fuzz_targets/smart_jit_diff.rs +++ b/fuzz/fuzz_targets/smart_jit_diff.rs @@ -8,7 +8,7 @@ use solana_rbpf::{ elf::{Executable, FunctionRegistry, SBPFVersion}, insn_builder::{Arch, Instruction, IntoBytes}, memory_region::MemoryRegion, - verifier::{RequisiteVerifier, TautologyVerifier, Verifier}, + verifier::{RequisiteVerifier, Verifier}, vm::{BuiltinProgram, TestContextObject}, }; use test_utils::create_vm; @@ -45,7 +45,7 @@ fuzz_target!(|data: FuzzData| { } let mut interp_mem = data.mem.clone(); let mut jit_mem = data.mem; - let mut executable = Executable::::from_text_bytes( + let mut executable = Executable::::from_text_bytes( prog.into_bytes(), std::sync::Arc::new(BuiltinProgram::new_loader(config, FunctionRegistry::default())), SBPFVersion::V2, diff --git a/fuzz/fuzz_targets/smarter_jit_diff.rs b/fuzz/fuzz_targets/smarter_jit_diff.rs index d2639f9e..50c906a8 100644 --- a/fuzz/fuzz_targets/smarter_jit_diff.rs +++ b/fuzz/fuzz_targets/smarter_jit_diff.rs @@ -9,7 +9,7 @@ use solana_rbpf::{ insn_builder::IntoBytes, memory_region::MemoryRegion, static_analysis::Analysis, - verifier::{RequisiteVerifier, TautologyVerifier, Verifier}, + verifier::{RequisiteVerifier, Verifier}, vm::{ BuiltinProgram, ContextObject, TestContextObject, }, @@ -28,8 +28,8 @@ struct FuzzData { mem: Vec, } -fn dump_insns(verified_executable: &Executable) { - let analysis = Analysis::from_executable(verified_executable).unwrap(); +fn dump_insns(executable: &Executable) { + let analysis = Analysis::from_executable(executable).unwrap(); eprint!("Using the following disassembly"); analysis.disassemble(&mut std::io::stderr().lock()).unwrap(); } @@ -44,7 +44,7 @@ fuzz_target!(|data: FuzzData| { } let mut interp_mem = data.mem.clone(); let mut jit_mem = data.mem; - let mut executable = Executable::::from_text_bytes( + let mut executable = Executable::::from_text_bytes( prog.into_bytes(), std::sync::Arc::new(BuiltinProgram::new_loader(config, FunctionRegistry::default())), SBPFVersion::V2, diff --git a/src/assembler.rs b/src/assembler.rs index 998870a8..5208ab08 100644 --- a/src/assembler.rs +++ b/src/assembler.rs @@ -19,7 +19,6 @@ use crate::{ }, ebpf::{self, Insn}, elf::{Executable, FunctionRegistry, SBPFVersion}, - verifier::TautologyVerifier, vm::{BuiltinProgram, ContextObject}, }; use std::{collections::HashMap, sync::Arc}; @@ -218,7 +217,7 @@ fn insn(opc: u8, dst: i64, src: i64, off: i64, imm: i64) -> Result pub fn assemble( src: &str, loader: Arc>, -) -> Result, String> { +) -> Result, String> { let sbpf_version = if loader.get_config().enable_sbpf_v2 { SBPFVersion::V2 } else { @@ -366,11 +365,6 @@ pub fn assemble( .iter() .flat_map(|insn| insn.to_vec()) .collect::>(); - Executable::::from_text_bytes( - &program, - loader, - sbpf_version, - function_registry, - ) - .map_err(|err| format!("Executable constructor {err:?}")) + Executable::::from_text_bytes(&program, loader, sbpf_version, function_registry) + .map_err(|err| format!("Executable constructor {err:?}")) } diff --git a/src/debugger.rs b/src/debugger.rs index db063412..8fa0f33e 100644 --- a/src/debugger.rs +++ b/src/debugger.rs @@ -25,7 +25,6 @@ use crate::{ ebpf, interpreter::{DebugState, Interpreter}, memory_region::AccessType, - verifier::Verifier, vm::{ContextObject, ProgramResult}, }; @@ -43,7 +42,7 @@ fn wait_for_tcp(port: u16) -> DynResult { } /// Connect to the debugger and hand over the control of the interpreter -pub fn execute(interpreter: &mut Interpreter, port: u16) { +pub fn execute(interpreter: &mut Interpreter, port: u16) { let connection: Box> = Box::new(wait_for_tcp(port).expect("Cannot connect to Debugger")); let mut dbg = GdbStub::new(connection) @@ -117,7 +116,7 @@ pub fn execute(interpreter: &mut Interpreter Target for Interpreter<'a, 'b, V, C> { +impl<'a, 'b, C: ContextObject> Target for Interpreter<'a, 'b, C> { type Arch = Bpf; type Error = &'static str; @@ -149,8 +148,8 @@ impl<'a, 'b, V: Verifier, C: ContextObject> Target for Interpreter<'a, 'b, V, C> } } -fn get_host_ptr( - interpreter: &mut Interpreter, +fn get_host_ptr( + interpreter: &mut Interpreter, mut vm_addr: u64, pc: usize, ) -> Result<*mut u8, Box> { @@ -168,7 +167,7 @@ fn get_host_ptr( } } -impl<'a, 'b, V: Verifier, C: ContextObject> SingleThreadBase for Interpreter<'a, 'b, V, C> { +impl<'a, 'b, C: ContextObject> SingleThreadBase for Interpreter<'a, 'b, C> { fn read_registers(&mut self, regs: &mut BpfRegs) -> TargetResult<(), Self> { for i in 0..10 { regs.r[i] = self.reg[i]; @@ -222,9 +221,8 @@ impl<'a, 'b, V: Verifier, C: ContextObject> SingleThreadBase for Interpreter<'a, } } -impl<'a, 'b, V: Verifier, C: ContextObject> - target::ext::base::single_register_access::SingleRegisterAccess<()> - for Interpreter<'a, 'b, V, C> +impl<'a, 'b, C: ContextObject> target::ext::base::single_register_access::SingleRegisterAccess<()> + for Interpreter<'a, 'b, C> { fn read_register( &mut self, @@ -262,7 +260,7 @@ impl<'a, 'b, V: Verifier, C: ContextObject> } } -impl<'a, 'b, V: Verifier, C: ContextObject> SingleThreadResume for Interpreter<'a, 'b, V, C> { +impl<'a, 'b, C: ContextObject> SingleThreadResume for Interpreter<'a, 'b, C> { fn resume(&mut self, signal: Option) -> Result<(), Self::Error> { if signal.is_some() { return Err("no support for continuing with signal"); @@ -281,8 +279,8 @@ impl<'a, 'b, V: Verifier, C: ContextObject> SingleThreadResume for Interpreter<' } } -impl<'a, 'b, V: Verifier, C: ContextObject> target::ext::base::singlethread::SingleThreadSingleStep - for Interpreter<'a, 'b, V, C> +impl<'a, 'b, C: ContextObject> target::ext::base::singlethread::SingleThreadSingleStep + for Interpreter<'a, 'b, C> { fn step(&mut self, signal: Option) -> Result<(), Self::Error> { if signal.is_some() { @@ -295,8 +293,8 @@ impl<'a, 'b, V: Verifier, C: ContextObject> target::ext::base::singlethread::Sin } } -impl<'a, 'b, V: Verifier, C: ContextObject> target::ext::section_offsets::SectionOffsets - for Interpreter<'a, 'b, V, C> +impl<'a, 'b, C: ContextObject> target::ext::section_offsets::SectionOffsets + for Interpreter<'a, 'b, C> { fn get_section_offsets(&mut self) -> Result, Self::Error> { Ok(Offsets::Sections { @@ -307,9 +305,7 @@ impl<'a, 'b, V: Verifier, C: ContextObject> target::ext::section_offsets::Sectio } } -impl<'a, 'b, V: Verifier, C: ContextObject> target::ext::breakpoints::Breakpoints - for Interpreter<'a, 'b, V, C> -{ +impl<'a, 'b, C: ContextObject> target::ext::breakpoints::Breakpoints for Interpreter<'a, 'b, C> { #[inline(always)] fn support_sw_breakpoint( &mut self, @@ -318,9 +314,7 @@ impl<'a, 'b, V: Verifier, C: ContextObject> target::ext::breakpoints::Breakpoint } } -impl<'a, 'b, V: Verifier, C: ContextObject> target::ext::breakpoints::SwBreakpoint - for Interpreter<'a, 'b, V, C> -{ +impl<'a, 'b, C: ContextObject> target::ext::breakpoints::SwBreakpoint for Interpreter<'a, 'b, C> { fn add_sw_breakpoint( &mut self, addr: u64, @@ -345,9 +339,8 @@ impl<'a, 'b, V: Verifier, C: ContextObject> target::ext::breakpoints::SwBreakpoi } } -impl<'a, 'b, V: Verifier, C: ContextObject> - target::ext::lldb_register_info_override::LldbRegisterInfoOverride - for Interpreter<'a, 'b, V, C> +impl<'a, 'b, C: ContextObject> target::ext::lldb_register_info_override::LldbRegisterInfoOverride + for Interpreter<'a, 'b, C> { fn lldb_register_info<'c>( &mut self, diff --git a/src/elf.rs b/src/elf.rs index ce1218b0..8baa89d6 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -22,7 +22,7 @@ use crate::{ }, error::EbpfError, memory_region::MemoryRegion, - verifier::{TautologyVerifier, Verifier}, + verifier::Verifier, vm::{BuiltinProgram, Config, ContextObject}, }; @@ -32,7 +32,6 @@ use byteorder::{ByteOrder, LittleEndian}; use std::{ collections::{btree_map::Entry, BTreeMap}, fmt::Debug, - marker::PhantomData, mem, ops::Range, str, @@ -409,9 +408,7 @@ impl FunctionRegistry { /// Elf loader/relocator #[derive(Debug, PartialEq)] -pub struct Executable { - /// Verifier that verified this program - _verifier: PhantomData, +pub struct Executable { /// Loaded and executable elf elf_bytes: AlignedMemory<{ HOST_ALIGN }>, /// Required SBPF capabilities @@ -431,7 +428,7 @@ pub struct Executable { compiled_program: Option, } -impl Executable { +impl Executable { /// Get the configuration settings pub fn get_config(&self) -> &Config { self.loader.get_config() @@ -500,22 +497,20 @@ impl Executable { } /// Verify the executable - pub fn verified(executable: Executable) -> Result { + pub fn verify(&self) -> Result<(), EbpfError> { ::verify( - executable.get_text_bytes().1, - executable.get_config(), - executable.get_sbpf_version(), - executable.get_function_registry(), + self.get_text_bytes().1, + self.get_config(), + self.get_sbpf_version(), + self.get_function_registry(), )?; - Ok(unsafe { - std::mem::transmute::, Executable>(executable) - }) + Ok(()) } /// JIT compile the executable #[cfg(all(feature = "jit", not(target_os = "windows"), target_arch = "x86_64"))] pub fn jit_compile(&mut self) -> Result<(), crate::error::EbpfError> { - let jit = JitCompiler::::new(self)?; + let jit = JitCompiler::::new(self)?; self.compiled_program = Some(jit.compile()?); Ok(()) } @@ -547,7 +542,6 @@ impl Executable { 0 }; Ok(Self { - _verifier: PhantomData, elf_bytes, sbpf_version, ro_section: Section::Borrowed(0, 0..text_bytes.len()), @@ -678,7 +672,6 @@ impl Executable { )?; Ok(Self { - _verifier: PhantomData, elf_bytes, sbpf_version, ro_section, @@ -1408,7 +1401,7 @@ mod test { use rand::{distributions::Uniform, Rng}; use std::{fs::File, io::Read}; use test_utils::assert_error; - type ElfExecutable = Executable; + type ElfExecutable = Executable; fn loader() -> Arc> { let mut function_registry = @@ -1533,7 +1526,7 @@ mod test { .expect("failed to read elf file"); let elf = ElfExecutable::load(&elf_bytes, loader.clone()).expect("validation failed"); let parsed_elf = NewParser::parse(&elf_bytes).unwrap(); - let executable: &Executable = &elf; + let executable: &Executable = &elf; assert_eq!(0, executable.get_entrypoint_instruction_offset()); let write_header = |header: Elf64Ehdr| unsafe { @@ -1548,7 +1541,7 @@ mod test { header.e_entry += 8; let elf_bytes = write_header(header.clone()); let elf = ElfExecutable::load(&elf_bytes, loader.clone()).expect("validation failed"); - let executable: &Executable = &elf; + let executable: &Executable = &elf; assert_eq!(1, executable.get_entrypoint_instruction_offset()); header.e_entry = 1; @@ -1575,7 +1568,7 @@ mod test { header.e_entry = initial_e_entry; let elf_bytes = write_header(header); let elf = ElfExecutable::load(&elf_bytes, loader).expect("validation failed"); - let executable: &Executable = &elf; + let executable: &Executable = &elf; assert_eq!(0, executable.get_entrypoint_instruction_offset()); } diff --git a/src/interpreter.rs b/src/interpreter.rs index 518d85ca..0ab0854c 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -16,7 +16,6 @@ use crate::{ ebpf::{self, STACK_PTR_REG}, elf::Executable, error::EbpfError, - verifier::Verifier, vm::{Config, ContextObject, EbpfVm, ProgramResult}, }; use std::convert::TryInto; @@ -65,9 +64,9 @@ pub enum DebugState { } /// State of an interpreter -pub struct Interpreter<'a, 'b, V: Verifier, C: ContextObject> { +pub struct Interpreter<'a, 'b, C: ContextObject> { pub(crate) vm: &'a mut EbpfVm<'b, C>, - pub(crate) executable: &'a Executable, + pub(crate) executable: &'a Executable, pub(crate) program: &'a [u8], pub(crate) program_vm_addr: u64, pub(crate) due_insn_count: u64, @@ -83,11 +82,11 @@ pub struct Interpreter<'a, 'b, V: Verifier, C: ContextObject> { pub(crate) breakpoints: Vec, } -impl<'a, 'b, V: Verifier, C: ContextObject> Interpreter<'a, 'b, V, C> { +impl<'a, 'b, C: ContextObject> Interpreter<'a, 'b, C> { /// Creates a new interpreter state pub fn new( vm: &'a mut EbpfVm<'b, C>, - executable: &'a Executable, + executable: &'a Executable, registers: [u64; 12], ) -> Self { let (program_vm_addr, program) = executable.get_text_bytes(); diff --git a/src/jit.rs b/src/jit.rs index d84a7a4c..12288163 100644 --- a/src/jit.rs +++ b/src/jit.rs @@ -21,7 +21,6 @@ use crate::{ allocate_pages, free_pages, get_system_page_size, protect_pages, round_to_page_size, }, memory_region::{AccessType, MemoryMapping}, - verifier::Verifier, vm::{Config, ContextObject, EbpfVm, ProgramResult}, x86::*, }; @@ -310,12 +309,12 @@ enum RuntimeEnvironmentSlot { and undo again can be anything, so we just set it to zero. */ -pub struct JitCompiler<'a, V: Verifier, C: ContextObject> { +pub struct JitCompiler<'a, C: ContextObject> { result: JitProgram, text_section_jumps: Vec, anchors: [*const u8; ANCHOR_COUNT], offset_in_text_section: usize, - executable: &'a Executable, + executable: &'a Executable, program: &'a [u8], program_vm_addr: u64, config: &'a Config, @@ -328,9 +327,9 @@ pub struct JitCompiler<'a, V: Verifier, C: ContextObject> { } #[rustfmt::skip] -impl<'a, V: Verifier, C: ContextObject> JitCompiler<'a, V, C> { +impl<'a, C: ContextObject> JitCompiler<'a, C> { /// Constructs a new compiler and allocates memory for the compilation output - pub fn new(executable: &'a Executable) -> Result { + pub fn new(executable: &'a Executable) -> Result { let config = executable.get_config(); let (program_vm_addr, program) = executable.get_text_bytes(); @@ -1603,7 +1602,6 @@ mod tests { use crate::{ elf::{FunctionRegistry, SBPFVersion}, syscalls, - verifier::TautologyVerifier, vm::{BuiltinFunction, BuiltinProgram, TestContextObject}, }; use byteorder::{ByteOrder, LittleEndian}; @@ -1644,9 +1642,7 @@ mod tests { check_slot!(env, memory_mapping, MemoryMapping); } - fn create_mockup_executable( - program: &[u8], - ) -> Executable { + fn create_mockup_executable(program: &[u8]) -> Executable { let mut function_registry = FunctionRegistry::>::default(); function_registry @@ -1663,7 +1659,7 @@ mod tests { function_registry .register_function(8, *b"function_foo", 8) .unwrap(); - Executable::::from_text_bytes( + Executable::::from_text_bytes( program, Arc::new(loader), SBPFVersion::V2, @@ -1680,8 +1676,7 @@ mod tests { let empty_program_machine_code_length = { prog[0] = ebpf::EXIT; let mut executable = create_mockup_executable(&prog[0..ebpf::INSN_SIZE]); - Executable::::jit_compile(&mut executable) - .unwrap(); + Executable::::jit_compile(&mut executable).unwrap(); executable .get_compiled_program() .unwrap() @@ -1708,8 +1703,7 @@ mod tests { LittleEndian::write_u32(&mut prog[pc * ebpf::INSN_SIZE + 4..], immediate); } let mut executable = create_mockup_executable(&prog); - let result = - Executable::::jit_compile(&mut executable); + let result = Executable::::jit_compile(&mut executable); if result.is_err() { assert!(matches!( result.unwrap_err(), diff --git a/src/static_analysis.rs b/src/static_analysis.rs index 07c7b09c..67fe9c99 100644 --- a/src/static_analysis.rs +++ b/src/static_analysis.rs @@ -6,7 +6,6 @@ use crate::{ ebpf, elf::Executable, error::EbpfError, - verifier::{TautologyVerifier, Verifier}, vm::{ContextObject, DynamicAnalysis, TestContextObject}, }; use rustc_demangle::demangle; @@ -127,7 +126,7 @@ impl Default for CfgNode { /// Result of the executable analysis pub struct Analysis<'a> { /// The program which is analyzed - executable: &'a Executable, + executable: &'a Executable, /// Plain list of instructions as they occur in the executable pub instructions: Vec, /// Functions in the executable @@ -148,8 +147,8 @@ pub struct Analysis<'a> { impl<'a> Analysis<'a> { /// Analyze an executable statically - pub fn from_executable( - executable: &'a Executable, + pub fn from_executable( + executable: &'a Executable, ) -> Result { let (_program_vm_addr, program) = executable.get_text_bytes(); let mut functions = BTreeMap::new(); diff --git a/src/verifier.rs b/src/verifier.rs index b3211977..d42ee63f 100644 --- a/src/verifier.rs +++ b/src/verifier.rs @@ -382,17 +382,3 @@ impl Verifier for RequisiteVerifier { Ok(()) } } - -/// Passes all inputs. Used to mark executables as unverified. -#[derive(Debug)] -pub struct TautologyVerifier {} -impl Verifier for TautologyVerifier { - fn verify( - _prog: &[u8], - _config: &Config, - _sbpf_version: &SBPFVersion, - _function_registry: &FunctionRegistry, - ) -> std::result::Result<(), VerifierError> { - Ok(()) - } -} diff --git a/src/vm.rs b/src/vm.rs index bd1dc94a..cf3feb46 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -19,7 +19,6 @@ use crate::{ interpreter::Interpreter, memory_region::MemoryMapping, static_analysis::{Analysis, TraceLogEntry}, - verifier::{TautologyVerifier, Verifier}, }; use std::{collections::BTreeMap, fmt::Debug, mem, sync::Arc}; @@ -234,7 +233,7 @@ impl Default for Config { } /// Static constructors for Executable -impl Executable { +impl Executable { /// Creates an executable from an ELF file pub fn from_elf(elf_bytes: &[u8], loader: Arc>) -> Result { let executable = Executable::load(elf_bytes, loader)?; @@ -362,7 +361,7 @@ pub struct CallFrame { /// ebpf, /// elf::{Executable, FunctionRegistry, SBPFVersion}, /// memory_region::{MemoryMapping, MemoryRegion}, -/// verifier::{TautologyVerifier, RequisiteVerifier}, +/// verifier::{RequisiteVerifier}, /// vm::{BuiltinProgram, Config, EbpfVm, TestContextObject}, /// }; /// @@ -375,18 +374,18 @@ pub struct CallFrame { /// /// let loader = std::sync::Arc::new(BuiltinProgram::new_mock()); /// let function_registry = FunctionRegistry::default(); -/// let mut executable = Executable::::from_text_bytes(prog, loader, SBPFVersion::V2, function_registry).unwrap(); -/// let verified_executable = Executable::::verified(executable).unwrap(); +/// let mut executable = Executable::::from_text_bytes(prog, loader, SBPFVersion::V2, function_registry).unwrap(); +/// executable.verify::().unwrap(); /// let mut context_object = TestContextObject::new(1); -/// let config = verified_executable.get_config(); -/// let sbpf_version = verified_executable.get_sbpf_version(); +/// let config = executable.get_config(); +/// let sbpf_version = executable.get_sbpf_version(); /// /// let mut stack = AlignedMemory::<{ebpf::HOST_ALIGN}>::zero_filled(config.stack_size()); /// let stack_len = stack.len(); /// let mut heap = AlignedMemory::<{ebpf::HOST_ALIGN}>::with_capacity(0); /// /// let regions: Vec = vec![ -/// verified_executable.get_ro_region(), +/// executable.get_ro_region(), /// MemoryRegion::new_writable( /// stack.as_slice_mut(), /// ebpf::MM_STACK_START, @@ -399,7 +398,7 @@ pub struct CallFrame { /// /// let mut vm = EbpfVm::new(config, sbpf_version, &mut context_object, memory_mapping, stack_len); /// -/// let (instruction_count, result) = vm.execute_program(&verified_executable, true); +/// let (instruction_count, result) = vm.execute_program(&executable, true); /// assert_eq!(instruction_count, 1); /// assert_eq!(result.unwrap(), 0); /// ``` @@ -477,9 +476,9 @@ impl<'a, C: ContextObject> EbpfVm<'a, C> { /// Execute the program /// /// If interpreted = `false` then the JIT compiled executable is used. - pub fn execute_program( + pub fn execute_program( &mut self, - executable: &Executable, + executable: &Executable, interpreted: bool, ) -> (u64, ProgramResult) { let mut registers = [0u64; 12]; diff --git a/src/x86.rs b/src/x86.rs index a191a34a..9d33ba7f 100644 --- a/src/x86.rs +++ b/src/x86.rs @@ -1,7 +1,6 @@ #![allow(clippy::arithmetic_side_effects)] use crate::{ jit::{JitCompiler, OperandSize}, - verifier::Verifier, vm::ContextObject, }; @@ -103,7 +102,7 @@ impl X86Instruction { }; #[inline] - pub fn emit(&self, jit: &mut JitCompiler) { + pub fn emit(&self, jit: &mut JitCompiler) { debug_assert!(!matches!(self.size, OperandSize::S0)); let mut rex = X86Rex { w: matches!(self.size, OperandSize::S64), diff --git a/test_utils/src/lib.rs b/test_utils/src/lib.rs index b26bb0c6..d173dd94 100644 --- a/test_utils/src/lib.rs +++ b/test_utils/src/lib.rs @@ -14,7 +14,6 @@ use solana_rbpf::{ elf::Executable, error::EbpfError, memory_region::{MemoryCowCallback, MemoryMapping, MemoryRegion}, - verifier::Verifier, vm::ContextObject, }; @@ -159,8 +158,8 @@ pub const TCP_SACK_NOMATCH: [u8; 66] = [ 0x9e, 0x27, // ]; -pub fn create_memory_mapping<'a, V: Verifier, C: ContextObject>( - executable: &'a Executable, +pub fn create_memory_mapping<'a, C: ContextObject>( + executable: &'a Executable, stack: &'a mut AlignedMemory<{ HOST_ALIGN }>, heap: &'a mut AlignedMemory<{ HOST_ALIGN }>, additional_regions: Vec, diff --git a/tests/execution.rs b/tests/execution.rs index 88a8293f..cc9725a1 100644 --- a/tests/execution.rs +++ b/tests/execution.rs @@ -23,7 +23,7 @@ use solana_rbpf::{ memory_region::{AccessType, MemoryMapping, MemoryRegion}, static_analysis::Analysis, syscalls, - verifier::{RequisiteVerifier, TautologyVerifier}, + verifier::RequisiteVerifier, vm::{ BuiltinFunction, BuiltinProgram, Config, ContextObject, ProgramResult, TestContextObject, }, @@ -49,24 +49,21 @@ macro_rules! test_interpreter_and_jit { if !expected_result.contains("ExceededMaxInstructions") { context_object.remaining = INSTRUCTION_METER_BUDGET; } - #[allow(unused_mut)] - let mut verified_executable = - Executable::::verified($executable).unwrap(); + $executable.verify::().unwrap(); let (instruction_count_interpreter, _tracer_interpreter) = { let mut mem = $mem; let mem_region = MemoryRegion::new_writable(&mut mem, ebpf::MM_INPUT_START); let mut context_object = context_object.clone(); create_vm!( vm, - &verified_executable, + &$executable, &mut context_object, stack, heap, vec![mem_region], None ); - let (instruction_count_interpreter, result) = - vm.execute_program(&verified_executable, true); + let (instruction_count_interpreter, result) = vm.execute_program(&$executable, true); assert_eq!(format!("{:?}", result), expected_result); if result.is_ok() { assert_eq!( @@ -82,12 +79,12 @@ macro_rules! test_interpreter_and_jit { #[cfg(all(not(windows), target_arch = "x86_64"))] { #[allow(unused_mut)] - let compilation_result = verified_executable.jit_compile(); + let compilation_result = $executable.jit_compile(); let mut mem = $mem; let mem_region = MemoryRegion::new_writable(&mut mem, ebpf::MM_INPUT_START); create_vm!( vm, - &verified_executable, + &$executable, &mut context_object, stack, heap, @@ -97,12 +94,11 @@ macro_rules! test_interpreter_and_jit { match compilation_result { Err(err) => assert_eq!(format!("{:?}", err), expected_result), Ok(()) => { - let (instruction_count_jit, result) = - vm.execute_program(&verified_executable, false); + let (instruction_count_jit, result) = vm.execute_program(&$executable, false); let tracer_jit = &vm.context_object_pointer; assert_eq!(format!("{:?}", result), expected_result); if !TestContextObject::compare_trace_log(&_tracer_interpreter, tracer_jit) { - let analysis = Analysis::from_executable(&verified_executable).unwrap(); + let analysis = Analysis::from_executable(&$executable).unwrap(); let stdout = std::io::stdout(); analysis .disassemble_trace_log( @@ -122,7 +118,7 @@ macro_rules! test_interpreter_and_jit { } } } - if verified_executable.get_config().enable_instruction_meter { + if $executable.get_config().enable_instruction_meter { assert_eq!(instruction_count_interpreter, expected_instruction_count); } }; @@ -161,7 +157,7 @@ macro_rules! test_interpreter_and_jit_elf { let mut function_registry = FunctionRegistry::>::default(); $(test_interpreter_and_jit!(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 executable = Executable::::from_elf(&elf, loader).unwrap(); test_interpreter_and_jit!(executable, $mem, $context_object, $expected_result); } }; @@ -2733,7 +2729,7 @@ fn test_err_mem_access_out_of_bound() { LittleEndian::write_u32(&mut prog[4..], address as u32); LittleEndian::write_u32(&mut prog[12..], (address >> 32) as u32); #[allow(unused_mut)] - let mut executable = Executable::::from_text_bytes( + let mut executable = Executable::::from_text_bytes( &prog, loader.clone(), SBPFVersion::V2, @@ -3457,7 +3453,7 @@ fn test_err_unresolved_syscall_reloc_64_32() { let mut elf = Vec::new(); file.read_to_end(&mut elf).unwrap(); assert_error!( - Executable::::from_elf(&elf, Arc::new(loader)), + Executable::::from_elf(&elf, Arc::new(loader)), "UnresolvedSymbol(\"log\", 68, 312)" ); } @@ -3851,7 +3847,7 @@ fn test_struct_func_pointer() { fn execute_generated_program(prog: &[u8]) -> bool { let max_instruction_count = 1024; let mem_size = 1024 * 1024; - let executable = Executable::::from_text_bytes( + let executable = Executable::::from_text_bytes( prog, Arc::new(BuiltinProgram::new_loader( Config { @@ -3863,19 +3859,12 @@ fn execute_generated_program(prog: &[u8]) -> bool { SBPFVersion::V2, FunctionRegistry::default(), ); - let executable = if let Ok(executable) = executable { + let mut executable = if let Ok(executable) = executable { executable } else { return false; }; - let verified_executable = - Executable::::verified(executable); - let mut verified_executable = if let Ok(verified_executable) = verified_executable { - verified_executable - } else { - return false; - }; - if verified_executable.jit_compile().is_err() { + if executable.verify::().is_err() || executable.jit_compile().is_err() { return false; } let (instruction_count_interpreter, tracer_interpreter, result_interpreter) = { @@ -3884,7 +3873,7 @@ fn execute_generated_program(prog: &[u8]) -> bool { let mem_region = MemoryRegion::new_writable(&mut mem, ebpf::MM_INPUT_START); create_vm!( vm, - &verified_executable, + &executable, &mut context_object, stack, heap, @@ -3892,7 +3881,7 @@ fn execute_generated_program(prog: &[u8]) -> bool { None ); let (instruction_count_interpreter, result_interpreter) = - vm.execute_program(&verified_executable, true); + vm.execute_program(&executable, true); let tracer_interpreter = vm.context_object_pointer.clone(); ( instruction_count_interpreter, @@ -3905,20 +3894,20 @@ fn execute_generated_program(prog: &[u8]) -> bool { let mem_region = MemoryRegion::new_writable(&mut mem, ebpf::MM_INPUT_START); create_vm!( vm, - &verified_executable, + &executable, &mut context_object, stack, heap, vec![mem_region], None ); - let (instruction_count_jit, result_jit) = vm.execute_program(&verified_executable, false); + let (instruction_count_jit, result_jit) = vm.execute_program(&executable, false); let tracer_jit = &vm.context_object_pointer; if format!("{result_interpreter:?}") != format!("{result_jit:?}") || !TestContextObject::compare_trace_log(&tracer_interpreter, tracer_jit) { let analysis = - solana_rbpf::static_analysis::Analysis::from_executable(&verified_executable).unwrap(); + solana_rbpf::static_analysis::Analysis::from_executable(&executable).unwrap(); println!("result_interpreter={result_interpreter:?}"); println!("result_jit={result_jit:?}"); let stdout = std::io::stdout(); @@ -3930,7 +3919,7 @@ fn execute_generated_program(prog: &[u8]) -> bool { .unwrap(); panic!(); } - if verified_executable.get_config().enable_instruction_meter { + if executable.get_config().enable_instruction_meter { assert_eq!(instruction_count_interpreter, instruction_count_jit); } true diff --git a/tests/verifier.rs b/tests/verifier.rs index e3be968b..5071fa9c 100644 --- a/tests/verifier.rs +++ b/tests/verifier.rs @@ -26,11 +26,11 @@ use solana_rbpf::{ assembler::assemble, ebpf, elf::{Executable, FunctionRegistry, SBPFVersion}, - verifier::{RequisiteVerifier, TautologyVerifier, Verifier, VerifierError}, + verifier::{RequisiteVerifier, Verifier, VerifierError}, vm::{BuiltinProgram, Config, TestContextObject}, }; use std::sync::Arc; -use test_utils::create_vm; +use test_utils::{assert_error, create_vm}; use thiserror::Error; /// Error definitions @@ -40,6 +40,18 @@ pub enum VerifierTestError { Rejected(String), } +struct TautologyVerifier {} +impl Verifier for TautologyVerifier { + fn verify( + _prog: &[u8], + _config: &Config, + _sbpf_version: &SBPFVersion, + _function_registry: &FunctionRegistry, + ) -> std::result::Result<(), VerifierError> { + Ok(()) + } +} + struct ContradictionVerifier {} impl Verifier for ContradictionVerifier { fn verify( @@ -61,11 +73,10 @@ fn test_verifier_success() { Arc::new(BuiltinProgram::new_mock()), ) .unwrap(); - let verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); create_vm!( _vm, - &verified_executable, + &executable, &mut TestContextObject::default(), stack, heap, @@ -84,8 +95,7 @@ fn test_verifier_fail() { Arc::new(BuiltinProgram::new_mock()), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -99,8 +109,7 @@ fn test_verifier_err_div_by_zero_imm() { Arc::new(BuiltinProgram::new_mock()), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -111,15 +120,14 @@ fn test_verifier_err_endian_size() { 0xb7, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ]; - let executable = Executable::::from_text_bytes( + let executable = Executable::::from_text_bytes( prog, Arc::new(BuiltinProgram::new_mock()), SBPFVersion::V2, FunctionRegistry::default(), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -130,15 +138,14 @@ fn test_verifier_err_incomplete_lddw() { 0x18, 0x00, 0x00, 0x00, 0x88, 0x77, 0x66, 0x55, // 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ]; - let executable = Executable::::from_text_bytes( + let executable = Executable::::from_text_bytes( prog, Arc::new(BuiltinProgram::new_mock()), SBPFVersion::V1, FunctionRegistry::default(), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -159,13 +166,8 @@ fn test_verifier_err_invalid_reg_dst() { )), ) .unwrap(); - let result = Executable::::verified(executable) - .map_err(|err| format!("Executable constructor {err:?}")); - - assert_eq!( - result.unwrap_err(), - "Executable constructor VerifierError(InvalidDestinationRegister(29))" - ); + let result = executable.verify::(); + assert_error!(result, "VerifierError(InvalidDestinationRegister(29))"); } } @@ -187,13 +189,8 @@ fn test_verifier_err_invalid_reg_src() { )), ) .unwrap(); - let result = Executable::::verified(executable) - .map_err(|err| format!("Executable constructor {err:?}")); - - assert_eq!( - result.unwrap_err(), - "Executable constructor VerifierError(InvalidSourceRegister(29))" - ); + let result = executable.verify::(); + assert_error!(result, "VerifierError(InvalidSourceRegister(29))"); } } @@ -213,8 +210,7 @@ fn test_verifier_resize_stack_ptr_success() { )), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -228,8 +224,7 @@ fn test_verifier_err_jmp_lddw() { Arc::new(BuiltinProgram::new_mock()), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -243,8 +238,7 @@ fn test_verifier_err_call_lddw() { Arc::new(BuiltinProgram::new_mock()), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -258,8 +252,7 @@ fn test_verifier_err_function_fallthrough() { Arc::new(BuiltinProgram::new_mock()), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -272,8 +265,7 @@ fn test_verifier_err_jmp_out() { Arc::new(BuiltinProgram::new_mock()), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -286,8 +278,7 @@ fn test_verifier_err_jmp_out_start() { Arc::new(BuiltinProgram::new_mock()), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -297,15 +288,14 @@ fn test_verifier_err_unknown_opcode() { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ]; - let executable = Executable::::from_text_bytes( + let executable = Executable::::from_text_bytes( prog, Arc::new(BuiltinProgram::new_mock()), SBPFVersion::V2, FunctionRegistry::default(), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -318,8 +308,7 @@ fn test_verifier_err_write_r10() { Arc::new(BuiltinProgram::new_mock()), ) .unwrap(); - let _verified_executable = - Executable::::verified(executable).unwrap(); + executable.verify::().unwrap(); } #[test] @@ -352,17 +341,10 @@ fn test_verifier_err_all_shift_overflows() { let assembly = format!("\n{overflowing_instruction}\nexit"); let executable = assemble::(&assembly, Arc::new(BuiltinProgram::new_mock())).unwrap(); - let result = Executable::::verified(executable) - .map_err(|err| format!("Executable constructor {err:?}")); + let result = executable.verify::(); match expected { Ok(()) => assert!(result.is_ok()), - Err(overflow_msg) => match result { - Err(err) => assert_eq!( - err, - format!("Executable constructor VerifierError({overflow_msg})"), - ), - _ => panic!("Expected error"), - }, + Err(overflow_msg) => assert_error!(result, "VerifierError({overflow_msg})"), } } } @@ -390,18 +372,15 @@ fn test_sdiv_disabled() { )), ) .unwrap(); - let result = Executable::::verified(executable) - .map_err(|err| format!("Executable constructor {err:?}")); + let result = executable.verify::(); if enable_sbpf_v2 { assert!(result.is_ok()); } else { - assert_eq!( - result.unwrap_err(), - format!( - "Executable constructor VerifierError(UnknownOpCode({}, {}))", - opc, - ebpf::ELF_INSN_DUMP_OFFSET - ), + assert_error!( + result, + "VerifierError(UnknownOpCode({}, {}))", + opc, + ebpf::ELF_INSN_DUMP_OFFSET ); } }