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]]
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]]

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-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"

View File

@ -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<Vec<u8>, Box<dyn std::e
let invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
// Verify the program
let executable = Executable::<InvokeContext>::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::<InvokeContext>::from_elf(&program_data, loader)
.map_err(|err| format!("ELF error: {err}"))?;
let _ = VerifiedExecutable::<RequisiteVerifier, InvokeContext>::from_executable(executable)
.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-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"

View File

@ -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"

View File

@ -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::<InvokeContext>::from_elf(programdata, config, syscall_registry)
.map_err(|err| {
ic_logger_msg!(log_collector, "{}", err);
InstructionError::InvalidAccountData
});
let executable = Executable::<InvokeContext>::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::<u32, (usize, String)>::new();
let executable = Executable::<TestContextObject>::from_text_bytes(
program,
config,
syscall_registry,
Arc::new(BuiltInProgram::new_loader(Config::default())),
bpf_functions,
)
.unwrap();

View File

@ -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<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 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<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>(
@ -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<InvokeContext<'b>>,
syscall: BuiltInFunction<InvokeContext<'b>>,
) -> Result<(Pubkey, u8), EbpfError> {
const SEEDS_VA: u64 = 0x100000000;
const PROGRAM_ID_VA: u64 = 0x200000000;

View File

@ -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]]

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-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" }

View File

@ -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::<InvokeContext>::from_elf(
&elf,
Config::default(),
SyscallRegistry::default(),
)
.unwrap();
let _ = Executable::<InvokeContext>::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::<InvokeContext>::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::<InvokeContext>::from_elf(&elf, loader).unwrap();
let mut verified_executable =
VerifiedExecutable::<RequisiteVerifier, InvokeContext>::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::<InvokeContext>::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::<InvokeContext>::from_elf(&elf, loader).unwrap();
let verified_executable =
VerifiedExecutable::<RequisiteVerifier, InvokeContext>::from_executable(executable)
@ -262,12 +281,15 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
)
.unwrap();
let executable = Executable::<InvokeContext>::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::<InvokeContext>::from_elf(&elf, loader).unwrap();
let verified_executable =
VerifiedExecutable::<RequisiteVerifier, InvokeContext>::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,
);

View File

@ -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::<InvokeContext>::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::<InvokeContext>::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(

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-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"] }

View File

@ -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::<InvokeContext>::from_elf(&contents, config, syscall_registry)
Executable::<InvokeContext>::from_elf(&contents, loader)
.map_err(|err| format!("Executable constructor failed: {err:?}"))
} else {
assemble::<InvokeContext>(
std::str::from_utf8(contents.as_slice()).unwrap(),
config,
syscall_registry,
)
assemble::<InvokeContext>(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::<u16>().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::<u16>().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<'a, InvokeContext<'b>>>,
analysis: Option<Analysis<'a>>,
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 {
return analysis;
}