summaryrefslogtreecommitdiff
path: root/zjit/src/disasm.rs
diff options
context:
space:
mode:
Diffstat (limited to 'zjit/src/disasm.rs')
-rw-r--r--zjit/src/disasm.rs72
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
+}