#[cfg(feature = "loader")]
use crate::errors::{DonutError, DonutResult};
#[cfg(feature = "loader")]
use alloc::vec::Vec;
#[cfg(feature = "loader")]
use azathoth_core::os::linux::consts::O_RDONLY;
#[cfg(feature = "loader")]
#[unsafe(link_section = ".text")]
pub fn read_file(path: &str) -> DonutResult<Vec<u8>> {
let c_path = path.as_bytes();
let mut null_terminated = Vec::with_capacity(c_path.len());
null_terminated.extend_from_slice(c_path);
null_terminated.push(0);
let fd = open(&null_terminated, O_RDONLY as u32);
if fd < 0 {
return Err(DonutError::NotFound("".into()));
}
let mut buf = Vec::new();
let mut tmp = [0u8; 4096];
loop {
let n = read(fd as _, tmp.as_mut_ptr(), tmp.len());
if n < 0 {
close(fd as u32);
return Err(DonutError::ParseFailed);
}
if n == 0 {
break;
}
buf.extend_from_slice(&tmp[..n as usize]);
}
close(fd as u32);
Ok(buf)
}
#[unsafe(link_section = ".text")]
pub fn parse_hex(bytes: &[u8]) -> Option<usize> {
core::str::from_utf8(bytes)
.ok()
.and_then(|s| usize::from_str_radix(s, 16).ok())
}
#[unsafe(link_section = ".text")]
pub fn sys_exit(code: usize) -> ! {
unsafe {
const SYS_EXIT: usize = 60;
azathoth_core::os::linux::syscalls::syscall3(SYS_EXIT, code, 0, 0);
core::hint::unreachable_unchecked();
}
}
#[inline(always)]
pub fn close(fd: u32) {
#[cfg(feature = "libc")]
unsafe {
libc::close(fd as _);
}
#[cfg(not(feature="libc"))]
azathoth_core::os::linux::syscalls::syscall3(crate::platform::linux::consts::SYS_CLOSE, fd as usize, 0, 0);
}
#[inline(always)]
pub unsafe fn execve(filename: *const u8, argv: *const *const u8, envp: *const *const u8) -> isize {
unsafe {
let ret: isize;
const SYS_EXECVE: u32 = 59;
core::arch::asm!(
"syscall",
in("rax") SYS_EXECVE,
in("rdi") filename,
in("rsi") argv,
in("rdx") envp,
lateout("rax") ret,
options(nostack, preserves_flags),
);
ret
}
}
#[inline(always)]
pub unsafe fn memfd_create(name: *const u8, flags: u32) -> isize {
const SYS_MEMFD_CREATE: u32 = 319;
azathoth_core::os::linux::syscalls::syscall2(SYS_MEMFD_CREATE as usize, name as usize, flags as usize)
}
#[inline(always)]
pub unsafe fn fork() -> isize {
const SYS_FORK: u32 = 57; unsafe {
let ret: isize;
core::arch::asm!(
"syscall",
in("rax") SYS_FORK,
lateout("rax") ret,
options(nostack, preserves_flags),
);
ret
}
}
#[unsafe(link_section = ".text")]
#[inline(always)]
pub unsafe fn write(fd: usize, buf: *const u8, count: usize) -> isize {
azathoth_core::os::linux::syscalls::syscall3(crate::platform::linux::consts::SYS_WRITE, fd, buf as usize, count)
}
#[cfg(feature = "loader")]
pub fn open(path: &[u8], flags: u32) -> isize {
#[cfg(feature = "libc")]
unsafe { libc::open(path.as_ptr() as _, flags as _) as isize }
#[cfg(not(feature="libc"))]
azathoth_core::os::linux::syscalls::syscall3(
crate::platform::linux::consts::SYS_OPEN,
path.as_ptr() as usize,
flags as _,
0,
)
}
#[cfg(feature = "loader")]
pub fn read(fd: usize, buf: *mut u8, count: usize) -> isize {
#[cfg(feature = "libc")]
unsafe { libc::read(fd as _, buf as _, count as _) as isize }
#[cfg(not(feature = "libc"))]
azathoth_core::os::linux::syscalls::syscall3(
crate::platform::linux::consts::SYS_READ,
fd,
buf as usize,
count,
)
}
#[cfg(feature = "loader")]
pub fn lseek(fd: usize, offset: isize, whence: usize) -> isize {
#[cfg(feature="libc")]
unsafe { libc::lseek(fd as _, offset as _, whence as _) as isize }
#[cfg(not(feature="libc"))]
azathoth_core::os::linux::syscalls::syscall3(
crate::platform::linux::consts::SYS_LSEEK,
fd,
offset as usize,
whence as _,
)
}
#[cfg(not(target_os="windows"))]
pub fn pread(fd: usize, buf: *mut u8, count: usize, offset: usize) -> isize {
#[cfg(feature="libc")]
unsafe { libc::pread(fd as _, buf as _, count as _, offset as _) as isize }
#[cfg(not(feature="libc"))]
azathoth_core::os::linux::syscalls::syscall4(
crate::platform::linux::consts::SYS_PREAD64,
fd,
buf as usize,
count as _,
offset as _,
)
}
pub fn mmap(
addr: *mut u8,
len: usize,
prot: usize,
flags: u32,
fd: usize,
offset: usize,
) -> *mut u8 {
mmap_inner(addr, len, prot, flags, fd, offset)
}
#[cfg(not(feature = "libc"))]
fn mmap_inner(
addr: *mut u8,
len: usize,
prot: usize,
flags: u32,
fd: usize,
offset: usize,
) -> *mut u8 {
azathoth_core::os::linux::syscalls::syscall6(
crate::platform::linux::consts::SYS_MMAP,
addr as _,
len as _,
prot as _,
flags as _,
fd as _,
offset as _,
) as *mut u8
}
#[cfg(feature = "libc")]
fn mmap_inner(
addr: *mut u8,
len: usize,
prot: usize,
flags: u32,
fd: usize,
offset: usize,
) -> *mut u8 {
unsafe {
#[cfg(target_os = "linux")]
let ptr = libc::mmap(addr as _, len as _, prot as _, flags as _, fd as _, offset as _,) as *mut u8;
#[cfg(not(target_os = "linux"))]
let ptr = core::ptr::null_mut();
ptr
}
}