Skip to main content

sys_rs/
print.rs

1use crate::{asm::Instruction, diag::Result};
2
3#[derive(PartialEq, Debug)]
4/// Controls how instructions are printed.
5///
6/// `Layout::Assembly` prints raw disassembly. `Layout::Source` indicates
7/// the caller prefers source-oriented output (e.g., showing source lines
8/// when DWARF info is available).
9pub enum Layout {
10    /// Print assembly/disassembly.
11    Assembly,
12    /// Prefer source-level printing when available.
13    Source,
14}
15
16impl From<bool> for Layout {
17    fn from(src_available: bool) -> Self {
18        if src_available {
19            Self::Source
20        } else {
21            Self::Assembly
22        }
23    }
24}
25
26/// Type alias for a printing callback used by the tracer/profile code.
27///
28/// The callback is invoked when the tracer or profiler wants to render an
29/// instruction. Implementations receive the current `Instruction` and the
30/// active `Layout` and may return an optional string containing the text that
31/// was printed.
32///
33/// # Arguments
34///
35/// * `instruction` - The instruction to print.
36/// * `layout` - The active printing layout (assembly or source-oriented).
37///
38/// # Returns
39///
40/// `Ok(Some(String))` when a string was printed and should be recorded,
41/// `Ok(None)` when nothing was printed, or `Err` for I/O or lookup errors.
42pub trait PrintFn = FnMut(&Instruction, &Layout) -> Result<Option<String>>;
43
44/// Default instruction printer which prints the `Instruction`'s `Display`
45/// representation.
46///
47/// The default printer formats the instruction using its `Display`
48/// implementation and writes it to stdout. The printed string is also
49/// returned inside `Ok(Some(...))` so callers can record or redisplay it.
50///
51/// # Arguments
52///
53/// * `instruction` - The `Instruction` to print.
54/// * `_` - The active `Layout` (unused by the default printer).
55///
56/// # Errors
57///
58/// Returns an `Err` if writing to stdout or other I/O performed by the
59/// underlying platform fails.
60///
61/// # Returns
62///
63/// `Ok(Some(String))` containing the printed text on success.
64pub fn default(instruction: &Instruction, _: &Layout) -> Result<Option<String>> {
65    let ret = format!("{instruction}");
66    println!("{ret}");
67    Ok(Some(ret))
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn test_print_default_returns_string() {
76        let parser = crate::asm::Parser::new().expect("parser new");
77        let opcode: [u8; 5] = [0xe8, 0x05, 0x00, 0x00, 0x00];
78        let inst = parser
79            .get_instruction_from(&opcode, 0x1000)
80            .expect("decoding");
81        let res = default(&inst, &Layout::Assembly).expect("print default failed");
82        assert!(res.is_some());
83        let s = res.unwrap();
84        assert!(s.contains("call") || s.contains("callq"));
85    }
86}