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 9 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 31 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 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 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