diff --git a/Cargo.lock b/Cargo.lock index 45f74ff624..39e12fabe7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6992,9 +6992,9 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.2.37" +version = "0.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0669f9f5c355899600732451c65cc717d0ef0c53717749f03520337c824fd8a1" +checksum = "a4e9e5085099858adba23d0a0b5298da8803f89999cb567ecafab9c916cdf53d" dependencies = [ "byteorder", "combine", @@ -7007,6 +7007,7 @@ dependencies = [ "rustc-demangle", "scroll", "thiserror", + "winapi 0.3.9", ] [[package]] diff --git a/cli/Cargo.toml b/cli/Cargo.toml index b265fbc8e6..b7fdb90f6f 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -55,7 +55,7 @@ solana-tpu-client = { path = "../tpu-client", version = "=1.15.0" } solana-transaction-status = { path = "../transaction-status", version = "=1.15.0" } solana-version = { path = "../version", version = "=1.15.0" } solana-vote-program = { path = "../programs/vote", version = "=1.15.0" } -solana_rbpf = "=0.2.37" +solana_rbpf = "=0.2.38" spl-memo = { version = "=3.0.1", features = ["no-entrypoint"] } thiserror = "1.0.31" tiny-bip39 = "0.8.2" diff --git a/cli/src/program.rs b/cli/src/program.rs index b632cacda0..6d9fd1ae1e 100644 --- a/cli/src/program.rs +++ b/cli/src/program.rs @@ -10,7 +10,7 @@ use { clap::{App, AppSettings, Arg, ArgMatches, SubCommand}, log::*, solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig}, - solana_bpf_loader_program::syscalls::register_syscalls, + solana_bpf_loader_program::syscalls::create_loader, solana_clap_utils::{self, input_parsers::*, input_validators::*, keypair::*}, solana_cli_output::{ CliProgram, CliProgramAccountType, CliProgramAuthority, CliProgramBuffer, CliProgramId, @@ -21,12 +21,8 @@ use { connection_cache::ConnectionCache, tpu_client::{TpuClient, TpuClientConfig}, }, - solana_program_runtime::invoke_context::InvokeContext, - solana_rbpf::{ - elf::Executable, - verifier::RequisiteVerifier, - vm::{Config, VerifiedExecutable}, - }, + solana_program_runtime::{compute_budget::ComputeBudget, invoke_context::InvokeContext}, + solana_rbpf::{elf::Executable, verifier::RequisiteVerifier, vm::VerifiedExecutable}, solana_remote_wallet::remote_wallet::RemoteWalletManager, solana_rpc_client::rpc_client::RpcClient, solana_rpc_client_api::{ @@ -1994,15 +1990,16 @@ fn read_and_verify_elf(program_location: &str) -> Result, Box::from_elf( - &program_data, - Config { - reject_broken_elfs: true, - ..Config::default() - }, - register_syscalls(&invoke_context.feature_set, true).unwrap(), + let loader = create_loader( + &invoke_context.feature_set, + &ComputeBudget::default(), + true, + true, + false, ) - .map_err(|err| format!("ELF error: {err}"))?; + .unwrap(); + let executable = Executable::::from_elf(&program_data, loader) + .map_err(|err| format!("ELF error: {err}"))?; let _ = VerifiedExecutable::::from_executable(executable) .map_err(|err| format!("ELF error: {err}"))?; diff --git a/program-runtime/Cargo.toml b/program-runtime/Cargo.toml index 8eba2c6837..2a3c830bdb 100644 --- a/program-runtime/Cargo.toml +++ b/program-runtime/Cargo.toml @@ -26,7 +26,7 @@ solana-frozen-abi = { path = "../frozen-abi", version = "=1.15.0" } solana-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.15.0" } solana-measure = { path = "../measure", version = "=1.15.0" } solana-metrics = { path = "../metrics", version = "=1.15.0" } -solana_rbpf = "=0.2.37" +solana_rbpf = "=0.2.38" solana-sdk = { path = "../sdk", version = "=1.15.0" } thiserror = "1.0" diff --git a/programs/bpf_loader/Cargo.toml b/programs/bpf_loader/Cargo.toml index 9570111288..1e1d7e5205 100644 --- a/programs/bpf_loader/Cargo.toml +++ b/programs/bpf_loader/Cargo.toml @@ -14,16 +14,14 @@ bincode = "1.3.3" byteorder = "1.4.3" libsecp256k1 = "0.6.0" log = "0.4.17" +rand = "0.7.3" solana-measure = { path = "../../measure", version = "=1.15.0" } solana-program-runtime = { path = "../../program-runtime", version = "=1.15.0" } solana-sdk = { path = "../../sdk", version = "=1.15.0" } solana-zk-token-sdk = { path = "../../zk-token-sdk", version = "=1.15.0" } -solana_rbpf = "=0.2.37" +solana_rbpf = "=0.2.38" thiserror = "1.0" -[dev-dependencies] -rand = "0.7.3" - [lib] crate-type = ["lib"] name = "solana_bpf_loader_program" diff --git a/programs/bpf_loader/src/lib.rs b/programs/bpf_loader/src/lib.rs index 69b80eb54d..b97b00289e 100644 --- a/programs/bpf_loader/src/lib.rs +++ b/programs/bpf_loader/src/lib.rs @@ -33,7 +33,7 @@ use { error::{EbpfError, UserDefinedError}, memory_region::MemoryRegion, verifier::{RequisiteVerifier, VerifierError}, - vm::{Config, ContextObject, EbpfVm, ProgramResult, VerifiedExecutable}, + vm::{ContextObject, EbpfVm, ProgramResult, VerifiedExecutable}, }, solana_sdk::{ bpf_loader, bpf_loader_deprecated, @@ -43,9 +43,8 @@ use { cap_accounts_data_allocations_per_transaction, cap_bpf_program_instruction_accounts, check_slice_translation_size, disable_deploy_of_alloc_free_syscall, disable_deprecated_loader, enable_bpf_loader_extend_program_ix, - enable_bpf_loader_set_authority_checked_ix, - error_on_syscall_bpf_function_hash_collisions, limit_max_instruction_trace_length, - reject_callx_r10, FeatureSet, + enable_bpf_loader_set_authority_checked_ix, limit_max_instruction_trace_length, + FeatureSet, }, instruction::{AccountMeta, InstructionError}, loader_instruction::LoaderInstruction, @@ -132,45 +131,24 @@ fn create_executor_from_bytes( let mut register_syscalls_time = Measure::start("register_syscalls_time"); let disable_deploy_of_alloc_free_syscall = reject_deployment_of_broken_elfs && feature_set.is_active(&disable_deploy_of_alloc_free_syscall::id()); - let register_syscall_result = - syscalls::register_syscalls(feature_set, disable_deploy_of_alloc_free_syscall); - register_syscalls_time.stop(); - create_executor_metrics.register_syscalls_us = register_syscalls_time.as_us(); - let syscall_registry = register_syscall_result.map_err(|e| { + let loader = syscalls::create_loader( + feature_set, + compute_budget, + reject_deployment_of_broken_elfs, + disable_deploy_of_alloc_free_syscall, + false, + ) + .map_err(|e| { ic_logger_msg!(log_collector, "Failed to register syscalls: {}", e); InstructionError::ProgramEnvironmentSetupFailure })?; - let config = Config { - max_call_depth: compute_budget.max_call_depth, - stack_frame_size: compute_budget.stack_frame_size, - enable_stack_frame_gaps: true, - instruction_meter_checkpoint_distance: 10000, - enable_instruction_meter: true, - enable_instruction_tracing: false, - enable_symbol_and_section_labels: false, - reject_broken_elfs: reject_deployment_of_broken_elfs, - noop_instruction_rate: 256, - sanitize_user_provided_values: true, - encrypt_environment_registers: true, - syscall_bpf_function_hash_collision: feature_set - .is_active(&error_on_syscall_bpf_function_hash_collisions::id()), - reject_callx_r10: feature_set.is_active(&reject_callx_r10::id()), - dynamic_stack_frames: false, - enable_sdiv: false, - optimize_rodata: false, - static_syscalls: false, - enable_elf_vaddr: false, - reject_rodata_stack_overlap: false, - new_elf_parser: false, - aligned_memory_mapping: true, - // Warning, do not use `Config::default()` so that configuration here is explicit. - }; + register_syscalls_time.stop(); + create_executor_metrics.register_syscalls_us = register_syscalls_time.as_us(); let mut load_elf_time = Measure::start("load_elf_time"); - let executable = Executable::::from_elf(programdata, config, syscall_registry) - .map_err(|err| { - ic_logger_msg!(log_collector, "{}", err); - InstructionError::InvalidAccountData - }); + let executable = Executable::::from_elf(programdata, loader).map_err(|err| { + ic_logger_msg!(log_collector, "{}", err); + InstructionError::InvalidAccountData + }); load_elf_time.stop(); create_executor_metrics.load_elf_us = load_elf_time.as_us(); let executable = executable?; @@ -1527,7 +1505,7 @@ mod tests { solana_rbpf::{ ebpf::MM_INPUT_START, verifier::Verifier, - vm::{ContextObject, FunctionRegistry, SyscallRegistry}, + vm::{BuiltInProgram, Config, ContextObject, FunctionRegistry}, }, solana_sdk::{ account::{ @@ -1611,13 +1589,10 @@ mod tests { 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit ]; let mut input_mem = [0x00]; - let config = Config::default(); - let syscall_registry = SyscallRegistry::default(); let bpf_functions = std::collections::BTreeMap::::new(); let executable = Executable::::from_text_bytes( program, - config, - syscall_registry, + Arc::new(BuiltInProgram::new_loader(Config::default())), bpf_functions, ) .unwrap(); diff --git a/programs/bpf_loader/src/syscalls/mod.rs b/programs/bpf_loader/src/syscalls/mod.rs index 03e07e2e83..a1b609ec6b 100644 --- a/programs/bpf_loader/src/syscalls/mod.rs +++ b/programs/bpf_loader/src/syscalls/mod.rs @@ -13,12 +13,13 @@ pub use self::{ use { crate::BpfError, solana_program_runtime::{ - ic_logger_msg, ic_msg, invoke_context::InvokeContext, stable_log, timings::ExecuteTimings, + compute_budget::ComputeBudget, ic_logger_msg, ic_msg, invoke_context::InvokeContext, + stable_log, timings::ExecuteTimings, }, solana_rbpf::{ error::EbpfError, memory_region::{AccessType, MemoryMapping}, - vm::{ProgramResult, SyscallRegistry}, + vm::{BuiltInProgram, Config, ProgramResult, PROGRAM_ENVIRONMENT_KEY_SHIFT}, }, solana_sdk::{ account::{ReadableAccount, WritableAccount}, @@ -36,7 +37,8 @@ use { check_syscall_outputs_do_not_overlap, curve25519_syscall_enabled, disable_cpi_setting_executable_and_rent_epoch, disable_fees_sysvar, enable_alt_bn128_syscall, enable_early_verification_of_account_modifications, - libsecp256k1_0_5_upgrade_enabled, limit_secp256k1_recovery_id, + error_on_syscall_bpf_function_hash_collisions, libsecp256k1_0_5_upgrade_enabled, + limit_secp256k1_recovery_id, reject_callx_r10, stop_sibling_instruction_search_at_parent, }, hash::{Hasher, HASH_BYTES}, @@ -136,155 +138,180 @@ fn consume_compute_meter(invoke_context: &InvokeContext, amount: u64) -> Result< Ok(()) } -macro_rules! register_feature_gated_syscall { - ($syscall_registry:expr, $is_feature_active:expr, $name:expr, $call:expr $(,)?) => { +macro_rules! register_feature_gated_function { + ($result:expr, $is_feature_active:expr, $name:expr, $call:expr $(,)?) => { if $is_feature_active { - $syscall_registry.register_syscall_by_name($name, $call) + $result.register_function_by_name($name, $call) } else { Ok(()) } }; } -pub fn register_syscalls<'a>( +pub fn create_loader<'a>( feature_set: &FeatureSet, + compute_budget: &ComputeBudget, + reject_deployment_of_broken_elfs: bool, disable_deploy_of_alloc_free_syscall: bool, -) -> Result>, EbpfError> { + debugging_features: bool, +) -> Result>>, EbpfError> { + use rand::Rng; + let config = Config { + max_call_depth: compute_budget.max_call_depth, + stack_frame_size: compute_budget.stack_frame_size, + enable_stack_frame_gaps: true, + instruction_meter_checkpoint_distance: 10000, + enable_instruction_meter: true, + enable_instruction_tracing: debugging_features, + enable_symbol_and_section_labels: debugging_features, + reject_broken_elfs: reject_deployment_of_broken_elfs, + noop_instruction_rate: 256, + sanitize_user_provided_values: true, + runtime_environment_key: rand::thread_rng() + .gen::() + .checked_shr(PROGRAM_ENVIRONMENT_KEY_SHIFT) + .unwrap_or(0), + external_internal_function_hash_collision: feature_set + .is_active(&error_on_syscall_bpf_function_hash_collisions::id()), + reject_callx_r10: feature_set.is_active(&reject_callx_r10::id()), + dynamic_stack_frames: false, + enable_sdiv: false, + optimize_rodata: false, + static_syscalls: false, + enable_elf_vaddr: false, + reject_rodata_stack_overlap: false, + new_elf_parser: false, + aligned_memory_mapping: true, + // Warning, do not use `Config::default()` so that configuration here is explicit. + }; + let enable_alt_bn128_syscall = feature_set.is_active(&enable_alt_bn128_syscall::id()); let blake3_syscall_enabled = feature_set.is_active(&blake3_syscall_enabled::id()); let curve25519_syscall_enabled = feature_set.is_active(&curve25519_syscall_enabled::id()); let disable_fees_sysvar = feature_set.is_active(&disable_fees_sysvar::id()); let is_abi_v2 = false; - let mut syscall_registry = SyscallRegistry::default(); + let mut result = BuiltInProgram::new_loader(config); // Abort - syscall_registry.register_syscall_by_name(b"abort", SyscallAbort::call)?; + result.register_function_by_name("abort", SyscallAbort::call)?; // Panic - syscall_registry.register_syscall_by_name(b"sol_panic_", SyscallPanic::call)?; + result.register_function_by_name("sol_panic_", SyscallPanic::call)?; // Logging - syscall_registry.register_syscall_by_name(b"sol_log_", SyscallLog::call)?; - syscall_registry.register_syscall_by_name(b"sol_log_64_", SyscallLogU64::call)?; - syscall_registry - .register_syscall_by_name(b"sol_log_compute_units_", SyscallLogBpfComputeUnits::call)?; - syscall_registry.register_syscall_by_name(b"sol_log_pubkey", SyscallLogPubkey::call)?; + result.register_function_by_name("sol_log_", SyscallLog::call)?; + result.register_function_by_name("sol_log_64_", SyscallLogU64::call)?; + result.register_function_by_name("sol_log_compute_units_", SyscallLogBpfComputeUnits::call)?; + result.register_function_by_name("sol_log_pubkey", SyscallLogPubkey::call)?; // Program defined addresses (PDA) - syscall_registry.register_syscall_by_name( - b"sol_create_program_address", + result.register_function_by_name( + "sol_create_program_address", SyscallCreateProgramAddress::call, )?; - syscall_registry.register_syscall_by_name( - b"sol_try_find_program_address", + result.register_function_by_name( + "sol_try_find_program_address", SyscallTryFindProgramAddress::call, )?; // Sha256 - syscall_registry.register_syscall_by_name(b"sol_sha256", SyscallSha256::call)?; + result.register_function_by_name("sol_sha256", SyscallSha256::call)?; // Keccak256 - syscall_registry.register_syscall_by_name(b"sol_keccak256", SyscallKeccak256::call)?; + result.register_function_by_name("sol_keccak256", SyscallKeccak256::call)?; // Secp256k1 Recover - syscall_registry - .register_syscall_by_name(b"sol_secp256k1_recover", SyscallSecp256k1Recover::call)?; + result.register_function_by_name("sol_secp256k1_recover", SyscallSecp256k1Recover::call)?; // Blake3 - register_feature_gated_syscall!( - syscall_registry, + register_feature_gated_function!( + result, blake3_syscall_enabled, - b"sol_blake3", + "sol_blake3", SyscallBlake3::call, )?; // Elliptic Curve Operations - register_feature_gated_syscall!( - syscall_registry, + register_feature_gated_function!( + result, curve25519_syscall_enabled, - b"sol_curve_validate_point", + "sol_curve_validate_point", SyscallCurvePointValidation::call, )?; - register_feature_gated_syscall!( - syscall_registry, + register_feature_gated_function!( + result, curve25519_syscall_enabled, - b"sol_curve_group_op", + "sol_curve_group_op", SyscallCurveGroupOps::call, )?; - register_feature_gated_syscall!( - syscall_registry, + register_feature_gated_function!( + result, curve25519_syscall_enabled, - b"sol_curve_multiscalar_mul", + "sol_curve_multiscalar_mul", SyscallCurveMultiscalarMultiplication::call, )?; // Sysvars - syscall_registry - .register_syscall_by_name(b"sol_get_clock_sysvar", SyscallGetClockSysvar::call)?; - syscall_registry.register_syscall_by_name( - b"sol_get_epoch_schedule_sysvar", + result.register_function_by_name("sol_get_clock_sysvar", SyscallGetClockSysvar::call)?; + result.register_function_by_name( + "sol_get_epoch_schedule_sysvar", SyscallGetEpochScheduleSysvar::call, )?; - register_feature_gated_syscall!( - syscall_registry, + register_feature_gated_function!( + result, !disable_fees_sysvar, - b"sol_get_fees_sysvar", + "sol_get_fees_sysvar", SyscallGetFeesSysvar::call, )?; - syscall_registry - .register_syscall_by_name(b"sol_get_rent_sysvar", SyscallGetRentSysvar::call)?; + result.register_function_by_name("sol_get_rent_sysvar", SyscallGetRentSysvar::call)?; // Memory ops - syscall_registry.register_syscall_by_name(b"sol_memcpy_", SyscallMemcpy::call)?; - syscall_registry.register_syscall_by_name(b"sol_memmove_", SyscallMemmove::call)?; - syscall_registry.register_syscall_by_name(b"sol_memcmp_", SyscallMemcmp::call)?; - syscall_registry.register_syscall_by_name(b"sol_memset_", SyscallMemset::call)?; + result.register_function_by_name("sol_memcpy_", SyscallMemcpy::call)?; + result.register_function_by_name("sol_memmove_", SyscallMemmove::call)?; + result.register_function_by_name("sol_memcmp_", SyscallMemcmp::call)?; + result.register_function_by_name("sol_memset_", SyscallMemset::call)?; if !is_abi_v2 { // Processed sibling instructions - syscall_registry.register_syscall_by_name( - b"sol_get_processed_sibling_instruction", + result.register_function_by_name( + "sol_get_processed_sibling_instruction", SyscallGetProcessedSiblingInstruction::call, )?; // Stack height - syscall_registry - .register_syscall_by_name(b"sol_get_stack_height", SyscallGetStackHeight::call)?; + result.register_function_by_name("sol_get_stack_height", SyscallGetStackHeight::call)?; // Return data - syscall_registry - .register_syscall_by_name(b"sol_set_return_data", SyscallSetReturnData::call)?; - syscall_registry - .register_syscall_by_name(b"sol_get_return_data", SyscallGetReturnData::call)?; + result.register_function_by_name("sol_set_return_data", SyscallSetReturnData::call)?; + result.register_function_by_name("sol_get_return_data", SyscallGetReturnData::call)?; // Cross-program invocation - syscall_registry - .register_syscall_by_name(b"sol_invoke_signed_c", SyscallInvokeSignedC::call)?; - syscall_registry - .register_syscall_by_name(b"sol_invoke_signed_rust", SyscallInvokeSignedRust::call)?; + result.register_function_by_name("sol_invoke_signed_c", SyscallInvokeSignedC::call)?; + result + .register_function_by_name("sol_invoke_signed_rust", SyscallInvokeSignedRust::call)?; // Memory allocator - register_feature_gated_syscall!( - syscall_registry, + register_feature_gated_function!( + result, !disable_deploy_of_alloc_free_syscall, - b"sol_alloc_free_", + "sol_alloc_free_", SyscallAllocFree::call, )?; // Alt_bn128 - register_feature_gated_syscall!( - syscall_registry, + register_feature_gated_function!( + result, enable_alt_bn128_syscall, - b"sol_alt_bn128_group_op", + "sol_alt_bn128_group_op", SyscallAltBn128::call, )?; } // Log data - syscall_registry.register_syscall_by_name(b"sol_log_data", SyscallLogData::call)?; + result.register_function_by_name("sol_log_data", SyscallLogData::call)?; - Ok(syscall_registry) + Ok(Arc::new(result)) } fn translate( @@ -293,7 +320,7 @@ fn translate( vm_addr: u64, len: u64, ) -> Result { - memory_mapping.map(access_type, vm_addr, len).into() + memory_mapping.map(access_type, vm_addr, len, 0).into() } fn translate_type_inner<'a, T>( @@ -1703,7 +1730,7 @@ mod tests { aligned_memory::AlignedMemory, ebpf::{self, HOST_ALIGN}, memory_region::MemoryRegion, - vm::{Config, SyscallFunction}, + vm::{BuiltInFunction, Config}, }, solana_sdk::{ account::AccountSharedData, @@ -3627,7 +3654,7 @@ mod tests { seeds: &[&[u8]], program_id: &Pubkey, overlap_outputs: bool, - syscall: SyscallFunction>, + syscall: BuiltInFunction>, ) -> Result<(Pubkey, u8), EbpfError> { const SEEDS_VA: u64 = 0x100000000; const PROGRAM_ID_VA: u64 = 0x200000000; diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 42b5e1a476..91664cc29f 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -4311,6 +4311,7 @@ dependencies = [ "byteorder 1.4.3", "libsecp256k1 0.6.0", "log", + "rand 0.7.3", "solana-measure", "solana-program-runtime", "solana-sdk 1.15.0", @@ -6190,9 +6191,9 @@ dependencies = [ [[package]] name = "solana_rbpf" -version = "0.2.37" +version = "0.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0669f9f5c355899600732451c65cc717d0ef0c53717749f03520337c824fd8a1" +checksum = "a4e9e5085099858adba23d0a0b5298da8803f89999cb567ecafab9c916cdf53d" dependencies = [ "byteorder 1.4.3", "combine", @@ -6204,6 +6205,7 @@ dependencies = [ "rustc-demangle", "scroll", "thiserror", + "winapi 0.3.9", ] [[package]] diff --git a/programs/sbf/Cargo.toml b/programs/sbf/Cargo.toml index e9c5ca7e11..6fb7cb681d 100644 --- a/programs/sbf/Cargo.toml +++ b/programs/sbf/Cargo.toml @@ -38,7 +38,7 @@ solana-sbf-rust-realloc = { path = "rust/realloc", version = "=1.15.0" } solana-sbf-rust-realloc-invoke = { path = "rust/realloc_invoke", version = "=1.15.0" } solana-sdk = { path = "../../sdk", version = "=1.15.0" } solana-transaction-status = { path = "../../transaction-status", version = "=1.15.0" } -solana_rbpf = "=0.2.37" +solana_rbpf = "=0.2.38" [dev-dependencies] solana-ledger = { path = "../../ledger", version = "=1.15.0" } diff --git a/programs/sbf/benches/bpf_loader.rs b/programs/sbf/benches/bpf_loader.rs index 5d722b0cab..d8731a94d1 100644 --- a/programs/sbf/benches/bpf_loader.rs +++ b/programs/sbf/benches/bpf_loader.rs @@ -8,16 +8,19 @@ extern crate solana_bpf_loader_program; use { byteorder::{ByteOrder, LittleEndian, WriteBytesExt}, solana_bpf_loader_program::{ - create_vm, serialization::serialize_parameters, syscalls::register_syscalls, + create_vm, serialization::serialize_parameters, syscalls::create_loader, }, solana_measure::measure::Measure, - solana_program_runtime::invoke_context::{with_mock_invoke_context, InvokeContext}, + solana_program_runtime::{ + compute_budget::ComputeBudget, + invoke_context::{with_mock_invoke_context, InvokeContext}, + }, solana_rbpf::{ ebpf::MM_INPUT_START, elf::Executable, memory_region::MemoryRegion, verifier::RequisiteVerifier, - vm::{Config, ContextObject, SyscallRegistry, VerifiedExecutable}, + vm::{ContextObject, VerifiedExecutable}, }, solana_runtime::{ bank::Bank, @@ -29,6 +32,7 @@ use { bpf_loader, client::SyncClient, entrypoint::SUCCESS, + feature_set::FeatureSet, instruction::{AccountMeta, Instruction}, message::Message, pubkey::Pubkey, @@ -80,13 +84,16 @@ const ARMSTRONG_EXPECTED: u64 = 5; fn bench_program_create_executable(bencher: &mut Bencher) { let elf = load_elf("bench_alu").unwrap(); + let loader = create_loader( + &FeatureSet::default(), + &ComputeBudget::default(), + true, + true, + false, + ) + .unwrap(); bencher.iter(|| { - let _ = Executable::::from_elf( - &elf, - Config::default(), - SyscallRegistry::default(), - ) - .unwrap(); + let _ = Executable::::from_elf(&elf, loader.clone()).unwrap(); }); } @@ -102,12 +109,15 @@ fn bench_program_alu(bencher: &mut Bencher) { let elf = load_elf("bench_alu").unwrap(); let loader_id = bpf_loader::id(); with_mock_invoke_context(loader_id, 10000001, false, |invoke_context| { - let executable = Executable::::from_elf( - &elf, - Config::default(), - register_syscalls(&invoke_context.feature_set, true).unwrap(), + let loader = create_loader( + &invoke_context.feature_set, + &ComputeBudget::default(), + true, + true, + false, ) .unwrap(); + let executable = Executable::::from_elf(&elf, loader).unwrap(); let mut verified_executable = VerifiedExecutable::::from_executable(executable) @@ -123,7 +133,9 @@ fn bench_program_alu(bencher: &mut Bencher) { .unwrap(); println!("Interpreted:"); - vm.context_object.mock_set_remaining(std::i64::MAX as u64); + vm.env + .context_object_pointer + .mock_set_remaining(std::i64::MAX as u64); let (instructions, result) = vm.execute_program(true); assert_eq!(SUCCESS, result.unwrap()); assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter)); @@ -133,7 +145,9 @@ fn bench_program_alu(bencher: &mut Bencher) { ); bencher.iter(|| { - vm.context_object.mock_set_remaining(std::i64::MAX as u64); + vm.env + .context_object_pointer + .mock_set_remaining(std::i64::MAX as u64); vm.execute_program(true).1.unwrap(); }); let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap(); @@ -153,7 +167,9 @@ fn bench_program_alu(bencher: &mut Bencher) { ); bencher.iter(|| { - vm.context_object.mock_set_remaining(std::i64::MAX as u64); + vm.env + .context_object_pointer + .mock_set_remaining(std::i64::MAX as u64); vm.execute_program(false).1.unwrap(); }); let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap(); @@ -220,12 +236,15 @@ fn bench_create_vm(bencher: &mut Bencher) { ) .unwrap(); - let executable = Executable::::from_elf( - &elf, - Config::default(), - register_syscalls(&invoke_context.feature_set, true).unwrap(), + let loader = create_loader( + &invoke_context.feature_set, + &ComputeBudget::default(), + true, + true, + false, ) .unwrap(); + let executable = Executable::::from_elf(&elf, loader).unwrap(); let verified_executable = VerifiedExecutable::::from_executable(executable) @@ -262,12 +281,15 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) { ) .unwrap(); - let executable = Executable::::from_elf( - &elf, - Config::default(), - register_syscalls(&invoke_context.feature_set, true).unwrap(), + let loader = create_loader( + &invoke_context.feature_set, + &ComputeBudget::default(), + true, + true, + false, ) .unwrap(); + let executable = Executable::::from_elf(&elf, loader).unwrap(); let verified_executable = VerifiedExecutable::::from_executable(executable) @@ -287,12 +309,12 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) { assert_eq!( 0, - vm.context_object.get_remaining(), + vm.env.context_object_pointer.get_remaining(), "Tuner must consume the whole budget" ); println!( "{:?} compute units took {:?} us ({:?} instructions)", - BUDGET - vm.context_object.get_remaining(), + BUDGET - vm.env.context_object_pointer.get_remaining(), measure.as_us(), instructions, ); diff --git a/programs/sbf/tests/programs.rs b/programs/sbf/tests/programs.rs index 3d8684a08d..839a26d1c4 100644 --- a/programs/sbf/tests/programs.rs +++ b/programs/sbf/tests/programs.rs @@ -56,14 +56,10 @@ use { solana_bpf_loader_program::{ create_vm, serialization::{deserialize_parameters, serialize_parameters}, - syscalls::register_syscalls, + syscalls::create_loader, }, solana_program_runtime::invoke_context::with_mock_invoke_context, - solana_rbpf::{ - elf::Executable, - verifier::RequisiteVerifier, - vm::{Config, VerifiedExecutable}, - }, + solana_rbpf::{elf::Executable, verifier::RequisiteVerifier, vm::VerifiedExecutable}, solana_runtime::{ bank::Bank, bank_client::BankClient, @@ -224,21 +220,15 @@ fn run_program(name: &str) -> u64 { file.read_to_end(&mut data).unwrap(); let loader_id = bpf_loader::id(); with_mock_invoke_context(loader_id, 0, false, |invoke_context| { - let config = Config { - enable_instruction_tracing: true, - reject_broken_elfs: true, - ..Config::default() - }; - let executable = Executable::::from_elf( - &data, - config, - register_syscalls( - &invoke_context.feature_set, - true, /* no sol_alloc_free */ - ) - .unwrap(), + let loader = create_loader( + &invoke_context.feature_set, + &ComputeBudget::default(), + true, + true, + true, ) .unwrap(); + let executable = Executable::::from_elf(&data, loader).unwrap(); #[allow(unused_mut)] let mut verified_executable = @@ -293,18 +283,16 @@ fn run_program(name: &str) -> u64 { assert_eq!(instruction_count, compute_units_consumed); } instruction_count = compute_units_consumed; - if config.enable_instruction_tracing { - if i == 0 { - trace_log = Some(vm.context_object.trace_log.clone()); - } else { - let interpreter = trace_log.as_ref().unwrap().as_slice(); - let mut jit = vm.context_object.trace_log.as_slice(); - if jit.len() > interpreter.len() { - jit = &jit[0..interpreter.len()]; - } - assert_eq!(interpreter, jit); - trace_log = None; + if i == 0 { + trace_log = Some(vm.env.context_object_pointer.trace_log.clone()); + } else { + let interpreter = trace_log.as_ref().unwrap().as_slice(); + let mut jit = vm.env.context_object_pointer.trace_log.as_slice(); + if jit.len() > interpreter.len() { + jit = &jit[0..interpreter.len()]; } + assert_eq!(interpreter, jit); + trace_log = None; } } assert!(match deserialize_parameters( diff --git a/rbpf-cli/Cargo.toml b/rbpf-cli/Cargo.toml index 28b5ed7ab8..735f55f095 100644 --- a/rbpf-cli/Cargo.toml +++ b/rbpf-cli/Cargo.toml @@ -17,4 +17,4 @@ solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.15. solana-logger = { path = "../logger", version = "=1.15.0" } solana-program-runtime = { path = "../program-runtime", version = "=1.15.0" } solana-sdk = { path = "../sdk", version = "=1.15.0" } -solana_rbpf = { version = "=0.2.37", features = ["debugger"] } +solana_rbpf = { version = "=0.2.38", features = ["debugger"] } diff --git a/rbpf-cli/src/main.rs b/rbpf-cli/src/main.rs index 0758a8927c..b4ea8ec803 100644 --- a/rbpf-cli/src/main.rs +++ b/rbpf-cli/src/main.rs @@ -3,17 +3,15 @@ use { serde::{Deserialize, Serialize}, serde_json::Result, solana_bpf_loader_program::{ - create_vm, serialization::serialize_parameters, syscalls::register_syscalls, + create_vm, serialization::serialize_parameters, syscalls::create_loader, + }, + solana_program_runtime::{ + compute_budget::ComputeBudget, + invoke_context::{prepare_mock_invoke_context, InvokeContext}, }, - solana_program_runtime::invoke_context::{prepare_mock_invoke_context, InvokeContext}, solana_rbpf::{ - assembler::assemble, - debugger, - elf::Executable, - interpreter::Interpreter, - static_analysis::Analysis, - verifier::RequisiteVerifier, - vm::{Config, VerifiedExecutable}, + assembler::assemble, elf::Executable, static_analysis::Analysis, + verifier::RequisiteVerifier, vm::VerifiedExecutable, }, solana_sdk::{ account::AccountSharedData, bpf_loader, instruction::AccountMeta, pubkey::Pubkey, @@ -161,10 +159,6 @@ before execting it in the virtual machine.", ) .get_matches(); - let config = Config { - enable_symbol_and_section_labels: true, - ..Config::default() - }; let loader_id = bpf_loader::id(); let mut transaction_accounts = vec![ ( @@ -247,16 +241,19 @@ before execting it in the virtual machine.", file.rewind().unwrap(); let mut contents = Vec::new(); file.read_to_end(&mut contents).unwrap(); - let syscall_registry = register_syscalls(&invoke_context.feature_set, true).unwrap(); + let loader = create_loader( + &invoke_context.feature_set, + &ComputeBudget::default(), + true, + true, + true, + ) + .unwrap(); let executable = if magic == [0x7f, 0x45, 0x4c, 0x46] { - Executable::::from_elf(&contents, config, syscall_registry) + Executable::::from_elf(&contents, loader) .map_err(|err| format!("Executable constructor failed: {err:?}")) } else { - assemble::( - std::str::from_utf8(contents.as_slice()).unwrap(), - config, - syscall_registry, - ) + assemble::(std::str::from_utf8(contents.as_slice()).unwrap(), loader) } .unwrap(); @@ -293,13 +290,10 @@ before execting it in the virtual machine.", ) .unwrap(); let start_time = Instant::now(); - let (instruction_count, result) = if matches.value_of("use").unwrap() == "debugger" { - let mut interpreter = Interpreter::new(&mut vm).unwrap(); - let port = matches.value_of("port").unwrap().parse::().unwrap(); - debugger::execute(&mut interpreter, port) - } else { - vm.execute_program(matches.value_of("use").unwrap() == "interpreter") - }; + 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(matches.value_of("use").unwrap() != "jit"); let duration = Instant::now() - start_time; drop(vm); @@ -351,7 +345,7 @@ impl Debug for Output { // Replace with std::lazy::Lazy when stabilized. // https://github.com/rust-lang/rust/issues/74465 struct LazyAnalysis<'a, 'b> { - analysis: Option>>, + analysis: Option>, executable: &'a Executable>, } @@ -363,7 +357,7 @@ impl<'a, 'b> LazyAnalysis<'a, 'b> { } } - fn analyze(&mut self) -> &Analysis> { + fn analyze(&mut self) -> &Analysis { if let Some(ref analysis) = self.analysis { return analysis; }