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:
Alexander Meißner 2022-10-06 20:31:58 +02:00 committed by GitHub
parent 66cd290d04
commit 30b0a13ba9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 1339 additions and 1806 deletions

4
Cargo.lock generated
View File

@ -6806,9 +6806,9 @@ dependencies = [
[[package]]
name = "solana_rbpf"
version = "0.2.33"
version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b13ec17b58709d07634895dbca4cae6bebeaddf3b83bf4fa8dfeaf3621222347"
checksum = "334bb11faee82f0306e39944cb4ac85824b7d261f3d99d1f2f8bd09851644f0b"
dependencies = [
"byteorder",
"combine",

View File

@ -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-version = { path = "../version", 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"] }
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, BpfError, ThisInstructionMeter},
solana_bpf_loader_program::{syscalls::register_syscalls, ThisInstructionMeter},
solana_clap_utils::{self, input_parsers::*, input_validators::*, keypair::*},
solana_cli_output::{
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, &[]);
// Verify the program
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
let executable = Executable::<ThisInstructionMeter>::from_elf(
&program_data,
Config {
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))?;
let _ =
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
executable,
)
.map_err(|err| format!("ELF error: {}", err))?;
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(executable)
.map_err(|err| format!("ELF error: {}", err))?;
Ok(program_data)
}

View File

