diff options
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/rt.rs | 51 |
3 files changed, 53 insertions, 0 deletions
@@ -4,3 +4,4 @@ version = "0.1.0" edition = "2021" [dependencies] +nix = "0.26.2" @@ -1,4 +1,5 @@ pub mod prelude; +pub mod rt; mod imm; mod insn; diff --git a/src/rt.rs b/src/rt.rs new file mode 100644 index 0000000..fc8c930 --- /dev/null +++ b/src/rt.rs @@ -0,0 +1,51 @@ +use core::ffi::c_void; +use nix::sys::mman::{mmap, munmap, MapFlags, ProtFlags}; + +/// A simple `mmap`ed runtime with executable pages. +pub struct Runtime { + buf: *mut c_void, + len: usize, +} + +impl Runtime { + /// Create a new [Runtime]. + pub fn new(code: &[u8]) -> Runtime { + // Allocate a single page. + let len = core::num::NonZeroUsize::new(4096).unwrap(); + let buf = unsafe { + mmap( + None, + len, + ProtFlags::PROT_WRITE | ProtFlags::PROT_READ | ProtFlags::PROT_EXEC, + MapFlags::MAP_PRIVATE | MapFlags::MAP_ANONYMOUS, + 0, /* fd */ + 0, /* off */ + ) + .unwrap() + }; + { + // Copy over code. + assert!(code.len() < len.get()); + unsafe { std::ptr::copy_nonoverlapping(code.as_ptr(), buf.cast(), len.get()) }; + } + + Runtime { + buf, + len: len.get(), + } + } + + /// Reinterpret the block of code as `F`. + #[inline] + pub unsafe fn as_fn<F>(&self) -> F { + unsafe { std::mem::transmute_copy(&self.buf) } + } +} + +impl Drop for Runtime { + fn drop(&mut self) { + unsafe { + munmap(self.buf, self.len).expect("Failed to munmap Runtime"); + } + } +} |