#![cfg(not(feature = "use_libc"))]
#[cfg(target_os = "macos")]
const SYS_MMAP: i64 = 0x2000000 + 197;
#[cfg(target_os = "linux")]
const SYS_MMAP: i64 = 0x09;
pub const PROT_READ: u64 = 0x01; pub const PROT_WRITE: u64 = 0x02; const _PROT_EXEC: u64 = 0x04;
const _MAP_SHARED: u64 = 0x0001; pub const MAP_PRIVATE: u64 = 0x0002;
const _MAP_FIXED: u64 = 0x0010; const _MAP_RENAME: u64 = 0x0020; const _MAP_NORESERVE: u64 = 0x0040; const _MAP_RESERVED: u64 = 0x0080; const _MAP_NOEXTEND: u64 = 0x0100; const _MAP_HASSEMAPHORE: u64 = 0x0200; const _MAP_NOCACHE: u64 = 0x0400; const _MAP_JIT: u64 = 0x0800;
const _MAP_FILE: u64 = 0x0000; #[cfg(target_os = "macos")]
pub const MAP_ANON: u64 = 0x1000; #[cfg(target_os = "linux")]
pub const MAP_ANON: u64 = 0x20;
const _MAP_ANONYMOUS: u64 = MAP_ANON;
#[derive(Debug)]
pub struct MmapError {
code: i64,
}
#[cfg(all(not(feature = "use_libc"), target_os = "linux"))]
pub unsafe fn mmap(
addr: *mut u8,
len: usize,
prot: u64,
flags: u64,
fd: u64,
offset: i64,
) -> Result<*mut u8, MmapError> {
let addr = addr as i64;
let out_addr: i64;
asm!(
r"
syscall
",
inout("eax") SYS_MMAP => out_addr,
in("edi") addr,
in("esi") len,
in("edx") prot,
in("r10d") flags,
in("r8d") fd,
in("r9d") offset,
);
if out_addr < 0 {
return Err(MmapError { code: (-out_addr) });
}
Ok(out_addr as *mut u8)
}
#[cfg(all(not(feature = "use_libc"), target_os = "macos"))]
pub unsafe fn mmap(
addr: *mut u8,
len: usize,
prot: u64,
flags: u64,
fd: u64,
offset: i64,
) -> Result<*mut u8, MmapError> {
let addr = addr as i64;
let out_addr: i64;
let err: i64;
asm!(
r"
// Make a syscall, using the parameters in the registers
syscall
// osx sets the carry bit if there's an error. If that happens, we jump
// to label 1
jc 1f
// Set edx to 0 to indicate no error
mov edx, 0
// Jump to label 2 to finish this
jmp 2f
1:
// There was an error. Set edx to 1 to indicate that.
mov edx, 1
2:
",
inout("eax") SYS_MMAP => out_addr,
in("edi") addr,
in("esi") len,
inout("edx") prot => err,
in("r10d") flags,
in("r8d") fd,
in("r9d") offset,
);
if err != 0 {
return Err(MmapError { code: out_addr });
}
Ok(out_addr as *mut u8)
}
#[cfg(test)]
mod tests {
use super::*;
use test_env_log::test;
#[test]
fn test_mmap() {
let ptr = unsafe {
mmap(
core::ptr::null_mut(),
8,
PROT_WRITE | PROT_READ,
MAP_ANON | MAP_PRIVATE,
0,
0,
)
};
assert!(ptr.is_ok(), "Error: {:?}", ptr.unwrap_err());
}
#[test]
fn test_mmap_err() {
let ptr = unsafe {
mmap(
core::ptr::null_mut(),
8,
PROT_WRITE | PROT_READ,
0,
0,
0,
)
};
assert!(ptr.is_err());
}
}