Bump solana_rbpf to v0.2.38 (#29137)

* Refactor register_syscalls() => create_loader().

* Bumps solana_rbpf to v0.2.38

* Replaces Config::encrypt_environment_registers by Config::runtime_environment_key.

* Adds pc parameter to MemoryMapping::map()

* Removes debugger from rbpf CLI.

* Adds debugger to rbpf CLI again.

* Renames vm.context_object => vm.env.context_object_pointer.

* Renames SyscallRegistry => BuiltInProgram.
Renames SyscallFunction => BuiltInFunction.
Renames register_syscall_by_name() => register_function_by_name().

* Removes ContextObject from Analysis.

* Renames Config::error_on_syscall_bpf_function_hash_collisions => Config::external_internal_function_hash_collision.
This commit is contained in:
Alexander Meißner 2022-12-12 08:47:09 +01:00 committed by GitHub
parent 254d3f20b2
commit 013f784e92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 232 additions and 228 deletions

5
Cargo.lock generated
View File

@ -6992,9 +6992,9 @@ dependencies = [
[[package]] [[package]]
name = "solana_rbpf" name = "solana_rbpf"
version = "0.2.37" version = "0.2.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0669f9f5c355899600732451c65cc717d0ef0c53717749f03520337c824fd8a1" checksum = "a4e9e5085099858adba23d0a0b5298da8803f89999cb567ecafab9c916cdf53d"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"combine", "combine",
@ -7007,6 +7007,7 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
"scroll", "scroll",
"thiserror", "thiserror",
"winapi 0.3.9",
] ]
[[package]] [[package]]

View File

