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}