From 24c9507c2d6529699edca9b2479d7e4f1a3415e6 Mon Sep 17 00:00:00 2001 From: Johannes Stoelp Date: Mon, 27 Feb 2023 22:28:40 +0100 Subject: Add minimal runtime to execute code --- src/lib.rs | 1 + src/rt.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 src/rt.rs (limited to 'src') diff --git a/src/lib.rs b/src/lib.rs index 3368e3d..4a7b73e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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(&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"); + } + } +} -- cgit v1.2.3