@ -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-transaction-status = { path = "../transaction-status", version = "=1.15.0" }
solana-version = { path = "../version", version = "=1.15.0" } solana-version = { path = "../version", version = "=1.15.0" }
solana-vote-program = { path = "../programs/vote", 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"] } spl-memo = { version = "=3.0.1", features = ["no-entrypoint"] }
thiserror = "1.0.31" thiserror = "1.0.31"
tiny-bip39 = "0.8.2" tiny-bip39 = "0.8.2"

View File

@ -10,7 +10,7 @@ use {
clap::{App, AppSettings, Arg, ArgMatches, SubCommand}, clap::{App, AppSettings, Arg, ArgMatches, SubCommand},
log::*, log::*,
solana_account_decoder::{UiAccountEncoding, UiDataSliceConfig}, 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_clap_utils::{self, input_parsers::*, input_validators::*, keypair::*},
solana_cli_output::{ solana_cli_output::{
CliProgram, CliProgramAccountType, CliProgramAuthority, CliProgramBuffer, CliProgramId, CliProgram, CliProgramAccountType, CliProgramAuthority, CliProgramBuffer, CliProgramId,
@ -21,12 +21,8 @@ use {
connection_cache::ConnectionCache, connection_cache::ConnectionCache,
tpu_client::{TpuClient, TpuClientConfig}, tpu_client::{TpuClient, TpuClientConfig},
}, },
solana_program_runtime::invoke_context::InvokeContext, solana_program_runtime::{compute_budget::ComputeBudget, invoke_context::InvokeContext},
solana_rbpf::{ solana_rbpf::{elf::Executable, verifier::RequisiteVerifier, vm::VerifiedExecutable},
elf::Executable,
verifier::RequisiteVerifier,
vm::{Config, VerifiedExecutable},
},
solana_remote_wallet::remote_wallet::RemoteWalletManager, solana_remote_wallet::remote_wallet::RemoteWalletManager,
solana_rpc_client::rpc_client::RpcClient, solana_rpc_client::rpc_client::RpcClient,
solana_rpc_client_api::{ solana_rpc_client_api::{
@ -1994,15 +1990,16 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]); let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Verify the program // Verify the program
let executable = Executable::<InvokeContext>::from_elf( let loader = create_loader(
&program_data, &invoke_context.feature_set,
Config { &ComputeBudget::default(),
reject_broken_elfs: true, true,
..Config::default() true,
}, false,
register_syscalls(&invoke_context.feature_set, true).unwrap(),
) )
.map_err(|err| format!("ELF error: {err}"))?; .unwrap();
let executable = Executable::<InvokeContext>::from_elf(&program_data, loader)
.map_err(|err| format!("ELF error: {err}"))?;
let _ = VerifiedExecutable::<RequisiteVerifier, InvokeContext>::from_executable(executable) let _ = VerifiedExecutable::<RequisiteVerifier, InvokeContext>::from_executable(executable)
.map_err(|err| format!("ELF error: {err}"))?; .map_err(|err| format!("ELF error: {err}"))?;

View File

@ -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-frozen-abi-macro = { path = "../frozen-abi/macro", version = "=1.15.0" }
solana-measure = { path = "../measure", version = "=1.15.0" } solana-measure = { path = "../measure", version = "=1.15.0" }
solana-metrics = { path = "../metrics", 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" } solana-sdk = { path = "../sdk", version = "=1.15.0" }
thiserror = "1.0" thiserror = "1.0"

View File

@ -14,16 +14,14 @@ bincode = "1.3.3"
byteorder = "1.4.3" byteorder = "1.4.3"
libsecp256k1 = "0.6.0" libsecp256k1 = "0.6.0"
log = "0.4.17" log = "0.4.17"
rand = "0.7.3"
solana-measure = { path = "../../measure", version = "=1.15.0" } solana-measure = { path = "../../measure", version = "=1.15.0" }
solana-program-runtime = { path = "../../program-runtime", version = "=1.15.0" } solana-program-runtime = { path = "../../program-runtime", version = "=1.15.0" }
solana-sdk = { path = "../../sdk", 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-zk-token-sdk = { path = "../../zk-token-sdk", version = "=1.15.0" }
solana_rbpf = "=0.2.37" solana_rbpf = "=0.2.38"
thiserror = "1.0" thiserror = "1.0"
[dev-dependencies]
rand = "0.7.3"
[lib] [lib]
crate-type = ["lib"] crate-type = ["lib"]
name = "solana_bpf_loader_program" name = "solana_bpf_loader_program"

View File

@ -33,7 +33,7 @@ use {
error::{EbpfError, UserDefinedError}, error::{EbpfError, UserDefinedError},
memory_region::MemoryRegion, memory_region::MemoryRegion,
verifier::{RequisiteVerifier, VerifierError}, verifier::{RequisiteVerifier, VerifierError},
vm::{Config, ContextObject, EbpfVm, ProgramResult, VerifiedExecutable}, vm::{ContextObject, EbpfVm, ProgramResult, VerifiedExecutable},
}, },
solana_sdk::{ solana_sdk::{
bpf_loader, bpf_loader_deprecated, bpf_loader, bpf_loader_deprecated,
@ -43,9 +43,8 @@ use {
cap_accounts_data_allocations_per_transaction, cap_bpf_program_instruction_accounts, cap_accounts_data_allocations_per_transaction, cap_bpf_program_instruction_accounts,
check_slice_translation_size, disable_deploy_of_alloc_free_syscall, check_slice_translation_size, disable_deploy_of_alloc_free_syscall,
disable_deprecated_loader, enable_bpf_loader_extend_program_ix, disable_deprecated_loader, enable_bpf_loader_extend_program_ix,
enable_bpf_loader_set_authority_checked_ix, enable_bpf_loader_set_authority_checked_ix, limit_max_instruction_trace_length,
error_on_syscall_bpf_function_hash_collisions, limit_max_instruction_trace_length, FeatureSet,
reject_callx_r10, FeatureSet,
}, },
instruction::{AccountMeta, InstructionError}, instruction::{AccountMeta, InstructionError},
loader_instruction::LoaderInstruction, loader_instruction::LoaderInstruction,
@ -132,45 +131,24 @@ fn create_executor_from_bytes(
let mut register_syscalls_time = Measure::start("register_syscalls_time"); let mut register_syscalls_time = Measure::start("register_syscalls_time");
let disable_deploy_of_alloc_free_syscall = reject_deployment_of_broken_elfs let disable_deploy_of_alloc_free_syscall = reject_deployment_of_broken_elfs
&& feature_set.is_active(&disable_deploy_of_alloc_free_syscall::id()); && feature_set.is_active(&disable_deploy_of_alloc_free_syscall::id());
let register_syscall_result = let loader = syscalls::create_loader(
syscalls::register_syscalls(feature_set, disable_deploy_of_alloc_free_syscall); feature_set,
register_syscalls_time.stop(); compute_budget,
create_executor_metrics.register_syscalls_us = register_syscalls_time.as_us(); reject_deployment_of_broken_elfs,
let syscall_registry = register_syscall_result.map_err(|e| { disable_deploy_of_alloc_free_syscall,
false,
)
.map_err(|e| {
ic_logger_msg!(log_collector, "Failed to register syscalls: {}", e); ic_logger_msg!(log_collector, "Failed to register syscalls: {}", e);
InstructionError::ProgramEnvironmentSetupFailure InstructionError::ProgramEnvironmentSetupFailure
})?; })?;
let config = Config { register_syscalls_time.stop();
max_call_depth: compute_budget.max_call_depth, create_executor_metrics.register_syscalls_us = register_syscalls_time.as_us();
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.
};
let mut load_elf_time = Measure::start("load_elf_time"); let mut load_elf_time = Measure::start("load_elf_time");
let executable = Executable::<InvokeContext>::from_elf(programdata, config, syscall_registry) let executable = Executable::<InvokeContext>::from_elf(programdata, loader).map_err(|err| {
.map_err(|err| { ic_logger_msg!(log_collector, "{}", err);
ic_logger_msg!(log_collector, "{}", err); InstructionError::InvalidAccountData
InstructionError::InvalidAccountData });
});
load_elf_time.stop(); load_elf_time.stop();
create_executor_metrics.load_elf_us = load_elf_time.as_us(); create_executor_metrics.load_elf_us = load_elf_time.as_us();
let executable = executable?; let executable = executable?;
@ -1527,7 +1505,7 @@ mod tests {
solana_rbpf::{ solana_rbpf::{
ebpf::MM_INPUT_START, ebpf::MM_INPUT_START,
verifier::Verifier, verifier::Verifier,
vm::{ContextObject, FunctionRegistry, SyscallRegistry}, vm::{BuiltInProgram, Config, ContextObject, FunctionRegistry},
}, },
solana_sdk::{ solana_sdk::{
account::{ account::{
@ -1611,13 +1589,10 @@ mod tests {
0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit 0x95, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exit
]; ];
let mut input_mem = [0x00]; let mut input_mem = [0x00];
let config = Config::default();
let syscall_registry = SyscallRegistry::default();
let bpf_functions = std::collections::BTreeMap::<u32, (usize, String)>::new(); let bpf_functions = std::collections::BTreeMap::<u32, (usize, String)>::new();
let executable = Executable::<TestContextObject>::from_text_bytes( let executable = Executable::<TestContextObject>::from_text_bytes(
program, program,
config, Arc::new(BuiltInProgram::new_loader(Config::default())),
syscall_registry,
bpf_functions, bpf_functions,
) )
.unwrap(); .unwrap();

View File

@ -13,12 +13,13 @@ pub use self::{
use { use {
crate::BpfError, crate::BpfError,
solana_program_runtime::{ 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::{ solana_rbpf::{
error::EbpfError, error::EbpfError,
memory_region::{AccessType, MemoryMapping}, memory_region::{AccessType, MemoryMapping},
vm::{ProgramResult, SyscallRegistry}, vm::{BuiltInProgram, Config, ProgramResult, PROGRAM_ENVIRONMENT_KEY_SHIFT},
}, },
solana_sdk::{ solana_sdk::{
account::{ReadableAccount, WritableAccount}, account::{ReadableAccount, WritableAccount},
@ -36,7 +37,8 @@ use {
check_syscall_outputs_do_not_overlap, curve25519_syscall_enabled, check_syscall_outputs_do_not_overlap, curve25519_syscall_enabled,
disable_cpi_setting_executable_and_rent_epoch, disable_fees_sysvar, disable_cpi_setting_executable_and_rent_epoch, disable_fees_sysvar,
enable_alt_bn128_syscall, enable_early_verification_of_account_modifications, 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, stop_sibling_instruction_search_at_parent,
}, },
hash::{Hasher, HASH_BYTES}, hash::{Hasher, HASH_BYTES},
@ -136,155 +138,180 @@ fn consume_compute_meter(invoke_context: &InvokeContext, amount: u64) -> Result<
Ok(()) Ok(())
} }
macro_rules! register_feature_gated_syscall { macro_rules! register_feature_gated_function {
($syscall_registry:expr, $is_feature_active:expr, $name:expr, $call:expr $(,)?) => { ($result:expr, $is_feature_active:expr, $name:expr, $call:expr $(,)?) => {
if $is_feature_active { if $is_feature_active {
$syscall_registry.register_syscall_by_name($name, $call) $result.register_function_by_name($name, $call)
} else { } else {
Ok(()) Ok(())
} }
}; };
} }
pub fn register_syscalls<'a>( pub fn create_loader<'a>(
feature_set: &FeatureSet, feature_set: &FeatureSet,
compute_budget: &ComputeBudget,
reject_deployment_of_broken_elfs: bool,
disable_deploy_of_alloc_free_syscall: bool, disable_deploy_of_alloc_free_syscall: bool,
) -> Result<SyscallRegistry<InvokeContext<'a>>, EbpfError> { debugging_features: bool,
) -> Result<Arc<BuiltInProgram<InvokeContext<'a>>>, 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::<i32>()
.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 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 blake3_syscall_enabled = feature_set.is_active(&blake3_syscall_enabled::id());
let curve25519_syscall_enabled = feature_set.is_active(&curve25519_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 disable_fees_sysvar = feature_set.is_active(&disable_fees_sysvar::id());
let is_abi_v2 = false; let is_abi_v2 = false;
let mut syscall_registry = SyscallRegistry::default(); let mut result = BuiltInProgram::new_loader(config);
// Abort // Abort
syscall_registry.register_syscall_by_name(b"abort", SyscallAbort::call)?; result.register_function_by_name("abort", SyscallAbort::call)?;
// Panic // Panic
syscall_registry.register_syscall_by_name(b"sol_panic_", SyscallPanic::call)?; result.register_function_by_name("sol_panic_", SyscallPanic::call)?;
// Logging // Logging
syscall_registry.register_syscall_by_name(b"sol_log_", SyscallLog::call)?; result.register_function_by_name("sol_log_", SyscallLog::call)?;
syscall_registry.register_syscall_by_name(b"sol_log_64_", SyscallLogU64::call)?; result.register_function_by_name("sol_log_64_", SyscallLogU64::call)?;
syscall_registry result.register_function_by_name("sol_log_compute_units_", SyscallLogBpfComputeUnits::call)?;
.register_syscall_by_name(b"sol_log_compute_units_", SyscallLogBpfComputeUnits::call)?; result.register_function_by_name("sol_log_pubkey", SyscallLogPubkey::call)?;
syscall_registry.register_syscall_by_name(b"sol_log_pubkey", SyscallLogPubkey::call)?;
// Program defined addresses (PDA) // Program defined addresses (PDA)
syscall_registry.register_syscall_by_name( result.register_function_by_name(
b"sol_create_program_address", "sol_create_program_address",
SyscallCreateProgramAddress::call, SyscallCreateProgramAddress::call,
)?; )?;
syscall_registry.register_syscall_by_name( result.register_function_by_name(
b"sol_try_find_program_address", "sol_try_find_program_address",
SyscallTryFindProgramAddress::call, SyscallTryFindProgramAddress::call,
)?; )?;
// Sha256 // Sha256
syscall_registry.register_syscall_by_name(b"sol_sha256", SyscallSha256::call)?; result.register_function_by_name("sol_sha256", SyscallSha256::call)?;
// Keccak256 // Keccak256
syscall_registry.register_syscall_by_name(b"sol_keccak256", SyscallKeccak256::call)?; result.register_function_by_name("sol_keccak256", SyscallKeccak256::call)?;
// Secp256k1 Recover // Secp256k1 Recover
syscall_registry result.register_function_by_name("sol_secp256k1_recover", SyscallSecp256k1Recover::call)?;
.register_syscall_by_name(b"sol_secp256k1_recover", SyscallSecp256k1Recover::call)?;
// Blake3 // Blake3
register_feature_gated_syscall!( register_feature_gated_function!(
syscall_registry, result,
blake3_syscall_enabled, blake3_syscall_enabled,
b"sol_blake3", "sol_blake3",
SyscallBlake3::call, SyscallBlake3::call,
)?; )?;
// Elliptic Curve Operations // Elliptic Curve Operations
register_feature_gated_syscall!( register_feature_gated_function!(
syscall_registry, result,
curve25519_syscall_enabled, curve25519_syscall_enabled,
b"sol_curve_validate_point", "sol_curve_validate_point",
SyscallCurvePointValidation::call, SyscallCurvePointValidation::call,
)?; )?;
register_feature_gated_syscall!( register_feature_gated_function!(
syscall_registry, result,
curve25519_syscall_enabled, curve25519_syscall_enabled,
b"sol_curve_group_op", "sol_curve_group_op",
SyscallCurveGroupOps::call, SyscallCurveGroupOps::call,
)?; )?;
register_feature_gated_syscall!( register_feature_gated_function!(
syscall_registry, result,
curve25519_syscall_enabled, curve25519_syscall_enabled,
b"sol_curve_multiscalar_mul", "sol_curve_multiscalar_mul",
SyscallCurveMultiscalarMultiplication::call, SyscallCurveMultiscalarMultiplication::call,
)?; )?;
// Sysvars // Sysvars
syscall_registry result.register_function_by_name("sol_get_clock_sysvar", SyscallGetClockSysvar::call)?;
.register_syscall_by_name(b"sol_get_clock_sysvar", SyscallGetClockSysvar::call)?; result.register_function_by_name(
syscall_registry.register_syscall_by_name( "sol_get_epoch_schedule_sysvar",
b"sol_get_epoch_schedule_sysvar",
SyscallGetEpochScheduleSysvar::call, SyscallGetEpochScheduleSysvar::call,
)?; )?;
register_feature_gated_syscall!( register_feature_gated_function!(
syscall_registry, result,
!disable_fees_sysvar, !disable_fees_sysvar,
b"sol_get_fees_sysvar", "sol_get_fees_sysvar",
SyscallGetFeesSysvar::call, SyscallGetFeesSysvar::call,
)?; )?;
syscall_registry result.register_function_by_name("sol_get_rent_sysvar", SyscallGetRentSysvar::call)?;
.register_syscall_by_name(b"sol_get_rent_sysvar", SyscallGetRentSysvar::call)?;
// Memory ops // Memory ops
syscall_registry.register_syscall_by_name(b"sol_memcpy_", SyscallMemcpy::call)?; result.register_function_by_name("sol_memcpy_", SyscallMemcpy::call)?;
syscall_registry.register_syscall_by_name(b"sol_memmove_", SyscallMemmove::call)?; result.register_function_by_name("sol_memmove_", SyscallMemmove::call)?;
syscall_registry.register_syscall_by_name(b"sol_memcmp_", SyscallMemcmp::call)?; result.register_function_by_name("sol_memcmp_", SyscallMemcmp::call)?;
syscall_registry.register_syscall_by_name(b"sol_memset_", SyscallMemset::call)?; result.register_function_by_name("sol_memset_", SyscallMemset::call)?;
if !is_abi_v2 { if !is_abi_v2 {
// Processed sibling instructions // Processed sibling instructions
syscall_registry.register_syscall_by_name( result.register_function_by_name(
b"sol_get_processed_sibling_instruction", "sol_get_processed_sibling_instruction",
SyscallGetProcessedSiblingInstruction::call, SyscallGetProcessedSiblingInstruction::call,
)?; )?;
// Stack height // Stack height
syscall_registry result.register_function_by_name("sol_get_stack_height", SyscallGetStackHeight::call)?;
.register_syscall_by_name(b"sol_get_stack_height", SyscallGetStackHeight::call)?;
// Return data // Return data
syscall_registry result.register_function_by_name("sol_set_return_data", SyscallSetReturnData::call)?;
.register_syscall_by_name(b"sol_set_return_data", SyscallSetReturnData::call)?; result.register_function_by_name("sol_get_return_data", SyscallGetReturnData::call)?;
syscall_registry
.register_syscall_by_name(b"sol_get_return_data", SyscallGetReturnData::call)?;
// Cross-program invocation // Cross-program invocation
syscall_registry result.register_function_by_name("sol_invoke_signed_c", SyscallInvokeSignedC::call)?;
.register_syscall_by_name(b"sol_invoke_signed_c", SyscallInvokeSignedC::call)?; result
syscall_registry .register_function_by_name("sol_invoke_signed_rust", SyscallInvokeSignedRust::call)?;
.register_syscall_by_name(b"sol_invoke_signed_rust", SyscallInvokeSignedRust::call)?;
// Memory allocator // Memory allocator
register_feature_gated_syscall!( register_feature_gated_function!(
syscall_registry, result,
!disable_deploy_of_alloc_free_syscall, !disable_deploy_of_alloc_free_syscall,
b"sol_alloc_free_", "sol_alloc_free_",
SyscallAllocFree::call, SyscallAllocFree::call,
)?; )?;
// Alt_bn128 // Alt_bn128
register_feature_gated_syscall!( register_feature_gated_function!(
syscall_registry, result,
enable_alt_bn128_syscall, enable_alt_bn128_syscall,
b"sol_alt_bn128_group_op", "sol_alt_bn128_group_op",
SyscallAltBn128::call, SyscallAltBn128::call,
)?; )?;
} }
// Log data // 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( fn translate(
@ -293,7 +320,7 @@ fn translate(
vm_addr: u64, vm_addr: u64,
len: u64, len: u64,
) -> Result<u64, EbpfError> { ) -> Result<u64, EbpfError> {
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>( fn translate_type_inner<'a, T>(
@ -1703,7 +1730,7 @@ mod tests {
aligned_memory::AlignedMemory, aligned_memory::AlignedMemory,
ebpf::{self, HOST_ALIGN}, ebpf::{self, HOST_ALIGN},
memory_region::MemoryRegion, memory_region::MemoryRegion,
vm::{Config, SyscallFunction}, vm::{BuiltInFunction, Config},
}, },
solana_sdk::{ solana_sdk::{
account::AccountSharedData, account::AccountSharedData,
@ -3627,7 +3654,7 @@ mod tests {
seeds: &[&[u8]], seeds: &[&[u8]],
program_id: &Pubkey, program_id: &Pubkey,
overlap_outputs: bool, overlap_outputs: bool,
syscall: SyscallFunction<InvokeContext<'b>>, syscall: BuiltInFunction<InvokeContext<'b>>,
) -> Result<(Pubkey, u8), EbpfError> { ) -> Result<(Pubkey, u8), EbpfError> {
const SEEDS_VA: u64 = 0x100000000; const SEEDS_VA: u64 = 0x100000000;
const PROGRAM_ID_VA: u64 = 0x200000000; const PROGRAM_ID_VA: u64 = 0x200000000;

View File

@ -4311,6 +4311,7 @@ dependencies = [
"byteorder 1.4.3", "byteorder 1.4.3",
"libsecp256k1 0.6.0", "libsecp256k1 0.6.0",
"log", "log",
"rand 0.7.3",
"solana-measure", "solana-measure",
"solana-program-runtime", "solana-program-runtime",
"solana-sdk 1.15.0", "solana-sdk 1.15.0",
@ -6190,9 +6191,9 @@ dependencies = [
[[package]] [[package]]
name = "solana_rbpf" name = "solana_rbpf"
version = "0.2.37" version = "0.2.38"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0669f9f5c355899600732451c65cc717d0ef0c53717749f03520337c824fd8a1" checksum = "a4e9e5085099858adba23d0a0b5298da8803f89999cb567ecafab9c916cdf53d"
dependencies = [ dependencies = [
"byteorder 1.4.3", "byteorder 1.4.3",
"combine", "combine",
@ -6204,6 +6205,7 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
"scroll", "scroll",
"thiserror", "thiserror",
"winapi 0.3.9",
] ]
[[package]] [[package]]

View File

@ -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-sbf-rust-realloc-invoke = { path = "rust/realloc_invoke", version = "=1.15.0" }
solana-sdk = { path = "../../sdk", version = "=1.15.0" } solana-sdk = { path = "../../sdk", version = "=1.15.0" }
solana-transaction-status = { path = "../../transaction-status", 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] [dev-dependencies]
solana-ledger = { path = "../../ledger", version = "=1.15.0" } solana-ledger = { path = "../../ledger", version = "=1.15.0" }

View File

@ -8,16 +8,19 @@ extern crate solana_bpf_loader_program;
use { use {
byteorder::{ByteOrder, LittleEndian, WriteBytesExt}, byteorder::{ByteOrder, LittleEndian, WriteBytesExt},
solana_bpf_loader_program::{ 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_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::{ solana_rbpf::{
ebpf::MM_INPUT_START, ebpf::MM_INPUT_START,
elf::Executable, elf::Executable,
memory_region::MemoryRegion, memory_region::MemoryRegion,
verifier::RequisiteVerifier, verifier::RequisiteVerifier,
vm::{Config, ContextObject, SyscallRegistry, VerifiedExecutable}, vm::{ContextObject, VerifiedExecutable},
}, },
solana_runtime::{ solana_runtime::{
bank::Bank, bank::Bank,
@ -29,6 +32,7 @@ use {
bpf_loader, bpf_loader,
client::SyncClient, client::SyncClient,
entrypoint::SUCCESS, entrypoint::SUCCESS,
feature_set::FeatureSet,
instruction::{AccountMeta, Instruction}, instruction::{AccountMeta, Instruction},
message::Message, message::Message,
pubkey::Pubkey, pubkey::Pubkey,
@ -80,13 +84,16 @@ const ARMSTRONG_EXPECTED: u64 = 5;
fn bench_program_create_executable(bencher: &mut Bencher) { fn bench_program_create_executable(bencher: &mut Bencher) {
let elf = load_elf("bench_alu").unwrap(); let elf = load_elf("bench_alu").unwrap();
let loader = create_loader(
&FeatureSet::default(),
&ComputeBudget::default(),
true,
true,
false,
)
.unwrap();
bencher.iter(|| { bencher.iter(|| {
let _ = Executable::<InvokeContext>::from_elf( let _ = Executable::<InvokeContext>::from_elf(&elf, loader.clone()).unwrap();
&elf,
Config::default(),
SyscallRegistry::default(),
)
.unwrap();
}); });
} }
@ -102,12 +109,15 @@ fn bench_program_alu(bencher: &mut Bencher) {
let elf = load_elf("bench_alu").unwrap(); let elf = load_elf("bench_alu").unwrap();
let loader_id = bpf_loader::id(); let loader_id = bpf_loader::id();
with_mock_invoke_context(loader_id, 10000001, false, |invoke_context| { with_mock_invoke_context(loader_id, 10000001, false, |invoke_context| {
let executable = Executable::<InvokeContext>::from_elf( let loader = create_loader(
&elf, &invoke_context.feature_set,
Config::default(), &ComputeBudget::default(),
register_syscalls(&invoke_context.feature_set, true).unwrap(), true,
true,
false,
) )
.unwrap(); .unwrap();
let executable = Executable::<InvokeContext>::from_elf(&elf, loader).unwrap();
let mut verified_executable = let mut verified_executable =
VerifiedExecutable::<RequisiteVerifier, InvokeContext>::from_executable(executable) VerifiedExecutable::<RequisiteVerifier, InvokeContext>::from_executable(executable)
@ -123,7 +133,9 @@ fn bench_program_alu(bencher: &mut Bencher) {
.unwrap(); .unwrap();
println!("Interpreted:"); 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); let (instructions, result) = vm.execute_program(true);
assert_eq!(SUCCESS, result.unwrap()); assert_eq!(SUCCESS, result.unwrap());
assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter)); assert_eq!(ARMSTRONG_LIMIT, LittleEndian::read_u64(&inner_iter));
@ -133,7 +145,9 @@ fn bench_program_alu(bencher: &mut Bencher) {
); );
bencher.iter(|| { 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(); vm.execute_program(true).1.unwrap();
}); });
let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap(); let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap();
@ -153,7 +167,9 @@ fn bench_program_alu(bencher: &mut Bencher) {
); );
bencher.iter(|| { 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(); vm.execute_program(false).1.unwrap();
}); });
let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap(); let summary = bencher.bench(|_bencher| Ok(())).unwrap().unwrap();
@ -220,12 +236,15 @@ fn bench_create_vm(bencher: &mut Bencher) {
) )
.unwrap(); .unwrap();
let executable = Executable::<InvokeContext>::from_elf( let loader = create_loader(
&elf, &invoke_context.feature_set,
Config::default(), &ComputeBudget::default(),
register_syscalls(&invoke_context.feature_set, true).unwrap(), true,
true,
false,
) )
.unwrap(); .unwrap();
let executable = Executable::<InvokeContext>::from_elf(&elf, loader).unwrap();
let verified_executable = let verified_executable =
VerifiedExecutable::<RequisiteVerifier, InvokeContext>::from_executable(executable) VerifiedExecutable::<RequisiteVerifier, InvokeContext>::from_executable(executable)
@ -262,12 +281,15 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
) )
.unwrap(); .unwrap();
let executable = Executable::<InvokeContext>::from_elf( let loader = create_loader(
&elf, &invoke_context.feature_set,
Config::default(), &ComputeBudget::default(),
register_syscalls(&invoke_context.feature_set, true).unwrap(), true,
true,
false,
) )
.unwrap(); .unwrap();
let executable = Executable::<InvokeContext>::from_elf(&elf, loader).unwrap();
let verified_executable = let verified_executable =
VerifiedExecutable::<RequisiteVerifier, InvokeContext>::from_executable(executable) VerifiedExecutable::<RequisiteVerifier, InvokeContext>::from_executable(executable)
@ -287,12 +309,12 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
assert_eq!( assert_eq!(
0, 0,
vm.context_object.get_remaining(), vm.env.context_object_pointer.get_remaining(),
"Tuner must consume the whole budget" "Tuner must consume the whole budget"
); );
println!( println!(
"{:?} compute units took {:?} us ({:?} instructions)", "{:?} compute units took {:?} us ({:?} instructions)",
BUDGET - vm.context_object.get_remaining(), BUDGET - vm.env.context_object_pointer.get_remaining(),
measure.as_us(), measure.as_us(),
instructions, instructions,
); );

View File

@ -56,14 +56,10 @@ use {
solana_bpf_loader_program::{ solana_bpf_loader_program::{
create_vm, create_vm,
serialization::{deserialize_parameters, serialize_parameters}, serialization::{deserialize_parameters, serialize_parameters},
syscalls::register_syscalls, syscalls::create_loader,
}, },
solana_program_runtime::invoke_context::with_mock_invoke_context, solana_program_runtime::invoke_context::with_mock_invoke_context,
solana_rbpf::{ solana_rbpf::{elf::Executable, verifier::RequisiteVerifier, vm::VerifiedExecutable},
elf::Executable,
verifier::RequisiteVerifier,
vm::{Config, VerifiedExecutable},
},
solana_runtime::{ solana_runtime::{
bank::Bank, bank::Bank,
bank_client::BankClient, bank_client::BankClient,
@ -224,21 +220,15 @@ fn run_program(name: &str) -> u64 {
file.read_to_end(&mut data).unwrap(); file.read_to_end(&mut data).unwrap();
let loader_id = bpf_loader::id(); let loader_id = bpf_loader::id();
with_mock_invoke_context(loader_id, 0, false, |invoke_context| { with_mock_invoke_context(loader_id, 0, false, |invoke_context| {
let config = Config { let loader = create_loader(
enable_instruction_tracing: true, &invoke_context.feature_set,
reject_broken_elfs: true, &ComputeBudget::default(),
..Config::default() true,
}; true,
let executable = Executable::<InvokeContext>::from_elf( true,
&data,
config,
register_syscalls(
&invoke_context.feature_set,
true, /* no sol_alloc_free */
)
.unwrap(),
) )
.unwrap(); .unwrap();
let executable = Executable::<InvokeContext>::from_elf(&data, loader).unwrap();
#[allow(unused_mut)] #[allow(unused_mut)]
let mut verified_executable = let mut verified_executable =
@ -293,18 +283,16 @@ fn run_program(name: &str) -> u64 {
assert_eq!(instruction_count, compute_units_consumed); assert_eq!(instruction_count, compute_units_consumed);
} }
instruction_count = compute_units_consumed; instruction_count = compute_units_consumed;
if config.enable_instruction_tracing { if i == 0 {
if i == 0 { trace_log = Some(vm.env.context_object_pointer.trace_log.clone());
trace_log = Some(vm.context_object.trace_log.clone()); } else {
} else { let interpreter = trace_log.as_ref().unwrap().as_slice();
let interpreter = trace_log.as_ref().unwrap().as_slice(); let mut jit = vm.env.context_object_pointer.trace_log.as_slice();
let mut jit = vm.context_object.trace_log.as_slice(); if jit.len() > interpreter.len() {
if jit.len() > interpreter.len() { jit = &jit[0..interpreter.len()];
jit = &jit[0..interpreter.len()];
}
assert_eq!(interpreter, jit);
trace_log = None;
} }
assert_eq!(interpreter, jit);
trace_log = None;
} }
} }
assert!(match deserialize_parameters( assert!(match deserialize_parameters(

View File

@ -17,4 +17,4 @@ solana-bpf-loader-program = { path = "../programs/bpf_loader", version = "=1.15.
solana-logger = { path = "../logger", version = "=1.15.0" } solana-logger = { path = "../logger", version = "=1.15.0" }
solana-program-runtime = { path = "../program-runtime", version = "=1.15.0" } solana-program-runtime = { path = "../program-runtime", version = "=1.15.0" }
solana-sdk = { path = "../sdk", 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"] }

View File

@ -3,17 +3,15 @@ use {
serde::{Deserialize, Serialize}, serde::{Deserialize, Serialize},
serde_json::Result, serde_json::Result,
solana_bpf_loader_program::{ 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::{ solana_rbpf::{
assembler::assemble, assembler::assemble, elf::Executable, static_analysis::Analysis,
debugger, verifier::RequisiteVerifier, vm::VerifiedExecutable,
elf::Executable,
interpreter::Interpreter,
static_analysis::Analysis,
verifier::RequisiteVerifier,
vm::{Config, VerifiedExecutable},
}, },
solana_sdk::{ solana_sdk::{
account::AccountSharedData, bpf_loader, instruction::AccountMeta, pubkey::Pubkey, account::AccountSharedData, bpf_loader, instruction::AccountMeta, pubkey::Pubkey,
@ -161,10 +159,6 @@ before execting it in the virtual machine.",
) )
.get_matches(); .get_matches();
let config = Config {
enable_symbol_and_section_labels: true,
..Config::default()
};
let loader_id = bpf_loader::id(); let loader_id = bpf_loader::id();
let mut transaction_accounts = vec![ let mut transaction_accounts = vec![
( (
@ -247,16 +241,19 @@ before execting it in the virtual machine.",
file.rewind().unwrap(); file.rewind().unwrap();
let mut contents = Vec::new(); let mut contents = Vec::new();
file.read_to_end(&mut contents).unwrap(); 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] { let executable = if magic == [0x7f, 0x45, 0x4c, 0x46] {
Executable::<InvokeContext>::from_elf(&contents, config, syscall_registry) Executable::<InvokeContext>::from_elf(&contents, loader)
.map_err(|err| format!("Executable constructor failed: {err:?}")) .map_err(|err| format!("Executable constructor failed: {err:?}"))
} else { } else {
assemble::<InvokeContext>( assemble::<InvokeContext>(std::str::from_utf8(contents.as_slice()).unwrap(), loader)
std::str::from_utf8(contents.as_slice()).unwrap(),
config,
syscall_registry,
)
} }
.unwrap(); .unwrap();
@ -293,13 +290,10 @@ before execting it in the virtual machine.",
) )
.unwrap(); .unwrap();
let start_time = Instant::now(); let start_time = Instant::now();
let (instruction_count, result) = if matches.value_of("use").unwrap() == "debugger" { if matches.value_of("use").unwrap() == "debugger" {
let mut interpreter = Interpreter::new(&mut vm).unwrap(); vm.debug_port = Some(matches.value_of("port").unwrap().parse::<u16>().unwrap());
let port = matches.value_of("port").unwrap().parse::<u16>().unwrap(); }
debugger::execute(&mut interpreter, port) let (instruction_count, result) = vm.execute_program(matches.value_of("use").unwrap() != "jit");
} else {
vm.execute_program(matches.value_of("use").unwrap() == "interpreter")
};
let duration = Instant::now() - start_time; let duration = Instant::now() - start_time;
drop(vm); drop(vm);
@ -351,7 +345,7 @@ impl Debug for Output {
// Replace with std::lazy::Lazy when stabilized. // Replace with std::lazy::Lazy when stabilized.
// https://github.com/rust-lang/rust/issues/74465 // https://github.com/rust-lang/rust/issues/74465
struct LazyAnalysis<'a, 'b> { struct LazyAnalysis<'a, 'b> {
analysis: Option<Analysis<'a, InvokeContext<'b>>>, analysis: Option<Analysis<'a>>,
executable: &'a Executable<InvokeContext<'b>>, executable: &'a Executable<InvokeContext<'b>>,
} }
@ -363,7 +357,7 @@ impl<'a, 'b> LazyAnalysis<'a, 'b> {
} }
} }
fn analyze(&mut self) -> &Analysis<InvokeContext<'b>> { fn analyze(&mut self) -> &Analysis {
if let Some(ref analysis) = self.analysis { if let Some(ref analysis) = self.analysis {
return analysis; return analysis;
} }