Add memory operation syscalls (#16447)
This commit is contained in:
@ -30,6 +30,7 @@ pub mod native_token;
|
||||
pub mod nonce;
|
||||
pub mod program;
|
||||
pub mod program_error;
|
||||
pub mod program_memory;
|
||||
pub mod program_option;
|
||||
pub mod program_pack;
|
||||
pub mod program_stubs;
|
||||
|
89
sdk/program/src/program_memory.rs
Normal file
89
sdk/program/src/program_memory.rs
Normal file
@ -0,0 +1,89 @@
|
||||
//! @brief Solana Rust-based BPF memory operations
|
||||
|
||||
/// Memcpy
|
||||
///
|
||||
/// @param dst - Destination
|
||||
/// @param src - Source
|
||||
/// @param n - Number of bytes to copy
|
||||
#[inline]
|
||||
pub fn sol_memcpy(dst: &mut [u8], src: &[u8], n: usize) {
|
||||
#[cfg(target_arch = "bpf")]
|
||||
{
|
||||
extern "C" {
|
||||
fn sol_memcpy_(dst: *mut u8, src: *const u8, n: u64);
|
||||
}
|
||||
unsafe {
|
||||
sol_memcpy_(dst.as_mut_ptr(), src.as_ptr(), n as u64);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "bpf"))]
|
||||
crate::program_stubs::sol_memcpy(dst.as_mut_ptr(), src.as_ptr(), n);
|
||||
}
|
||||
|
||||
/// Memmove
|
||||
///
|
||||
/// @param dst - Destination
|
||||
/// @param src - Source
|
||||
/// @param n - Number of bytes to copy
|
||||
///
|
||||
/// # Safety
|
||||
#[inline]
|
||||
pub unsafe fn sol_memmove(dst: *mut u8, src: *mut u8, n: usize) {
|
||||
#[cfg(target_arch = "bpf")]
|
||||
{
|
||||
extern "C" {
|
||||
fn sol_memmove_(dst: *mut u8, src: *const u8, n: u64);
|
||||
}
|
||||
sol_memmove_(dst, src, n as u64);
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "bpf"))]
|
||||
crate::program_stubs::sol_memmove(dst, src, n);
|
||||
}
|
||||
|
||||
/// Memcmp
|
||||
///
|
||||
/// @param s1 - Slice to be compared
|
||||
/// @param s2 - Slice to be compared
|
||||
/// @param n - Number of bytes to compare
|
||||
#[inline]
|
||||
pub fn sol_memcmp(s1: &[u8], s2: &[u8], n: usize) -> i32 {
|
||||
let mut result = 0;
|
||||
|
||||
#[cfg(target_arch = "bpf")]
|
||||
{
|
||||
extern "C" {
|
||||
fn sol_memcmp_(s1: *const u8, s2: *const u8, n: u64, result: *mut i32);
|
||||
}
|
||||
unsafe {
|
||||
sol_memcmp_(s1.as_ptr(), s2.as_ptr(), n as u64, &mut result as *mut i32);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "bpf"))]
|
||||
crate::program_stubs::sol_memcmp(s1.as_ptr(), s2.as_ptr(), n, &mut result as *mut i32);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Memset
|
||||
///
|
||||
/// @param s1 - Slice to be compared
|
||||
/// @param s2 - Slice to be compared
|
||||
/// @param n - Number of bytes to compare
|
||||
#[inline]
|
||||
pub fn sol_memset(s: &mut [u8], c: u8, n: usize) {
|
||||
#[cfg(target_arch = "bpf")]
|
||||
{
|
||||
extern "C" {
|
||||
fn sol_memset_(s: *mut u8, c: u8, n: u64);
|
||||
}
|
||||
unsafe {
|
||||
sol_memset_(s.as_mut_ptr(), c, n as u64);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "bpf"))]
|
||||
crate::program_stubs::sol_memset(s.as_mut_ptr(), c, n);
|
||||
}
|
@ -12,12 +12,13 @@ lazy_static::lazy_static! {
|
||||
static ref SYSCALL_STUBS: Arc<RwLock<Box<dyn SyscallStubs>>> = Arc::new(RwLock::new(Box::new(DefaultSyscallStubs {})));
|
||||
}
|
||||
|
||||
// The default syscall stubs don't do much, but `set_syscalls()` can be used to swap in
|
||||
// alternatives
|
||||
// The default syscall stubs may not do much, but `set_syscalls()` can be used
|
||||
// to swap in alternatives
|
||||
pub fn set_syscall_stubs(syscall_stubs: Box<dyn SyscallStubs>) -> Box<dyn SyscallStubs> {
|
||||
std::mem::replace(&mut SYSCALL_STUBS.write().unwrap(), syscall_stubs)
|
||||
}
|
||||
|
||||
#[allow(clippy::integer_arithmetic)]
|
||||
pub trait SyscallStubs: Sync + Send {
|
||||
fn sol_log(&self, message: &str) {
|
||||
println!("{}", message);
|
||||
@ -34,7 +35,6 @@ pub trait SyscallStubs: Sync + Send {
|
||||
sol_log("SyscallStubs: sol_invoke_signed() not available");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sol_get_clock_sysvar(&self, _var_addr: *mut u8) -> u64 {
|
||||
UNSUPPORTED_SYSVAR
|
||||
}
|
||||
@ -47,6 +47,39 @@ pub trait SyscallStubs: Sync + Send {
|
||||
fn sol_get_rent_sysvar(&self, _var_addr: *mut u8) -> u64 {
|
||||
UNSUPPORTED_SYSVAR
|
||||
}
|
||||
/// # Safety
|
||||
unsafe fn sol_memcpy(&self, dst: *mut u8, src: *const u8, n: usize) {
|
||||
// cannot be overlapping
|
||||
if dst as usize + n > src as usize && src as usize > dst as usize {
|
||||
panic!("memcpy does not support oveerlapping regions");
|
||||
}
|
||||
std::ptr::copy_nonoverlapping(src, dst, n as usize);
|
||||
}
|
||||
/// # Safety
|
||||
unsafe fn sol_memmove(&self, dst: *mut u8, src: *const u8, n: usize) {
|
||||
std::ptr::copy(src, dst, n as usize);
|
||||
}
|
||||
/// # Safety
|
||||
unsafe fn sol_memcmp(&self, s1: *const u8, s2: *const u8, n: usize, result: *mut i32) {
|
||||
let mut i = 0;
|
||||
while i < n {
|
||||
let a = *s1.add(i);
|
||||
let b = *s2.add(i);
|
||||
if a != b {
|
||||
*result = a as i32 - b as i32;
|
||||
return;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
*result = 0
|
||||
}
|
||||
/// # Safety
|
||||
unsafe fn sol_memset(&self, s: *mut u8, c: u8, n: usize) {
|
||||
let s = std::slice::from_raw_parts_mut(s, n);
|
||||
for val in s.iter_mut().take(n) {
|
||||
*val = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DefaultSyscallStubs {}
|
||||
@ -96,3 +129,27 @@ pub(crate) fn sol_get_fees_sysvar(var_addr: *mut u8) -> u64 {
|
||||
pub(crate) fn sol_get_rent_sysvar(var_addr: *mut u8) -> u64 {
|
||||
SYSCALL_STUBS.read().unwrap().sol_get_rent_sysvar(var_addr)
|
||||
}
|
||||
|
||||
pub(crate) fn sol_memcpy(dst: *mut u8, src: *const u8, n: usize) {
|
||||
unsafe {
|
||||
SYSCALL_STUBS.read().unwrap().sol_memcpy(dst, src, n);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn sol_memmove(dst: *mut u8, src: *const u8, n: usize) {
|
||||
unsafe {
|
||||
SYSCALL_STUBS.read().unwrap().sol_memmove(dst, src, n);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn sol_memcmp(s1: *const u8, s2: *const u8, n: usize, result: *mut i32) {
|
||||
unsafe {
|
||||
SYSCALL_STUBS.read().unwrap().sol_memcmp(s1, s2, n, result);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn sol_memset(s: *mut u8, c: u8, n: usize) {
|
||||
unsafe {
|
||||
SYSCALL_STUBS.read().unwrap().sol_memset(s, c, n);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user