#![allow(clippy::arithmetic_side_effects)]
#![allow(clippy::too_many_arguments)]
use crate::{declare_builtin_function, memory_region::AccessType, test_utils::TestContextObject};
use std::str::from_utf8;
declare_builtin_function!(
SyscallTracePrintf,
fn rust(
_context_object: &mut TestContextObject,
_arg1: u64,
_arg2: u64,
arg3: u64,
arg4: u64,
arg5: u64,
) -> Result<u64, Box<dyn std::error::Error>> {
println!("bpf_trace_printf: {arg3:#x}, {arg4:#x}, {arg5:#x}");
let size_arg = |x| {
if x == 0 {
1
} else {
(x as f64).log(16.0).floor() as u64 + 1
}
};
Ok("bpf_trace_printf: 0x, 0x, 0x\n".len() as u64
+ size_arg(arg3)
+ size_arg(arg4)
+ size_arg(arg5))
}
);
declare_builtin_function!(
SyscallGatherBytes,
fn rust(
_context_object: &mut TestContextObject,
arg1: u64,
arg2: u64,
arg3: u64,
arg4: u64,
arg5: u64,
) -> Result<u64, Box<dyn std::error::Error>> {
Ok(arg1.wrapping_shl(32)
| arg2.wrapping_shl(24)
| arg3.wrapping_shl(16)
| arg4.wrapping_shl(8)
| arg5)
}
);
declare_builtin_function!(
SyscallMemFrob,
fn rust(
context_object: &mut TestContextObject,
vm_addr: u64,
len: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
) -> Result<u64, Box<dyn std::error::Error>> {
if len == 0 {
return Ok(0);
}
let buf = Result::from(
context_object
.memory_mapping
.map(AccessType::Store, vm_addr, len),
)?;
unsafe {
for p in buf.ptr_mut().as_mut_unchecked() {
*p ^= 0b101010;
}
}
Ok(0)
}
);
declare_builtin_function!(
SyscallStrCmp,
fn rust(
context_object: &mut TestContextObject,
arg1: u64,
arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
) -> Result<u64, Box<dyn std::error::Error>> {
if arg1 == 0 || arg2 == 0 {
return Ok(u64::MAX);
}
let mut a = Result::from(context_object.memory_mapping.map(AccessType::Load, arg1, 1))?
.ptr()
.cast::<u8>();
let mut b = Result::from(context_object.memory_mapping.map(AccessType::Load, arg2, 1))?
.ptr()
.cast::<u8>();
unsafe {
let (mut a_val, mut b_val) = (*a, *b);
while a_val == b_val && a_val != 0 && b_val != 0 {
(a, b) = (a.add(1), b.add(1));
(a_val, b_val) = (*a, *b);
}
if a_val >= b_val {
Ok((a_val - b_val) as u64)
} else {
Ok((b_val - a_val) as u64)
}
}
}
);
declare_builtin_function!(
SyscallString,
fn rust(
context_object: &mut TestContextObject,
vm_addr: u64,
len: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
) -> Result<u64, Box<dyn std::error::Error>> {
if len == 0 {
return Ok(0);
}
let host_buffer = Result::from(context_object.memory_mapping.map(
AccessType::Load,
vm_addr,
len,
))?;
unsafe {
let c_buf = host_buffer.ptr().as_ref_unchecked();
let len = c_buf.iter().position(|c| *c == 0).unwrap_or(len as usize);
let message = from_utf8(&c_buf[0..len]).unwrap_or("Invalid UTF-8 String");
println!("log: {message}");
}
Ok(0)
}
);
declare_builtin_function!(
SyscallU64,
fn rust(
context_object: &mut TestContextObject,
arg1: u64,
arg2: u64,
arg3: u64,
arg4: u64,
arg5: u64,
) -> Result<u64, Box<dyn std::error::Error>> {
println!(
"dump_64: {:#x}, {:#x}, {:#x}, {:#x}, {:#x}, {:?}",
arg1, arg2, arg3, arg4, arg5, &raw const context_object.memory_mapping
);
Ok(0)
}
);
declare_builtin_function!(
SyscallGenericTest<G: Clone>,
fn rust(
_context_object: &mut TestContextObject,
_arg1: u64,
_arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
) -> Result<u64, Box<dyn std::error::Error>> {
loop {
let _ = G::clone;
}
}
);