| 635 | /// Get the disassembly of the buffer, using the given capstone context. |
| 636 | #[cfg(feature = "disas")] |
| 637 | pub fn disassemble( |
| 638 | &self, |
| 639 | params: Option<&crate::ir::function::FunctionParameters>, |
| 640 | cs: &capstone::Capstone, |
| 641 | ) -> Result<String, anyhow::Error> { |
| 642 | use core::fmt::Write; |
| 643 | |
| 644 | let mut buf = String::new(); |
| 645 | |
| 646 | let relocs = self.buffer.relocs(); |
| 647 | let traps = self.buffer.traps(); |
| 648 | let mut patchables = self.buffer.patchable_call_sites().peekable(); |
| 649 | |
| 650 | // Normalize the block starts to include an initial block of offset 0. |
| 651 | let mut block_starts = Vec::new(); |
| 652 | if self.bb_starts.first().copied() != Some(0) { |
| 653 | block_starts.push(0); |
| 654 | } |
| 655 | block_starts.extend_from_slice(&self.bb_starts); |
| 656 | block_starts.push(self.buffer.data().len() as u32); |
| 657 | |
| 658 | // Iterate over block regions, to ensure that we always produce block labels |
| 659 | for (n, (&start, &end)) in block_starts |
| 660 | .iter() |
| 661 | .zip(block_starts.iter().skip(1)) |
| 662 | .enumerate() |
| 663 | { |
| 664 | writeln!(buf, "block{n}: ; offset 0x{start:x}")?; |
| 665 | |
| 666 | let buffer = &self.buffer.data()[start as usize..end as usize]; |
| 667 | let insns = cs.disasm_all(buffer, start as u64).map_err(map_caperr)?; |
| 668 | for i in insns.iter() { |
| 669 | write!(buf, " ")?; |
| 670 | |
| 671 | let op_str = i.op_str().unwrap_or(""); |
| 672 | if let Some(s) = i.mnemonic() { |
| 673 | write!(buf, "{s}")?; |
| 674 | if !op_str.is_empty() { |
| 675 | write!(buf, " ")?; |
| 676 | } |
| 677 | } |
| 678 | |
| 679 | write!(buf, "{op_str}")?; |
| 680 | |
| 681 | let end = i.address() + i.bytes().len() as u64; |
| 682 | let contains = |off| i.address() <= off && off < end; |
| 683 | |
| 684 | for reloc in relocs.iter().filter(|reloc| contains(reloc.offset as u64)) { |
| 685 | write!( |
| 686 | buf, |
| 687 | " ; reloc_external {} {} {}", |
| 688 | reloc.kind, |
| 689 | reloc.target.display(params), |
| 690 | reloc.addend, |
| 691 | )?; |
| 692 | } |
| 693 | |
| 694 | if let Some(trap) = traps.iter().find(|trap| contains(trap.offset as u64)) { |