More general runtime
This commit is contained in:
parent
84cc1db691
commit
8c257e9216
88
Cargo.lock
generated
88
Cargo.lock
generated
|
@ -220,8 +220,7 @@ name = "hbxrt"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hbvm",
|
"hbvm",
|
||||||
"nix",
|
"memmap2",
|
||||||
"windows",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -257,6 +256,15 @@ version = "2.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memmap2"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "deaba38d7abf1d4cca21cc89e932e542ba2b9258664d2a9ef0e61512039c9375"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.7.1"
|
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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
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]]
|
[[package]]
|
||||||
name = "with_builtin_macros"
|
name = "with_builtin_macros"
|
||||||
version = "0.0.3"
|
version = "0.0.3"
|
||||||
|
|
|
@ -6,16 +6,4 @@ default-run = "hbxrt"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
hbvm.path = "../hbvm"
|
hbvm.path = "../hbvm"
|
||||||
|
memmap2 = "0.9"
|
||||||
[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",
|
|
||||||
]
|
|
||||||
|
|
|
@ -2,43 +2,50 @@
|
||||||
|
|
||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
#[cfg(unix)]
|
mod eca;
|
||||||
#[path = "unix.rs"]
|
|
||||||
mod platform;
|
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
#[path = "win32.rs"]
|
|
||||||
mod platform;
|
|
||||||
|
|
||||||
mod mem;
|
mod mem;
|
||||||
|
|
||||||
use {
|
use {
|
||||||
hbvm::{mem::Address, Vm, VmRunOk},
|
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>> {
|
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
eprintln!("== HB×RT (Holey Bytes Experimental Runtime) v0.1 ==");
|
eprintln!("== HB×RT (Holey Bytes Experimental Runtime) v0.1 ==");
|
||||||
eprintln!("[W] Currently supporting only flat images");
|
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");
|
eprintln!("[E] Missing image path");
|
||||||
exit(1);
|
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
|
// Allocate stack
|
||||||
let stack_ptr = unsafe { platform::alloc_stack(1024 * 1024 * 2) }?;
|
let mut stack = Box::new(MaybeUninit::<[u8; 1024 * 1024 * 2]>::uninit());
|
||||||
eprintln!("[I] Stack allocated at {stack_ptr:p}");
|
eprintln!("[I] Stack allocated at {:p}", stack.as_ptr());
|
||||||
|
|
||||||
// Load program
|
// Load program
|
||||||
eprintln!("[I] Loading image from \"{image_path}\"");
|
eprintln!("[I] Loading image from \"{image_path}\"");
|
||||||
let ptr = unsafe { platform::mmap_bytecode(image_path) }?;
|
let file_handle = File::open(image_path)?;
|
||||||
eprintln!("[I] Image loaded at {ptr:p}");
|
let mmap = unsafe { Mmap::map(&file_handle) }?;
|
||||||
|
|
||||||
let mut vm = unsafe { Vm::<_, 0>::new(mem::HostMemory, Address::new(ptr as u64)) };
|
eprintln!("[I] Image loaded at {:p}", mmap.as_ptr());
|
||||||
vm.write_reg(254, stack_ptr as u64);
|
|
||||||
|
|
||||||
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
|
// Execute program
|
||||||
let stat = loop {
|
let stat = loop {
|
||||||
|
@ -48,7 +55,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
vm.pc, vm.registers
|
vm.pc, vm.registers
|
||||||
),
|
),
|
||||||
Ok(VmRunOk::Timer) => (),
|
Ok(VmRunOk::Timer) => (),
|
||||||
Ok(VmRunOk::Ecall) => unsafe {
|
Ok(VmRunOk::Ecall) if dsls => unsafe {
|
||||||
std::arch::asm!(
|
std::arch::asm!(
|
||||||
"syscall",
|
"syscall",
|
||||||
inlateout("rax") vm.registers[1].0,
|
inlateout("rax") vm.registers[1].0,
|
||||||
|
@ -60,6 +67,10 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
in("r9") vm.registers[7].0,
|
in("r9") vm.registers[7].0,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
Ok(VmRunOk::Ecall) => {
|
||||||
|
eprintln!("[E] General environment calls not supported");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
Ok(VmRunOk::End) => break Ok(()),
|
Ok(VmRunOk::End) => break Ok(()),
|
||||||
Err(e) => break Err(e),
|
Err(e) => break Err(e),
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(())
|
|
||||||
}
|
|
|
@ -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
BIN
program.hbf
Normal file
Binary file not shown.
Loading…
Reference in a new issue