From 8ca27aeeb99a0da43e92e39918aa07c0b1443c07 Mon Sep 17 00:00:00 2001 From: Johannes Stoelp Date: Thu, 19 Dec 2024 19:47:19 +0100 Subject: rt: remove dump() and add disasm(), to directly disasm code using ndisasm if available --- examples/add.rs | 5 ++--- examples/fib.rs | 5 ++--- src/rt.rs | 55 ++++++++++++++++++++++++++++++++++++++++++++----------- 3 files changed, 48 insertions(+), 17 deletions(-) diff --git a/examples/add.rs b/examples/add.rs index 3ad8893..fee5392 100644 --- a/examples/add.rs +++ b/examples/add.rs @@ -30,9 +30,8 @@ fn main() { let mut rt = Runtime::new(); let add42 = unsafe { rt.add_code:: u32>(asm.into_code()) }; - // Write out JIT code for visualization. - // Disassemble for example with `ndisasm -b 64 jit.asm`. - rt.dump(); + // Disassemble JIT code and write to stdout. + rt.disasm(); let res = add42(5); assert_eq!(res, 47); diff --git a/examples/fib.rs b/examples/fib.rs index c38589f..573b27c 100644 --- a/examples/fib.rs +++ b/examples/fib.rs @@ -66,9 +66,8 @@ fn main() { let mut rt = Runtime::new(); let fib = unsafe { rt.add_code:: u64>(asm.into_code()) }; - // Write out JIT code for visualization. - // Disassemble for example with `ndisasm -b 64 jit.asm`. - rt.dump(); + // Disassemble JIT code and write to stdout. + rt.disasm(); for n in 0..15 { let fib_jit = fib(n); diff --git a/src/rt.rs b/src/rt.rs index 4c4309b..a47cada 100644 --- a/src/rt.rs +++ b/src/rt.rs @@ -156,22 +156,55 @@ impl Runtime { unsafe { Self::as_fn::(fn_start) } } - /// Dump the code added so far to the runtime into a file called `jit.asm` in the processes - /// current working directory. - /// - /// The code can be inspected with a disassembler as for example `ndiasm` from - /// [nasm.us](https://nasm.us/index.php). - /// ```sh - /// ndisasm -b 64 jit.asm - /// ``` + /// Disassemble the code currently added to the runtime, using + /// [`ndisasm`](https://nasm.us/index.php) and print it to _stdout_. If + /// `ndisasm` is not available on the system this prints a warning and + /// becomes a nop. /// /// # Panics /// - /// Panics if writing the file failed. - pub fn dump(&self) { + /// Panics if anything goes wrong with spawning, writing to or reading from + /// the `ndisasm` child process. + pub fn disasm(&self) { assert!(self.idx <= self.len); let code = unsafe { core::slice::from_raw_parts(self.buf, self.idx) }; - std::fs::write("jit.asm", code).expect("Failed to write file"); + + // Create ndisasm process, which expects input on stdin. + let mut child = match std::process::Command::new("ndisasm") + .args(["-b64", "-"]) + .stdin(std::process::Stdio::piped()) + .stdout(std::process::Stdio::piped()) + .spawn() + { + Ok(child) => child, + Err(err) if err.kind() == std::io::ErrorKind::NotFound => { + println!("Runtime::disasm: ndisasm not found, skipping!"); + return; + } + Err(err) => { + panic!("{:?}", err); + } + }; + + // Write code to stdin of ndisasm. + use std::io::Write; + child + .stdin + .take() + .expect("failed to take stdin") + .write_all(code) + .expect("failed to write bytes to stdin"); + + // Wait for output from ndisasm and print to stdout. + println!( + "{}", + String::from_utf8_lossy( + &child + .wait_with_output() + .expect("failed to get stdout") + .stdout + ) + ); } /// Reinterpret the block of code pointed to by `fn_start` as `F`. -- cgit v1.2.3