Skip to main content

clif_util/
disasm.rs

1use anyhow::Result;
2use cranelift_codegen::ir::Function;
3use cranelift_codegen::ir::function::FunctionParameters;
4use cranelift_codegen::isa::TargetIsa;
5use cranelift_codegen::{FinalizedMachReloc, MachTrap};
6use std::fmt::Write;
7
8fn print_relocs(func_params: &FunctionParameters, relocs: &[FinalizedMachReloc]) -> String {
9    let mut text = String::new();
10    for &FinalizedMachReloc {
11        kind,
12        offset,
13        ref target,
14        addend,
15    } in relocs
16    {
17        writeln!(
18            text,
19            "reloc_external: {} {} {} at {}",
20            kind,
21            target.display(Some(func_params)),
22            addend,
23            offset
24        )
25        .unwrap();
26    }
27    text
28}
29
30pub fn print_traps(traps: &[MachTrap]) -> String {
31    let mut text = String::new();
32    for &MachTrap { offset, code } in traps {
33        writeln!(text, "trap: {code} at {offset:#x}").unwrap();
34    }
35    text
36}
37
38cfg_select! {
39    feature = "disas" => {
40        pub fn print_disassembly(func: &Function, isa: &dyn TargetIsa, mem: &[u8]) -> Result<()> {
41            #[cfg(feature = "pulley")]
42            let is_pulley = match isa.triple().architecture {
43                target_lexicon::Architecture::Pulley32 | target_lexicon::Architecture::Pulley64 => true,
44                _ => false,
45            };
46            println!("\nDisassembly of {} bytes <{}>:", mem.len(), func.name);
47
48            #[cfg(feature = "pulley")]
49            if is_pulley {
50                let mut disas = pulley_interpreter::disas::Disassembler::new(mem);
51                pulley_interpreter::decode::Decoder::decode_all(&mut disas)?;
52                println!("{}", disas.disas());
53                return Ok(());
54            }
55            let cs = isa.to_capstone().map_err(|e| anyhow::format_err!("{e}"))?;
56
57            let insns = cs.disasm_all(&mem, 0x0).unwrap();
58            for i in insns.iter() {
59                let mut line = String::new();
60
61                write!(&mut line, "{:4x}:\t", i.address()).unwrap();
62
63                let mut bytes_str = String::new();
64                let mut len = 0;
65                let mut first = true;
66                for b in i.bytes() {
67                    if !first {
68                        write!(&mut bytes_str, " ").unwrap();
69                    }
70                    write!(&mut bytes_str, "{b:02x}").unwrap();
71                    len += 1;
72                    first = false;
73                }
74                write!(&mut line, "{bytes_str:21}\t").unwrap();
75                if len > 8 {
76                    write!(&mut line, "\n\t\t\t\t").unwrap();
77                }
78
79                if let Some(s) = i.mnemonic() {
80                    write!(&mut line, "{s}\t").unwrap();
81                }
82
83                if let Some(s) = i.op_str() {
84                    write!(&mut line, "{s}").unwrap();
85                }
86
87                println!("{line}");
88            }
89            Ok(())
90        }
91    }
92    _ => {
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}