Add basic Win32 support

This commit is contained in:
Erin 2023-11-24 01:09:15 +01:00
parent 2165f7babb
commit 3bedc33034
8 changed files with 173 additions and 126 deletions

77
Cargo.lock generated
View file

@ -221,6 +221,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"hbvm", "hbvm",
"nix", "nix",
"windows",
] ]
[[package]] [[package]]
@ -527,6 +528,82 @@ 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"

View file

@ -1,5 +0,0 @@
target
artifacts
corpus
coverage
Cargo.lock

View file

@ -1,30 +0,0 @@
[package]
name = "hbvm-fuzz"
version = "0.0.0"
publish = false
edition = "2021"
[package.metadata]
cargo-fuzz = true
[dependencies]
libfuzzer-sys = "0.4"
[dependencies.hbvm]
path = ".."
[dependencies.hbbytecode]
path = "../../hbbytecode"
# Prevent this from interfering with workspaces
[workspace]
members = ["."]
[profile.release]
debug = 1
[[bin]]
name = "vm"
path = "fuzz_targets/vm.rs"
test = false
doc = false

View file

@ -1,82 +0,0 @@
#![no_main]
use {
hbvm::{
mem::{
softpaging::{
paging::{PageTable, Permission},
HandlePageFault, PageSize, SoftPagedMem,
},
Address, MemoryAccessReason,
},
Vm,
},
libfuzzer_sys::fuzz_target,
};
fuzz_target!(|data: &[u8]| {
let mut vm = unsafe {
Vm::<_, 16384>::new(
SoftPagedMem::<_, true> {
pf_handler: TestTrapHandler,
program: data,
root_pt: Box::into_raw(Default::default()),
icache: Default::default(),
},
Address::new(4),
)
};
// Alloc and map some memory
let pages = [
alloc_and_map(&mut vm.memory, 0),
alloc_and_map(&mut vm.memory, 4096),
];
// Run VM
let _ = vm.run();
// Unmap and dealloc the memory
for (i, page) in pages.into_iter().enumerate() {
unmap_and_dealloc(&mut vm.memory, page, i as u64 * 4096);
}
let _ = unsafe { Box::from_raw(vm.memory.root_pt) };
});
fn alloc_and_map(memory: &mut SoftPagedMem<TestTrapHandler>, at: u64) -> *mut u8 {
let ptr = Box::into_raw(Box::<Page>::default()).cast();
unsafe {
memory
.map(ptr, Address::new(at), Permission::Write, PageSize::Size4K)
.unwrap()
};
ptr
}
fn unmap_and_dealloc(memory: &mut SoftPagedMem<TestTrapHandler>, ptr: *mut u8, from: u64) {
memory.unmap(Address::new(from)).unwrap();
let _ = unsafe { Box::from_raw(ptr.cast::<Page>()) };
}
#[repr(align(4096))]
struct Page([u8; 4096]);
impl Default for Page {
fn default() -> Self {
unsafe { std::mem::MaybeUninit::zeroed().assume_init() }
}
}
struct TestTrapHandler;
impl HandlePageFault for TestTrapHandler {
fn page_fault(
&mut self,
_: MemoryAccessReason,
_: &mut PageTable,
_: Address,
_: PageSize,
_: *mut u8,
) -> bool {
false
}
}

View file

@ -6,4 +6,16 @@ default-run = "hbxrt"
[dependencies] [dependencies]
hbvm.path = "../hbvm" hbvm.path = "../hbvm"
nix = { version = "0.27", features = ["mman", "signal"] }
[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",
]

View file

@ -2,17 +2,23 @@
#![deny(unsafe_op_in_unsafe_fn)] #![deny(unsafe_op_in_unsafe_fn)]
mod linux; #[cfg(unix)]
#[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},
nix::sys::mman::{mmap, MapFlags, ProtFlags}, std::{env::args, process::exit},
std::{env::args, fs::File, num::NonZeroUsize, process::exit},
}; };
fn main() -> Result<(), Box<dyn std::error::Error>> { fn main() -> Result<(), Box<dyn std::error::Error>> {
eprintln!("== HB×RT (Holey Bytes Linux 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 Some(image_path) = args().nth(1) else {
@ -21,18 +27,18 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
}; };
// Allocate stack // Allocate stack
let stack_ptr = unsafe { linux::alloc_stack(1024 * 1024 * 2) }?; let stack_ptr = unsafe { platform::alloc_stack(1024 * 1024 * 2) }?;
eprintln!("[I] Stack allocated at {stack_ptr:p}"); eprintln!("[I] Stack allocated at {stack_ptr:p}");
// Load program // Load program
eprintln!("[I] Loading image from \"{image_path}\""); eprintln!("[I] Loading image from \"{image_path}\"");
let ptr = unsafe { linux::mmap_bytecode(image_path) }?; let ptr = unsafe { platform::mmap_bytecode(image_path) }?;
eprintln!("[I] Image loaded at {ptr:p}"); eprintln!("[I] Image loaded at {ptr:p}");
let mut vm = unsafe { Vm::<_, 0>::new(mem::HostMemory, Address::new(ptr as u64)) }; let mut vm = unsafe { Vm::<_, 0>::new(mem::HostMemory, Address::new(ptr as u64)) };
vm.write_reg(254, stack_ptr as u64); vm.write_reg(254, stack_ptr as u64);
unsafe { linux::hook_pagefault() }?; unsafe { platform::catch_mafs() }?;
// Execute program // Execute program
let stat = loop { let stat = loop {

View file

@ -38,7 +38,7 @@ pub unsafe fn mmap_bytecode(path: impl AsRef<Path>) -> Result<*mut u8, Box<dyn s
} }
/// Set handler for page fault /// Set handler for page fault
pub unsafe fn hook_pagefault() -> nix::Result<()> { pub unsafe fn catch_mafs() -> nix::Result<()> {
unsafe { unsafe {
use nix::sys::signal; use nix::sys::signal;

69
hbxrt/src/win32.rs Normal file
View file

@ -0,0 +1,69 @@
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(())
}