Skip to content

Commit 182e5a0

Browse files
committed
Add ArchTag trait and its implementations for supported architectures
This commit is the first commit among a series of patches that implement the compile-time architecture tag proposal in #118. It contains the following major changes: - Add the ArchTag trait. This trait indicates a "tag" type that represents a specific architecture. Its associated types specify specific data types corresponding to the architecture it represents. - Add ArchTag implementations for supported architectures, and a special DynamicArchTag that indicates the target architecture is unknown at compile time. - Update existing general type definitions (e.g. Capstone, Insn, etc.) to acquire a general arch tag type parameter.
1 parent 74ccb09 commit 182e5a0

16 files changed

+732
-200
lines changed

capstone-rs/src/arch/arm.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ use capstone_sys::{
99
use libc::c_uint;
1010

1111
pub use crate::arch::arch_builder::arm::*;
12-
use crate::arch::DetailsArchInsn;
12+
use crate::arch::{ArchTag, DetailsArchInsn};
13+
use crate::arch::internal::ArchTagSealed;
1314
use crate::instruction::{RegId, RegIdInt};
15+
use crate::{Arch, InsnDetail};
1416

1517
pub use capstone_sys::arm_insn_group as ArmInsnGroup;
1618
pub use capstone_sys::arm_insn as ArmInsn;
@@ -22,9 +24,37 @@ pub use capstone_sys::arm_cc as ArmCC;
2224
pub use capstone_sys::arm_mem_barrier as ArmMemBarrier;
2325
pub use capstone_sys::arm_setend_type as ArmSetendType;
2426

27+
pub struct ArmArchTag;
28+
29+
impl ArchTagSealed for ArmArchTag {}
30+
31+
impl ArchTag for ArmArchTag {
32+
type Builder = ArchCapstoneBuilder;
33+
34+
type Mode = ArchMode;
35+
type ExtraMode = ArchExtraMode;
36+
type Syntax = ArchSyntax;
37+
38+
type RegId = ArmReg::Type;
39+
type InsnId = ArmInsn;
40+
type InsnGroupId = ArmInsnGroup::Type;
41+
42+
type InsnDetail<'a> = ArmInsnDetail<'a>;
43+
44+
fn support_arch(arch: Arch) -> bool {
45+
arch == Arch::ARM
46+
}
47+
}
48+
2549
/// Contains ARM-specific details for an instruction
2650
pub struct ArmInsnDetail<'a>(pub(crate) &'a cs_arm);
2751

52+
impl<'a, 'i> From<&'i InsnDetail<'a, ArmArchTag>> for ArmInsnDetail<'a> {
53+
fn from(value: &'i InsnDetail<'a, ArmArchTag>) -> Self {
54+
Self(unsafe { &value.0.__bindgen_anon_1.arm })
55+
}
56+
}
57+
2858
/// ARM shift amount
2959
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
3060
pub enum ArmShift {

capstone-rs/src/arch/arm64.rs

+34-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
//! Contains arm64-specific types
22
3+
use core::convert::From;
4+
use core::{cmp, fmt, mem, slice};
5+
6+
use capstone_sys::{arm64_op_mem, arm64_op_type, cs_arm64, cs_arm64_op};
37
use libc::c_uint;
48

59
pub use crate::arch::arch_builder::arm64::*;
6-
use crate::arch::DetailsArchInsn;
7-
use capstone_sys::{arm64_op_mem, arm64_op_type, cs_arm64, cs_arm64_op};
10+
use crate::arch::{ArchTag, DetailsArchInsn};
11+
use crate::arch::internal::ArchTagSealed;
812
use crate::instruction::{RegId, RegIdInt};
9-
use core::convert::From;
10-
use core::{cmp, fmt, mem, slice};
13+
use crate::{Arch, InsnDetail};
1114

1215
// Re-exports
1316
pub use capstone_sys::arm64_insn_group as Arm64InsnGroup;
@@ -26,10 +29,37 @@ pub use capstone_sys::arm64_barrier_op as Arm64BarrierOp;
2629
use capstone_sys::cs_arm64_op__bindgen_ty_2;
2730
use capstone_sys::arm64_shifter;
2831

32+
pub struct Arm64ArchTag;
33+
34+
impl ArchTagSealed for Arm64ArchTag {}
35+
36+
impl ArchTag for Arm64ArchTag {
37+
type Builder = ArchCapstoneBuilder;
38+
39+
type Mode = ArchMode;
40+
type ExtraMode = ArchExtraMode;
41+
type Syntax = ArchSyntax;
42+
43+
type RegId = Arm64Reg::Type;
44+
type InsnId = Arm64Insn;
45+
type InsnGroupId = Arm64InsnGroup::Type;
46+
47+
type InsnDetail<'a> = Arm64InsnDetail<'a>;
48+
49+
fn support_arch(arch: Arch) -> bool {
50+
arch == Arch::ARM64
51+
}
52+
}
2953

3054
/// Contains ARM64-specific details for an instruction
3155
pub struct Arm64InsnDetail<'a>(pub(crate) &'a cs_arm64);
3256

