diff --git a/Cargo.lock b/Cargo.lock index 750936b..ec87402 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,24 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "aho-corasick" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +dependencies = [ + "memchr", +] + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "argh" version = "0.1.12" @@ -48,6 +66,17 @@ dependencies = [ "serde", ] +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + [[package]] name = "backtrace" version = "0.3.69" @@ -56,13 +85,43 @@ checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", - "cfg-if", + "cfg-if 1.0.0", "libc", "miniz_oxide", "object", "rustc-demangle", ] +[[package]] +name = "bindgen" +version = "0.53.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c72a978d268b1d70b0e963217e60fdabd9523a941457a6c42a7315d15c7e89e5" +dependencies = [ + "bitflags 1.3.2", + "cexpr", + "cfg-if 0.1.10", + "clang-sys", + "clap", + "env_logger", + "lazy_static", + "lazycell", + "log", + "peeking_take_while", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "which", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.4.1" @@ -78,12 +137,53 @@ dependencies = [ "libc", ] +[[package]] +name = "cexpr" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "clang-sys" +version = "0.29.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe6837df1d5cba2397b835c8530f51723267e16abbf83892e9e5af4f0e5dd10a" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim", + "textwrap", + "unicode-width", + "vec_map", +] + [[package]] name = "color-eyre" version = "0.6.2" @@ -111,6 +211,19 @@ dependencies = [ "tracing-error", ] +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + [[package]] name = "eyre" version = "0.6.8" @@ -127,6 +240,12 @@ version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "hbbytecode" version = "0.1.0" @@ -147,6 +266,25 @@ version = "0.1.0" dependencies = [ "hbvm", "nix", + "setjmp", +] + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", ] [[package]] @@ -161,12 +299,34 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b" +[[package]] +name = "libloading" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +dependencies = [ + "cc", + "winapi", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + [[package]] name = "memchr" version = "2.6.4" @@ -188,11 +348,21 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags", - "cfg-if", + "bitflags 2.4.1", + "cfg-if 1.0.0", "libc", ] +[[package]] +name = "nom" +version = "5.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" +dependencies = [ + "memchr", + "version_check", +] + [[package]] name = "object" version = "0.32.1" @@ -214,6 +384,12 @@ version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -229,6 +405,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.33" @@ -238,12 +420,47 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "regex" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" + [[package]] name = "rustc-demangle" version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "serde" version = "1.0.189" @@ -264,6 +481,17 @@ dependencies = [ "syn 2.0.38", ] +[[package]] +name = "setjmp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bce8e042e9b4349ccf7ce5caeb5c9b7ee6007ff543b494733ae8ed4ea083c73" +dependencies = [ + "bindgen", + "clang-sys", + "libc", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -273,6 +501,18 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "syn" version = "1.0.109" @@ -295,13 +535,31 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "termcolor" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width", +] + [[package]] name = "thread_local" version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "once_cell", ] @@ -352,12 +610,70 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +[[package]] +name = "unicode-width" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" + [[package]] name = "valuable" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "which" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" +dependencies = [ + "libc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "with_builtin_macros" version = "0.0.3" diff --git a/examples/linux-hello.hbf b/examples/linux-hello.hbf index d1d8616..1b962c9 100644 Binary files a/examples/linux-hello.hbf and b/examples/linux-hello.hbf differ diff --git a/hbvm/src/vmrun.rs b/hbvm/src/vmrun.rs index 965ebab..37b6db8 100644 --- a/hbvm/src/vmrun.rs +++ b/hbvm/src/vmrun.rs @@ -23,7 +23,7 @@ macro_rules! handler { ($self:expr, |$ty:ident ($($ident:pat),* $(,)?)| $expr:expr) => {{ let $ty($($ident),*) = $self.decode::<$ty>(); #[allow(clippy::no_effect)] let e = $expr; - $self.bump_pc::<$ty>(); + $self.bump_pc::<$ty, true>(); e }}; } @@ -61,11 +61,11 @@ where unsafe { match self.memory.prog_read::(self.pc as _) { UN => { - self.bump_pc::(); + self.bump_pc::(); return Err(VmRunError::Unreachable); } TX => { - self.bump_pc::(); + self.bump_pc::(); return Ok(VmRunOk::End); } NOP => handler!(self, |OpsN()| ()), @@ -254,7 +254,7 @@ where // We are done, shift program counter core::task::Poll::Ready(Ok(())) => { self.copier = None; - self.bump_pc::(); + self.bump_pc::(); } // Error, shift program counter (for consistency) // and yield error @@ -305,11 +305,11 @@ where self.timer = self.timer.wrapping_add(1); } - self.bump_pc::(); + self.bump_pc::(); return Ok(VmRunOk::Ecall); } EBP => { - self.bump_pc::(); + self.bump_pc::(); return Ok(VmRunOk::Breakpoint); } FADD32 => self.binary_op::(ops::Add::add), @@ -399,8 +399,8 @@ where /// Bump instruction pointer #[inline(always)] - fn bump_pc(&mut self) { - self.pc = self.pc.wrapping_add(core::mem::size_of::() + 1); + fn bump_pc(&mut self) { + self.pc = self.pc.wrapping_add(core::mem::size_of::() + PAST_OP as usize); } /// Decode instruction operands @@ -460,7 +460,7 @@ where tg, op(self.read_reg(a0).cast::(), self.read_reg(a1).cast::()), ); - self.bump_pc::(); + self.bump_pc::(); } /// Perform binary operation over register and immediate @@ -469,8 +469,8 @@ where let OpsRR(tg, reg) = self.decode(); let imm: T = self.decode(); self.write_reg(tg, op(self.read_reg(reg).cast::(), imm)); - self.bump_pc::(); - self.bump_pc::(); + self.bump_pc::(); + self.bump_pc::(); } /// Perform binary operation over register and shift immediate @@ -478,7 +478,7 @@ where unsafe fn binary_op_ims(&mut self, op: impl Fn(T, u32) -> T) { let OpsRRW(tg, reg, imm) = self.decode(); self.write_reg(tg, op(self.read_reg(reg).cast::(), imm)); - self.bump_pc::(); + self.bump_pc::(); } /// Fused division-remainder @@ -539,7 +539,7 @@ where self.pc = Address::new(((self.pc.get() as i64).wrapping_add(ja as i64)) as u64); } - self.bump_pc::(); + self.bump_pc::(); } /// Read register diff --git a/hbxrt/Cargo.toml b/hbxrt/Cargo.toml index 0dbf35e..6831f3e 100644 --- a/hbxrt/Cargo.toml +++ b/hbxrt/Cargo.toml @@ -6,4 +6,5 @@ default-run = "hbxrt" [dependencies] hbvm.path = "../hbvm" -nix = { version = "0.27", features = ["mman"] } +nix = { version = "0.27", features = ["mman", "signal"] } +setjmp = "0.1" diff --git a/hbxrt/src/main.rs b/hbxrt/src/main.rs index 9be88ad..e10194b 100644 --- a/hbxrt/src/main.rs +++ b/hbxrt/src/main.rs @@ -1,11 +1,13 @@ //! Holey Bytes Experimental Runtime - mod mem; use { hbvm::{mem::Address, Vm, VmRunOk}, nix::sys::mman::{mmap, MapFlags, ProtFlags}, - std::{env::args, fs::File, num::NonZeroUsize, process::exit}, + setjmp::sigjmp_buf, + std::{ + cell::UnsafeCell, env::args, fs::File, mem::MaybeUninit, num::NonZeroUsize, process::exit, + }, }; fn main() -> Result<(), Box> { @@ -35,6 +37,44 @@ fn main() -> Result<(), Box> { // Execute program let mut vm = unsafe { Vm::<_, 0>::new(mem::HostMemory, Address::new(ptr as u64)) }; + + // Memory access fault handling + unsafe { + use nix::sys::signal; + + static JMP_BUF: SyncUnsafeCell> = + SyncUnsafeCell::new(MaybeUninit::uninit()); + + 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()); + setjmp::siglongjmp((*JMP_BUF.get()).as_mut_ptr(), 1); + } + } + + if setjmp::sigsetjmp((*JMP_BUF.get()).as_mut_ptr(), 0) > 0 { + eprintln!( + " Program counter: {:#x}\n\n== Registers ==\n{:?}", + vm.pc.get(), + vm.registers + ); + exit(3); + } + + signal::sigaction( + signal::Signal::SIGSEGV, + &nix::sys::signal::SigAction::new( + signal::SigHandler::SigAction(action), + signal::SaFlags::SA_NODEFER, + nix::sys::signalfd::SigSet::empty(), + ), + )?; + } + let stat = loop { match vm.run() { Ok(VmRunOk::Breakpoint) => eprintln!( @@ -67,3 +107,25 @@ fn main() -> Result<(), Box> { Ok(()) } + +#[repr(transparent)] +struct SyncUnsafeCell { + value: UnsafeCell, +} + +unsafe impl Sync for SyncUnsafeCell {} +impl SyncUnsafeCell { + #[inline(always)] + pub const fn new(value: T) -> Self { + Self { + value: UnsafeCell::new(value), + } + } +} + +impl SyncUnsafeCell { + #[inline(always)] + pub const fn get(&self) -> *mut T { + self.value.get() + } +}