More general runtime

trunk
Erin 2023-11-26 04:13:30 +01:00
parent 84cc1db691
commit 8c257e9216
7 changed files with 49 additions and 245 deletions

88
Cargo.lock generated
View File

@ -220,8 +220,7 @@ name = "hbxrt"
version = "0.1.0"
dependencies = [
"hbvm",
"nix",
"windows",
"memmap2",
]
[[package]]
@ -257,6 +256,15 @@ version = "2.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
[[package]]
name = "memmap2"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "deaba38d7abf1d4cca21cc89e932e542ba2b9258664d2a9ef0e61512039c9375"
dependencies = [
"libc",
]
[[package]]
name = "miniz_oxide"
version = "0.7.1"
@ -528,82 +536,6 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "windows"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
dependencies = [
"windows-core",
"windows-targets",
]
[[package]]
name = "windows-core"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
[[package]]
name = "windows_i686_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
[[package]]
name = "windows_i686_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "with_builtin_macros"
version = "0.0.3"

View File

@ -6,16 +6,4 @@ default-run = "hbxrt"
[dependencies]
hbvm.path = "../hbvm"
[target.'cfg(unix)'.dependencies]
nix = { version = "0.27", features = ["mman", "signal"] }
[target.'cfg(windows)'.dependencies.windows]
version = "0.52"
features = [
"Win32_Foundation",
"Win32_System_Memory",
"Win32_System_SystemServices",
"Win32_Security",
"Win32_Storage_FileSystem",
]
memmap2 = "0.9"

View File

