machinecode/
lib.rs

1use std::io;
2use std::fmt;
3
4// Error for copying machine code to executable memory
5#[derive(Debug, Clone)]
6pub struct MemCopyError;
7
8impl fmt::Display for MemCopyError {
9    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10        write!(f, "could not copy code over to the executable memory area")
11    }
12}
13
14impl std::error::Error for MemCopyError {}
15
16// Convert a space-separated hex string to a Vec<u8>
17pub fn string_to_bytes(hexstring: &str) -> Result<Vec<u8>, std::num::ParseIntError> {
18    hexstring.split_whitespace()
19        .map(|s| u8::from_str_radix(s, 16))
20        .collect()
21}
22
23// Execute machine code and return the value
24pub fn execute(code: &[u8]) -> Result<i32, Box<dyn std::error::Error>> {
25    let size = code.len();
26    let executable_area = unsafe {
27        libc::mmap(
28            std::ptr::null_mut(),
29            size,
30            libc::PROT_WRITE | libc::PROT_EXEC,
31            libc::MAP_ANONYMOUS | libc::MAP_PRIVATE,
32            -1,
33            0,
34        ) as *mut u8
35    };
36
37    if executable_area.is_null() {
38        return Err(Box::new(io::Error::last_os_error()));
39    }
40
41    unsafe {
42        std::ptr::copy_nonoverlapping(code.as_ptr(), executable_area, size);
43        let f: extern "C" fn() -> i32 = std::mem::transmute(executable_area);
44        Ok(f())
45    }
46}