Bump solana_rbpf to 0.2.34 (#28198)
* Bumps solana_rbpf to 0.2.34 * Removes generic UserError from EbpfError. * Uses ProgramResult for syscalls. Removes use sites of the question_mark! macro by wrapping the call method of SyscallObjects. * Uses InvokeContext as syscall context object directly. * Replaces bind_syscall_context_object() by a parameter in the constructor. * Inlines bind_syscall_context_objects() at its only call site.
This commit is contained in:
parent
66cd290d04
commit
30b0a13ba9
|
@ -6806,9 +6806,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana_rbpf"
|
name = "solana_rbpf"
|
||||||
version = "0.2.33"
|
version = "0.2.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b13ec17b58709d07634895dbca4cae6bebeaddf3b83bf4fa8dfeaf3621222347"
|
checksum = "334bb11faee82f0306e39944cb4ac85824b7d261f3d99d1f2f8bd09851644f0b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"combine",
|
"combine",
|
||||||
|
|
|
@ -54,7 +54,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.33"
|
solana_rbpf = "=0.2.34"
|
||||||
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"
|
||||||
|
|
|
@ -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, BpfError, ThisInstructionMeter},
|
solana_bpf_loader_program::{syscalls::register_syscalls, ThisInstructionMeter},
|
||||||
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,
|
||||||
|
@ -2086,7 +2086,7 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
|
||||||
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
|
let mut invoke_context = InvokeContext::new_mock(&mut transaction_context, &[]);
|
||||||
|
|
||||||
// Verify the program
|
// Verify the program
|
||||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||||
&program_data,
|
&program_data,
|
||||||
Config {
|
Config {
|
||||||
reject_broken_elfs: true,
|
reject_broken_elfs: true,
|
||||||
|
@ -2097,10 +2097,8 @@ fn read_and_verify_elf(program_location: &str) -> Result<Vec<u8>, Box<dyn std::e
|
||||||
.map_err(|err| format!("ELF error: {}", err))?;
|
.map_err(|err| format!("ELF error: {}", err))?;
|
||||||
|
|
||||||
let _ =
|
let _ =
|
||||||
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
|
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(executable)
|
||||||
executable,
|
.map_err(|err| format!("ELF error: {}", err))?;
|
||||||
)
|
|
||||||
.map_err(|err| format!("ELF error: {}", err))?;
|
|
||||||
|
|
||||||
Ok(program_data)
|
Ok(program_data)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6000,9 +6000,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana_rbpf"
|
name = "solana_rbpf"
|
||||||
version = "0.2.33"
|
version = "0.2.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b13ec17b58709d07634895dbca4cae6bebeaddf3b83bf4fa8dfeaf3621222347"
|
checksum = "334bb11faee82f0306e39944cb4ac85824b7d261f3d99d1f2f8bd09851644f0b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.4.3",
|
"byteorder 1.4.3",
|
||||||
"combine",
|
"combine",
|
||||||
|
|
|
@ -38,7 +38,7 @@ solana-program-runtime = { path = "../../program-runtime", version = "=1.15.0" }
|
||||||
solana-runtime = { path = "../../runtime", version = "=1.15.0" }
|
solana-runtime = { path = "../../runtime", 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.33"
|
solana_rbpf = "=0.2.34"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
solana-ledger = { path = "../../ledger", version = "=1.15.0" }
|
solana-ledger = { path = "../../ledger", version = "=1.15.0" }
|
||||||
|
|
|
@ -8,7 +8,7 @@ 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, BpfError,
|
create_vm, serialization::serialize_parameters, syscalls::register_syscalls,
|
||||||
ThisInstructionMeter,
|
ThisInstructionMeter,
|
||||||
},
|
},
|
||||||
solana_measure::measure::Measure,
|
solana_measure::measure::Measure,
|
||||||
|
@ -81,7 +81,7 @@ fn bench_program_create_executable(bencher: &mut Bencher) {
|
||||||
let elf = load_elf("bench_alu").unwrap();
|
let elf = load_elf("bench_alu").unwrap();
|
||||||
|
|
||||||
bencher.iter(|| {
|
bencher.iter(|| {
|
||||||
let _ = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
let _ = Executable::<ThisInstructionMeter>::from_elf(
|
||||||
&elf,
|
&elf,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
SyscallRegistry::default(),
|
SyscallRegistry::default(),
|
||||||
|
@ -106,19 +106,18 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
.get_compute_meter()
|
.get_compute_meter()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.mock_set_remaining(std::i64::MAX as u64);
|
.mock_set_remaining(std::i64::MAX as u64);
|
||||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||||
&elf,
|
&elf,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
register_syscalls(invoke_context, true).unwrap(),
|
register_syscalls(invoke_context, true).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut verified_executable = VerifiedExecutable::<
|
let mut verified_executable =
|
||||||
RequisiteVerifier,
|
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
|
||||||
BpfError,
|
executable,
|
||||||
ThisInstructionMeter,
|
)
|
||||||
>::from_executable(executable)
|
.unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
verified_executable.jit_compile().unwrap();
|
verified_executable.jit_compile().unwrap();
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
|
@ -235,19 +234,18 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||||
&elf,
|
&elf,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
register_syscalls(invoke_context, true).unwrap(),
|
register_syscalls(invoke_context, true).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let verified_executable = VerifiedExecutable::<
|
let verified_executable =
|
||||||
RequisiteVerifier,
|
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
|
||||||
BpfError,
|
executable,
|
||||||
ThisInstructionMeter,
|
)
|
||||||
>::from_executable(executable)
|
.unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
bencher.iter(|| {
|
bencher.iter(|| {
|
||||||
let _ = create_vm(
|
let _ = create_vm(
|
||||||
|
@ -283,19 +281,18 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||||
&elf,
|
&elf,
|
||||||
Config::default(),
|
Config::default(),
|
||||||
register_syscalls(invoke_context, true).unwrap(),
|
register_syscalls(invoke_context, true).unwrap(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let verified_executable = VerifiedExecutable::<
|
let verified_executable =
|
||||||
RequisiteVerifier,
|
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
|
||||||
BpfError,
|
executable,
|
||||||
ThisInstructionMeter,
|
)
|
||||||
>::from_executable(executable)
|
.unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
|
|
|
@ -55,7 +55,7 @@ use {
|
||||||
create_vm,
|
create_vm,
|
||||||
serialization::{deserialize_parameters, serialize_parameters},
|
serialization::{deserialize_parameters, serialize_parameters},
|
||||||
syscalls::register_syscalls,
|
syscalls::register_syscalls,
|
||||||
BpfError, ThisInstructionMeter,
|
ThisInstructionMeter,
|
||||||
},
|
},
|
||||||
solana_program_runtime::invoke_context::with_mock_invoke_context,
|
solana_program_runtime::invoke_context::with_mock_invoke_context,
|
||||||
solana_rbpf::{
|
solana_rbpf::{
|
||||||
|
@ -241,7 +241,7 @@ fn run_program(name: &str) -> u64 {
|
||||||
reject_broken_elfs: true,
|
reject_broken_elfs: true,
|
||||||
..Config::default()
|
..Config::default()
|
||||||
};
|
};
|
||||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||||
&data,
|
&data,
|
||||||
config,
|
config,
|
||||||
register_syscalls(invoke_context, true /* no sol_alloc_free */).unwrap(),
|
register_syscalls(invoke_context, true /* no sol_alloc_free */).unwrap(),
|
||||||
|
@ -249,12 +249,11 @@ fn run_program(name: &str) -> u64 {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
let mut verified_executable = VerifiedExecutable::<
|
let mut verified_executable =
|
||||||
RequisiteVerifier,
|
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
|
||||||
BpfError,
|
executable,
|
||||||
ThisInstructionMeter,
|
)
|
||||||
>::from_executable(executable)
|
.unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let run_program_iterations = {
|
let run_program_iterations = {
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
@ -300,7 +299,10 @@ fn run_program(name: &str) -> u64 {
|
||||||
instruction_count = vm.get_total_instruction_count();
|
instruction_count = vm.get_total_instruction_count();
|
||||||
if config.enable_instruction_tracing {
|
if config.enable_instruction_tracing {
|
||||||
if i == 1 {
|
if i == 1 {
|
||||||
if !Tracer::compare(tracer.as_ref().unwrap(), vm.get_tracer()) {
|
if !Tracer::compare(
|
||||||
|
tracer.as_ref().unwrap(),
|
||||||
|
&vm.get_program_environment().tracer,
|
||||||
|
) {
|
||||||
let analysis =
|
let analysis =
|
||||||
Analysis::from_executable(verified_executable.get_executable())
|
Analysis::from_executable(verified_executable.get_executable())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -312,7 +314,8 @@ fn run_program(name: &str) -> u64 {
|
||||||
.write(&mut stdout.lock(), &analysis)
|
.write(&mut stdout.lock(), &analysis)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
println!("TRACE (jit):");
|
println!("TRACE (jit):");
|
||||||
vm.get_tracer()
|
vm.get_program_environment()
|
||||||
|
.tracer
|
||||||
.write(&mut stdout.lock(), &analysis)
|
.write(&mut stdout.lock(), &analysis)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(false);
|
assert!(false);
|
||||||
|
@ -330,7 +333,7 @@ fn run_program(name: &str) -> u64 {
|
||||||
trace!("BPF Program Instruction Trace:\n{}", trace_string);
|
trace!("BPF Program Instruction Trace:\n{}", trace_string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tracer = Some(vm.get_tracer().clone());
|
tracer = Some(vm.get_program_environment().tracer.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert!(match deserialize_parameters(
|
assert!(match deserialize_parameters(
|
||||||
|
|
|
@ -19,7 +19,7 @@ solana-metrics = { path = "../../metrics", 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.33"
|
solana_rbpf = "=0.2.34"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -14,6 +14,7 @@ extern crate solana_metrics;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
crate::{
|
crate::{
|
||||||
|
allocator_bump::BpfAllocator,
|
||||||
serialization::{deserialize_parameters, serialize_parameters},
|
serialization::{deserialize_parameters, serialize_parameters},
|
||||||
syscalls::SyscallError,
|
syscalls::SyscallError,
|
||||||
},
|
},
|
||||||
|
@ -28,13 +29,13 @@ use {
|
||||||
},
|
},
|
||||||
solana_rbpf::{
|
solana_rbpf::{
|
||||||
aligned_memory::AlignedMemory,
|
aligned_memory::AlignedMemory,
|
||||||
ebpf::{HOST_ALIGN, MM_INPUT_START},
|
ebpf::{HOST_ALIGN, MM_HEAP_START, MM_INPUT_START},
|
||||||
elf::Executable,
|
elf::Executable,
|
||||||
error::{EbpfError, UserDefinedError},
|
error::{EbpfError, UserDefinedError},
|
||||||
memory_region::MemoryRegion,
|
memory_region::MemoryRegion,
|
||||||
static_analysis::Analysis,
|
static_analysis::Analysis,
|
||||||
verifier::{RequisiteVerifier, VerifierError},
|
verifier::{RequisiteVerifier, VerifierError},
|
||||||
vm::{Config, EbpfVm, InstructionMeter, VerifiedExecutable},
|
vm::{Config, EbpfVm, InstructionMeter, ProgramResult, VerifiedExecutable},
|
||||||
},
|
},
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
bpf_loader, bpf_loader_deprecated,
|
bpf_loader, bpf_loader_deprecated,
|
||||||
|
@ -42,9 +43,10 @@ use {
|
||||||
entrypoint::{HEAP_LENGTH, SUCCESS},
|
entrypoint::{HEAP_LENGTH, SUCCESS},
|
||||||
feature_set::{
|
feature_set::{
|
||||||
cap_accounts_data_allocations_per_transaction, cap_bpf_program_instruction_accounts,
|
cap_accounts_data_allocations_per_transaction, cap_bpf_program_instruction_accounts,
|
||||||
disable_deploy_of_alloc_free_syscall, disable_deprecated_loader,
|
check_slice_translation_size, disable_deploy_of_alloc_free_syscall,
|
||||||
enable_bpf_loader_extend_program_ix, error_on_syscall_bpf_function_hash_collisions,
|
disable_deprecated_loader, enable_bpf_loader_extend_program_ix,
|
||||||
limit_max_instruction_trace_length, reject_callx_r10,
|
error_on_syscall_bpf_function_hash_collisions, limit_max_instruction_trace_length,
|
||||||
|
reject_callx_r10,
|
||||||
},
|
},
|
||||||
instruction::{AccountMeta, InstructionError},
|
instruction::{AccountMeta, InstructionError},
|
||||||
loader_instruction::LoaderInstruction,
|
loader_instruction::LoaderInstruction,
|
||||||
|
@ -80,7 +82,7 @@ pub enum BpfError {
|
||||||
}
|
}
|
||||||
impl UserDefinedError for BpfError {}
|
impl UserDefinedError for BpfError {}
|
||||||
|
|
||||||
fn map_ebpf_error(invoke_context: &InvokeContext, e: EbpfError<BpfError>) -> InstructionError {
|
fn map_ebpf_error(invoke_context: &InvokeContext, e: EbpfError) -> InstructionError {
|
||||||
ic_msg!(invoke_context, "{}", e);
|
ic_msg!(invoke_context, "{}", e);
|
||||||
InstructionError::InvalidAccountData
|
InstructionError::InvalidAccountData
|
||||||
}
|
}
|
||||||
|
@ -201,7 +203,7 @@ pub fn create_executor(
|
||||||
)?;
|
)?;
|
||||||
create_executor_metrics.program_id = programdata.get_key().to_string();
|
create_executor_metrics.program_id = programdata.get_key().to_string();
|
||||||
let mut load_elf_time = Measure::start("load_elf_time");
|
let mut load_elf_time = Measure::start("load_elf_time");
|
||||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
let executable = Executable::<ThisInstructionMeter>::from_elf(
|
||||||
programdata
|
programdata
|
||||||
.get_data()
|
.get_data()
|
||||||
.get(programdata_offset..)
|
.get(programdata_offset..)
|
||||||
|
@ -220,10 +222,8 @@ pub fn create_executor(
|
||||||
.map_err(|e| map_ebpf_error(invoke_context, e))?;
|
.map_err(|e| map_ebpf_error(invoke_context, e))?;
|
||||||
let mut verify_code_time = Measure::start("verify_code_time");
|
let mut verify_code_time = Measure::start("verify_code_time");
|
||||||
let mut verified_executable =
|
let mut verified_executable =
|
||||||
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
|
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(executable)
|
||||||
executable,
|
.map_err(|e| map_ebpf_error(invoke_context, e))?;
|
||||||
)
|
|
||||||
.map_err(|e| map_ebpf_error(invoke_context, e))?;
|
|
||||||
verify_code_time.stop();
|
verify_code_time.stop();
|
||||||
create_executor_metrics.verify_code_us = verify_code_time.as_us();
|
create_executor_metrics.verify_code_us = verify_code_time.as_us();
|
||||||
invoke_context.timings.create_executor_verify_code_us = invoke_context
|
invoke_context.timings.create_executor_verify_code_us = invoke_context
|
||||||
|
@ -289,11 +289,11 @@ fn check_loader_id(id: &Pubkey) -> bool {
|
||||||
|
|
||||||
/// Create the BPF virtual machine
|
/// Create the BPF virtual machine
|
||||||
pub fn create_vm<'a, 'b>(
|
pub fn create_vm<'a, 'b>(
|
||||||
program: &'a VerifiedExecutable<RequisiteVerifier, BpfError, ThisInstructionMeter>,
|
program: &'a VerifiedExecutable<RequisiteVerifier, ThisInstructionMeter>,
|
||||||
parameter_bytes: &mut [u8],
|
parameter_bytes: &mut [u8],
|
||||||
orig_account_lengths: Vec<usize>,
|
orig_account_lengths: Vec<usize>,
|
||||||
invoke_context: &'a mut InvokeContext<'b>,
|
invoke_context: &'a mut InvokeContext<'b>,
|
||||||
) -> Result<EbpfVm<'a, RequisiteVerifier, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
|
) -> Result<EbpfVm<'a, RequisiteVerifier, ThisInstructionMeter>, EbpfError> {
|
||||||
let compute_budget = invoke_context.get_compute_budget();
|
let compute_budget = invoke_context.get_compute_budget();
|
||||||
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
|
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
|
||||||
let _ = invoke_context.get_compute_meter().borrow_mut().consume(
|
let _ = invoke_context.get_compute_meter().borrow_mut().consume(
|
||||||
|
@ -304,8 +304,33 @@ pub fn create_vm<'a, 'b>(
|
||||||
let mut heap =
|
let mut heap =
|
||||||
AlignedMemory::<HOST_ALIGN>::zero_filled(compute_budget.heap_size.unwrap_or(HEAP_LENGTH));
|
AlignedMemory::<HOST_ALIGN>::zero_filled(compute_budget.heap_size.unwrap_or(HEAP_LENGTH));
|
||||||
let parameter_region = MemoryRegion::new_writable(parameter_bytes, MM_INPUT_START);
|
let parameter_region = MemoryRegion::new_writable(parameter_bytes, MM_INPUT_START);
|
||||||
let mut vm = EbpfVm::new(program, heap.as_slice_mut(), vec![parameter_region])?;
|
let vm = EbpfVm::new(
|
||||||
syscalls::bind_syscall_context_objects(&mut vm, invoke_context, heap, orig_account_lengths)?;
|
program,
|
||||||
|
invoke_context,
|
||||||
|
heap.as_slice_mut(),
|
||||||
|
vec![parameter_region],
|
||||||
|
)?;
|
||||||
|
let check_aligned = bpf_loader_deprecated::id()
|
||||||
|
!= invoke_context
|
||||||
|
.transaction_context
|
||||||
|
.get_current_instruction_context()
|
||||||
|
.and_then(|instruction_context| {
|
||||||
|
instruction_context
|
||||||
|
.try_borrow_last_program_account(invoke_context.transaction_context)
|
||||||
|
})
|
||||||
|
.map(|program_account| *program_account.get_owner())
|
||||||
|
.map_err(SyscallError::InstructionError)?;
|
||||||
|
let check_size = invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&check_slice_translation_size::id());
|
||||||
|
invoke_context
|
||||||
|
.set_syscall_context(
|
||||||
|
check_aligned,
|
||||||
|
check_size,
|
||||||
|
orig_account_lengths,
|
||||||
|
Rc::new(RefCell::new(BpfAllocator::new(heap, MM_HEAP_START))),
|
||||||
|
)
|
||||||
|
.map_err(SyscallError::InstructionError)?;
|
||||||
Ok(vm)
|
Ok(vm)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1281,7 +1306,7 @@ impl InstructionMeter for ThisInstructionMeter {
|
||||||
|
|
||||||
/// BPF Loader's Executor implementation
|
/// BPF Loader's Executor implementation
|
||||||
pub struct BpfExecutor {
|
pub struct BpfExecutor {
|
||||||
verified_executable: VerifiedExecutable<RequisiteVerifier, BpfError, ThisInstructionMeter>,
|
verified_executable: VerifiedExecutable<RequisiteVerifier, ThisInstructionMeter>,
|
||||||
use_jit: bool,
|
use_jit: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1353,7 +1378,10 @@ impl Executor for BpfExecutor {
|
||||||
let mut trace_buffer = Vec::<u8>::new();
|
let mut trace_buffer = Vec::<u8>::new();
|
||||||
let analysis =
|
let analysis =
|
||||||
Analysis::from_executable(self.verified_executable.get_executable()).unwrap();
|
Analysis::from_executable(self.verified_executable.get_executable()).unwrap();
|
||||||
vm.get_tracer().write(&mut trace_buffer, &analysis).unwrap();
|
vm.get_program_environment()
|
||||||
|
.tracer
|
||||||
|
.write(&mut trace_buffer, &analysis)
|
||||||
|
.unwrap();
|
||||||
let trace_string = String::from_utf8(trace_buffer).unwrap();
|
let trace_string = String::from_utf8(trace_buffer).unwrap();
|
||||||
trace!("BPF Program Instruction Trace:\n{}", trace_string);
|
trace!("BPF Program Instruction Trace:\n{}", trace_string);
|
||||||
}
|
}
|
||||||
|
@ -1364,7 +1392,7 @@ impl Executor for BpfExecutor {
|
||||||
stable_log::program_return(&log_collector, &program_id, return_data);
|
stable_log::program_return(&log_collector, &program_id, return_data);
|
||||||
}
|
}
|
||||||
match result {
|
match result {
|
||||||
Ok(status) if status != SUCCESS => {
|
ProgramResult::Ok(status) if status != SUCCESS => {
|
||||||
let error: InstructionError = if (status
|
let error: InstructionError = if (status
|
||||||
== MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED
|
== MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED
|
||||||
&& !invoke_context
|
&& !invoke_context
|
||||||
|
@ -1386,11 +1414,24 @@ impl Executor for BpfExecutor {
|
||||||
stable_log::program_failure(&log_collector, &program_id, &error);
|
stable_log::program_failure(&log_collector, &program_id, &error);
|
||||||
Err(error)
|
Err(error)
|
||||||
}
|
}
|
||||||
Err(error) => {
|
ProgramResult::Err(error) => {
|
||||||
let error = match error {
|
let error = match error {
|
||||||
EbpfError::UserError(BpfError::SyscallError(
|
/*EbpfError::UserError(user_error) if let BpfError::SyscallError(
|
||||||
SyscallError::InstructionError(error),
|
SyscallError::InstructionError(instruction_error),
|
||||||
)) => error,
|
) = user_error.downcast_ref::<BpfError>().unwrap() => instruction_error.clone(),*/
|
||||||
|
EbpfError::UserError(user_error)
|
||||||
|
if matches!(
|
||||||
|
user_error.downcast_ref::<BpfError>().unwrap(),
|
||||||
|
BpfError::SyscallError(SyscallError::InstructionError(_)),
|
||||||
|
) =>
|
||||||
|
{
|
||||||
|
match user_error.downcast_ref::<BpfError>().unwrap() {
|
||||||
|
BpfError::SyscallError(SyscallError::InstructionError(
|
||||||
|
instruction_error,
|
||||||
|
)) => instruction_error.clone(),
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
err => {
|
err => {
|
||||||
ic_logger_msg!(log_collector, "Program failed to complete: {}", err);
|
ic_logger_msg!(log_collector, "Program failed to complete: {}", err);
|
||||||
InstructionError::ProgramFailedToComplete
|
InstructionError::ProgramFailedToComplete
|
||||||
|
@ -1536,21 +1577,21 @@ mod tests {
|
||||||
"entrypoint",
|
"entrypoint",
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let executable = Executable::<BpfError, TestInstructionMeter>::from_text_bytes(
|
let executable = Executable::<TestInstructionMeter>::from_text_bytes(
|
||||||
program,
|
program,
|
||||||
config,
|
config,
|
||||||
syscall_registry,
|
syscall_registry,
|
||||||
bpf_functions,
|
bpf_functions,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let verified_executable = VerifiedExecutable::<
|
let verified_executable =
|
||||||
TautologyVerifier,
|
VerifiedExecutable::<TautologyVerifier, TestInstructionMeter>::from_executable(
|
||||||
BpfError,
|
executable,
|
||||||
TestInstructionMeter,
|
)
|
||||||
>::from_executable(executable)
|
.unwrap();
|
||||||
.unwrap();
|
|
||||||
let input_region = MemoryRegion::new_writable(&mut input_mem, MM_INPUT_START);
|
let input_region = MemoryRegion::new_writable(&mut input_mem, MM_INPUT_START);
|
||||||
let mut vm = EbpfVm::new(&verified_executable, &mut [], vec![input_region]).unwrap();
|
let mut vm =
|
||||||
|
EbpfVm::new(&verified_executable, &mut (), &mut [], vec![input_region]).unwrap();
|
||||||
let mut instruction_meter = TestInstructionMeter { remaining: 10 };
|
let mut instruction_meter = TestInstructionMeter { remaining: 10 };
|
||||||
vm.execute_program_interpreted(&mut instruction_meter)
|
vm.execute_program_interpreted(&mut instruction_meter)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -23,71 +23,59 @@ struct CallerAccount<'a> {
|
||||||
type TranslatedAccounts<'a> = Vec<(IndexOfAccount, Option<CallerAccount<'a>>)>;
|
type TranslatedAccounts<'a> = Vec<(IndexOfAccount, Option<CallerAccount<'a>>)>;
|
||||||
|
|
||||||
/// Implemented by language specific data structure translators
|
/// Implemented by language specific data structure translators
|
||||||
trait SyscallInvokeSigned<'a, 'b> {
|
trait SyscallInvokeSigned {
|
||||||
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>>;
|
|
||||||
fn translate_instruction(
|
fn translate_instruction(
|
||||||
&self,
|
|
||||||
addr: u64,
|
addr: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<Instruction, EbpfError<BpfError>>;
|
) -> Result<Instruction, EbpfError>;
|
||||||
fn translate_accounts<'c>(
|
fn translate_accounts<'a>(
|
||||||
&'c self,
|
|
||||||
instruction_accounts: &[InstructionAccount],
|
instruction_accounts: &[InstructionAccount],
|
||||||
program_indices: &[IndexOfAccount],
|
program_indices: &[IndexOfAccount],
|
||||||
account_infos_addr: u64,
|
account_infos_addr: u64,
|
||||||
account_infos_len: u64,
|
account_infos_len: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>>;
|
) -> Result<TranslatedAccounts<'a>, EbpfError>;
|
||||||
fn translate_signers(
|
fn translate_signers(
|
||||||
&self,
|
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
signers_seeds_addr: u64,
|
signers_seeds_addr: u64,
|
||||||
signers_seeds_len: u64,
|
signers_seeds_len: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
) -> Result<Vec<Pubkey>, EbpfError<BpfError>>;
|
) -> Result<Vec<Pubkey>, EbpfError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// Cross-program invocation called from Rust
|
/// Cross-program invocation called from Rust
|
||||||
SyscallInvokeSignedRust,
|
SyscallInvokeSignedRust,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
instruction_addr: u64,
|
instruction_addr: u64,
|
||||||
account_infos_addr: u64,
|
account_infos_addr: u64,
|
||||||
account_infos_len: u64,
|
account_infos_len: u64,
|
||||||
signers_seeds_addr: u64,
|
signers_seeds_addr: u64,
|
||||||
signers_seeds_len: u64,
|
signers_seeds_len: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
cpi_common::<Self>(
|
||||||
*result = call(
|
invoke_context,
|
||||||
self,
|
|
||||||
instruction_addr,
|
instruction_addr,
|
||||||
account_infos_addr,
|
account_infos_addr,
|
||||||
account_infos_len,
|
account_infos_len,
|
||||||
signers_seeds_addr,
|
signers_seeds_addr,
|
||||||
signers_seeds_len,
|
signers_seeds_len,
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
|
impl SyscallInvokeSigned for SyscallInvokeSignedRust {
|
||||||
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>> {
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow_mut()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn translate_instruction(
|
fn translate_instruction(
|
||||||
&self,
|
|
||||||
addr: u64,
|
addr: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<Instruction, EbpfError<BpfError>> {
|
) -> Result<Instruction, EbpfError> {
|
||||||
let ix = translate_type::<Instruction>(
|
let ix = translate_type::<Instruction>(
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
addr,
|
addr,
|
||||||
|
@ -131,15 +119,14 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn translate_accounts<'c>(
|
fn translate_accounts<'a>(
|
||||||
&'c self,
|
|
||||||
instruction_accounts: &[InstructionAccount],
|
instruction_accounts: &[InstructionAccount],
|
||||||
program_indices: &[IndexOfAccount],
|
program_indices: &[IndexOfAccount],
|
||||||
account_infos_addr: u64,
|
account_infos_addr: u64,
|
||||||
account_infos_len: u64,
|
account_infos_len: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>> {
|
) -> Result<TranslatedAccounts<'a>, EbpfError> {
|
||||||
let account_infos = translate_slice::<AccountInfo>(
|
let account_infos = translate_slice::<AccountInfo>(
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
account_infos_addr,
|
account_infos_addr,
|
||||||
|
@ -157,7 +144,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_aligned(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
.collect::<Result<Vec<_>, EbpfError>>()?;
|
||||||
|
|
||||||
let translate = |account_info: &AccountInfo, invoke_context: &InvokeContext| {
|
let translate = |account_info: &AccountInfo, invoke_context: &InvokeContext| {
|
||||||
// Translate the account from user space
|
// Translate the account from user space
|
||||||
|
@ -235,13 +222,12 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn translate_signers(
|
fn translate_signers(
|
||||||
&self,
|
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
signers_seeds_addr: u64,
|
signers_seeds_addr: u64,
|
||||||
signers_seeds_len: u64,
|
signers_seeds_len: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
) -> Result<Vec<Pubkey>, EbpfError<BpfError>> {
|
) -> Result<Vec<Pubkey>, EbpfError> {
|
||||||
let mut signers = Vec::new();
|
let mut signers = Vec::new();
|
||||||
if signers_seeds_len > 0 {
|
if signers_seeds_len > 0 {
|
||||||
let signers_seeds = translate_slice::<&[&[u8]]>(
|
let signers_seeds = translate_slice::<&[&[u8]]>(
|
||||||
|
@ -279,7 +265,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
|
||||||
invoke_context.get_check_size(),
|
invoke_context.get_check_size(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
.collect::<Result<Vec<_>, EbpfError>>()?;
|
||||||
let signer = Pubkey::create_program_address(&seeds, program_id)
|
let signer = Pubkey::create_program_address(&seeds, program_id)
|
||||||
.map_err(SyscallError::BadSeeds)?;
|
.map_err(SyscallError::BadSeeds)?;
|
||||||
signers.push(signer);
|
signers.push(signer);
|
||||||
|
@ -347,41 +333,33 @@ struct SolSignerSeedsC {
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// Cross-program invocation called from C
|
/// Cross-program invocation called from C
|
||||||
SyscallInvokeSignedC,
|
SyscallInvokeSignedC,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
instruction_addr: u64,
|
instruction_addr: u64,
|
||||||
account_infos_addr: u64,
|
account_infos_addr: u64,
|
||||||
account_infos_len: u64,
|
account_infos_len: u64,
|
||||||
signers_seeds_addr: u64,
|
signers_seeds_addr: u64,
|
||||||
signers_seeds_len: u64,
|
signers_seeds_len: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
cpi_common::<Self>(
|
||||||
*result = call(
|
invoke_context,
|
||||||
self,
|
|
||||||
instruction_addr,
|
instruction_addr,
|
||||||
account_infos_addr,
|
account_infos_addr,
|
||||||
account_infos_len,
|
account_infos_len,
|
||||||
signers_seeds_addr,
|
signers_seeds_addr,
|
||||||
signers_seeds_len,
|
signers_seeds_len,
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
impl SyscallInvokeSigned for SyscallInvokeSignedC {
|
||||||
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>> {
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow_mut()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn translate_instruction(
|
fn translate_instruction(
|
||||||
&self,
|
|
||||||
addr: u64,
|
addr: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<Instruction, EbpfError<BpfError>> {
|
) -> Result<Instruction, EbpfError> {
|
||||||
let ix_c = translate_type::<SolInstruction>(
|
let ix_c = translate_type::<SolInstruction>(
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
addr,
|
addr,
|
||||||
|
@ -439,7 +417,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
||||||
is_writable: meta_c.is_writable,
|
is_writable: meta_c.is_writable,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<AccountMeta>, EbpfError<BpfError>>>()?;
|
.collect::<Result<Vec<AccountMeta>, EbpfError>>()?;
|
||||||
|
|
||||||
Ok(Instruction {
|
Ok(Instruction {
|
||||||
program_id: *program_id,
|
program_id: *program_id,
|
||||||
|
@ -448,15 +426,14 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn translate_accounts<'c>(
|
fn translate_accounts<'a>(
|
||||||
&'c self,
|
|
||||||
instruction_accounts: &[InstructionAccount],
|
instruction_accounts: &[InstructionAccount],
|
||||||
program_indices: &[IndexOfAccount],
|
program_indices: &[IndexOfAccount],
|
||||||
account_infos_addr: u64,
|
account_infos_addr: u64,
|
||||||
account_infos_len: u64,
|
account_infos_len: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>> {
|
) -> Result<TranslatedAccounts<'a>, EbpfError> {
|
||||||
let account_infos = translate_slice::<SolAccountInfo>(
|
let account_infos = translate_slice::<SolAccountInfo>(
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
account_infos_addr,
|
account_infos_addr,
|
||||||
|
@ -474,7 +451,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_aligned(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
.collect::<Result<Vec<_>, EbpfError>>()?;
|
||||||
|
|
||||||
let translate = |account_info: &SolAccountInfo, invoke_context: &InvokeContext| {
|
let translate = |account_info: &SolAccountInfo, invoke_context: &InvokeContext| {
|
||||||
// Translate the account from user space
|
// Translate the account from user space
|
||||||
|
@ -551,13 +528,12 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn translate_signers(
|
fn translate_signers(
|
||||||
&self,
|
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
signers_seeds_addr: u64,
|
signers_seeds_addr: u64,
|
||||||
signers_seeds_len: u64,
|
signers_seeds_len: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
) -> Result<Vec<Pubkey>, EbpfError<BpfError>> {
|
) -> Result<Vec<Pubkey>, EbpfError> {
|
||||||
if signers_seeds_len > 0 {
|
if signers_seeds_len > 0 {
|
||||||
let signers_seeds = translate_slice::<SolSignerSeedsC>(
|
let signers_seeds = translate_slice::<SolSignerSeedsC>(
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
|
@ -596,11 +572,11 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
|
||||||
invoke_context.get_check_size(),
|
invoke_context.get_check_size(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
|
.collect::<Result<Vec<_>, EbpfError>>()?;
|
||||||
Pubkey::create_program_address(&seeds_bytes, program_id)
|
Pubkey::create_program_address(&seeds_bytes, program_id)
|
||||||
.map_err(|err| SyscallError::BadSeeds(err).into())
|
.map_err(|err| SyscallError::BadSeeds(err).into())
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?)
|
.collect::<Result<Vec<_>, EbpfError>>()?)
|
||||||
} else {
|
} else {
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
|
@ -614,9 +590,9 @@ fn get_translated_accounts<'a, T, F>(
|
||||||
account_infos: &[T],
|
account_infos: &[T],
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
do_translate: F,
|
do_translate: F,
|
||||||
) -> Result<TranslatedAccounts<'a>, EbpfError<BpfError>>
|
) -> Result<TranslatedAccounts<'a>, EbpfError>
|
||||||
where
|
where
|
||||||
F: Fn(&T, &InvokeContext) -> Result<CallerAccount<'a>, EbpfError<BpfError>>,
|
F: Fn(&T, &InvokeContext) -> Result<CallerAccount<'a>, EbpfError>,
|
||||||
{
|
{
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context
|
let instruction_context = transaction_context
|
||||||
|
@ -686,9 +662,9 @@ where
|
||||||
.set_data_from_slice(caller_account.data)
|
.set_data_from_slice(caller_account.data)
|
||||||
.map_err(SyscallError::InstructionError)?,
|
.map_err(SyscallError::InstructionError)?,
|
||||||
Err(err) if callee_account.get_data() != caller_account.data => {
|
Err(err) if callee_account.get_data() != caller_account.data => {
|
||||||
return Err(EbpfError::UserError(BpfError::SyscallError(
|
return Err(EbpfError::UserError(Box::new(BpfError::SyscallError(
|
||||||
SyscallError::InstructionError(err),
|
SyscallError::InstructionError(err),
|
||||||
)));
|
))));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -764,7 +740,7 @@ fn check_instruction_size(
|
||||||
num_accounts: usize,
|
num_accounts: usize,
|
||||||
data_len: usize,
|
data_len: usize,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<(), EbpfError<BpfError>> {
|
) -> Result<(), EbpfError> {
|
||||||
if invoke_context
|
if invoke_context
|
||||||
.feature_set
|
.feature_set
|
||||||
.is_active(&feature_set::loosen_cpi_size_restriction::id())
|
.is_active(&feature_set::loosen_cpi_size_restriction::id())
|
||||||
|
@ -803,7 +779,7 @@ fn check_instruction_size(
|
||||||
fn check_account_infos(
|
fn check_account_infos(
|
||||||
num_account_infos: usize,
|
num_account_infos: usize,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<(), EbpfError<BpfError>> {
|
) -> Result<(), EbpfError> {
|
||||||
if invoke_context
|
if invoke_context
|
||||||
.feature_set
|
.feature_set
|
||||||
.is_active(&feature_set::loosen_cpi_size_restriction::id())
|
.is_active(&feature_set::loosen_cpi_size_restriction::id())
|
||||||
|
@ -850,7 +826,7 @@ fn check_authorized_program(
|
||||||
program_id: &Pubkey,
|
program_id: &Pubkey,
|
||||||
instruction_data: &[u8],
|
instruction_data: &[u8],
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
) -> Result<(), EbpfError<BpfError>> {
|
) -> Result<(), EbpfError> {
|
||||||
if native_loader::check_id(program_id)
|
if native_loader::check_id(program_id)
|
||||||
|| bpf_loader::check_id(program_id)
|
|| bpf_loader::check_id(program_id)
|
||||||
|| bpf_loader_deprecated::check_id(program_id)
|
|| bpf_loader_deprecated::check_id(program_id)
|
||||||
|
@ -868,23 +844,21 @@ fn check_authorized_program(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Call process instruction, common to both Rust and C
|
/// Call process instruction, common to both Rust and C
|
||||||
fn call<'a, 'b: 'a>(
|
fn cpi_common<S: SyscallInvokeSigned>(
|
||||||
syscall: &mut dyn SyscallInvokeSigned<'a, 'b>,
|
invoke_context: &mut InvokeContext,
|
||||||
instruction_addr: u64,
|
instruction_addr: u64,
|
||||||
account_infos_addr: u64,
|
account_infos_addr: u64,
|
||||||
account_infos_len: u64,
|
account_infos_len: u64,
|
||||||
signers_seeds_addr: u64,
|
signers_seeds_addr: u64,
|
||||||
signers_seeds_len: u64,
|
signers_seeds_len: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
) -> Result<u64, EbpfError<BpfError>> {
|
) -> Result<u64, EbpfError> {
|
||||||
let mut invoke_context = syscall.get_context_mut()?;
|
|
||||||
invoke_context
|
invoke_context
|
||||||
.get_compute_meter()
|
.get_compute_meter()
|
||||||
.consume(invoke_context.get_compute_budget().invoke_units)?;
|
.consume(invoke_context.get_compute_budget().invoke_units)?;
|
||||||
|
|
||||||
// Translate and verify caller's data
|
// Translate and verify caller's data
|
||||||
let instruction =
|
let instruction = S::translate_instruction(instruction_addr, memory_mapping, invoke_context)?;
|
||||||
syscall.translate_instruction(instruction_addr, memory_mapping, *invoke_context)?;
|
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context
|
let instruction_context = transaction_context
|
||||||
.get_current_instruction_context()
|
.get_current_instruction_context()
|
||||||
|
@ -892,24 +866,24 @@ fn call<'a, 'b: 'a>(
|
||||||
let caller_program_id = instruction_context
|
let caller_program_id = instruction_context
|
||||||
.get_last_program_key(transaction_context)
|
.get_last_program_key(transaction_context)
|
||||||
.map_err(SyscallError::InstructionError)?;
|
.map_err(SyscallError::InstructionError)?;
|
||||||
let signers = syscall.translate_signers(
|
let signers = S::translate_signers(
|
||||||
caller_program_id,
|
caller_program_id,
|
||||||
signers_seeds_addr,
|
signers_seeds_addr,
|
||||||
signers_seeds_len,
|
signers_seeds_len,
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
*invoke_context,
|
invoke_context,
|
||||||
)?;
|
)?;
|
||||||
let (instruction_accounts, program_indices) = invoke_context
|
let (instruction_accounts, program_indices) = invoke_context
|
||||||
.prepare_instruction(&instruction, &signers)
|
.prepare_instruction(&instruction, &signers)
|
||||||
.map_err(SyscallError::InstructionError)?;
|
.map_err(SyscallError::InstructionError)?;
|
||||||
check_authorized_program(&instruction.program_id, &instruction.data, *invoke_context)?;
|
check_authorized_program(&instruction.program_id, &instruction.data, invoke_context)?;
|
||||||
let mut accounts = syscall.translate_accounts(
|
let mut accounts = S::translate_accounts(
|
||||||
&instruction_accounts,
|
&instruction_accounts,
|
||||||
&program_indices,
|
&program_indices,
|
||||||
account_infos_addr,
|
account_infos_addr,
|
||||||
account_infos_len,
|
account_infos_len,
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
*invoke_context,
|
invoke_context,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Process instruction
|
// Process instruction
|
||||||
|
|
|
@ -3,67 +3,50 @@ use {super::*, crate::declare_syscall};
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// Log a user's info message
|
/// Log a user's info message
|
||||||
SyscallLog,
|
SyscallLog,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
addr: u64,
|
addr: u64,
|
||||||
len: u64,
|
len: u64,
|
||||||
_arg3: u64,
|
_arg3: u64,
|
||||||
_arg4: u64,
|
_arg4: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
|
||||||
let invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
let cost = invoke_context
|
let cost = invoke_context
|
||||||
.get_compute_budget()
|
.get_compute_budget()
|
||||||
.syscall_base_cost
|
.syscall_base_cost
|
||||||
.max(len);
|
.max(len);
|
||||||
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
invoke_context.get_compute_meter().consume(cost)?;
|
||||||
|
|
||||||
question_mark!(
|
translate_string_and_do(
|
||||||
translate_string_and_do(
|
memory_mapping,
|
||||||
memory_mapping,
|
addr,
|
||||||
addr,
|
len,
|
||||||
len,
|
invoke_context.get_check_aligned(),
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_size(),
|
||||||
invoke_context.get_check_size(),
|
&mut |string: &str| {
|
||||||
&mut |string: &str| {
|
stable_log::program_log(&invoke_context.get_log_collector(), string);
|
||||||
stable_log::program_log(&invoke_context.get_log_collector(), string);
|
Ok(0)
|
||||||
Ok(0)
|
},
|
||||||
}
|
)?;
|
||||||
),
|
Ok(0)
|
||||||
result
|
|
||||||
);
|
|
||||||
*result = Ok(0);
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// Log 5 64-bit values
|
/// Log 5 64-bit values
|
||||||
SyscallLogU64,
|
SyscallLogU64,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
arg1: u64,
|
arg1: u64,
|
||||||
arg2: u64,
|
arg2: u64,
|
||||||
arg3: u64,
|
arg3: u64,
|
||||||
arg4: u64,
|
arg4: u64,
|
||||||
arg5: u64,
|
arg5: u64,
|
||||||
_memory_mapping: &mut MemoryMapping,
|
_memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
|
||||||
let invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
let cost = invoke_context.get_compute_budget().log_64_units;
|
let cost = invoke_context.get_compute_budget().log_64_units;
|
||||||
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
invoke_context.get_compute_meter().consume(cost)?;
|
||||||
|
|
||||||
stable_log::program_log(
|
stable_log::program_log(
|
||||||
&invoke_context.get_log_collector(),
|
&invoke_context.get_log_collector(),
|
||||||
|
@ -72,151 +55,112 @@ declare_syscall!(
|
||||||
arg1, arg2, arg3, arg4, arg5
|
arg1, arg2, arg3, arg4, arg5
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
*result = Ok(0);
|
Ok(0)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// Log current compute consumption
|
/// Log current compute consumption
|
||||||
SyscallLogBpfComputeUnits,
|
SyscallLogBpfComputeUnits,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
_arg1: u64,
|
_arg1: u64,
|
||||||
_arg2: u64,
|
_arg2: u64,
|
||||||
_arg3: u64,
|
_arg3: u64,
|
||||||
_arg4: u64,
|
_arg4: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
_memory_mapping: &mut MemoryMapping,
|
_memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
|
||||||
let invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
let cost = invoke_context.get_compute_budget().syscall_base_cost;
|
let cost = invoke_context.get_compute_budget().syscall_base_cost;
|
||||||
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
invoke_context.get_compute_meter().consume(cost)?;
|
||||||
|
|
||||||
ic_logger_msg!(
|
ic_logger_msg!(
|
||||||
invoke_context.get_log_collector(),
|
invoke_context.get_log_collector(),
|
||||||
"Program consumption: {} units remaining",
|
"Program consumption: {} units remaining",
|
||||||
invoke_context.get_compute_meter().borrow().get_remaining()
|
invoke_context.get_compute_meter().borrow().get_remaining()
|
||||||
);
|
);
|
||||||
*result = Ok(0);
|
Ok(0)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// Log 5 64-bit values
|
/// Log 5 64-bit values
|
||||||
SyscallLogPubkey,
|
SyscallLogPubkey,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
pubkey_addr: u64,
|
pubkey_addr: u64,
|
||||||
_arg2: u64,
|
_arg2: u64,
|
||||||
_arg3: u64,
|
_arg3: u64,
|
||||||
_arg4: u64,
|
_arg4: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
|
||||||
let invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
let cost = invoke_context.get_compute_budget().log_pubkey_units;
|
let cost = invoke_context.get_compute_budget().log_pubkey_units;
|
||||||
question_mark!(invoke_context.get_compute_meter().consume(cost), result);
|
invoke_context.get_compute_meter().consume(cost)?;
|
||||||
|
|
||||||
let pubkey = question_mark!(
|
let pubkey = translate_type::<Pubkey>(
|
||||||
translate_type::<Pubkey>(
|
memory_mapping,
|
||||||
memory_mapping,
|
pubkey_addr,
|
||||||
pubkey_addr,
|
invoke_context.get_check_aligned(),
|
||||||
invoke_context.get_check_aligned()
|
)?;
|
||||||
),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
stable_log::program_log(&invoke_context.get_log_collector(), &pubkey.to_string());
|
stable_log::program_log(&invoke_context.get_log_collector(), &pubkey.to_string());
|
||||||
*result = Ok(0);
|
Ok(0)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// Log data handling
|
/// Log data handling
|
||||||
SyscallLogData,
|
SyscallLogData,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
addr: u64,
|
addr: u64,
|
||||||
len: u64,
|
len: u64,
|
||||||
_arg3: u64,
|
_arg3: u64,
|
||||||
_arg4: u64,
|
_arg4: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
|
||||||
let invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
let budget = invoke_context.get_compute_budget();
|
let budget = invoke_context.get_compute_budget();
|
||||||
|
|
||||||
question_mark!(
|
invoke_context
|
||||||
invoke_context
|
.get_compute_meter()
|
||||||
.get_compute_meter()
|
.consume(budget.syscall_base_cost)?;
|
||||||
.consume(budget.syscall_base_cost),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
|
|
||||||
let untranslated_fields = question_mark!(
|
let untranslated_fields = translate_slice::<&[u8]>(
|
||||||
translate_slice::<&[u8]>(
|
memory_mapping,
|
||||||
memory_mapping,
|
addr,
|
||||||
addr,
|
len,
|
||||||
len,
|
invoke_context.get_check_aligned(),
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_size(),
|
||||||
invoke_context.get_check_size(),
|
)?;
|
||||||
),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
|
|
||||||
question_mark!(
|
invoke_context.get_compute_meter().consume(
|
||||||
invoke_context.get_compute_meter().consume(
|
budget
|
||||||
budget
|
.syscall_base_cost
|
||||||
.syscall_base_cost
|
.saturating_mul(untranslated_fields.len() as u64),
|
||||||
.saturating_mul(untranslated_fields.len() as u64)
|
)?;
|
||||||
),
|
invoke_context.get_compute_meter().consume(
|
||||||
result
|
untranslated_fields
|
||||||
);
|
.iter()
|
||||||
question_mark!(
|
.fold(0, |total, e| total.saturating_add(e.len() as u64)),
|
||||||
invoke_context.get_compute_meter().consume(
|
)?;
|
||||||
untranslated_fields
|
|
||||||
.iter()
|
|
||||||
.fold(0, |total, e| total.saturating_add(e.len() as u64))
|
|
||||||
),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut fields = Vec::with_capacity(untranslated_fields.len());
|
let mut fields = Vec::with_capacity(untranslated_fields.len());
|
||||||
|
|
||||||
for untranslated_field in untranslated_fields {
|
for untranslated_field in untranslated_fields {
|
||||||
fields.push(question_mark!(
|
fields.push(translate_slice::<u8>(
|
||||||
translate_slice::<u8>(
|
memory_mapping,
|
||||||
memory_mapping,
|
untranslated_field.as_ptr() as *const _ as u64,
|
||||||
untranslated_field.as_ptr() as *const _ as u64,
|
untranslated_field.len() as u64,
|
||||||
untranslated_field.len() as u64,
|
invoke_context.get_check_aligned(),
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_size(),
|
||||||
invoke_context.get_check_size(),
|
)?);
|
||||||
),
|
|
||||||
result
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let log_collector = invoke_context.get_log_collector();
|
let log_collector = invoke_context.get_log_collector();
|
||||||
|
|
||||||
stable_log::program_data(&log_collector, &fields);
|
stable_log::program_data(&log_collector, &fields);
|
||||||
|
|
||||||
*result = Ok(0);
|
Ok(0)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
use {super::*, crate::declare_syscall};
|
use {super::*, crate::declare_syscall};
|
||||||
|
|
||||||
fn mem_op_consume<'a, 'b>(
|
fn mem_op_consume(invoke_context: &mut InvokeContext, n: u64) -> Result<(), EbpfError> {
|
||||||
invoke_context: &Ref<&'a mut InvokeContext<'b>>,
|
|
||||||
n: u64,
|
|
||||||
) -> Result<(), EbpfError<BpfError>> {
|
|
||||||
let compute_budget = invoke_context.get_compute_budget();
|
let compute_budget = invoke_context.get_compute_budget();
|
||||||
let cost = compute_budget
|
let cost = compute_budget
|
||||||
.mem_op_base_cost
|
.mem_op_base_cost
|
||||||
|
@ -14,54 +11,40 @@ fn mem_op_consume<'a, 'b>(
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// memcpy
|
/// memcpy
|
||||||
SyscallMemcpy,
|
SyscallMemcpy,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
dst_addr: u64,
|
dst_addr: u64,
|
||||||
src_addr: u64,
|
src_addr: u64,
|
||||||
n: u64,
|
n: u64,
|
||||||
_arg4: u64,
|
_arg4: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
mem_op_consume(invoke_context, n)?;
|
||||||
let invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
question_mark!(mem_op_consume(&invoke_context, n), result);
|
|
||||||
|
|
||||||
let do_check_physical_overlapping = invoke_context
|
let do_check_physical_overlapping = invoke_context
|
||||||
.feature_set
|
.feature_set
|
||||||
.is_active(&check_physical_overlapping::id());
|
.is_active(&check_physical_overlapping::id());
|
||||||
|
|
||||||
if !is_nonoverlapping(src_addr, dst_addr, n) {
|
if !is_nonoverlapping(src_addr, dst_addr, n) {
|
||||||
*result = Err(SyscallError::CopyOverlapping.into());
|
return Err(SyscallError::CopyOverlapping.into());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let dst_ptr = question_mark!(
|
let dst_ptr = translate_slice_mut::<u8>(
|
||||||
translate_slice_mut::<u8>(
|
memory_mapping,
|
||||||
memory_mapping,
|
dst_addr,
|
||||||
dst_addr,
|
n,
|
||||||
n,
|
invoke_context.get_check_aligned(),
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_size(),
|
||||||
invoke_context.get_check_size()
|
)?
|
||||||
),
|
|
||||||
result
|
|
||||||
)
|
|
||||||
.as_mut_ptr();
|
.as_mut_ptr();
|
||||||
let src_ptr = question_mark!(
|
let src_ptr = translate_slice::<u8>(
|
||||||
translate_slice::<u8>(
|
memory_mapping,
|
||||||
memory_mapping,
|
src_addr,
|
||||||
src_addr,
|
n,
|
||||||
n,
|
invoke_context.get_check_aligned(),
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_size(),
|
||||||
invoke_context.get_check_size()
|
)?
|
||||||
),
|
|
||||||
result
|
|
||||||
)
|
|
||||||
.as_ptr();
|
.as_ptr();
|
||||||
if do_check_physical_overlapping
|
if do_check_physical_overlapping
|
||||||
&& !is_nonoverlapping(src_ptr as usize, dst_ptr as usize, n as usize)
|
&& !is_nonoverlapping(src_ptr as usize, dst_ptr as usize, n as usize)
|
||||||
|
@ -74,111 +57,82 @@ declare_syscall!(
|
||||||
std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, n as usize);
|
std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, n as usize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*result = Ok(0);
|
Ok(0)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// memmove
|
/// memmove
|
||||||
SyscallMemmove,
|
SyscallMemmove,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
dst_addr: u64,
|
dst_addr: u64,
|
||||||
src_addr: u64,
|
src_addr: u64,
|
||||||
n: u64,
|
n: u64,
|
||||||
_arg4: u64,
|
_arg4: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
mem_op_consume(invoke_context, n)?;
|
||||||
let invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
question_mark!(mem_op_consume(&invoke_context, n), result);
|
|
||||||
|
|
||||||
let dst = question_mark!(
|
let dst = translate_slice_mut::<u8>(
|
||||||
translate_slice_mut::<u8>(
|
memory_mapping,
|
||||||
memory_mapping,
|
dst_addr,
|
||||||
dst_addr,
|
n,
|
||||||
n,
|
invoke_context.get_check_aligned(),
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_size(),
|
||||||
invoke_context.get_check_size()
|
)?;
|
||||||
),
|
let src = translate_slice::<u8>(
|
||||||
result
|
memory_mapping,
|
||||||
);
|
src_addr,
|
||||||
let src = question_mark!(
|
n,
|
||||||
translate_slice::<u8>(
|
invoke_context.get_check_aligned(),
|
||||||
memory_mapping,
|
invoke_context.get_check_size(),
|
||||||
src_addr,
|
)?;
|
||||||
n,
|
|
||||||
invoke_context.get_check_aligned(),
|
|
||||||
invoke_context.get_check_size()
|
|
||||||
),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
std::ptr::copy(src.as_ptr(), dst.as_mut_ptr(), n as usize);
|
std::ptr::copy(src.as_ptr(), dst.as_mut_ptr(), n as usize);
|
||||||
}
|
}
|
||||||
*result = Ok(0);
|
Ok(0)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// memcmp
|
/// memcmp
|
||||||
SyscallMemcmp,
|
SyscallMemcmp,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
s1_addr: u64,
|
s1_addr: u64,
|
||||||
s2_addr: u64,
|
s2_addr: u64,
|
||||||
n: u64,
|
n: u64,
|
||||||
cmp_result_addr: u64,
|
cmp_result_addr: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
mem_op_consume(invoke_context, n)?;
|
||||||
let invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
question_mark!(mem_op_consume(&invoke_context, n), result);
|
|
||||||
|
|
||||||
let s1 = question_mark!(
|
let s1 = translate_slice::<u8>(
|
||||||
translate_slice::<u8>(
|
memory_mapping,
|
||||||
memory_mapping,
|
s1_addr,
|
||||||
s1_addr,
|
n,
|
||||||
n,
|
invoke_context.get_check_aligned(),
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_size(),
|
||||||
invoke_context.get_check_size(),
|
)?;
|
||||||
),
|
let s2 = translate_slice::<u8>(
|
||||||
result
|
memory_mapping,
|
||||||
);
|
s2_addr,
|
||||||
let s2 = question_mark!(
|
n,
|
||||||
translate_slice::<u8>(
|
invoke_context.get_check_aligned(),
|
||||||
memory_mapping,
|
invoke_context.get_check_size(),
|
||||||
s2_addr,
|
)?;
|
||||||
n,
|
let cmp_result = translate_type_mut::<i32>(
|
||||||
invoke_context.get_check_aligned(),
|
memory_mapping,
|
||||||
invoke_context.get_check_size(),
|
cmp_result_addr,
|
||||||
),
|
invoke_context.get_check_aligned(),
|
||||||
result
|
)?;
|
||||||
);
|
|
||||||
let cmp_result = question_mark!(
|
|
||||||
translate_type_mut::<i32>(
|
|
||||||
memory_mapping,
|
|
||||||
cmp_result_addr,
|
|
||||||
invoke_context.get_check_aligned()
|
|
||||||
),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
while i < n as usize {
|
while i < n as usize {
|
||||||
let a = *question_mark!(s1.get(i).ok_or(SyscallError::InvalidLength,), result);
|
let a = *s1.get(i).ok_or(SyscallError::InvalidLength)?;
|
||||||
let b = *question_mark!(s2.get(i).ok_or(SyscallError::InvalidLength,), result);
|
let b = *s2.get(i).ok_or(SyscallError::InvalidLength)?;
|
||||||
if a != b {
|
if a != b {
|
||||||
*cmp_result = if invoke_context
|
*cmp_result = if invoke_context
|
||||||
.feature_set
|
.feature_set
|
||||||
|
@ -191,50 +145,39 @@ declare_syscall!(
|
||||||
a as i32 - b as i32
|
a as i32 - b as i32
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
*result = Ok(0);
|
return Ok(0);
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
i = i.saturating_add(1);
|
i = i.saturating_add(1);
|
||||||
}
|
}
|
||||||
*cmp_result = 0;
|
*cmp_result = 0;
|
||||||
*result = Ok(0);
|
Ok(0)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// memset
|
/// memset
|
||||||
SyscallMemset,
|
SyscallMemset,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
s_addr: u64,
|
s_addr: u64,
|
||||||
c: u64,
|
c: u64,
|
||||||
n: u64,
|
n: u64,
|
||||||
_arg4: u64,
|
_arg4: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
mem_op_consume(invoke_context, n)?;
|
||||||
let invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
question_mark!(mem_op_consume(&invoke_context, n), result);
|
|
||||||
|
|
||||||
let s = question_mark!(
|
let s = translate_slice_mut::<u8>(
|
||||||
translate_slice_mut::<u8>(
|
memory_mapping,
|
||||||
memory_mapping,
|
s_addr,
|
||||||
s_addr,
|
n,
|
||||||
n,
|
invoke_context.get_check_aligned(),
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_size(),
|
||||||
invoke_context.get_check_size(),
|
)?;
|
||||||
),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
for val in s.iter_mut().take(n as usize) {
|
for val in s.iter_mut().take(n as usize) {
|
||||||
*val = c as u8;
|
*val = c as u8;
|
||||||
}
|
}
|
||||||
*result = Ok(0);
|
Ok(0)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -6,7 +6,7 @@ fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId + Clone>(
|
||||||
check_aligned: bool,
|
check_aligned: bool,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<u64, EbpfError<BpfError>> {
|
) -> Result<u64, EbpfError> {
|
||||||
invoke_context.get_compute_meter().consume(
|
invoke_context.get_compute_meter().consume(
|
||||||
invoke_context
|
invoke_context
|
||||||
.get_compute_budget()
|
.get_compute_budget()
|
||||||
|
@ -24,89 +24,68 @@ fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId + Clone>(
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// Get a Clock sysvar
|
/// Get a Clock sysvar
|
||||||
SyscallGetClockSysvar,
|
SyscallGetClockSysvar,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
var_addr: u64,
|
var_addr: u64,
|
||||||
_arg2: u64,
|
_arg2: u64,
|
||||||
_arg3: u64,
|
_arg3: u64,
|
||||||
_arg4: u64,
|
_arg4: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
get_sysvar(
|
||||||
let mut invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow_mut()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
*result = get_sysvar(
|
|
||||||
invoke_context.get_sysvar_cache().get_clock(),
|
invoke_context.get_sysvar_cache().get_clock(),
|
||||||
var_addr,
|
var_addr,
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_aligned(),
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
&mut invoke_context,
|
invoke_context,
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// Get a EpochSchedule sysvar
|
/// Get a EpochSchedule sysvar
|
||||||
SyscallGetEpochScheduleSysvar,
|
SyscallGetEpochScheduleSysvar,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
var_addr: u64,
|
var_addr: u64,
|
||||||
_arg2: u64,
|
_arg2: u64,
|
||||||
_arg3: u64,
|
_arg3: u64,
|
||||||
_arg4: u64,
|
_arg4: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
get_sysvar(
|
||||||
let mut invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow_mut()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
*result = get_sysvar(
|
|
||||||
invoke_context.get_sysvar_cache().get_epoch_schedule(),
|
invoke_context.get_sysvar_cache().get_epoch_schedule(),
|
||||||
var_addr,
|
var_addr,
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_aligned(),
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
&mut invoke_context,
|
invoke_context,
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// Get a Fees sysvar
|
/// Get a Fees sysvar
|
||||||
SyscallGetFeesSysvar,
|
SyscallGetFeesSysvar,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
var_addr: u64,
|
var_addr: u64,
|
||||||
_arg2: u64,
|
_arg2: u64,
|
||||||
_arg3: u64,
|
_arg3: u64,
|
||||||
_arg4: u64,
|
_arg4: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
|
||||||
let mut invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow_mut()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
{
|
{
|
||||||
*result = get_sysvar(
|
get_sysvar(
|
||||||
invoke_context.get_sysvar_cache().get_fees(),
|
invoke_context.get_sysvar_cache().get_fees(),
|
||||||
var_addr,
|
var_addr,
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_aligned(),
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
&mut invoke_context,
|
invoke_context,
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -114,28 +93,21 @@ declare_syscall!(
|
||||||
declare_syscall!(
|
declare_syscall!(
|
||||||
/// Get a Rent sysvar
|
/// Get a Rent sysvar
|
||||||
SyscallGetRentSysvar,
|
SyscallGetRentSysvar,
|
||||||
fn call(
|
fn inner_call(
|
||||||
&mut self,
|
invoke_context: &mut InvokeContext,
|
||||||
var_addr: u64,
|
var_addr: u64,
|
||||||
_arg2: u64,
|
_arg2: u64,
|
||||||
_arg3: u64,
|
_arg3: u64,
|
||||||
_arg4: u64,
|
_arg4: u64,
|
||||||
_arg5: u64,
|
_arg5: u64,
|
||||||
memory_mapping: &mut MemoryMapping,
|
memory_mapping: &mut MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
) -> Result<u64, EbpfError> {
|
||||||
) {
|
get_sysvar(
|
||||||
let mut invoke_context = question_mark!(
|
|
||||||
self.invoke_context
|
|
||||||
.try_borrow_mut()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
|
||||||
result
|
|
||||||
);
|
|
||||||
*result = get_sysvar(
|
|
||||||
invoke_context.get_sysvar_cache().get_rent(),
|
invoke_context.get_sysvar_cache().get_rent(),
|
||||||
var_addr,
|
var_addr,
|
||||||
invoke_context.get_check_aligned(),
|
invoke_context.get_check_aligned(),
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
&mut invoke_context,
|
invoke_context,
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -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 = "=0.2.33"
|
solana_rbpf = "=0.2.34"
|
||||||
|
|
|
@ -3,7 +3,7 @@ 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, BpfError,
|
create_vm, serialization::serialize_parameters, syscalls::register_syscalls,
|
||||||
ThisInstructionMeter,
|
ThisInstructionMeter,
|
||||||
},
|
},
|
||||||
solana_program_runtime::invoke_context::{prepare_mock_invoke_context, InvokeContext},
|
solana_program_runtime::invoke_context::{prepare_mock_invoke_context, InvokeContext},
|
||||||
|
@ -254,10 +254,10 @@ native machine code before execting it in the virtual machine.",
|
||||||
file.read_to_end(&mut contents).unwrap();
|
file.read_to_end(&mut contents).unwrap();
|
||||||
let syscall_registry = register_syscalls(&mut invoke_context, true).unwrap();
|
let syscall_registry = register_syscalls(&mut invoke_context, true).unwrap();
|
||||||
let executable = if magic == [0x7f, 0x45, 0x4c, 0x46] {
|
let executable = if magic == [0x7f, 0x45, 0x4c, 0x46] {
|
||||||
Executable::<BpfError, ThisInstructionMeter>::from_elf(&contents, config, syscall_registry)
|
Executable::<ThisInstructionMeter>::from_elf(&contents, config, syscall_registry)
|
||||||
.map_err(|err| format!("Executable constructor failed: {:?}", err))
|
.map_err(|err| format!("Executable constructor failed: {:?}", err))
|
||||||
} else {
|
} else {
|
||||||
assemble::<BpfError, ThisInstructionMeter>(
|
assemble::<ThisInstructionMeter>(
|
||||||
std::str::from_utf8(contents.as_slice()).unwrap(),
|
std::str::from_utf8(contents.as_slice()).unwrap(),
|
||||||
config,
|
config,
|
||||||
syscall_registry,
|
syscall_registry,
|
||||||
|
@ -266,11 +266,9 @@ native machine code before execting it in the virtual machine.",
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut verified_executable =
|
let mut verified_executable =
|
||||||
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
|
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(executable)
|
||||||
executable,
|
.map_err(|err| format!("Executable verifier failed: {:?}", err))
|
||||||
)
|
.unwrap();
|
||||||
.map_err(|err| format!("Executable verifier failed: {:?}", err))
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
verified_executable.jit_compile().unwrap();
|
verified_executable.jit_compile().unwrap();
|
||||||
let mut analysis = LazyAnalysis::new(verified_executable.get_executable());
|
let mut analysis = LazyAnalysis::new(verified_executable.get_executable());
|
||||||
|
@ -310,13 +308,14 @@ native machine code before execting it in the virtual machine.",
|
||||||
if matches.is_present("trace") {
|
if matches.is_present("trace") {
|
||||||
eprintln!("Trace is saved in trace.out");
|
eprintln!("Trace is saved in trace.out");
|
||||||
let mut file = File::create("trace.out").unwrap();
|
let mut file = File::create("trace.out").unwrap();
|
||||||
vm.get_tracer()
|
vm.get_program_environment()
|
||||||
|
.tracer
|
||||||
.write(&mut file, analysis.analyze())
|
.write(&mut file, analysis.analyze())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
if matches.is_present("profile") {
|
if matches.is_present("profile") {
|
||||||
eprintln!("Profile is saved in profile.dot");
|
eprintln!("Profile is saved in profile.dot");
|
||||||
let tracer = &vm.get_tracer();
|
let tracer = &vm.get_program_environment().tracer;
|
||||||
let analysis = analysis.analyze();
|
let analysis = analysis.analyze();
|
||||||
let dynamic_analysis = DynamicAnalysis::new(tracer, analysis);
|
let dynamic_analysis = DynamicAnalysis::new(tracer, analysis);
|
||||||
let mut file = File::create("profile.dot").unwrap();
|
let mut file = File::create("profile.dot").unwrap();
|
||||||
|
@ -376,19 +375,19 @@ 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> {
|
struct LazyAnalysis<'a> {
|
||||||
analysis: Option<Analysis<'a, BpfError, ThisInstructionMeter>>,
|
analysis: Option<Analysis<'a, ThisInstructionMeter>>,
|
||||||
executable: &'a Executable<BpfError, ThisInstructionMeter>,
|
executable: &'a Executable<ThisInstructionMeter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LazyAnalysis<'a> {
|
impl<'a> LazyAnalysis<'a> {
|
||||||
fn new(executable: &'a Executable<BpfError, ThisInstructionMeter>) -> Self {
|
fn new(executable: &'a Executable<ThisInstructionMeter>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
analysis: None,
|
analysis: None,
|
||||||
executable,
|
executable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn analyze(&mut self) -> &Analysis<BpfError, ThisInstructionMeter> {
|
fn analyze(&mut self) -> &Analysis<ThisInstructionMeter> {
|
||||||
if let Some(ref analysis) = self.analysis {
|
if let Some(ref analysis) = self.analysis {
|
||||||
return analysis;
|
return analysis;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue