diff options
author | Johannes Stoelp <johannes.stoelp@gmail.com> | 2023-02-27 22:28:40 +0100 |
---|---|---|
committer | Johannes Stoelp <johannes.stoelp@gmail.com> | 2023-02-27 22:40:26 +0100 |
commit | 24c9507c2d6529699edca9b2479d7e4f1a3415e6 (patch) | |
tree | dd8a81c80b64ca3f8af9ed16536efbfcd87236c9 /src | |
parent | fed6ae454f659f4d2b36520474d1998b526a27dd (diff) | |
download | juicebox-asm-24c9507c2d6529699edca9b2479d7e4f1a3415e6.tar.gz juicebox-asm-24c9507c2d6529699edca9b2479d7e4f1a3415e6.zip |
Add minimal runtime to execute code
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 1 | ||||
-rw-r--r-- | src/rt.rs | 51 |
2 files changed, 52 insertions, 0 deletions
@@ -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"); + } + } +} |