parent
6deaf649ef
commit
de9d8cd849
|
@ -4249,9 +4249,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana_rbpf"
|
name = "solana_rbpf"
|
||||||
version = "0.1.25"
|
version = "0.1.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "87d4395203039cac872c125dea2534e6b98ae85e28e3f800872a7571ffa87df8"
|
checksum = "1d6bee545321a2fed2f9a24066bf7bf08f9b814fd48865b7c629ee40f33f3207"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"combine",
|
"combine",
|
||||||
|
|
|
@ -1546,7 +1546,7 @@ dependencies = [
|
||||||
"solana-logger 1.2.0",
|
"solana-logger 1.2.0",
|
||||||
"solana-runtime 1.2.0",
|
"solana-runtime 1.2.0",
|
||||||
"solana-sdk 1.2.0",
|
"solana-sdk 1.2.0",
|
||||||
"solana_rbpf 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"solana_rbpf 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"thiserror 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"thiserror 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1561,7 +1561,7 @@ dependencies = [
|
||||||
"solana-logger 1.2.0",
|
"solana-logger 1.2.0",
|
||||||
"solana-runtime 1.2.0",
|
"solana-runtime 1.2.0",
|
||||||
"solana-sdk 1.2.0",
|
"solana-sdk 1.2.0",
|
||||||
"solana_rbpf 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
|
"solana_rbpf 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1915,7 +1915,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana_rbpf"
|
name = "solana_rbpf"
|
||||||
version = "0.1.25"
|
version = "0.1.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2708,7 +2708,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
|
||||||
"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
|
"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6"
|
||||||
"checksum smallvec 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
|
"checksum smallvec 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c7cb5678e1615754284ec264d9bb5b4c27d2018577fd90ac0ceb578591ed5ee4"
|
||||||
"checksum solana_rbpf 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "87d4395203039cac872c125dea2534e6b98ae85e28e3f800872a7571ffa87df8"
|
"checksum solana_rbpf 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "1d6bee545321a2fed2f9a24066bf7bf08f9b814fd48865b7c629ee40f33f3207"
|
||||||
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||||
"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
|
"checksum subtle 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee"
|
||||||
|
|
|
@ -26,7 +26,7 @@ solana-bpf-loader-program = { path = "../bpf_loader", version = "1.2.0" }
|
||||||
solana-logger = { path = "../../logger", version = "1.2.0" }
|
solana-logger = { path = "../../logger", version = "1.2.0" }
|
||||||
solana-runtime = { path = "../../runtime", version = "1.2.0" }
|
solana-runtime = { path = "../../runtime", version = "1.2.0" }
|
||||||
solana-sdk = { path = "../../sdk", version = "1.2.0" }
|
solana-sdk = { path = "../../sdk", version = "1.2.0" }
|
||||||
solana_rbpf = "=0.1.25"
|
solana_rbpf = "=0.1.26"
|
||||||
|
|
||||||
[[bench]]
|
[[bench]]
|
||||||
name = "bpf_loader"
|
name = "bpf_loader"
|
||||||
|
|
|
@ -18,7 +18,7 @@ num-traits = { version = "0.2" }
|
||||||
solana-logger = { path = "../../logger", version = "1.2.0" }
|
solana-logger = { path = "../../logger", version = "1.2.0" }
|
||||||
solana-runtime = { path = "../../runtime", version = "1.2.0" }
|
solana-runtime = { path = "../../runtime", version = "1.2.0" }
|
||||||
solana-sdk = { path = "../../sdk", version = "1.2.0" }
|
solana-sdk = { path = "../../sdk", version = "1.2.0" }
|
||||||
solana_rbpf = "=0.1.25"
|
solana_rbpf = "=0.1.26"
|
||||||
thiserror = "1.0"
|
thiserror = "1.0"
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
pub mod alloc;
|
pub mod alloc;
|
||||||
pub mod allocator_bump;
|
pub mod allocator_bump;
|
||||||
pub mod bpf_verifier;
|
pub mod bpf_verifier;
|
||||||
pub mod helpers;
|
pub mod syscalls;
|
||||||
|
|
||||||
use crate::{bpf_verifier::VerifierError, helpers::HelperError};
|
use crate::{bpf_verifier::VerifierError, syscalls::SyscallError};
|
||||||
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
|
use byteorder::{ByteOrder, LittleEndian, WriteBytesExt};
|
||||||
use log::*;
|
use log::*;
|
||||||
use num_derive::{FromPrimitive, ToPrimitive};
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
|
@ -51,7 +51,7 @@ pub enum BPFError {
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
VerifierError(#[from] VerifierError),
|
VerifierError(#[from] VerifierError),
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
HelperError(#[from] HelperError),
|
SyscallError(#[from] SyscallError),
|
||||||
}
|
}
|
||||||
impl UserDefinedError for BPFError {}
|
impl UserDefinedError for BPFError {}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ pub fn create_vm<'a>(
|
||||||
vm.set_max_instruction_count(100_000)?;
|
vm.set_max_instruction_count(100_000)?;
|
||||||
vm.set_elf(&prog)?;
|
vm.set_elf(&prog)?;
|
||||||
|
|
||||||
let heap_region = helpers::register_helpers(&mut vm, invoke_context)?;
|
let heap_region = syscalls::register_syscalls(&mut vm, invoke_context)?;
|
||||||
|
|
||||||
Ok((vm, heap_region))
|
Ok((vm, heap_region))
|
||||||
}
|
}
|
||||||
|
@ -202,8 +202,8 @@ pub fn process_instruction(
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
warn!("BPF program {} failed: {}", program.unsigned_key(), error);
|
warn!("BPF program {} failed: {}", program.unsigned_key(), error);
|
||||||
return match error {
|
return match error {
|
||||||
EbpfError::UserError(BPFError::HelperError(
|
EbpfError::UserError(BPFError::SyscallError(
|
||||||
HelperError::InstructionError(error),
|
SyscallError::InstructionError(error),
|
||||||
)) => Err(error),
|
)) => Err(error),
|
||||||
_ => Err(BPFLoaderError::VirtualMachineFailedToRunProgram.into()),
|
_ => Err(BPFLoaderError::VirtualMachineFailedToRunProgram.into()),
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{alloc, BPFError};
|
||||||
use alloc::Alloc;
|
use alloc::Alloc;
|
||||||
use log::*;
|
use log::*;
|
||||||
use solana_rbpf::{
|
use solana_rbpf::{
|
||||||
ebpf::{EbpfError, HelperObject, ELF_INSN_DUMP_OFFSET, MM_HEAP_START},
|
ebpf::{EbpfError, SyscallObject, ELF_INSN_DUMP_OFFSET, MM_HEAP_START},
|
||||||
memory_region::{translate_addr, MemoryRegion},
|
memory_region::{translate_addr, MemoryRegion},
|
||||||
EbpfVm,
|
EbpfVm,
|
||||||
};
|
};
|
||||||
|
@ -32,7 +32,7 @@ use thiserror::Error as ThisError;
|
||||||
|
|
||||||
/// Error definitions
|
/// Error definitions
|
||||||
#[derive(Debug, ThisError)]
|
#[derive(Debug, ThisError)]
|
||||||
pub enum HelperError {
|
pub enum SyscallError {
|
||||||
#[error("{0}: {1:?}")]
|
#[error("{0}: {1:?}")]
|
||||||
InvalidString(Utf8Error, Vec<u8>),
|
InvalidString(Utf8Error, Vec<u8>),
|
||||||
#[error("BPF program called abort()!")]
|
#[error("BPF program called abort()!")]
|
||||||
|
@ -50,8 +50,8 @@ pub enum HelperError {
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
InstructionError(InstructionError),
|
InstructionError(InstructionError),
|
||||||
}
|
}
|
||||||
impl From<HelperError> for EbpfError<BPFError> {
|
impl From<SyscallError> for EbpfError<BPFError> {
|
||||||
fn from(error: HelperError) -> Self {
|
fn from(error: SyscallError) -> Self {
|
||||||
EbpfError::UserError(error.into())
|
EbpfError::UserError(error.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,37 +68,37 @@ use crate::allocator_bump::BPFAllocator;
|
||||||
/// are expected to enforce this
|
/// are expected to enforce this
|
||||||
const DEFAULT_HEAP_SIZE: usize = 32 * 1024;
|
const DEFAULT_HEAP_SIZE: usize = 32 * 1024;
|
||||||
|
|
||||||
pub fn register_helpers<'a>(
|
pub fn register_syscalls<'a>(
|
||||||
vm: &mut EbpfVm<'a, BPFError>,
|
vm: &mut EbpfVm<'a, BPFError>,
|
||||||
invoke_context: &'a mut dyn InvokeContext,
|
invoke_context: &'a mut dyn InvokeContext,
|
||||||
) -> Result<MemoryRegion, EbpfError<BPFError>> {
|
) -> Result<MemoryRegion, EbpfError<BPFError>> {
|
||||||
vm.register_helper_ex("abort", helper_abort)?;
|
vm.register_syscall_ex("abort", syscall_abort)?;
|
||||||
vm.register_helper_ex("sol_panic", helper_sol_panic)?;
|
vm.register_syscall_ex("sol_panic", syscall_sol_panic)?;
|
||||||
vm.register_helper_ex("sol_panic_", helper_sol_panic)?;
|
vm.register_syscall_ex("sol_panic_", syscall_sol_panic)?;
|
||||||
vm.register_helper_ex("sol_log", helper_sol_log)?;
|
vm.register_syscall_ex("sol_log", syscall_sol_log)?;
|
||||||
vm.register_helper_ex("sol_log_", helper_sol_log)?;
|
vm.register_syscall_ex("sol_log_", syscall_sol_log)?;
|
||||||
vm.register_helper_ex("sol_log_64", helper_sol_log_u64)?;
|
vm.register_syscall_ex("sol_log_64", syscall_sol_log_u64)?;
|
||||||
vm.register_helper_ex("sol_log_64_", helper_sol_log_u64)?;
|
vm.register_syscall_ex("sol_log_64_", syscall_sol_log_u64)?;
|
||||||
|
|
||||||
let invoke_context = Rc::new(RefCell::new(invoke_context));
|
let invoke_context = Rc::new(RefCell::new(invoke_context));
|
||||||
vm.register_helper_with_context_ex(
|
vm.register_syscall_with_context_ex(
|
||||||
"sol_invoke_signed_rust",
|
"sol_invoke_signed_rust",
|
||||||
Box::new(HelperProcessInstructionRust {
|
Box::new(SyscallProcessInstructionRust {
|
||||||
invoke_context: invoke_context.clone(),
|
invoke_context: invoke_context.clone(),
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
vm.register_helper_with_context_ex(
|
vm.register_syscall_with_context_ex(
|
||||||
"sol_invoke_signed_c",
|
"sol_invoke_signed_c",
|
||||||
Box::new(HelperProcessSolInstructionC {
|
Box::new(SyscallProcessSolInstructionC {
|
||||||
invoke_context: invoke_context.clone(),
|
invoke_context: invoke_context.clone(),
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let heap = vec![0_u8; DEFAULT_HEAP_SIZE];
|
let heap = vec![0_u8; DEFAULT_HEAP_SIZE];
|
||||||
let heap_region = MemoryRegion::new_from_slice(&heap, MM_HEAP_START);
|
let heap_region = MemoryRegion::new_from_slice(&heap, MM_HEAP_START);
|
||||||
vm.register_helper_with_context_ex(
|
vm.register_syscall_with_context_ex(
|
||||||
"sol_alloc_free_",
|
"sol_alloc_free_",
|
||||||
Box::new(HelperSolAllocFree {
|
Box::new(SyscallSolAllocFree {
|
||||||
allocator: BPFAllocator::new(heap, MM_HEAP_START),
|
allocator: BPFAllocator::new(heap, MM_HEAP_START),
|
||||||
}),
|
}),
|
||||||
)?;
|
)?;
|
||||||
|
@ -186,14 +186,14 @@ fn translate_string_and_do(
|
||||||
};
|
};
|
||||||
match from_utf8(&buf[..i]) {
|
match from_utf8(&buf[..i]) {
|
||||||
Ok(message) => work(message),
|
Ok(message) => work(message),
|
||||||
Err(err) => Err(HelperError::InvalidString(err, buf[..i].to_vec()).into()),
|
Err(err) => Err(SyscallError::InvalidString(err, buf[..i].to_vec()).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Abort helper functions, called when the BPF program calls `abort()`
|
/// Abort syscall functions, called when the BPF program calls `abort()`
|
||||||
/// The verify function returns an error which will cause the BPF program
|
/// The verify function returns an error which will cause the BPF program
|
||||||
/// to be halted immediately
|
/// to be halted immediately
|
||||||
pub fn helper_abort(
|
pub fn syscall_abort(
|
||||||
_arg1: u64,
|
_arg1: u64,
|
||||||
_arg2: u64,
|
_arg2: u64,
|
||||||
_arg3: u64,
|
_arg3: u64,
|
||||||
|
@ -202,13 +202,13 @@ pub fn helper_abort(
|
||||||
_ro_regions: &[MemoryRegion],
|
_ro_regions: &[MemoryRegion],
|
||||||
_rw_regions: &[MemoryRegion],
|
_rw_regions: &[MemoryRegion],
|
||||||
) -> Result<u64, EbpfError<BPFError>> {
|
) -> Result<u64, EbpfError<BPFError>> {
|
||||||
Err(HelperError::Abort.into())
|
Err(SyscallError::Abort.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Panic helper functions, called when the BPF program calls 'sol_panic_()`
|
/// Panic syscall functions, called when the BPF program calls 'sol_panic_()`
|
||||||
/// The verify function returns an error which will cause the BPF program
|
/// The verify function returns an error which will cause the BPF program
|
||||||
/// to be halted immediately
|
/// to be halted immediately
|
||||||
pub fn helper_sol_panic(
|
pub fn syscall_sol_panic(
|
||||||
file: u64,
|
file: u64,
|
||||||
len: u64,
|
len: u64,
|
||||||
line: u64,
|
line: u64,
|
||||||
|
@ -218,12 +218,12 @@ pub fn helper_sol_panic(
|
||||||
_rw_regions: &[MemoryRegion],
|
_rw_regions: &[MemoryRegion],
|
||||||
) -> Result<u64, EbpfError<BPFError>> {
|
) -> Result<u64, EbpfError<BPFError>> {
|
||||||
translate_string_and_do(file, len, ro_regions, &|string: &str| {
|
translate_string_and_do(file, len, ro_regions, &|string: &str| {
|
||||||
Err(HelperError::Panic(string.to_string(), line, column).into())
|
Err(SyscallError::Panic(string.to_string(), line, column).into())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Log a user's info message
|
/// Log a user's info message
|
||||||
pub fn helper_sol_log(
|
pub fn syscall_sol_log(
|
||||||
addr: u64,
|
addr: u64,
|
||||||
len: u64,
|
len: u64,
|
||||||
_arg3: u64,
|
_arg3: u64,
|
||||||
|
@ -242,7 +242,7 @@ pub fn helper_sol_log(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Log 5 u64 values
|
/// Log 5 u64 values
|
||||||
pub fn helper_sol_log_u64(
|
pub fn syscall_sol_log_u64(
|
||||||
arg1: u64,
|
arg1: u64,
|
||||||
arg2: u64,
|
arg2: u64,
|
||||||
arg3: u64,
|
arg3: u64,
|
||||||
|
@ -260,16 +260,16 @@ pub fn helper_sol_log_u64(
|
||||||
Ok(0)
|
Ok(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dynamic memory allocation helper called when the BPF program calls
|
/// Dynamic memory allocation syscall called when the BPF program calls
|
||||||
/// `sol_alloc_free_()`. The allocator is expected to allocate/free
|
/// `sol_alloc_free_()`. The allocator is expected to allocate/free
|
||||||
/// from/to a given chunk of memory and enforce size restrictions. The
|
/// from/to a given chunk of memory and enforce size restrictions. The
|
||||||
/// memory chunk is given to the allocator during allocator creation and
|
/// memory chunk is given to the allocator during allocator creation and
|
||||||
/// information about that memory (start address and size) is passed
|
/// information about that memory (start address and size) is passed
|
||||||
/// to the VM to use for enforcement.
|
/// to the VM to use for enforcement.
|
||||||
pub struct HelperSolAllocFree {
|
pub struct SyscallSolAllocFree {
|
||||||
allocator: BPFAllocator,
|
allocator: BPFAllocator,
|
||||||
}
|
}
|
||||||
impl HelperObject<BPFError> for HelperSolAllocFree {
|
impl SyscallObject<BPFError> for SyscallSolAllocFree {
|
||||||
fn call(
|
fn call(
|
||||||
&mut self,
|
&mut self,
|
||||||
size: u64,
|
size: u64,
|
||||||
|
@ -293,12 +293,12 @@ impl HelperObject<BPFError> for HelperSolAllocFree {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cross-program invocation helpers
|
// Cross-program invocation syscalls
|
||||||
|
|
||||||
pub type TranslatedAccounts<'a> = (Vec<Rc<RefCell<Account>>>, Vec<(&'a mut u64, &'a mut [u8])>);
|
pub type TranslatedAccounts<'a> = (Vec<Rc<RefCell<Account>>>, Vec<(&'a mut u64, &'a mut [u8])>);
|
||||||
|
|
||||||
/// Implemented by language specific data structure translators
|
/// Implemented by language specific data structure translators
|
||||||
trait HelperProcessInstruction<'a> {
|
trait SyscallProcessInstruction<'a> {
|
||||||
fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>>;
|
fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>>;
|
||||||
fn translate_instruction(
|
fn translate_instruction(
|
||||||
&self,
|
&self,
|
||||||
|
@ -323,14 +323,14 @@ trait HelperProcessInstruction<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cross-program invocation called from Rust
|
/// Cross-program invocation called from Rust
|
||||||
pub struct HelperProcessInstructionRust<'a> {
|
pub struct SyscallProcessInstructionRust<'a> {
|
||||||
invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>,
|
invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>,
|
||||||
}
|
}
|
||||||
impl<'a> HelperProcessInstruction<'a> for HelperProcessInstructionRust<'a> {
|
impl<'a> SyscallProcessInstruction<'a> for SyscallProcessInstructionRust<'a> {
|
||||||
fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> {
|
fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> {
|
||||||
self.invoke_context
|
self.invoke_context
|
||||||
.try_borrow_mut()
|
.try_borrow_mut()
|
||||||
.map_err(|_| HelperError::InvokeContextBorrowFailed.into())
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
|
||||||
}
|
}
|
||||||
fn translate_instruction(
|
fn translate_instruction(
|
||||||
&self,
|
&self,
|
||||||
|
@ -403,7 +403,7 @@ impl<'a> HelperProcessInstruction<'a> for HelperProcessInstructionRust<'a> {
|
||||||
continue 'root;
|
continue 'root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(HelperError::InstructionError(InstructionError::MissingAccount).into());
|
return Err(SyscallError::InstructionError(InstructionError::MissingAccount).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((accounts, refs))
|
Ok((accounts, refs))
|
||||||
|
@ -433,12 +433,12 @@ impl<'a> HelperProcessInstruction<'a> for HelperProcessInstructionRust<'a> {
|
||||||
ro_regions
|
ro_regions
|
||||||
)?;
|
)?;
|
||||||
from_utf8(seed_bytes).map_err(|err| {
|
from_utf8(seed_bytes).map_err(|err| {
|
||||||
HelperError::MalformedSignerSeed(err, seed_bytes.to_vec()).into()
|
SyscallError::MalformedSignerSeed(err, seed_bytes.to_vec()).into()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, EbpfError<BPFError>>>()?;
|
.collect::<Result<Vec<_>, EbpfError<BPFError>>>()?;
|
||||||
let signer = Pubkey::create_program_address(&seeds, program_id)
|
let signer = Pubkey::create_program_address(&seeds, program_id)
|
||||||
.map_err(HelperError::BadSeeds)?;
|
.map_err(SyscallError::BadSeeds)?;
|
||||||
signers.push(signer);
|
signers.push(signer);
|
||||||
}
|
}
|
||||||
Ok(signers)
|
Ok(signers)
|
||||||
|
@ -447,7 +447,7 @@ impl<'a> HelperProcessInstruction<'a> for HelperProcessInstructionRust<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> HelperObject<BPFError> for HelperProcessInstructionRust<'a> {
|
impl<'a> SyscallObject<BPFError> for SyscallProcessInstructionRust<'a> {
|
||||||
fn call(
|
fn call(
|
||||||
&mut self,
|
&mut self,
|
||||||
instruction_addr: u64,
|
instruction_addr: u64,
|
||||||
|
@ -518,14 +518,14 @@ struct SolSignerSeedsC {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cross-program invocation called from C
|
/// Cross-program invocation called from C
|
||||||
pub struct HelperProcessSolInstructionC<'a> {
|
pub struct SyscallProcessSolInstructionC<'a> {
|
||||||
invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>,
|
invoke_context: Rc<RefCell<&'a mut dyn InvokeContext>>,
|
||||||
}
|
}
|
||||||
impl<'a> HelperProcessInstruction<'a> for HelperProcessSolInstructionC<'a> {
|
impl<'a> SyscallProcessInstruction<'a> for SyscallProcessSolInstructionC<'a> {
|
||||||
fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> {
|
fn get_context_mut(&self) -> Result<RefMut<&'a mut dyn InvokeContext>, EbpfError<BPFError>> {
|
||||||
self.invoke_context
|
self.invoke_context
|
||||||
.try_borrow_mut()
|
.try_borrow_mut()
|
||||||
.map_err(|_| HelperError::InvokeContextBorrowFailed.into())
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn translate_instruction(
|
fn translate_instruction(
|
||||||
|
@ -603,7 +603,7 @@ impl<'a> HelperProcessInstruction<'a> for HelperProcessSolInstructionC<'a> {
|
||||||
continue 'root;
|
continue 'root;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(HelperError::InstructionError(InstructionError::MissingAccount).into());
|
return Err(SyscallError::InstructionError(InstructionError::MissingAccount).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok((accounts, refs))
|
Ok((accounts, refs))
|
||||||
|
@ -637,12 +637,12 @@ impl<'a> HelperProcessInstruction<'a> for HelperProcessSolInstructionC<'a> {
|
||||||
.map(|seed| {
|
.map(|seed| {
|
||||||
let seed_bytes = translate_slice!(u8, seed.addr, seed.len, ro_regions)?;
|
let seed_bytes = translate_slice!(u8, seed.addr, seed.len, ro_regions)?;
|
||||||
std::str::from_utf8(seed_bytes).map_err(|err| {
|
std::str::from_utf8(seed_bytes).map_err(|err| {
|
||||||
HelperError::MalformedSignerSeed(err, seed_bytes.to_vec()).into()
|
SyscallError::MalformedSignerSeed(err, seed_bytes.to_vec()).into()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, EbpfError<BPFError>>>()?;
|
.collect::<Result<Vec<_>, EbpfError<BPFError>>>()?;
|
||||||
Pubkey::create_program_address(&seed_strs, program_id)
|
Pubkey::create_program_address(&seed_strs, program_id)
|
||||||
.map_err(|err| HelperError::BadSeeds(err).into())
|
.map_err(|err| SyscallError::BadSeeds(err).into())
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<_>, EbpfError<BPFError>>>()?)
|
.collect::<Result<Vec<_>, EbpfError<BPFError>>>()?)
|
||||||
} else {
|
} else {
|
||||||
|
@ -650,7 +650,7 @@ impl<'a> HelperProcessInstruction<'a> for HelperProcessSolInstructionC<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl<'a> HelperObject<BPFError> for HelperProcessSolInstructionC<'a> {
|
impl<'a> SyscallObject<BPFError> for SyscallProcessSolInstructionC<'a> {
|
||||||
fn call(
|
fn call(
|
||||||
&mut self,
|
&mut self,
|
||||||
instruction_addr: u64,
|
instruction_addr: u64,
|
||||||
|
@ -676,7 +676,7 @@ impl<'a> HelperObject<BPFError> for HelperProcessSolInstructionC<'a> {
|
||||||
|
|
||||||
/// Call process instruction, common to both Rust and C
|
/// Call process instruction, common to both Rust and C
|
||||||
fn call<'a>(
|
fn call<'a>(
|
||||||
helper: &mut dyn HelperProcessInstruction<'a>,
|
syscall: &mut dyn SyscallProcessInstruction<'a>,
|
||||||
instruction_addr: u64,
|
instruction_addr: u64,
|
||||||
account_infos_addr: u64,
|
account_infos_addr: u64,
|
||||||
account_infos_len: u64,
|
account_infos_len: u64,
|
||||||
|
@ -685,22 +685,22 @@ fn call<'a>(
|
||||||
ro_regions: &[MemoryRegion],
|
ro_regions: &[MemoryRegion],
|
||||||
rw_regions: &[MemoryRegion],
|
rw_regions: &[MemoryRegion],
|
||||||
) -> Result<u64, EbpfError<BPFError>> {
|
) -> Result<u64, EbpfError<BPFError>> {
|
||||||
let mut invoke_context = helper.get_context_mut()?;
|
let mut invoke_context = syscall.get_context_mut()?;
|
||||||
|
|
||||||
// Translate data passed from the VM
|
// Translate data passed from the VM
|
||||||
|
|
||||||
let instruction = helper.translate_instruction(instruction_addr, ro_regions)?;
|
let instruction = syscall.translate_instruction(instruction_addr, ro_regions)?;
|
||||||
let message = Message::new(&[instruction]);
|
let message = Message::new(&[instruction]);
|
||||||
let program_id_index = message.instructions[0].program_id_index as usize;
|
let program_id_index = message.instructions[0].program_id_index as usize;
|
||||||
let program_id = message.account_keys[program_id_index];
|
let program_id = message.account_keys[program_id_index];
|
||||||
let (accounts, refs) = helper.translate_accounts(
|
let (accounts, refs) = syscall.translate_accounts(
|
||||||
&message,
|
&message,
|
||||||
account_infos_addr,
|
account_infos_addr,
|
||||||
account_infos_len as usize,
|
account_infos_len as usize,
|
||||||
ro_regions,
|
ro_regions,
|
||||||
rw_regions,
|
rw_regions,
|
||||||
)?;
|
)?;
|
||||||
let signers = helper.translate_signers(
|
let signers = syscall.translate_signers(
|
||||||
&program_id,
|
&program_id,
|
||||||
signers_seeds_addr,
|
signers_seeds_addr,
|
||||||
signers_seeds_len as usize,
|
signers_seeds_len as usize,
|
||||||
|
@ -712,7 +712,7 @@ fn call<'a>(
|
||||||
let program_account = (*accounts[program_id_index]).clone();
|
let program_account = (*accounts[program_id_index]).clone();
|
||||||
if program_account.borrow().owner != bpf_loader::id() {
|
if program_account.borrow().owner != bpf_loader::id() {
|
||||||
// Only BPF programs supported for now
|
// Only BPF programs supported for now
|
||||||
return Err(HelperError::ProgramNotSupported.into());
|
return Err(SyscallError::ProgramNotSupported.into());
|
||||||
}
|
}
|
||||||
let executable_accounts = vec![(program_id, program_account)];
|
let executable_accounts = vec![(program_id, program_account)];
|
||||||
|
|
||||||
|
@ -728,7 +728,7 @@ fn call<'a>(
|
||||||
Ok(()) => (),
|
Ok(()) => (),
|
||||||
Err(err) => match ProgramError::try_from(err) {
|
Err(err) => match ProgramError::try_from(err) {
|
||||||
Ok(err) => return Ok(err.into()),
|
Ok(err) => return Ok(err.into()),
|
||||||
Err(err) => return Err(HelperError::InstructionError(err).into()),
|
Err(err) => return Err(SyscallError::InstructionError(err).into()),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -858,16 +858,16 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "UserError(HelperError(Abort))")]
|
#[should_panic(expected = "UserError(SyscallError(Abort))")]
|
||||||
fn test_helper_abort() {
|
fn test_syscall_abort() {
|
||||||
let ro_region = MemoryRegion::default();
|
let ro_region = MemoryRegion::default();
|
||||||
let rw_region = MemoryRegion::default();
|
let rw_region = MemoryRegion::default();
|
||||||
helper_abort(0, 0, 0, 0, 0, &[ro_region], &[rw_region]).unwrap();
|
syscall_abort(0, 0, 0, 0, 0, &[ro_region], &[rw_region]).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[should_panic(expected = "UserError(HelperError(Panic(\"Gaggablaghblagh!\", 42, 84)))")]
|
#[should_panic(expected = "UserError(SyscallError(Panic(\"Gaggablaghblagh!\", 42, 84)))")]
|
||||||
fn test_helper_sol_panic() {
|
fn test_syscall_sol_panic() {
|
||||||
let string = "Gaggablaghblagh!";
|
let string = "Gaggablaghblagh!";
|
||||||
let addr = string.as_ptr() as *const _ as u64;
|
let addr = string.as_ptr() as *const _ as u64;
|
||||||
let ro_region = MemoryRegion {
|
let ro_region = MemoryRegion {
|
||||||
|
@ -876,7 +876,7 @@ mod tests {
|
||||||
len: string.len() as u64,
|
len: string.len() as u64,
|
||||||
};
|
};
|
||||||
let rw_region = MemoryRegion::default();
|
let rw_region = MemoryRegion::default();
|
||||||
helper_sol_panic(
|
syscall_sol_panic(
|
||||||
100,
|
100,
|
||||||
string.len() as u64,
|
string.len() as u64,
|
||||||
42,
|
42,
|
||||||
|
@ -892,7 +892,7 @@ mod tests {
|
||||||
// this results in the bad string length being ignored and not returning an error
|
// this results in the bad string length being ignored and not returning an error
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn test_helper_sol_log() {
|
fn test_syscall_sol_log() {
|
||||||
let string = "Gaggablaghblagh!";
|
let string = "Gaggablaghblagh!";
|
||||||
let addr = string.as_ptr() as *const _ as u64;
|
let addr = string.as_ptr() as *const _ as u64;
|
||||||
let ro_regions = &[MemoryRegion {
|
let ro_regions = &[MemoryRegion {
|
||||||
|
@ -902,9 +902,9 @@ mod tests {
|
||||||
}];
|
}];
|
||||||
let rw_regions = &[MemoryRegion::default()];
|
let rw_regions = &[MemoryRegion::default()];
|
||||||
solana_logger::setup_with_default("solana=info");
|
solana_logger::setup_with_default("solana=info");
|
||||||
helper_sol_log(100, string.len() as u64, 0, 0, 0, ro_regions, rw_regions).unwrap();
|
syscall_sol_log(100, string.len() as u64, 0, 0, 0, ro_regions, rw_regions).unwrap();
|
||||||
solana_logger::setup_with_default("solana=info");
|
solana_logger::setup_with_default("solana=info");
|
||||||
helper_sol_log(
|
syscall_sol_log(
|
||||||
100,
|
100,
|
||||||
string.len() as u64 * 2,
|
string.len() as u64 * 2,
|
||||||
0,
|
0,
|
||||||
|
@ -920,32 +920,32 @@ mod tests {
|
||||||
// this results in the bad string length being ignored and not returning an error
|
// this results in the bad string length being ignored and not returning an error
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
fn test_helper_sol_log_u64() {
|
fn test_syscall_sol_log_u64() {
|
||||||
solana_logger::setup_with_default("solana=info");
|
solana_logger::setup_with_default("solana=info");
|
||||||
|
|
||||||
let ro_regions = &[MemoryRegion::default()];
|
let ro_regions = &[MemoryRegion::default()];
|
||||||
let rw_regions = &[MemoryRegion::default()];
|
let rw_regions = &[MemoryRegion::default()];
|
||||||
helper_sol_log_u64(1, 2, 3, 4, 5, ro_regions, rw_regions).unwrap();
|
syscall_sol_log_u64(1, 2, 3, 4, 5, ro_regions, rw_regions).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_helper_sol_alloc_free() {
|
fn test_syscall_sol_alloc_free() {
|
||||||
// large alloc
|
// large alloc
|
||||||
{
|
{
|
||||||
let heap = vec![0_u8; 100];
|
let heap = vec![0_u8; 100];
|
||||||
let ro_regions = &[MemoryRegion::default()];
|
let ro_regions = &[MemoryRegion::default()];
|
||||||
let rw_regions = &[MemoryRegion::new_from_slice(&heap, MM_HEAP_START)];
|
let rw_regions = &[MemoryRegion::new_from_slice(&heap, MM_HEAP_START)];
|
||||||
let mut helper = HelperSolAllocFree {
|
let mut syscall = SyscallSolAllocFree {
|
||||||
allocator: BPFAllocator::new(heap, MM_HEAP_START),
|
allocator: BPFAllocator::new(heap, MM_HEAP_START),
|
||||||
};
|
};
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
helper
|
syscall
|
||||||
.call(100, 0, 0, 0, 0, ro_regions, rw_regions)
|
.call(100, 0, 0, 0, 0, ro_regions, rw_regions)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
helper
|
syscall
|
||||||
.call(100, 0, 0, 0, 0, ro_regions, rw_regions)
|
.call(100, 0, 0, 0, 0, ro_regions, rw_regions)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
0
|
0
|
||||||
|
@ -956,17 +956,17 @@ mod tests {
|
||||||
let heap = vec![0_u8; 100];
|
let heap = vec![0_u8; 100];
|
||||||
let ro_regions = &[MemoryRegion::default()];
|
let ro_regions = &[MemoryRegion::default()];
|
||||||
let rw_regions = &[MemoryRegion::new_from_slice(&heap, MM_HEAP_START)];
|
let rw_regions = &[MemoryRegion::new_from_slice(&heap, MM_HEAP_START)];
|
||||||
let mut helper = HelperSolAllocFree {
|
let mut syscall = SyscallSolAllocFree {
|
||||||
allocator: BPFAllocator::new(heap, MM_HEAP_START),
|
allocator: BPFAllocator::new(heap, MM_HEAP_START),
|
||||||
};
|
};
|
||||||
for _ in 0..100 {
|
for _ in 0..100 {
|
||||||
assert_ne!(
|
assert_ne!(
|
||||||
helper.call(1, 0, 0, 0, 0, ro_regions, rw_regions).unwrap(),
|
syscall.call(1, 0, 0, 0, 0, ro_regions, rw_regions).unwrap(),
|
||||||
0
|
0
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
helper
|
syscall
|
||||||
.call(100, 0, 0, 0, 0, ro_regions, rw_regions)
|
.call(100, 0, 0, 0, 0, ro_regions, rw_regions)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
0
|
0
|
|
@ -126,14 +126,13 @@ static_assert(sizeof(uint64_t) == 8);
|
||||||
#define SOL_FN_PREFIX __attribute__((always_inline)) static
|
#define SOL_FN_PREFIX __attribute__((always_inline)) static
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function that prints a string to stdout
|
* Prints a string to stdout
|
||||||
*/
|
*/
|
||||||
void sol_log_(const char *, uint64_t);
|
void sol_log_(const char *, uint64_t);
|
||||||
#define sol_log(message) sol_log_(message, sol_strlen(message))
|
#define sol_log(message) sol_log_(message, sol_strlen(message))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function that prints a 64 bit values represented in hexadecimal
|
* Prints a 64 bit values represented in hexadecimal to stdout
|
||||||
* to stdout
|
|
||||||
*/
|
*/
|
||||||
void sol_log_64(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
|
void sol_log_64(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t);
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
//! @brief Solana Rust-based BPF program utility functions and types
|
//! @brief Stubs for syscalls when building tests for x86
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
|
Loading…
Reference in New Issue