Skip to content

Commit

Permalink
Make examples and benches compile
Browse files Browse the repository at this point in the history
This commit contains changes that make existing examples and benches compile
with the latest API design. Unit tests will be covered in later commits.

The primary changes include:
- Implement DetailArchInsn for ArchDetail.
- Add ArchOperandIterator enum that iterates values of ArchOperand inside an
  ArchDetail. The enum is basically a wrapper that holds all available arch-
  specific operand iterators in different variants.

This commit also contains some refactors and minor changes, including:
- Rename ArchDetail to ArchInsnDetail as the old name is a bit confusing.
- Fully add sysz support.
- Update existing examples and benches. In most cases, to migrate these existing
  examples and benches, I just need to add a small number of generic type
  arguments (e.g. X86ArchTag, ArmArchTag, DynamicArchTag, etc.) and the code
  just compiles.
  • Loading branch information
Lancern committed Aug 29, 2023
1 parent 061994f commit 3422ee7
Show file tree
Hide file tree
Showing 21 changed files with 223 additions and 111 deletions.
5 changes: 3 additions & 2 deletions capstone-rs/benches/my_benchmark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ extern crate capstone;
#[macro_use]
extern crate criterion;

use capstone::arch::DynamicArchTag;
use capstone::prelude::*;
use capstone::{Arch, Endian, ExtraMode, Mode, NO_EXTRA_MODE};
use criterion::{black_box, Criterion};
Expand All @@ -17,8 +18,8 @@ fn arch_bench<T: Iterator<Item = ExtraMode>>(
endian: Option<Endian>,
detail: bool,
) {
let mut cs =
Capstone::new_raw(arch, mode, extra_mode, endian).expect("failed to make capstone");
let mut cs = Capstone::<DynamicArchTag>::new_raw(arch, mode, extra_mode, endian)
.expect("failed to make capstone");
cs.set_detail(detail).expect("failed to set detail");

let insns = cs.disasm_all(code, 0x1000).expect("failed to disassemble");
Expand Down
34 changes: 16 additions & 18 deletions capstone-rs/examples/demo.rs
Original file line number Diff line number Diff line change
@@ -1,37 +1,42 @@
extern crate capstone;

use capstone::arch::mips::MipsArchTag;
use capstone::arch::x86::X86ArchTag;
use capstone::arch::{ArchTag, DetailsArchInsn};
use capstone::prelude::*;
use capstone::InsnDetail;

const MIPS_CODE: &[u8] = b"\x56\x34\x21\x34\xc2\x17\x01\x00";

const X86_CODE: &[u8] = b"\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\x14\x9e\x08\x00\x45\x31\xe4";

#[cfg(feature = "full")]
/// Print register names
fn reg_names(cs: &Capstone, regs: &[RegId]) -> String {
fn reg_names<A: ArchTag>(cs: &Capstone<A>, regs: &[A::RegId]) -> String {
let names: Vec<String> = regs.iter().map(|&x| cs.reg_name(x).unwrap()).collect();
names.join(", ")
}

#[cfg(feature = "full")]
/// Print instruction group names
fn group_names(cs: &Capstone, regs: &[InsnGroupId]) -> String {
fn group_names<A: ArchTag>(cs: &Capstone<A>, regs: &[A::InsnGroupId]) -> String {
let names: Vec<String> = regs.iter().map(|&x| cs.group_name(x).unwrap()).collect();
names.join(", ")
}

/// Disassemble code and print information
fn arch_example(cs: &mut Capstone, code: &[u8]) -> CsResult<()> {
fn arch_example<A: ArchTag>(arch: &'static str, cs: &mut Capstone<A>, code: &[u8]) -> CsResult<()> {
println!("\n*************************************");
println!("Architecture {}:", arch);

let insns = cs.disasm_all(code, 0x1000)?;
println!("Found {} instructions", insns.len());
for i in insns.iter() {
println!();
println!("{}", i);

let detail: InsnDetail = cs.insn_detail(i)?;
let arch_detail: ArchDetail = detail.arch_detail();
let ops = arch_detail.operands();
let detail = cs.insn_detail(i)?;
let arch_detail = detail.arch_detail();
let ops: Vec<_> = arch_detail.operands().collect();

#[cfg(feature = "full")]
let output: &[(&str, String)] = &[
Expand Down Expand Up @@ -61,26 +66,19 @@ fn arch_example(cs: &mut Capstone, code: &[u8]) -> CsResult<()> {
}

fn example() -> CsResult<()> {
let cs_mips: Capstone = Capstone::new()
.mips()
let mut cs_mips = Capstone::<MipsArchTag>::new()
.mode(arch::mips::ArchMode::Mips32R6)
.detail(true)
.build()?;

let cs_x86 = Capstone::new()
.x86()
let mut cs_x86 = Capstone::<X86ArchTag>::new()
.mode(arch::x86::ArchMode::Mode64)
.syntax(arch::x86::ArchSyntax::Att)
.detail(true)
.build()?;

let mut examples = [("MIPS", cs_mips, MIPS_CODE), ("X86", cs_x86, X86_CODE)];

for &mut (arch, ref mut cs, code) in examples.iter_mut() {
println!("\n*************************************");
println!("Architecture {}:", arch);
arch_example(cs, code)?;
}
arch_example("MIPS", &mut cs_mips, MIPS_CODE)?;
arch_example("X86", &mut cs_x86, X86_CODE)?;

Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions capstone-rs/examples/objdump.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
extern crate capstone;
extern crate macho;

use capstone::arch::x86::X86ArchTag;
use capstone::prelude::*;
use std::env;
use std::fs;
use std::io::Read;
use std::process;

fn main() {
let cs = Capstone::new()
.x86()
let cs = Capstone::<X86ArchTag>::new()
.mode(arch::x86::ArchMode::Mode64)
.build()
.expect("Failed to create capstone handle");
Expand Down
6 changes: 3 additions & 3 deletions capstone-rs/examples/parallel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
//!
//! We shard the input by using parallel iterators from the rayon crate.
use capstone::arch::x86::X86ArchTag;
use capstone::prelude::*;
use rayon::prelude::*;

fn main() -> CsResult<()> {
// Closure to create `Capstone` instance
let create_cs = || -> CsResult<Capstone> {
let cs = Capstone::new()
.x86()
let create_cs = || -> CsResult<Capstone<X86ArchTag>> {
let cs = Capstone::<X86ArchTag>::new()
.mode(arch::x86::ArchMode::Mode64)
.detail(true)
.build()?;
Expand Down
5 changes: 2 additions & 3 deletions capstone-rs/src/arch/arm.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Contains arm-specific types
use core::convert::From;
use core::{cmp, fmt, slice};

use capstone_sys::{
arm_op_mem, arm_op_type, cs_arm, cs_arm_op, arm_shifter,
Expand Down Expand Up @@ -274,7 +273,7 @@ impl_PartialEq_repr_fields!(ArmOpMem;
base, index, scale, disp
);

impl cmp::Eq for ArmOpMem {}
impl Eq for ArmOpMem {}

impl Default for ArmOperand {
fn default() -> Self {
Expand Down Expand Up @@ -310,7 +309,7 @@ def_arch_details_struct!(
Operand = ArmOperand;
OperandIterator = ArmOperandIterator;
OperandIteratorLife = ArmOperandIterator<'a>;
[ pub struct ArmOperandIterator<'a>(slice::Iter<'a, cs_arm_op>); ]
[ pub struct ArmOperandIterator<'a>(core::slice::Iter<'a, cs_arm_op>); ]
cs_arch_op = cs_arm_op;
cs_arch = cs_arm;
);
Expand Down
2 changes: 1 addition & 1 deletion capstone-rs/src/arch/arm64.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! Contains arm64-specific types
use core::convert::From;
use core::{cmp, fmt, mem, slice};
use core::{cmp, mem, slice};

use capstone_sys::{arm64_op_mem, arm64_op_type, cs_arm64, cs_arm64_op};
use libc::c_uint;
Expand Down
29 changes: 15 additions & 14 deletions capstone-rs/src/arch/evm.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! Contains EVM-specific types
use core::fmt;
use core::fmt::{Debug, Formatter};
use core::marker::PhantomData;

use capstone_sys::cs_evm;

Expand Down Expand Up @@ -73,53 +74,53 @@ pub struct EvmOperand(());

/// Iterates over instruction operands
#[derive(Clone)]
pub struct EvmOperandIterator(());
pub struct EvmOperandIterator<'a>(PhantomData<&'a ()>);

impl EvmOperandIterator {
fn new() -> EvmOperandIterator {
EvmOperandIterator(())
impl<'a> EvmOperandIterator<'a> {
fn new() -> EvmOperandIterator<'a> {
EvmOperandIterator(PhantomData::default())
}
}

impl Iterator for EvmOperandIterator {
impl<'a> Iterator for EvmOperandIterator<'a> {
type Item = EvmOperand;

fn next(&mut self) -> Option<Self::Item> {
None
}
}

impl ExactSizeIterator for EvmOperandIterator {
impl<'a> ExactSizeIterator for EvmOperandIterator<'a> {
fn len(&self) -> usize {
0
}
}

impl PartialEq for EvmOperandIterator {
impl<'a> PartialEq for EvmOperandIterator<'a> {
fn eq(&self, _other: &EvmOperandIterator) -> bool {
false
}
}

impl fmt::Debug for EvmOperandIterator {
fn fmt(&self, fmt: &mut fmt::Formatter) -> ::core::fmt::Result {
impl<'a> Debug for EvmOperandIterator<'a> {
fn fmt(&self, fmt: &mut Formatter) -> ::core::fmt::Result {
fmt.debug_struct("EvmOperandIterator").finish()
}
}

impl<'a> fmt::Debug for EvmInsnDetail<'a> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> ::core::fmt::Result {
impl<'a> Debug for EvmInsnDetail<'a> {
fn fmt(&self, fmt: &mut Formatter) -> ::core::fmt::Result {
fmt.debug_struct("EvmInsnDetail")
.field("cs_evm", &(self.0 as *const cs_evm))
.finish()
}
}

impl<'a> DetailsArchInsn for EvmInsnDetail<'a> {
type OperandIterator = EvmOperandIterator;
type OperandIterator = EvmOperandIterator<'a>;
type Operand = EvmOperand;

fn operands(&self) -> EvmOperandIterator {
fn operands(&self) -> EvmOperandIterator<'a> {
EvmOperandIterator::new()
}
}
Expand Down
3 changes: 1 addition & 2 deletions capstone-rs/src/arch/m680x.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Contains m680x-specific types
use core::convert::From;
use core::{fmt, slice};

use capstone_sys::{
cs_m680x, cs_m680x_op, m680x_op_ext, m680x_op_idx, m680x_op_rel, m680x_op_type,
Expand Down Expand Up @@ -268,7 +267,7 @@ def_arch_details_struct!(
Operand = M680xOperand;
OperandIterator = M680xOperandIterator;
OperandIteratorLife = M680xOperandIterator<'a>;
[ pub struct M680xOperandIterator<'a>(slice::Iter<'a, cs_m680x_op>); ]
[ pub struct M680xOperandIterator<'a>(core::slice::Iter<'a, cs_m680x_op>); ]
cs_arch_op = cs_m680x_op;
cs_arch = cs_m680x;
);
Expand Down
5 changes: 2 additions & 3 deletions capstone-rs/src/arch/m68k.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Contains m68k-specific types
use core::convert::From;
use core::{cmp, fmt, slice};

use capstone_sys::{
cs_m68k, cs_m68k_op, cs_m68k_op__bindgen_ty_1, m68k_address_mode, m68k_cpu_size, m68k_fpu_size,
Expand Down Expand Up @@ -467,7 +466,7 @@ impl_PartialEq_repr_fields!(M68kOpMem;
address_mode, extra_info
);

impl cmp::Eq for M68kOpMem {}
impl Eq for M68kOpMem {}

impl<'a> From<&'a cs_m68k_op> for M68kOperand {
fn from(insn: &cs_m68k_op) -> M68kOperand {
Expand All @@ -480,7 +479,7 @@ def_arch_details_struct!(
Operand = M68kOperand;
OperandIterator = M68kOperandIterator;
OperandIteratorLife = M68kOperandIterator<'a>;
[ pub struct M68kOperandIterator<'a>(slice::Iter<'a, cs_m68k_op>); ]
[ pub struct M68kOperandIterator<'a>(core::slice::Iter<'a, cs_m68k_op>); ]
cs_arch_op = cs_m68k_op;
cs_arch = cs_m68k;
);
Expand Down
5 changes: 2 additions & 3 deletions capstone-rs/src/arch/mips.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Contains mips-specific types
use core::convert::From;
use core::{cmp, fmt, slice};

use capstone_sys::{cs_mips, cs_mips_op, mips_op_mem, mips_op_type};

Expand Down Expand Up @@ -93,7 +92,7 @@ impl_PartialEq_repr_fields!(MipsOpMem;
base, disp
);

impl cmp::Eq for MipsOpMem {}
impl Eq for MipsOpMem {}

impl<'a> From<&'a cs_mips_op> for MipsOperand {
fn from(insn: &cs_mips_op) -> MipsOperand {
Expand All @@ -115,7 +114,7 @@ def_arch_details_struct!(
Operand = MipsOperand;
OperandIterator = MipsOperandIterator;
OperandIteratorLife = MipsOperandIterator<'a>;
[ pub struct MipsOperandIterator<'a>(slice::Iter<'a, cs_mips_op>); ]
[ pub struct MipsOperandIterator<'a>(core::slice::Iter<'a, cs_mips_op>); ]
cs_arch_op = cs_mips_op;
cs_arch = cs_mips;
);
Expand Down
Loading

0 comments on commit 3422ee7

Please sign in to comment.