juicebox_asm/disasm.rs
1// SPDX-License-Identifier: MIT
2//
3// Copyright (c) 2024, Johannes Stoelp <dev@memzero.de>
4
5use std::io::{ErrorKind, Write};
6use std::process::{Command, Stdio};
7
8/// Disassemble the code using [`ndisasm`](https://nasm.us/index.php)
9/// and print it to _stdout_. If `ndisasm` is not available on the
10/// system this prints a warning and becomes a nop.
11///
12/// # Panics
13///
14/// Panics if anything goes wrong with spawning, writing to or reading from
15/// the `ndisasm` child process.
16pub(crate) fn disasm<T: AsRef<[u8]>>(code: T) {
17 let code = code.as_ref();
18
19 // Create ndisasm process, which expects input on stdin.
20 let mut child = match Command::new("ndisasm")
21 .args(["-b64", "-"])
22 .stdin(Stdio::piped())
23 .stdout(Stdio::piped())
24 .spawn()
25 {
26 Ok(child) => child,
27 Err(err) if err.kind() == ErrorKind::NotFound => {
28 println!("disasm: skipping, ndisasm not found");
29 return;
30 }
31 Err(err) => {
32 panic!("{:?}", err);
33 }
34 };
35
36 // Write code to stdin of ndisasm.
37 child
38 .stdin
39 .take()
40 .expect("failed to take stdin")
41 .write_all(code)
42 .expect("failed to write bytes to stdin");
43
44 // Wait for output from ndisasm and print to stdout.
45 println!(
46 "{}",
47 String::from_utf8_lossy(
48 &child
49 .wait_with_output()
50 .expect("failed to get stdout")
51 .stdout
52 )
53 );
54}