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}