@ -2,43 +2,50 @@
#![deny(unsafe_op_in_unsafe_fn)]
#[cfg(unix)]
#[path = "unix.rs"]
mod platform;
#[cfg(windows)]
#[path = "win32.rs"]
mod platform;
mod eca;
mod mem;
use {
hbvm::{mem::Address, Vm, VmRunOk},
std::{env::args, process::exit},
memmap2::Mmap,
std::{env::args, fs::File, io::Read, mem::MaybeUninit, process::exit},
};
type RtVm = Vm<mem::HostMemory, 0>;
fn main() -> Result<(), Box<dyn std::error::Error>> {
eprintln!("== HB×RT (Holey Bytes Experimental Runtime) v0.1 ==");
eprintln!("[W] Currently supporting only flat images");
let Some(image_path) = args().nth(1) else {
let mut args = args().skip(1);
let Some(image_path) = args.next() else {
eprintln!("[E] Missing image path");
exit(1);
};
let dsls = args.next().as_deref() == Some("-L");
if cfg!(not(target_os = "linux")) && dsls {
eprintln!("[E] Unsupported platform for Direct Linux syscall mode");
exit(1);
}
if dsls {
eprintln!("[I] Direct Linux syscall mode activated")
}
// Allocate stack
let stack_ptr = unsafe { platform::alloc_stack(1024 * 1024 * 2) }?;
eprintln!("[I] Stack allocated at {stack_ptr:p}");
let mut stack = Box::new(MaybeUninit::<[u8; 1024 * 1024 * 2]>::uninit());
eprintln!("[I] Stack allocated at {:p}", stack.as_ptr());
// Load program
eprintln!("[I] Loading image from \"{image_path}\"");
let ptr = unsafe { platform::mmap_bytecode(image_path) }?;
eprintln!("[I] Image loaded at {ptr:p}");
let file_handle = File::open(image_path)?;
let mmap = unsafe { Mmap::map(&file_handle) }?;
let mut vm = unsafe { Vm::<_, 0>::new(mem::HostMemory, Address::new(ptr as u64)) };
vm.write_reg(254, stack_ptr as u64);
eprintln!("[I] Image loaded at {:p}", mmap.as_ptr());
unsafe { platform::catch_mafs() }?;
let mut vm = unsafe { Vm::<_, 0>::new(mem::HostMemory, Address::new(mmap.as_ptr() as u64)) };
vm.write_reg(254, stack.as_mut_ptr() as u64);
// Execute program
let stat = loop {
@ -48,7 +55,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
vm.pc, vm.registers
),
Ok(VmRunOk::Timer) => (),
Ok(VmRunOk::Ecall) => unsafe {
Ok(VmRunOk::Ecall) if dsls => unsafe {
std::arch::asm!(
"syscall",
inlateout("rax") vm.registers[1].0,
@ -60,6 +67,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
in("r9") vm.registers[7].0,
)
},
Ok(VmRunOk::Ecall) => {
eprintln!("[E] General environment calls not supported");
exit(1);
}
Ok(VmRunOk::End) => break Ok(()),
Err(e) => break Err(e),
}

View File

@ -1,67 +0,0 @@
use {
nix::sys::mman::{mmap, MapFlags, ProtFlags},
std::{fs::File, num::NonZeroUsize, path::Path, process::exit},
};
/// Allocate stack for program
pub unsafe fn alloc_stack(size: usize) -> nix::Result<*mut u8> {
unsafe {
Ok(mmap::<std::fs::File>(
None,
NonZeroUsize::new(size).expect("Stack size should be > 0"),
ProtFlags::PROT_GROWSDOWN | ProtFlags::PROT_READ | ProtFlags::PROT_WRITE,
MapFlags::MAP_GROWSDOWN
| MapFlags::MAP_STACK
| MapFlags::MAP_ANON
| MapFlags::MAP_PRIVATE,
None,
0,
)?
.cast())
}
}
/// Memory map bytecode
pub unsafe fn mmap_bytecode(path: impl AsRef<Path>) -> Result<*mut u8, Box<dyn std::error::Error>> {
let file = File::open(&path)?;
Ok(unsafe {
mmap(
None,
NonZeroUsize::new(file.metadata()?.len() as usize).ok_or("File is empty")?,
ProtFlags::PROT_READ,
MapFlags::MAP_PRIVATE,
Some(&file),
0,
)?
.cast()
})
}
/// Set handler for page fault
pub unsafe fn catch_mafs() -> nix::Result<()> {
unsafe {
use nix::sys::signal;
extern "C" fn action(
_: std::ffi::c_int,
info: *mut nix::libc::siginfo_t,
_: *mut std::ffi::c_void,
) {
unsafe {
eprintln!("[E] Memory access fault at {:p}", (*info).si_addr());
exit(2);
}
}
signal::sigaction(
signal::Signal::SIGSEGV,
&nix::sys::signal::SigAction::new(
signal::SigHandler::SigAction(action),
signal::SaFlags::SA_NODEFER,
nix::sys::signalfd::SigSet::empty(),
),
)?;
}
Ok(())
}

View File

@ -1,69 +0,0 @@
use {
std::path::Path,
windows::{
core::PCSTR,
Win32::{
Foundation::{GetLastError, GENERIC_READ},
Storage::FileSystem,
System::{
Memory::{self},
SystemServices::{self},
},
},
},
};
/// Allocates tack for the program
pub unsafe fn alloc_stack(size: usize) -> windows::core::Result<*mut u8> {
let ptr = unsafe {
Memory::VirtualAlloc(
None,
size,
Memory::VIRTUAL_ALLOCATION_TYPE(SystemServices::MEM_TOP_DOWN) | Memory::MEM_COMMIT,
Memory::PAGE_READWRITE,
)
};
if ptr.is_null() {
unsafe { GetLastError() }?;
}
Ok(ptr.cast())
}
/// Memory map bytecode
pub unsafe fn mmap_bytecode(path: impl AsRef<Path>) -> windows::core::Result<*mut u8> {
unsafe {
let file = FileSystem::CreateFileA(
PCSTR(path.as_ref().as_os_str().as_encoded_bytes().as_ptr()),
GENERIC_READ.0,
FileSystem::FILE_SHARE_READ,
None,
FileSystem::OPEN_EXISTING,
FileSystem::FILE_ATTRIBUTE_NORMAL,
None,
)?;
let h = Memory::CreateFileMappingA(
file,
None,
Memory::PAGE_READONLY,
0,
0,
PCSTR("Bytecode\0".as_ptr()),
)?;
let addr = Memory::MapViewOfFile(h, Memory::FILE_MAP_READ, 0, 0, 0);
if addr.Value.is_null() {
GetLastError()?;
}
Ok(addr.Value.cast())
}
}
/// Catch memory access faults
pub unsafe fn catch_mafs() -> std::io::Result<()> {
Ok(())
}

BIN
program.hbf Normal file

Binary file not shown.

9
test.hba Normal file
View File

@ -0,0 +1,9 @@
let hello = data::str("Hello, world!");
li8(r1, 6);
li8(r2, 10);
lra16(r3, r0, hello);
li8(r4, hello.len);
eca();
tx();