57+
impl<'a, 'i> From<&'i InsnDetail<'a, Arm64ArchTag>> for Arm64InsnDetail<'a> {
58+
fn from(value: &'i InsnDetail<'a, Arm64ArchTag>) -> Self {
59+
Self(unsafe { &value.0.__bindgen_anon_1.arm64 })
60+
}
61+
}
62+
3363
/// ARM64 shift amount
3464
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
3565
pub enum Arm64Shift {

capstone-rs/src/arch/evm.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,31 @@ pub use capstone_sys::evm_insn_group as EvmInsnGroup;
99
pub use capstone_sys::evm_insn as EvmInsn;
1010

1111
pub use crate::arch::arch_builder::evm::*;
12-
use crate::arch::DetailsArchInsn;
12+
use crate::arch::{ArchTag, DetailsArchInsn};
13+
use crate::arch::internal::ArchTagSealed;
14+
use crate::{Arch, InsnDetail};
15+
16+
pub struct EvmArchTag;
17+
18+
impl ArchTagSealed for EvmArchTag {}
19+
20+
impl ArchTag for EvmArchTag {
21+
type Builder = ArchCapstoneBuilder;
22+
23+
type Mode = ArchMode;
24+
type ExtraMode = ArchExtraMode;
25+
type Syntax = ArchSyntax;
26+
27+
type RegId = u32;
28+
type InsnId = EvmInsn;
29+
type InsnGroupId = EvmInsnGroup::Type;
30+
31+
type InsnDetail<'a> = EvmInsnDetail<'a>;
32+
33+
fn support_arch(arch: Arch) -> bool {
34+
arch == Arch::EVM
35+
}
36+
}
1337

1438
/// Contains EVM-specific details for an instruction
1539
pub struct EvmInsnDetail<'a>(pub(crate) &'a cs_evm);
@@ -35,6 +59,12 @@ impl_PartialEq_repr_fields!(EvmInsnDetail<'a> [ 'a ];
3559
popped_items, pushed_items, fee
3660
);
3761

62+
impl<'a, 'i> From<&'i InsnDetail<'a, EvmArchTag>> for EvmInsnDetail<'a> {
63+
fn from(value: &'i InsnDetail<'a, EvmArchTag>) -> Self {
64+
Self(unsafe { &value.0.__bindgen_anon_1.evm })
65+
}
66+
}
67+
3868
/// EVM has no operands, so this is a zero-size type.
3969
#[derive(Clone, Debug, Eq, PartialEq, Default)]
4070
pub struct EvmOperand(());

capstone-rs/src/arch/m680x.rs

+30-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,32 @@ pub use capstone_sys::m680x_insn as M680xInsn;
1212
pub use capstone_sys::m680x_reg as M680xReg;
1313

1414
pub use crate::arch::arch_builder::m680x::*;
15-
use crate::arch::DetailsArchInsn;
15+
use crate::arch::{ArchTag, DetailsArchInsn};
16+
use crate::arch::internal::ArchTagSealed;
1617
use crate::instruction::{RegId, RegIdInt};
18+
use crate::{Arch, InsnDetail};
1719

20+
pub struct M680xArchTag;
21+
22+
impl ArchTagSealed for M680xArchTag {}
23+
24+
impl ArchTag for M680xArchTag {
25+
type Builder = ArchCapstoneBuilder;
26+
27+
type Mode = ArchMode;
28+
type ExtraMode = ArchExtraMode;
29+
type Syntax = ArchSyntax;
30+
31+
type RegId = M680xReg::Type;
32+
type InsnId = M680xInsn;
33+
type InsnGroupId = u32;
34+
35+
type InsnDetail<'a> = M680xInsnDetail<'a>;
36+
37+
fn support_arch(arch: Arch) -> bool {
38+
arch == Arch::M680X
39+
}
40+
}
1841

1942
/// Contains M680X-specific details for an instruction
2043
pub struct M680xInsnDetail<'a>(pub(crate) &'a cs_m680x);
@@ -23,6 +46,12 @@ impl_PartialEq_repr_fields!(M680xInsnDetail<'a> [ 'a ];
2346
operands, flags
2447
);
2548

49+
impl<'a, 'i> From<&'i InsnDetail<'a, M680xArchTag>> for M680xInsnDetail<'a> {
50+
fn from(value: &'i InsnDetail<'a, M680xArchTag>) -> Self {
51+
Self(unsafe { &value.0.__bindgen_anon_1.m680x })
52+
}
53+
}
54+
2655
// M680X instruction flags
2756
const M680X_FIRST_OP_IN_MNEM: u8 = 1;
2857
const M680X_SECOND_OP_IN_MNEM: u8 = 2;

capstone-rs/src/arch/m68k.rs

+33-7
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,33 @@ pub use capstone_sys::m68k_insn as M68kInsn;
1414
pub use capstone_sys::m68k_reg as M68kReg;
1515

