clif_util/
disasm.rs

1use anyhow::Result;
2use cfg_if::cfg_if;
3use cranelift_codegen::ir::function::FunctionParameters;
4use cranelift_codegen::ir::Function;
5use cranelift_codegen::isa::TargetIsa;
6use cranelift_codegen::{FinalizedMachReloc, MachTrap};
7use std::fmt::Write;
8
9fn print_relocs(func_params: &FunctionParameters, relocs: &[FinalizedMachReloc]) -> String {
10    let mut text = String::new();
11    for &FinalizedMachReloc {
12        kind,
13        offset,
14        ref target,
15        addend,
16    } in relocs
17    {
18        writeln!(
19            text,
20            "reloc_external: {} {} {} at {}",
21            kind,
22            target.display(Some(func_params)),
23            addend,
24            offset
25        )
26        .unwrap();
27    }
28    text
29}
30
31pub fn print_traps(traps: &[MachTrap]) -> String {
32    let mut text = String::new();
33    for &MachTrap { offset, code } in traps {
34        writeln!(text, "trap: {code} at {offset:#x}").unwrap();
35    }
36    text
37}
38
39cfg_if! {
40    if #[cfg(feature = "disas")] {
41        pub fn print_disassembly(func: &Function, isa: &dyn TargetIsa, mem: &[u8]) -> Result<()> {
42            #[cfg(feature = "pulley")]
43            let is_pulley = match isa.triple().architecture {
44                target_lexicon::Architecture::Pulley32 | target_lexicon::Architecture::Pulley64 => true,
45                _ => false,
46            };
47            println!("\nDisassembly of {} bytes <{}>:", mem.len(), func.name);
48
49            #[cfg(feature = "pulley")]
50            if is_pulley {
51                let mut disas = pulley_interpreter::disas::Disassembler::new(mem);
52                pulley_interpreter::decode::Decoder::decode_all(&mut disas)?;
53                println!("{}", disas.disas());
54                return Ok(());
55            }
56            let cs = isa.to_capstone().map_err(|e| anyhow::format_err!("{}", e))?;
57
58            let insns = cs.disasm_all(&mem, 0x0).unwrap();
59            for i in insns.iter() {
60                let mut line = String::new();
61
62                write!(&mut line, "{:4x}:\t", i.address()).unwrap();
63
64                let mut bytes_str = String::new();
65                let mut len = 0;
66                let mut first = true;
67                for b in i.bytes() {
68                    if !first {
69                        write!(&mut bytes_str, " ").unwrap();
70                    }
71                    write!(&mut bytes_str, "{b:02x}").unwrap();
72                    len += 1;
73                    first = false;
74                }
75                write!(&mut line, "{bytes_str:21}\t").unwrap();
76                if len > 8 {
77                    write!(&mut line, "\n\t\t\t\t").unwrap();
78                }
79
80                if let Some(s) = i.mnemonic() {
81                    write!(&mut line, "{s}\t").unwrap();
82                }
83
84                if let Some(s) = i.op_str() {
85                    write!(&mut line, "{s}").unwrap();
86                }
87
88                println!("{line}");
89            }
90            Ok(())
91        }
92    } else {
93        pub fn print_disassembly(_: &Function, _: &dyn TargetIsa, _: &[u8]) -> Result<()> {
94            println!("\nNo disassembly available.");
95            Ok(())
96        }
97    }
98}
99
100pub fn print_all(
101    isa: &dyn TargetIsa,
102    func: &Function,
103    mem: &[u8],
104    code_size: u32,
105    print: bool,
106    relocs: &[FinalizedMachReloc],
107    traps: &[MachTrap],
108) -> Result<()> {
109    print_bytes(&mem);
110    print_disassembly(func, isa, &mem[0..code_size as usize])?;
111    if print {
112        println!(
113            "\n{}\n{}",
114            print_relocs(&func.params, relocs),
115            print_traps(traps),
116        );
117    }
118    Ok(())
119}
120
121pub fn print_bytes(mem: &[u8]) {
122    print!(".byte ");
123    let mut first = true;
124    for byte in mem.iter() {
125        if first {
126            first = false;
127        } else {
128            print!(", ");
129        }
130        print!("{byte}");
131    }
132    println!();
133}