diff options
Diffstat (limited to 'zjit/src/disasm.rs')
| -rw-r--r-- | zjit/src/disasm.rs | 72 |
1 files changed, 72 insertions, 0 deletions
diff --git a/zjit/src/disasm.rs b/zjit/src/disasm.rs new file mode 100644 index 0000000000..36bb90cff7 --- /dev/null +++ b/zjit/src/disasm.rs @@ -0,0 +1,72 @@ +use crate::{asm::CodeBlock, options::DumpDisasm, virtualmem::CodePtr}; + +/// Dump disassembly for a range in a [CodeBlock]. +pub fn dump_disasm_addr_range(cb: &CodeBlock, start_addr: CodePtr, end_addr: CodePtr, dump_disasm: &DumpDisasm) { + let disasm = disasm_addr_range(cb, start_addr.raw_ptr(cb) as usize, end_addr.raw_ptr(cb) as usize); + if disasm.is_empty() { + return; + } + + match dump_disasm { + DumpDisasm::Stdout => println!("{disasm}"), + DumpDisasm::File(fd) => { + use std::io::Write; + use std::os::unix::io::{FromRawFd, IntoRawFd}; + + let mut file = unsafe { std::fs::File::from_raw_fd(*fd) }; + file.write_all(disasm.as_bytes()).unwrap(); + let _ = file.into_raw_fd(); + } + } +} + +pub fn disasm_addr_range(cb: &CodeBlock, start_addr: usize, end_addr: usize) -> String { + use std::fmt::Write; + + let mut out = String::from(""); + + // Initialize capstone + use capstone::prelude::*; + + #[cfg(target_arch = "x86_64")] + let mut cs = Capstone::new() + .x86() + .mode(arch::x86::ArchMode::Mode64) + .syntax(arch::x86::ArchSyntax::Intel) + .build() + .unwrap(); + #[cfg(target_arch = "aarch64")] + let mut cs = Capstone::new() + .arm64() + .mode(arch::arm64::ArchMode::Arm) + .detail(true) + .build() + .unwrap(); + + cs.set_skipdata(true).unwrap(); + + // Disassemble the instructions + let code_size = end_addr - start_addr; + let code_slice = unsafe { std::slice::from_raw_parts(start_addr as _, code_size) }; + // Stabilize output for cargo test + #[cfg(test)] + let start_addr = 0; + let insns = cs.disasm_all(code_slice, start_addr as u64).unwrap(); + + let colors = crate::ttycolors::get_colors(); + let bold_begin = colors.bold_begin; + let bold_end = colors.bold_end; + + // For each instruction in this block + for insn in insns.as_ref() { + // Comments for this block + if let Some(comment_list) = cb.comments_at(insn.address() as usize) { + for comment in comment_list { + writeln!(&mut out, " {bold_begin}# {comment}{bold_end}").unwrap(); + } + } + writeln!(&mut out, " {}", format!("{insn}").trim()).unwrap(); + } + + out +} |