1616
pub use crate::arch::arch_builder::m68k::*;
17-
use crate::arch::DetailsArchInsn;
18-
use crate::Error;
17+
use crate::arch::{ArchTag, DetailsArchInsn};
18+
use crate::arch::internal::ArchTagSealed;
19+
use crate::{Arch, Error, InsnDetail};
1920
use crate::instruction::{RegId, RegIdInt};
2021
use crate::prelude::*;
2122

23+
pub struct M68kArchTag;
24+
25+
impl ArchTagSealed for M68kArchTag {}
26+
27+
impl ArchTag for M68kArchTag {
28+
type Builder = ArchCapstoneBuilder;
29+
30+
type Mode = ArchMode;
31+
type ExtraMode = ArchExtraMode;
32+
type Syntax = ArchSyntax;
33+
34+
type RegId = M68kReg::Type;
35+
type InsnId = M68kInsn;
36+
type InsnGroupId = u32;
37+
38+
type InsnDetail<'a> = M68kInsnDetail<'a>;
39+
40+
fn support_arch(arch: Arch) -> bool {
41+
arch == Arch::M68K
42+
}
43+
}
2244

2345
/// Contains M68K-specific details for an instruction
2446
pub struct M68kInsnDetail<'a>(pub(crate) &'a cs_m68k);
@@ -30,6 +52,12 @@ impl<'a> M68kInsnDetail<'a> {
3052
}
3153
}
3254

55+
impl<'a, 'i> From<&'i InsnDetail<'a, M68kArchTag>> for M68kInsnDetail<'a> {
56+
fn from(value: &'i InsnDetail<'a, M68kArchTag>) -> Self {
57+
Self(unsafe { &value.0.__bindgen_anon_1.m68k })
58+
}
59+
}
60+
3361
define_cs_enum_wrapper_reverse!(
3462
[
3563
/// Operation size of the CPU instructions
@@ -638,8 +666,7 @@ mod test {
638666
use crate::instruction::*;
639667
use crate::arch::DetailsArchInsn;
640668

641-
let cs = Capstone::new()
642-
.m68k()
669+
let cs = Capstone::<M68kArchTag>::new()
643670
.mode(arch::m68k::ArchMode::M68k040)
644671
.detail(true)
645672
.build()
@@ -657,10 +684,9 @@ mod test {
657684
let mut insns_iter = insns.iter();
658685

659686
// jsr
660-
let insn_jsr: &Insn = insns_iter.next().unwrap();
687+
let insn_jsr: &Insn<M68kArchTag> = insns_iter.next().unwrap();
661688
let detail = cs.insn_detail(insn_jsr).unwrap();
662-
let _arch_detail = detail.arch_detail();
663-
let arch_detail = _arch_detail.m68k().unwrap();
689+
let arch_detail = detail.arch_detail();
664690
let mut ops = arch_detail.operands();
665691
if let M68kOperand::Mem(mem) = ops.next().unwrap() {
666692
assert_eq!(mem.imm(), Some(0x12));

capstone-rs/src/arch/mips.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,32 @@ pub use capstone_sys::mips_insn as MipsInsn;
1111
pub use capstone_sys::mips_reg as MipsReg;
1212

1313
pub use crate::arch::arch_builder::mips::*;
14-
use crate::arch::DetailsArchInsn;
14+
use crate::arch::{ArchTag, DetailsArchInsn};
15+
use crate::arch::internal::ArchTagSealed;
1516
use crate::instruction::{RegId, RegIdInt};
17+
use crate::{Arch, InsnDetail};
18+
19+
pub struct MipsArchTag;
20+
21+
impl ArchTagSealed for MipsArchTag {}
22+
23+
impl ArchTag for MipsArchTag {
24+
type Builder = ArchCapstoneBuilder;
25+
26+
type Mode = ArchMode;
27+
type ExtraMode = ArchExtraMode;
28+
type Syntax = ArchSyntax;
29+
30+
type RegId = MipsReg::Type;
31+
type InsnId = MipsInsn;
32+
type InsnGroupId = MipsInsnGroup::Type;
33+
34+
type InsnDetail<'a> = MipsInsnDetail<'a>;
35+
36+
fn support_arch(arch: Arch) -> bool {
37+
arch == Arch::MIPS
38+
}
39+
}
1640

1741
/// Contains MIPS-specific details for an instruction
1842
pub struct MipsInsnDetail<'a>(pub(crate) &'a cs_mips);
@@ -21,6 +45,12 @@ impl_PartialEq_repr_fields!(MipsInsnDetail<'a> [ 'a ];
2145
operands
2246
);
2347

48+
impl<'a, 'i> From<&'i InsnDetail<'a, MipsArchTag>> for MipsInsnDetail<'a> {
49+
fn from(value: &'i InsnDetail<'a, MipsArchTag>) -> Self {
50+
Self(unsafe { &value.0.__bindgen_anon_1.mips })
51+
}
52+
}
53+
2454
/// MIPS operand
2555
#[derive(Clone, Debug, Eq, PartialEq)]
2656
pub enum MipsOperand {

0 commit comments

Comments
 (0)