Skip to content

Commit

Permalink
Bump solana_rbpf to v0.2.40 (solana-labs#30668)
Browse files Browse the repository at this point in the history
Update to solana_rbpf v0.2.40
  • Loading branch information
alessandrod authored and nickfrosty committed Mar 12, 2023
1 parent 6d6279f commit 95196af
Show file tree
Hide file tree
Showing 11 changed files with 314 additions and 448 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ signal-hook = "0.3.14"
smpl_jwt = "0.7.1"
socket2 = "0.4.7"
soketto = "0.7"
solana_rbpf = "=0.2.39"
solana_rbpf = "=0.2.40"
solana-account-decoder = { path = "account-decoder", version = "=1.16.0" }
solana-address-lookup-table-program = { path = "programs/address-lookup-table", version = "=1.16.0" }
solana-banks-client = { path = "banks-client", version = "=1.16.0" }
Expand Down
4 changes: 2 additions & 2 deletions programs/bpf_loader/src/allocator_bump.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ impl BpfAllocator {
}
}

pub fn get_heap(&mut self) -> &mut [u8] {
self.heap.as_slice_mut()
pub fn heap_mut(&mut self) -> &mut AlignedMemory<HOST_ALIGN> {
&mut self.heap
}
}

Expand Down
138 changes: 113 additions & 25 deletions programs/bpf_loader/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,18 @@ use {
},
solana_rbpf::{
aligned_memory::AlignedMemory,
ebpf::{HOST_ALIGN, MM_HEAP_START},
ebpf::{self, HOST_ALIGN, MM_HEAP_START},
elf::Executable,
error::{EbpfError, UserDefinedError},
memory_region::MemoryRegion,
memory_region::{MemoryCowCallback, MemoryMapping, MemoryRegion},
verifier::{RequisiteVerifier, VerifierError},
vm::{ContextObject, EbpfVm, ProgramResult, VerifiedExecutable},
},
solana_sdk::{
bpf_loader, bpf_loader_deprecated,
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
clock::Slot,
entrypoint::{HEAP_LENGTH, SUCCESS},
entrypoint::SUCCESS,
feature_set::{
cap_accounts_data_allocations_per_transaction, cap_bpf_program_instruction_accounts,
check_slice_translation_size, delay_visibility_of_program_deployment,
Expand All @@ -64,6 +65,7 @@ use {
std::{
cell::{RefCell, RefMut},
fmt::Debug,
mem,
rc::Rc,
sync::Arc,
},
Expand Down Expand Up @@ -296,21 +298,19 @@ fn check_loader_id(id: &Pubkey) -> bool {
}

/// Create the SBF virtual machine
pub fn create_vm<'a, 'b>(
pub fn create_ebpf_vm<'a, 'b>(
program: &'a VerifiedExecutable<RequisiteVerifier, InvokeContext<'b>>,
stack: &'a mut AlignedMemory<HOST_ALIGN>,
heap: AlignedMemory<HOST_ALIGN>,
regions: Vec<MemoryRegion>,
orig_account_lengths: Vec<usize>,
invoke_context: &'a mut InvokeContext<'b>,
) -> Result<EbpfVm<'a, RequisiteVerifier, InvokeContext<'b>>, EbpfError> {
let compute_budget = invoke_context.get_compute_budget();
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
let _ = invoke_context.consume_checked(
((heap_size as u64).saturating_div(32_u64.saturating_mul(1024)))
((heap.len() as u64).saturating_div(32_u64.saturating_mul(1024)))
.saturating_sub(1)
.saturating_mul(compute_budget.heap_cost),
.saturating_mul(invoke_context.get_compute_budget().heap_cost),
);
let heap =
AlignedMemory::<HOST_ALIGN>::zero_filled(compute_budget.heap_size.unwrap_or(HEAP_LENGTH));
let check_aligned = bpf_loader_deprecated::id()
!= invoke_context
.transaction_context
Expand All @@ -333,13 +333,76 @@ pub fn create_vm<'a, 'b>(
allocator.clone(),
)
.map_err(SyscallError::InstructionError)?;
let result = EbpfVm::new(
program,
invoke_context,
allocator.borrow_mut().get_heap(),
let stack_len = stack.len();
let memory_mapping = create_memory_mapping(
program.get_executable(),
stack,
allocator.borrow_mut().heap_mut(),
regions,
);
result
None,
)?;

EbpfVm::new(program, invoke_context, memory_mapping, stack_len)
}

#[macro_export]
macro_rules! create_vm {
($vm_name:ident, $executable:expr, $stack:ident, $heap:ident, $additional_regions:expr, $orig_account_lengths:expr, $invoke_context:expr) => {
let mut $stack = solana_rbpf::aligned_memory::AlignedMemory::<
{ solana_rbpf::ebpf::HOST_ALIGN },
>::zero_filled($executable.get_executable().get_config().stack_size());

// this is needed if the caller passes "&mut invoke_context" to the
// macro. The lint complains that (&mut invoke_context).get_compute_budget()
// does an unnecessary mutable borrow
#[allow(clippy::unnecessary_mut_passed)]
let heap_size = $invoke_context
.get_compute_budget()
.heap_size
.unwrap_or(solana_sdk::entrypoint::HEAP_LENGTH);
let $heap = solana_rbpf::aligned_memory::AlignedMemory::<{ solana_rbpf::ebpf::HOST_ALIGN }>::zero_filled(heap_size);

let $vm_name = create_ebpf_vm(
$executable,
&mut $stack,
$heap,
$additional_regions,
$orig_account_lengths,
$invoke_context,
);
};
}

fn create_memory_mapping<'a, 'b, C: ContextObject>(
executable: &'a Executable<C>,
stack: &'b mut AlignedMemory<{ HOST_ALIGN }>,
heap: &'b mut AlignedMemory<{ HOST_ALIGN }>,
additional_regions: Vec<MemoryRegion>,
cow_cb: Option<MemoryCowCallback>,
) -> Result<MemoryMapping<'a>, EbpfError> {
let config = executable.get_config();
let regions: Vec<MemoryRegion> = vec![
executable.get_ro_region(),
MemoryRegion::new_writable_gapped(
stack.as_slice_mut(),
ebpf::MM_STACK_START,
if !config.dynamic_stack_frames && config.enable_stack_frame_gaps {
config.stack_frame_size as u64
} else {
0
},
),
MemoryRegion::new_writable(heap.as_slice_mut(), ebpf::MM_HEAP_START),
]
.into_iter()
.chain(additional_regions.into_iter())
.collect();

Ok(if let Some(cow_cb) = cow_cb {
MemoryMapping::new_with_cow(regions, cow_cb, config)?
} else {
MemoryMapping::new(regions, config)?
})
}

pub fn process_instruction(invoke_context: &mut InvokeContext) -> Result<(), InstructionError> {
Expand Down Expand Up @@ -1345,9 +1408,9 @@ fn process_loader_instruction(
Ok(())
}

fn execute(
executable: &VerifiedExecutable<RequisiteVerifier, InvokeContext<'static>>,
invoke_context: &mut InvokeContext,
fn execute<'a, 'b: 'a>(
executable: &'a VerifiedExecutable<RequisiteVerifier, InvokeContext<'static>>,
invoke_context: &'a mut InvokeContext<'b>,
) -> Result<(), InstructionError> {
let log_collector = invoke_context.get_log_collector();
let stack_height = invoke_context.get_stack_height();
Expand All @@ -1373,14 +1436,22 @@ fn execute(
let mut execute_time;
let execution_result = {
let compute_meter_prev = invoke_context.get_remaining();
let mut vm = match create_vm(
create_vm!(
vm,
// We dropped the lifetime tracking in the Executor by setting it to 'static,
// thus we need to reintroduce the correct lifetime of InvokeContext here again.
unsafe { std::mem::transmute(executable) },
unsafe {
mem::transmute::<_, &'a VerifiedExecutable<RequisiteVerifier, InvokeContext<'b>>>(
executable,
)
},
stack,
heap,
regions,
account_lengths,
invoke_context,
) {
invoke_context
);
let mut vm = match vm {
Ok(info) => info,
Err(e) => {
ic_logger_msg!(log_collector, "Failed to create SBF VM: {}", e);
Expand Down Expand Up @@ -1592,11 +1663,28 @@ mod tests {
.unwrap();
let input_region = MemoryRegion::new_writable(&mut input_mem, MM_INPUT_START);
let mut context_object = TestContextObject { remaining: 10 };
let mut stack = AlignedMemory::zero_filled(
verified_executable
.get_executable()
.get_config()
.stack_size(),
);
let mut heap = AlignedMemory::with_capacity(0);
let stack_len = stack.len();

let memory_mapping = create_memory_mapping(
verified_executable.get_executable(),
&mut stack,
&mut heap,
vec![input_region],
None,
)
.unwrap();
let mut vm = EbpfVm::new(
&verified_executable,
&mut context_object,
&mut [],
vec![input_region],
memory_mapping,
stack_len,
)
.unwrap();
vm.execute_program(true).1.unwrap();
Expand Down
10 changes: 5 additions & 5 deletions programs/bpf_loader/src/syscalls/cpi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1333,7 +1333,7 @@ mod tests {
..Config::default()
};
let memory_mapping =
MemoryMapping::new(vec![mock_caller_account.region.clone()], &config).unwrap();
MemoryMapping::new(mock_caller_account.regions.split_off(0), &config).unwrap();

let mut caller_account = mock_caller_account.caller_account();

Expand Down Expand Up @@ -1390,7 +1390,7 @@ mod tests {
..Config::default()
};
let memory_mapping =
MemoryMapping::new(vec![mock_caller_account.region.clone()], &config).unwrap();
MemoryMapping::new(mock_caller_account.regions.split_off(0), &config).unwrap();

let data_slice = mock_caller_account.data_slice();
let len_ptr = unsafe {
Expand Down Expand Up @@ -1608,7 +1608,7 @@ mod tests {
vm_addr: u64,
data: Vec<u8>,
len: u64,
region: MemoryRegion,
regions: Vec<MemoryRegion>,
}

impl MockCallerAccount {
Expand All @@ -1620,7 +1620,7 @@ mod tests {
d[mem::size_of::<u64>()..][..data.len()].copy_from_slice(data);

// the memory region must include the realloc data
let region = MemoryRegion::new_writable(d.as_mut_slice(), vm_addr);
let regions = vec![MemoryRegion::new_writable(d.as_mut_slice(), vm_addr)];

// caller_account.data must have the actual data length
d.truncate(mem::size_of::<u64>() + data.len());
Expand All @@ -1631,7 +1631,7 @@ mod tests {
vm_addr,
data: d,
len: data.len() as u64,
region,
regions,
}
}

Expand Down
Loading

0 comments on commit 95196af

Please sign in to comment.