xref: /wasmtime-44.0.1/cranelift/src/disasm.rs (revision 557cc2d6)
1 use anyhow::Result;
2 use cfg_if::cfg_if;
3 use cranelift_codegen::ir::Function;
4 use cranelift_codegen::ir::function::FunctionParameters;
5 use cranelift_codegen::isa::TargetIsa;
6 use cranelift_codegen::{FinalizedMachReloc, MachTrap};
7 use std::fmt::Write;
8 
print_relocs(func_params: &FunctionParameters, relocs: &[FinalizedMachReloc]) -> String9 fn 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 
print_traps(traps: &[MachTrap]) -> String31 pub 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 
39 cfg_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 
print_all( isa: &dyn TargetIsa, func: &Function, mem: &[u8], code_size: u32, print: bool, relocs: &[FinalizedMachReloc], traps: &[MachTrap], ) -> Result<()>100 pub 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 
print_bytes(mem: &[u8])121 pub 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 }
134