@ -6000,9 +6000,9 @@ dependencies = [
[[package]]
name = "solana_rbpf"
version = "0.2.33"
version = "0.2.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b13ec17b58709d07634895dbca4cae6bebeaddf3b83bf4fa8dfeaf3621222347"
checksum = "334bb11faee82f0306e39944cb4ac85824b7d261f3d99d1f2f8bd09851644f0b"
dependencies = [
"byteorder 1.4.3",
"combine",

View File

@ -38,7 +38,7 @@ solana-program-runtime = { path = "../../program-runtime", version = "=1.15.0" }
solana-runtime = { path = "../../runtime", 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.33"
solana_rbpf = "=0.2.34"
[dev-dependencies]
solana-ledger = { path = "../../ledger", version = "=1.15.0" }

View File

@ -8,7 +8,7 @@ extern crate solana_bpf_loader_program;
use {
byteorder::{ByteOrder, LittleEndian, WriteBytesExt},
solana_bpf_loader_program::{
create_vm, serialization::serialize_parameters, syscalls::register_syscalls, BpfError,
create_vm, serialization::serialize_parameters, syscalls::register_syscalls,
ThisInstructionMeter,
},
solana_measure::measure::Measure,
@ -81,7 +81,7 @@ fn bench_program_create_executable(bencher: &mut Bencher) {
let elf = load_elf("bench_alu").unwrap();
bencher.iter(|| {
let _ = Executable::<BpfError, ThisInstructionMeter>::from_elf(
let _ = Executable::<ThisInstructionMeter>::from_elf(
&elf,
Config::default(),
SyscallRegistry::default(),
@ -106,19 +106,18 @@ fn bench_program_alu(bencher: &mut Bencher) {
.get_compute_meter()
.borrow_mut()
.mock_set_remaining(std::i64::MAX as u64);
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
let executable = Executable::<ThisInstructionMeter>::from_elf(
&elf,
Config::default(),
register_syscalls(invoke_context, true).unwrap(),
)
.unwrap();
let mut verified_executable = VerifiedExecutable::<
RequisiteVerifier,
BpfError,
ThisInstructionMeter,
>::from_executable(executable)
.unwrap();
let mut verified_executable =
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
executable,
)
.unwrap();
verified_executable.jit_compile().unwrap();
let compute_meter = invoke_context.get_compute_meter();
@ -235,19 +234,18 @@ fn bench_create_vm(bencher: &mut Bencher) {
)
.unwrap();
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
let executable = Executable::<ThisInstructionMeter>::from_elf(
&elf,
Config::default(),
register_syscalls(invoke_context, true).unwrap(),
)
.unwrap();
let verified_executable = VerifiedExecutable::<
RequisiteVerifier,
BpfError,
ThisInstructionMeter,
>::from_executable(executable)
.unwrap();
let verified_executable =
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
executable,
)
.unwrap();
bencher.iter(|| {
let _ = create_vm(
@ -283,19 +281,18 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
)
.unwrap();
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
let executable = Executable::<ThisInstructionMeter>::from_elf(
&elf,
Config::default(),
register_syscalls(invoke_context, true).unwrap(),
)
.unwrap();
let verified_executable = VerifiedExecutable::<
RequisiteVerifier,
BpfError,
ThisInstructionMeter,
>::from_executable(executable)
.unwrap();
let verified_executable =
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
executable,
)
.unwrap();
let compute_meter = invoke_context.get_compute_meter();
let mut instruction_meter = ThisInstructionMeter { compute_meter };

View File

@ -55,7 +55,7 @@ use {
create_vm,
serialization::{deserialize_parameters, serialize_parameters},
syscalls::register_syscalls,
BpfError, ThisInstructionMeter,
ThisInstructionMeter,
},
solana_program_runtime::invoke_context::with_mock_invoke_context,
solana_rbpf::{
@ -241,7 +241,7 @@ fn run_program(name: &str) -> u64 {
reject_broken_elfs: true,
..Config::default()
};
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
let executable = Executable::<ThisInstructionMeter>::from_elf(
&data,
config,
register_syscalls(invoke_context, true /* no sol_alloc_free */).unwrap(),
@ -249,12 +249,11 @@ fn run_program(name: &str) -> u64 {
.unwrap();
#[allow(unused_mut)]
let mut verified_executable = VerifiedExecutable::<
RequisiteVerifier,
BpfError,
ThisInstructionMeter,
>::from_executable(executable)
.unwrap();
let mut verified_executable =
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(
executable,
)
.unwrap();
let run_program_iterations = {
#[cfg(target_arch = "x86_64")]
@ -300,7 +299,10 @@ fn run_program(name: &str) -> u64 {
instruction_count = vm.get_total_instruction_count();
if config.enable_instruction_tracing {
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 =
Analysis::from_executable(verified_executable.get_executable())
.unwrap();
@ -312,7 +314,8 @@ fn run_program(name: &str) -> u64 {
.write(&mut stdout.lock(), &analysis)
.unwrap();
println!("TRACE (jit):");
vm.get_tracer()
vm.get_program_environment()
.tracer
.write(&mut stdout.lock(), &analysis)
.unwrap();
assert!(false);
@ -330,7 +333,7 @@ fn run_program(name: &str) -> u64 {
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(

View File

@ -19,7 +19,7 @@ solana-metrics = { path = "../../metrics", 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.33"
solana_rbpf = "=0.2.34"
thiserror = "1.0"
[dev-dependencies]

View File

@ -14,6 +14,7 @@ extern crate solana_metrics;
use {
crate::{
allocator_bump::BpfAllocator,
serialization::{deserialize_parameters, serialize_parameters},
syscalls::SyscallError,
},
@ -28,13 +29,13 @@ use {
},
solana_rbpf::{
aligned_memory::AlignedMemory,
ebpf::{HOST_ALIGN, MM_INPUT_START},
ebpf::{HOST_ALIGN, MM_HEAP_START, MM_INPUT_START},
elf::Executable,
error::{EbpfError, UserDefinedError},
memory_region::MemoryRegion,
static_analysis::Analysis,
verifier::{RequisiteVerifier, VerifierError},
vm::{Config, EbpfVm, InstructionMeter, VerifiedExecutable},
vm::{Config, EbpfVm, InstructionMeter, ProgramResult, VerifiedExecutable},
},
solana_sdk::{
bpf_loader, bpf_loader_deprecated,
@ -42,9 +43,10 @@ use {
entrypoint::{HEAP_LENGTH, SUCCESS},
feature_set::{
cap_accounts_data_allocations_per_transaction, cap_bpf_program_instruction_accounts,
disable_deploy_of_alloc_free_syscall, disable_deprecated_loader,
enable_bpf_loader_extend_program_ix, error_on_syscall_bpf_function_hash_collisions,
limit_max_instruction_trace_length, reject_callx_r10,
check_slice_translation_size, disable_deploy_of_alloc_free_syscall,
disable_deprecated_loader, enable_bpf_loader_extend_program_ix,
error_on_syscall_bpf_function_hash_collisions, limit_max_instruction_trace_length,
reject_callx_r10,
},
instruction::{AccountMeta, InstructionError},
loader_instruction::LoaderInstruction,
@ -80,7 +82,7 @@ pub enum 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);
InstructionError::InvalidAccountData
}
@ -201,7 +203,7 @@ pub fn create_executor(
)?;
create_executor_metrics.program_id = programdata.get_key().to_string();
let mut load_elf_time = Measure::start("load_elf_time");
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
let executable = Executable::<ThisInstructionMeter>::from_elf(
programdata
.get_data()
.get(programdata_offset..)
@ -220,10 +222,8 @@ pub fn create_executor(
.map_err(|e| map_ebpf_error(invoke_context, e))?;
let mut verify_code_time = Measure::start("verify_code_time");
let mut verified_executable =
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
executable,
)
.map_err(|e| map_ebpf_error(invoke_context, e))?;
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(executable)
.map_err(|e| map_ebpf_error(invoke_context, e))?;
verify_code_time.stop();
create_executor_metrics.verify_code_us = verify_code_time.as_us();
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
pub fn create_vm<'a, 'b>(
program: &'a VerifiedExecutable<RequisiteVerifier, BpfError, ThisInstructionMeter>,
program: &'a VerifiedExecutable<RequisiteVerifier, ThisInstructionMeter>,
parameter_bytes: &mut [u8],
orig_account_lengths: Vec<usize>,
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 heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
let _ = invoke_context.get_compute_meter().borrow_mut().consume(
@ -304,8 +304,33 @@ pub fn create_vm<'a, 'b>(
let mut heap =
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 mut vm = EbpfVm::new(program, heap.as_slice_mut(), vec![parameter_region])?;
syscalls::bind_syscall_context_objects(&mut vm, invoke_context, heap, orig_account_lengths)?;
let vm = EbpfVm::new(
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)
}
@ -1281,7 +1306,7 @@ impl InstructionMeter for ThisInstructionMeter {
/// BPF Loader's Executor implementation
pub struct BpfExecutor {
verified_executable: VerifiedExecutable<RequisiteVerifier, BpfError, ThisInstructionMeter>,
verified_executable: VerifiedExecutable<RequisiteVerifier, ThisInstructionMeter>,
use_jit: bool,
}
@ -1353,7 +1378,10 @@ impl Executor for BpfExecutor {
let mut trace_buffer = Vec::<u8>::new();
let analysis =
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();
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);
}
match result {
Ok(status) if status != SUCCESS => {
ProgramResult::Ok(status) if status != SUCCESS => {
let error: InstructionError = if (status
== MAX_ACCOUNTS_DATA_ALLOCATIONS_EXCEEDED
&& !invoke_context
@ -1386,11 +1414,24 @@ impl Executor for BpfExecutor {
stable_log::program_failure(&log_collector, &program_id, &error);
Err(error)
}
Err(error) => {
ProgramResult::Err(error) => {
let error = match error {
EbpfError::UserError(BpfError::SyscallError(
SyscallError::InstructionError(error),
)) => error,
/*EbpfError::UserError(user_error) if let BpfError::SyscallError(
SyscallError::InstructionError(instruction_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 => {
ic_logger_msg!(log_collector, "Program failed to complete: {}", err);
InstructionError::ProgramFailedToComplete
@ -1536,21 +1577,21 @@ mod tests {
"entrypoint",
)
.unwrap();
let executable = Executable::<BpfError, TestInstructionMeter>::from_text_bytes(
let executable = Executable::<TestInstructionMeter>::from_text_bytes(
program,
config,
syscall_registry,
bpf_functions,
)
.unwrap();
let verified_executable = VerifiedExecutable::<
TautologyVerifier,
BpfError,
TestInstructionMeter,
>::from_executable(executable)
.unwrap();
let verified_executable =
VerifiedExecutable::<TautologyVerifier, TestInstructionMeter>::from_executable(
executable,
)
.unwrap();
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 };
vm.execute_program_interpreted(&mut instruction_meter)
.unwrap();

View File

@ -23,71 +23,59 @@ struct CallerAccount<'a> {
type TranslatedAccounts<'a> = Vec<(IndexOfAccount, Option<CallerAccount<'a>>)>;
/// Implemented by language specific data structure translators
trait SyscallInvokeSigned<'a, 'b> {
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>>;
trait SyscallInvokeSigned {
fn translate_instruction(
&self,
addr: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &mut InvokeContext,
) -> Result<Instruction, EbpfError<BpfError>>;
fn translate_accounts<'c>(
&'c self,
) -> Result<Instruction, EbpfError>;
fn translate_accounts<'a>(
instruction_accounts: &[InstructionAccount],
program_indices: &[IndexOfAccount],
account_infos_addr: u64,
account_infos_len: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &mut InvokeContext,
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>>;
) -> Result<TranslatedAccounts<'a>, EbpfError>;
fn translate_signers(
&self,
program_id: &Pubkey,
signers_seeds_addr: u64,
signers_seeds_len: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &InvokeContext,
) -> Result<Vec<Pubkey>, EbpfError<BpfError>>;
) -> Result<Vec<Pubkey>, EbpfError>;
}
declare_syscall!(
/// Cross-program invocation called from Rust
SyscallInvokeSignedRust,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
instruction_addr: u64,
account_infos_addr: u64,
account_infos_len: u64,
signers_seeds_addr: u64,
signers_seeds_len: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
*result = call(
self,
) -> Result<u64, EbpfError> {
cpi_common::<Self>(
invoke_context,
instruction_addr,
account_infos_addr,
account_infos_len,
signers_seeds_addr,
signers_seeds_len,
memory_mapping,
);
)
}
);
impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>> {
self.invoke_context
.try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
}
impl SyscallInvokeSigned for SyscallInvokeSignedRust {
fn translate_instruction(
&self,
addr: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &mut InvokeContext,
) -> Result<Instruction, EbpfError<BpfError>> {
) -> Result<Instruction, EbpfError> {
let ix = translate_type::<Instruction>(
memory_mapping,
addr,
@ -131,15 +119,14 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
})
}
fn translate_accounts<'c>(
&'c self,
fn translate_accounts<'a>(
instruction_accounts: &[InstructionAccount],
program_indices: &[IndexOfAccount],
account_infos_addr: u64,
account_infos_len: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &mut InvokeContext,
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>> {
) -> Result<TranslatedAccounts<'a>, EbpfError> {
let account_infos = translate_slice::<AccountInfo>(
memory_mapping,
account_infos_addr,
@ -157,7 +144,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
invoke_context.get_check_aligned(),
)
})
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
.collect::<Result<Vec<_>, EbpfError>>()?;
let translate = |account_info: &AccountInfo, invoke_context: &InvokeContext| {
// Translate the account from user space
@ -235,13 +222,12 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedRust<'a, 'b> {
}
fn translate_signers(
&self,
program_id: &Pubkey,
signers_seeds_addr: u64,
signers_seeds_len: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &InvokeContext,
) -> Result<Vec<Pubkey>, EbpfError<BpfError>> {
) -> Result<Vec<Pubkey>, EbpfError> {
let mut signers = Vec::new();
if signers_seeds_len > 0 {
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(),
)
})
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
.collect::<Result<Vec<_>, EbpfError>>()?;
let signer = Pubkey::create_program_address(&seeds, program_id)
.map_err(SyscallError::BadSeeds)?;
signers.push(signer);
@ -347,41 +333,33 @@ struct SolSignerSeedsC {
declare_syscall!(
/// Cross-program invocation called from C
SyscallInvokeSignedC,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
instruction_addr: u64,
account_infos_addr: u64,
account_infos_len: u64,
signers_seeds_addr: u64,
signers_seeds_len: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
*result = call(
self,
) -> Result<u64, EbpfError> {
cpi_common::<Self>(
invoke_context,
instruction_addr,
account_infos_addr,
account_infos_len,
signers_seeds_addr,
signers_seeds_len,
memory_mapping,
);
)
}
);
impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
fn get_context_mut(&self) -> Result<RefMut<&'a mut InvokeContext<'b>>, EbpfError<BpfError>> {
self.invoke_context
.try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
}
impl SyscallInvokeSigned for SyscallInvokeSignedC {
fn translate_instruction(
&self,
addr: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &mut InvokeContext,
) -> Result<Instruction, EbpfError<BpfError>> {
) -> Result<Instruction, EbpfError> {
let ix_c = translate_type::<SolInstruction>(
memory_mapping,
addr,
@ -439,7 +417,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
is_writable: meta_c.is_writable,
})
})
.collect::<Result<Vec<AccountMeta>, EbpfError<BpfError>>>()?;
.collect::<Result<Vec<AccountMeta>, EbpfError>>()?;
Ok(Instruction {
program_id: *program_id,
@ -448,15 +426,14 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
})
}
fn translate_accounts<'c>(
&'c self,
fn translate_accounts<'a>(
instruction_accounts: &[InstructionAccount],
program_indices: &[IndexOfAccount],
account_infos_addr: u64,
account_infos_len: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &mut InvokeContext,
) -> Result<TranslatedAccounts<'c>, EbpfError<BpfError>> {
) -> Result<TranslatedAccounts<'a>, EbpfError> {
let account_infos = translate_slice::<SolAccountInfo>(
memory_mapping,
account_infos_addr,
@ -474,7 +451,7 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
invoke_context.get_check_aligned(),
)
})
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
.collect::<Result<Vec<_>, EbpfError>>()?;
let translate = |account_info: &SolAccountInfo, invoke_context: &InvokeContext| {
// Translate the account from user space
@ -551,13 +528,12 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
}
fn translate_signers(
&self,
program_id: &Pubkey,
signers_seeds_addr: u64,
signers_seeds_len: u64,
memory_mapping: &mut MemoryMapping,
invoke_context: &InvokeContext,
) -> Result<Vec<Pubkey>, EbpfError<BpfError>> {
) -> Result<Vec<Pubkey>, EbpfError> {
if signers_seeds_len > 0 {
let signers_seeds = translate_slice::<SolSignerSeedsC>(
memory_mapping,
@ -596,11 +572,11 @@ impl<'a, 'b> SyscallInvokeSigned<'a, 'b> for SyscallInvokeSignedC<'a, 'b> {
invoke_context.get_check_size(),
)
})
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?;
.collect::<Result<Vec<_>, EbpfError>>()?;
Pubkey::create_program_address(&seeds_bytes, program_id)
.map_err(|err| SyscallError::BadSeeds(err).into())
})
.collect::<Result<Vec<_>, EbpfError<BpfError>>>()?)
.collect::<Result<Vec<_>, EbpfError>>()?)
} else {
Ok(vec![])
}
@ -614,9 +590,9 @@ fn get_translated_accounts<'a, T, F>(
account_infos: &[T],
invoke_context: &mut InvokeContext,
do_translate: F,
) -> Result<TranslatedAccounts<'a>, EbpfError<BpfError>>
) -> Result<TranslatedAccounts<'a>, EbpfError>
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 instruction_context = transaction_context
@ -686,9 +662,9 @@ where
.set_data_from_slice(caller_account.data)
.map_err(SyscallError::InstructionError)?,
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),
)));
))));
}
_ => {}
}
@ -764,7 +740,7 @@ fn check_instruction_size(
num_accounts: usize,
data_len: usize,
invoke_context: &mut InvokeContext,
) -> Result<(), EbpfError<BpfError>> {
) -> Result<(), EbpfError> {
if invoke_context
.feature_set
.is_active(&feature_set::loosen_cpi_size_restriction::id())
@ -803,7 +779,7 @@ fn check_instruction_size(
fn check_account_infos(
num_account_infos: usize,
invoke_context: &mut InvokeContext,
) -> Result<(), EbpfError<BpfError>> {
) -> Result<(), EbpfError> {
if invoke_context
.feature_set
.is_active(&feature_set::loosen_cpi_size_restriction::id())
@ -850,7 +826,7 @@ fn check_authorized_program(
program_id: &Pubkey,
instruction_data: &[u8],
invoke_context: &InvokeContext,
) -> Result<(), EbpfError<BpfError>> {
) -> Result<(), EbpfError> {
if native_loader::check_id(program_id)
|| bpf_loader::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
fn call<'a, 'b: 'a>(
syscall: &mut dyn SyscallInvokeSigned<'a, 'b>,
fn cpi_common<S: SyscallInvokeSigned>(
invoke_context: &mut InvokeContext,
instruction_addr: u64,
account_infos_addr: u64,
account_infos_len: u64,
signers_seeds_addr: u64,
signers_seeds_len: u64,
memory_mapping: &mut MemoryMapping,
) -> Result<u64, EbpfError<BpfError>> {
let mut invoke_context = syscall.get_context_mut()?;
) -> Result<u64, EbpfError> {
invoke_context
.get_compute_meter()
.consume(invoke_context.get_compute_budget().invoke_units)?;
// Translate and verify caller's data
let instruction =
syscall.translate_instruction(instruction_addr, memory_mapping, *invoke_context)?;
let instruction = S::translate_instruction(instruction_addr, memory_mapping, invoke_context)?;
let transaction_context = &invoke_context.transaction_context;
let instruction_context = transaction_context
.get_current_instruction_context()
@ -892,24 +866,24 @@ fn call<'a, 'b: 'a>(
let caller_program_id = instruction_context
.get_last_program_key(transaction_context)
.map_err(SyscallError::InstructionError)?;
let signers = syscall.translate_signers(
let signers = S::translate_signers(
caller_program_id,
signers_seeds_addr,
signers_seeds_len,
memory_mapping,
*invoke_context,
invoke_context,
)?;
let (instruction_accounts, program_indices) = invoke_context
.prepare_instruction(&instruction, &signers)
.map_err(SyscallError::InstructionError)?;
check_authorized_program(&instruction.program_id, &instruction.data, *invoke_context)?;
let mut accounts = syscall.translate_accounts(
check_authorized_program(&instruction.program_id, &instruction.data, invoke_context)?;
let mut accounts = S::translate_accounts(
&instruction_accounts,
&program_indices,
account_infos_addr,
account_infos_len,
memory_mapping,
*invoke_context,
invoke_context,
)?;
// Process instruction

View File

@ -3,67 +3,50 @@ use {super::*, crate::declare_syscall};
declare_syscall!(
/// Log a user's info message
SyscallLog,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
addr: u64,
len: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let invoke_context = question_mark!(
self.invoke_context
.try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
) -> Result<u64, EbpfError> {
let cost = invoke_context
.get_compute_budget()
.syscall_base_cost
.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(
memory_mapping,
addr,
len,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
&mut |string: &str| {
stable_log::program_log(&invoke_context.get_log_collector(), string);
Ok(0)
}
),
result
);
*result = Ok(0);
translate_string_and_do(
memory_mapping,
addr,
len,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
&mut |string: &str| {
stable_log::program_log(&invoke_context.get_log_collector(), string);
Ok(0)
},
)?;
Ok(0)
}
);
declare_syscall!(
/// Log 5 64-bit values
SyscallLogU64,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
arg1: u64,
arg2: u64,
arg3: u64,
arg4: u64,
arg5: u64,
_memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let invoke_context = question_mark!(
self.invoke_context
.try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
) -> Result<u64, EbpfError> {
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(
&invoke_context.get_log_collector(),
@ -72,151 +55,112 @@ declare_syscall!(
arg1, arg2, arg3, arg4, arg5
),
);
*result = Ok(0);
Ok(0)
}
);
declare_syscall!(
/// Log current compute consumption
SyscallLogBpfComputeUnits,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
_arg1: u64,
_arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
_memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let invoke_context = question_mark!(
self.invoke_context
.try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
) -> Result<u64, EbpfError> {
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!(
invoke_context.get_log_collector(),
"Program consumption: {} units remaining",
invoke_context.get_compute_meter().borrow().get_remaining()
);
*result = Ok(0);
Ok(0)
}
);
declare_syscall!(
/// Log 5 64-bit values
SyscallLogPubkey,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
pubkey_addr: u64,
_arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let invoke_context = question_mark!(
self.invoke_context
.try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
) -> Result<u64, EbpfError> {
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!(
translate_type::<Pubkey>(
memory_mapping,
pubkey_addr,
invoke_context.get_check_aligned()
),
result
);
let pubkey = translate_type::<Pubkey>(
memory_mapping,
pubkey_addr,
invoke_context.get_check_aligned(),
)?;
stable_log::program_log(&invoke_context.get_log_collector(), &pubkey.to_string());
*result = Ok(0);
Ok(0)
}
);
declare_syscall!(
/// Log data handling
SyscallLogData,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
addr: u64,
len: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let invoke_context = question_mark!(
self.invoke_context
.try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
) -> Result<u64, EbpfError> {
let budget = invoke_context.get_compute_budget();
question_mark!(
invoke_context
.get_compute_meter()
.consume(budget.syscall_base_cost),
result
);
invoke_context
.get_compute_meter()
.consume(budget.syscall_base_cost)?;
let untranslated_fields = question_mark!(
translate_slice::<&[u8]>(
memory_mapping,
addr,
len,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
),
result
);
let untranslated_fields = translate_slice::<&[u8]>(
memory_mapping,
addr,
len,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
)?;
question_mark!(
invoke_context.get_compute_meter().consume(
budget
.syscall_base_cost
.saturating_mul(untranslated_fields.len() as u64)
),
result
);
question_mark!(
invoke_context.get_compute_meter().consume(
untranslated_fields
.iter()
.fold(0, |total, e| total.saturating_add(e.len() as u64))
),
result
);
invoke_context.get_compute_meter().consume(
budget
.syscall_base_cost
.saturating_mul(untranslated_fields.len() as u64),
)?;
invoke_context.get_compute_meter().consume(
untranslated_fields
.iter()
.fold(0, |total, e| total.saturating_add(e.len() as u64)),
)?;
let mut fields = Vec::with_capacity(untranslated_fields.len());
for untranslated_field in untranslated_fields {
fields.push(question_mark!(
translate_slice::<u8>(
memory_mapping,
untranslated_field.as_ptr() as *const _ as u64,
untranslated_field.len() as u64,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
),
result
));
fields.push(translate_slice::<u8>(
memory_mapping,
untranslated_field.as_ptr() as *const _ as u64,
untranslated_field.len() as u64,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
)?);
}
let log_collector = invoke_context.get_log_collector();
stable_log::program_data(&log_collector, &fields);
*result = Ok(0);
Ok(0)
}
);

View File

@ -1,9 +1,6 @@
use {super::*, crate::declare_syscall};
fn mem_op_consume<'a, 'b>(
invoke_context: &Ref<&'a mut InvokeContext<'b>>,
n: u64,
) -> Result<(), EbpfError<BpfError>> {
fn mem_op_consume(invoke_context: &mut InvokeContext, n: u64) -> Result<(), EbpfError> {
let compute_budget = invoke_context.get_compute_budget();
let cost = compute_budget
.mem_op_base_cost
@ -14,54 +11,40 @@ fn mem_op_consume<'a, 'b>(
declare_syscall!(
/// memcpy
SyscallMemcpy,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
dst_addr: u64,
src_addr: u64,
n: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let invoke_context = question_mark!(
self.invoke_context
.try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
question_mark!(mem_op_consume(&invoke_context, n), result);
) -> Result<u64, EbpfError> {
mem_op_consume(invoke_context, n)?;
let do_check_physical_overlapping = invoke_context
.feature_set
.is_active(&check_physical_overlapping::id());
if !is_nonoverlapping(src_addr, dst_addr, n) {
*result = Err(SyscallError::CopyOverlapping.into());
return;
return Err(SyscallError::CopyOverlapping.into());
}
let dst_ptr = question_mark!(
translate_slice_mut::<u8>(
memory_mapping,
dst_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size()
),
result
)
let dst_ptr = translate_slice_mut::<u8>(
memory_mapping,
dst_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
)?
.as_mut_ptr();
let src_ptr = question_mark!(
translate_slice::<u8>(
memory_mapping,
src_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size()
),
result
)
let src_ptr = translate_slice::<u8>(
memory_mapping,
src_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
)?
.as_ptr();
if do_check_physical_overlapping
&& !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);
}
}
*result = Ok(0);
Ok(0)
}
);
declare_syscall!(
/// memmove
SyscallMemmove,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
dst_addr: u64,
src_addr: u64,
n: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let invoke_context = question_mark!(
self.invoke_context
.try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
question_mark!(mem_op_consume(&invoke_context, n), result);
) -> Result<u64, EbpfError> {
mem_op_consume(invoke_context, n)?;
let dst = question_mark!(
translate_slice_mut::<u8>(
memory_mapping,
dst_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size()
),
result
);
let src = question_mark!(
translate_slice::<u8>(
memory_mapping,
src_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size()
),
result
);
let dst = translate_slice_mut::<u8>(
memory_mapping,
dst_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
)?;
let src = translate_slice::<u8>(
memory_mapping,
src_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
)?;
unsafe {
std::ptr::copy(src.as_ptr(), dst.as_mut_ptr(), n as usize);
}
*result = Ok(0);
Ok(0)
}
);
declare_syscall!(
/// memcmp
SyscallMemcmp,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
s1_addr: u64,
s2_addr: u64,
n: u64,
cmp_result_addr: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let invoke_context = question_mark!(
self.invoke_context
.try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
question_mark!(mem_op_consume(&invoke_context, n), result);
) -> Result<u64, EbpfError> {
mem_op_consume(invoke_context, n)?;
let s1 = question_mark!(
translate_slice::<u8>(
memory_mapping,
s1_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
),
result
);
let s2 = question_mark!(
translate_slice::<u8>(
memory_mapping,
s2_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
),
result
);
let cmp_result = question_mark!(
translate_type_mut::<i32>(
memory_mapping,
cmp_result_addr,
invoke_context.get_check_aligned()
),
result
);
let s1 = translate_slice::<u8>(
memory_mapping,
s1_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
)?;
let s2 = translate_slice::<u8>(
memory_mapping,
s2_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
)?;
let cmp_result = translate_type_mut::<i32>(
memory_mapping,
cmp_result_addr,
invoke_context.get_check_aligned(),
)?;
let mut i = 0;
while i < n as usize {
let a = *question_mark!(s1.get(i).ok_or(SyscallError::InvalidLength,), result);
let b = *question_mark!(s2.get(i).ok_or(SyscallError::InvalidLength,), result);
let a = *s1.get(i).ok_or(SyscallError::InvalidLength)?;
let b = *s2.get(i).ok_or(SyscallError::InvalidLength)?;
if a != b {
*cmp_result = if invoke_context
.feature_set
@ -191,50 +145,39 @@ declare_syscall!(
a as i32 - b as i32
}
};
*result = Ok(0);
return;
return Ok(0);
};
i = i.saturating_add(1);
}
*cmp_result = 0;
*result = Ok(0);
Ok(0)
}
);
declare_syscall!(
/// memset
SyscallMemset,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
s_addr: u64,
c: u64,
n: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let invoke_context = question_mark!(
self.invoke_context
.try_borrow()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
question_mark!(mem_op_consume(&invoke_context, n), result);
) -> Result<u64, EbpfError> {
mem_op_consume(invoke_context, n)?;
let s = question_mark!(
translate_slice_mut::<u8>(
memory_mapping,
s_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
),
result
);
let s = translate_slice_mut::<u8>(
memory_mapping,
s_addr,
n,
invoke_context.get_check_aligned(),
invoke_context.get_check_size(),
)?;
for val in s.iter_mut().take(n as usize) {
*val = c as u8;
}
*result = Ok(0);
Ok(0)
}
);

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId + Clone>(
check_aligned: bool,
memory_mapping: &mut MemoryMapping,
invoke_context: &mut InvokeContext,
) -> Result<u64, EbpfError<BpfError>> {
) -> Result<u64, EbpfError> {
invoke_context.get_compute_meter().consume(
invoke_context
.get_compute_budget()
@ -24,89 +24,68 @@ fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId + Clone>(
declare_syscall!(
/// Get a Clock sysvar
SyscallGetClockSysvar,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
var_addr: u64,
_arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let mut invoke_context = question_mark!(
self.invoke_context
.try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
*result = get_sysvar(
) -> Result<u64, EbpfError> {
get_sysvar(
invoke_context.get_sysvar_cache().get_clock(),
var_addr,
invoke_context.get_check_aligned(),
memory_mapping,
&mut invoke_context,
);
invoke_context,
)
}
);
declare_syscall!(
/// Get a EpochSchedule sysvar
SyscallGetEpochScheduleSysvar,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
var_addr: u64,
_arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let mut invoke_context = question_mark!(
self.invoke_context
.try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
*result = get_sysvar(
) -> Result<u64, EbpfError> {
get_sysvar(
invoke_context.get_sysvar_cache().get_epoch_schedule(),
var_addr,
invoke_context.get_check_aligned(),
memory_mapping,
&mut invoke_context,
);
invoke_context,
)
}
);
declare_syscall!(
/// Get a Fees sysvar
SyscallGetFeesSysvar,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
var_addr: u64,
_arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let mut invoke_context = question_mark!(
self.invoke_context
.try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
) -> Result<u64, EbpfError> {
#[allow(deprecated)]
{
*result = get_sysvar(
get_sysvar(
invoke_context.get_sysvar_cache().get_fees(),
var_addr,
invoke_context.get_check_aligned(),
memory_mapping,
&mut invoke_context,
);
invoke_context,
)
}
}
);
@ -114,28 +93,21 @@ declare_syscall!(
declare_syscall!(
/// Get a Rent sysvar
SyscallGetRentSysvar,
fn call(
&mut self,
fn inner_call(
invoke_context: &mut InvokeContext,
var_addr: u64,
_arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
result: &mut Result<u64, EbpfError<BpfError>>,
) {
let mut invoke_context = question_mark!(
self.invoke_context
.try_borrow_mut()
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
result
);
*result = get_sysvar(
) -> Result<u64, EbpfError> {
get_sysvar(
invoke_context.get_sysvar_cache().get_rent(),
var_addr,
invoke_context.get_check_aligned(),
memory_mapping,
&mut invoke_context,
);
invoke_context,
)
}
);

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 = "=0.2.33"
solana_rbpf = "=0.2.34"

View File

@ -3,7 +3,7 @@ use {
serde::{Deserialize, Serialize},
serde_json::Result,
solana_bpf_loader_program::{
create_vm, serialization::serialize_parameters, syscalls::register_syscalls, BpfError,
create_vm, serialization::serialize_parameters, syscalls::register_syscalls,
ThisInstructionMeter,
},
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();
let syscall_registry = register_syscalls(&mut invoke_context, true).unwrap();
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))
} else {
assemble::<BpfError, ThisInstructionMeter>(
assemble::<ThisInstructionMeter>(
std::str::from_utf8(contents.as_slice()).unwrap(),
config,
syscall_registry,
@ -266,11 +266,9 @@ native machine code before execting it in the virtual machine.",
.unwrap();
let mut verified_executable =
VerifiedExecutable::<RequisiteVerifier, BpfError, ThisInstructionMeter>::from_executable(
executable,
)
.map_err(|err| format!("Executable verifier failed: {:?}", err))
.unwrap();
VerifiedExecutable::<RequisiteVerifier, ThisInstructionMeter>::from_executable(executable)
.map_err(|err| format!("Executable verifier failed: {:?}", err))
.unwrap();
verified_executable.jit_compile().unwrap();
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") {
eprintln!("Trace is saved in trace.out");
let mut file = File::create("trace.out").unwrap();
vm.get_tracer()
vm.get_program_environment()
.tracer
.write(&mut file, analysis.analyze())
.unwrap();
}
if matches.is_present("profile") {
eprintln!("Profile is saved in profile.dot");
let tracer = &vm.get_tracer();
let tracer = &vm.get_program_environment().tracer;
let analysis = analysis.analyze();
let dynamic_analysis = DynamicAnalysis::new(tracer, analysis);
let mut file = File::create("profile.dot").unwrap();
@ -376,19 +375,19 @@ impl Debug for Output {
// Replace with std::lazy::Lazy when stabilized.
// https://github.com/rust-lang/rust/issues/74465
struct LazyAnalysis<'a> {
analysis: Option<Analysis<'a, BpfError, ThisInstructionMeter>>,
executable: &'a Executable<BpfError, ThisInstructionMeter>,
analysis: Option<Analysis<'a, ThisInstructionMeter>>,
executable: &'a Executable<ThisInstructionMeter>,
}
impl<'a> LazyAnalysis<'a> {
fn new(executable: &'a Executable<BpfError, ThisInstructionMeter>) -> Self {
fn new(executable: &'a Executable<ThisInstructionMeter>) -> Self {
Self {
analysis: None,
executable,
}
}
fn analyze(&mut self) -> &Analysis<BpfError, ThisInstructionMeter> {
fn analyze(&mut self) -> &Analysis<ThisInstructionMeter> {
if let Some(ref analysis) = self.analysis {
return analysis;
}