use std::{io, ptr::NonNull};
use libc::{mmap, mprotect, munmap, MAP_ANON, MAP_PRIVATE, PROT_EXEC, PROT_READ, PROT_WRITE};
pub fn get_page_size() -> usize {
unsafe {
libc::sysconf(libc::_SC_PAGESIZE) as usize
}
}
pub fn alloc_rw(size: usize) -> io::Result<NonNull<u8>> {
unsafe {
let ptr = mmap(std::ptr::null_mut(), size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
if ptr == libc::MAP_FAILED {
return Err(io::Error::last_os_error());
}
Ok(NonNull::new_unchecked(ptr as *mut u8))
}
}
pub unsafe fn dealloc(ptr: *mut u8, size: usize) {
unsafe {
munmap(ptr as *mut _, size);
}
}
pub unsafe fn make_executable(ptr: *mut u8, size: usize) -> io::Result<()> {
unsafe {
if mprotect(ptr as _, size, PROT_READ | PROT_EXEC) != 0 {
return Err(io::Error::last_os_error());
}
}
Ok(())
}
pub unsafe fn make_writable(ptr: *mut u8, size: usize) -> io::Result<()> {
unsafe {
if mprotect(ptr as _, size, PROT_READ | PROT_WRITE) != 0 {
return Err(io::Error::last_os_error());
}
}
Ok(())
}
pub unsafe fn write_protect_scoped<F, R>(ptr: *mut u8, size: usize, f: F) -> io::Result<R>
where
F: FnOnce() -> R,
{
unsafe {
if mprotect(ptr as _, size, PROT_READ | PROT_WRITE) != 0 {
return Err(io::Error::last_os_error());
}
}
Ok(f())
}