diff options
| -rw-r--r-- | zjit/Cargo.lock | 44 | ||||
| -rw-r--r-- | zjit/Cargo.toml | 9 | ||||
| -rw-r--r-- | zjit/src/disasm.rs | 55 | ||||
| -rw-r--r-- | zjit/src/lib.rs | 22 |
4 files changed, 120 insertions, 10 deletions
diff --git a/zjit/Cargo.lock b/zjit/Cargo.lock index cdf798516c..f42fa9d735 100644 --- a/zjit/Cargo.lock +++ b/zjit/Cargo.lock @@ -3,5 +3,49 @@ version = 3 [[package]] +name = "capstone" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "015ef5d5ca1743e3f94af9509ba6bd2886523cfee46e48d15c2ef5216fd4ac9a" +dependencies = [ + "capstone-sys", + "libc", +] + +[[package]] +name = "capstone-sys" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2267cb8d16a1e4197863ec4284ffd1aec26fe7e57c58af46b02590a0235809a0" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "cc" +version = "1.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "755717a7de9ec452bf7f3f1a3099085deabd7f2962b861dae91ecd7a365903d2" +dependencies = [ + "shlex", +] + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "zjit" version = "0.0.0" +dependencies = [ + "capstone", +] diff --git a/zjit/Cargo.toml b/zjit/Cargo.toml index 11cdc333c0..dc71f01692 100644 --- a/zjit/Cargo.toml +++ b/zjit/Cargo.toml @@ -21,3 +21,12 @@ debug = true lto = "thin" [dependencies] +# No required dependencies to simplify build process. TODO: Link to yet to be +# written rationale. Optional For development and testing purposes +capstone = { version = "0.13.0", optional = true } + +# NOTE: Development builds select a set of these via configure.ac +# For debugging, `make V=1` shows exact cargo invocation. +[features] +# Support --yjit-dump-disasm and RubyVM::YJIT.disasm using libcapstone. +disasm = ["capstone"] diff --git a/zjit/src/disasm.rs b/zjit/src/disasm.rs new file mode 100644 index 0000000000..f18fad1ae0 --- /dev/null +++ b/zjit/src/disasm.rs @@ -0,0 +1,55 @@ +#[cfg(feature = "disasm")] +pub fn disasm_addr_range(cb: &CodeBlock, start_addr: usize, end_addr: usize) -> String { + 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 = get_colors(); + + // 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 { + if cb.outlined { + write!(&mut out, "{}", colors.blue_begin).unwrap(); // Make outlined code blue + } + writeln!(&mut out, " {}# {comment}{}", colors.bold_begin, colors.bold_end).unwrap(); // Make comments bold + } + } + if cb.outlined { + write!(&mut out, "{}", colors.blue_begin).unwrap(); // Make outlined code blue + } + writeln!(&mut out, " {insn}").unwrap(); + if cb.outlined { + write!(&mut out, "{}", colors.blue_end).unwrap(); // Disable blue + } + } + + return out; +} diff --git a/zjit/src/lib.rs b/zjit/src/lib.rs index c096832edf..511999f9b7 100644 --- a/zjit/src/lib.rs +++ b/zjit/src/lib.rs @@ -9,8 +9,8 @@ mod utils; mod virtualmem; mod asm; mod backend; +mod disasm; -#[cfg(target_arch = "x86_64")] use backend::x86_emit; use codegen::ZJITState; use crate::cruby::*; @@ -81,17 +81,19 @@ pub extern "C" fn rb_zjit_parse_option() -> bool { pub extern "C" fn rb_zjit_iseq_gen_entry_point(iseq: IseqPtr, _ec: EcPtr) -> *const u8 { ir::iseq_to_ssa(iseq); - #[cfg(target_arch = "x86_64")] - { - let cb = ZJITState::get_code_block(); + let cb = ZJITState::get_code_block(); + let start_ptr = cb.get_write_ptr(); + x86_emit(cb); + let _end_ptr = cb.get_write_ptr(); - let start_ptr = cb.get_write_ptr(); - x86_emit(cb); + #[cfg(feature = "disasm")] + { + let _disasm = disasm_addr_range(); + } - // TODO: use std::ptr::null() if compilation fails + if cfg!(target_arch = "x86_64") { start_ptr.raw_ptr(cb) + } else { + std::ptr::null() } - - #[cfg(target_arch = "aarch64")] - std::ptr::null() } |
