1#![allow(clippy::unnecessary_cast)]
6
7use alloc::vec::Vec;
8use core::fmt::Debug;
9use core::marker::PhantomData;
10
11use crate::capstone::Capstone;
12use crate::constants::Endian;
13use crate::error::CsResult;
14
15#[derive(Clone, Copy, Debug, PartialEq, Eq)]
16pub struct InsnOffsetSpan {
17 pub offset: u8,
18 pub size: u8,
19}
20
21macro_rules! define_subset_enum {
22 ( [
23 $subset_enum:ident = $base_enum:ident
24 ]
25 $( $variant:ident, )*
26 ) => {
27 #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
28 pub enum $subset_enum {
29 $(
30 $variant,
31 )*
32 }
33
34 impl From<$subset_enum> for $base_enum {
35 fn from(other: $subset_enum) -> $base_enum {
36 match other {
37 $(
38 $subset_enum::$variant => $base_enum::$variant,
39 )*
40 }
41 }
42 }
43 };
44}
45
46macro_rules! define_arch_builder {
48 ( @extra_modes () ) => {};
50 ( @extra_modes ( $( $extra_mode:ident, )+ ) ) => {
51 impl super::BuildsCapstoneExtraMode<ArchMode, ArchExtraMode> for ArchCapstoneBuilder {
52 fn extra_mode<T: Iterator<Item=ArchExtraMode>>(mut self, extra_mode: T) -> Self {
53 self.extra_mode.clear();
54 self.extra_mode.extend(extra_mode);
55 self
56 }
57 }
58 };
59
60 ( @syntax () ) => {};
62 ( @syntax ( $( $syntax:ident, )+ ) ) => {
63 impl super::BuildsCapstoneSyntax<ArchMode, ArchSyntax> for ArchCapstoneBuilder {
64 fn syntax(mut self, syntax: ArchSyntax) -> Self {
65 self.syntax = Some(syntax);
66 self
67 }
68 }
69 };
70
71 ( @endian ( false) ) => {};
73 ( @endian ( true ) ) => {
74 impl super::BuildsCapstoneEndian<ArchMode> for ArchCapstoneBuilder {
75 fn endian(mut self, endian: Endian) -> Self {
76 self.endian = Some(endian);
77 self
78 }
79 }
80 };
81
82 (
84 $( [
85 ( $arch:ident, $arch_variant:ident, $feature:literal )
86 ( mode: $( $mode:ident, )+ )
87 ( extra_modes: $( $extra_mode:ident, )* )
88 ( syntax: $( $syntax:ident, )* )
89 ( both_endian: $( $endian:ident )* )
90 ] )+
91 ) => {
92 $(
96 #[cfg(feature = $feature)]
98 pub mod $arch {
99 use alloc::vec::Vec;
100
101 use crate::capstone::Capstone;
102 use crate::constants::{Arch, Endian, ExtraMode, Mode, Syntax};
103 use crate::error::{CsResult, Error};
104
105 define_arch_builder!( @syntax ( $( $syntax, )* ) );
106 define_arch_builder!( @endian ( $( $endian )* ) );
107 define_arch_builder!( @extra_modes ( $( $extra_mode, )* ) );
108
109 define_subset_enum!(
110 [ ArchMode = Mode ]
111 $( $mode, )*
112 );
113
114 define_subset_enum!(
115 [ ArchExtraMode = ExtraMode ]
116 $( $extra_mode, )*
117 );
118
119 define_subset_enum!(
120 [ ArchSyntax = Syntax ]
121 $( $syntax, )*
122 );
123
124 #[derive(Clone)]
125 pub struct ArchCapstoneBuilder {
126 pub(crate) mode: Option<ArchMode>,
127 pub(crate) is_detail: bool,
128 pub(crate) extra_mode: Vec<ArchExtraMode>,
129 pub(crate) syntax: Option<ArchSyntax>,
130 pub(crate) endian: Option<Endian>,
131 }
132
133 impl super::BuildsCapstone<ArchMode> for ArchCapstoneBuilder {
134 fn mode(mut self, mode: ArchMode) -> Self {
135 self.mode = Some(mode);
136 self
137 }
138
139 fn detail(mut self, enable_detail: bool) -> Self {
140 self.is_detail = enable_detail;
141 self
142 }
143
144 fn build(self) -> CsResult<Capstone> {
145 let mode = match self.mode {
146 Some(mode) => mode,
147 None => {
148 let msg: &'static str = concat!(
149 "Must specify mode for ",
150 stringify!($arch),
151 "::ArchCapstoneBuilder with `mode()` method",
152 );
153 return Err(Error::CustomError(msg));
154 }
155 };
156 let extra_mode = self.extra_mode.iter().map(|x| ExtraMode::from(*x));
157 let mut capstone = Capstone::new_raw(Arch::$arch_variant,
158 mode.into(),
159 extra_mode,
160 self.endian)?;
161
162 if let Some(syntax) = self.syntax {
163 capstone.set_syntax(Syntax::from(syntax))?;
164 }
165 if self.is_detail {
166 capstone.set_detail(self.is_detail)?;
167 }
168
169 Ok(capstone)
170 }
171 }
172
173 impl Default for ArchCapstoneBuilder {
174 fn default() -> Self {
175 ArchCapstoneBuilder {
176 mode: None,
177 is_detail: false,
178 extra_mode: vec![],
179 endian: None,
180 syntax: None,
181 }
182 }
183 }
184 }
185 )+
186
187 impl CapstoneBuilder {
188 $(
189 #[cfg(feature = $feature)]
190 pub fn $arch(self) -> $arch::ArchCapstoneBuilder {
191 Default::default()
192 }
193 )*
194 }
195 }
196}
197
198macro_rules! arch_info_base {
205 ($x_macro:ident) => {
206 $x_macro!(
207 [
208 ( arm, ARM, "arch_arm" )
209 ( mode:
210 Arm,
211 Thumb,
212 )
213 ( extra_modes:
214 MClass,
215 V8,
216 )
217 ( syntax:
218 NoRegName,
219 )
220 ( both_endian: true )
221 ]
222 [
223 ( arm64, ARM64, "arch_arm64" )
224 ( mode:
225 Arm,
226 )
227 ( extra_modes: )
228 ( syntax: )
229 ( both_endian: true )
230 ]
231 [
232 ( evm, EVM, "arch_evm" )
233 ( mode:
234 Default,
235 )
236 ( extra_modes: )
237 ( syntax: )
238 ( both_endian: false )
239 ]
240 [
241 ( m680x, M680X, "arch_m680x" )
242 ( mode:
243 M680x6301,
244 M680x6309,
245 M680x6800,
246 M680x6801,
247 M680x6805,
248 M680x6808,
249 M680x6809,
250 M680x6811,
251 M680xCpu12,
252 M680xHcs08,
253 )
254 ( extra_modes: )
255 ( syntax: )
256 ( both_endian: false )
257 ]
258 [
259 ( m68k, M68K, "arch_m68k" )
260 ( mode:
261 M68k000,
262 M68k010,
263 M68k020,
264 M68k030,
265 M68k040,
266 )
267 ( extra_modes: )
268 ( syntax: )
269 ( both_endian: false )
270 ]
271 [
272 ( mips, MIPS, "arch_mips" )
273 ( mode:
274 Mips32,
275 Mips64,
276 Mips2,
277 Mips3,
278 Mips32R6,
279 )
280 ( extra_modes:
281 Micro,
282 )
283 ( syntax: )
284 ( both_endian: true )
285 ]
286 [
287 ( mos65xx, MOS65XX, "arch_mos65xx" )
288 ( mode:
289 Mos65xx6502,
290 Mos65xx65c02,
291 Mos65xxW65c02,
292 Mos65xx65816,
293 Mos65xx65816LongM,
294 Mos65xx65816LongX,
295 Mos65xx65816LongMx,
296 )
297 ( extra_modes: )
298 ( syntax: )
299 ( both_endian: false )
300 ]
301 [
302 ( ppc, PPC, "arch_powerpc" )
303 ( mode:
304 Mode32,
305 Mode64,
306 Qpx,
307 )
308 ( extra_modes: )
309 ( syntax:
310 NoRegName,
311 )
312 ( both_endian: true )
313 ]
314 [
315 ( riscv, RISCV, "arch_riscv" )
316 ( mode:
317 RiscV32,
318 RiscV64,
319 )
320 ( extra_modes:
321 RiscVC,
322 )
323 ( syntax: )
324 ( both_endian: true )
325 ]
326 [
327 ( sh, SH, "arch_sh" )
328 ( mode:
329 Sh2,
330 Sh2a,
331 Sh3,
332 Sh4,
333 Sh4a,
334 ShFpu,
335 ShDsp,
336 )
337 ( extra_modes: )
338 ( syntax: )
339 ( both_endian: false )
340 ]
341 [
342 ( sparc, SPARC, "arch_sparc" )
343 ( mode:
344 Default,
345 V9,
346 )
347 ( extra_modes: )
348 ( syntax: )
349 ( both_endian: false )
350 ]
351 [
352 ( sysz, SYSZ, "arch_sysz" )
353 ( mode:
354 Default,
355 )
356 ( extra_modes: )
357 ( syntax: )
358 ( both_endian: false )
359 ]
360 [
361 ( tms320c64x, TMS320C64X, "arch_tms320c64x" )
362 ( mode:
363 Default,
364 )
365 ( extra_modes: )
366 ( syntax: )
367 ( both_endian: true )
368 ]
369 [
370 ( tricore, TRICORE, "arch_tricore" )
371 ( mode:
372 TriCore110,
373 TriCore120,
374 TriCore130,
375 TriCore131,
376 TriCore160,
377 TriCore161,
378 TriCore162,
379 )
380 ( extra_modes: )
381 ( syntax: )
382 ( both_endian: true )
383 ]
384 [
385 ( x86, X86, "arch_x86" )
386 ( mode:
387 Mode16,
388 Mode32,
389 Mode64,
390 )
391 ( extra_modes: )
392 ( syntax:
393 Intel,
394 Att,
395 Masm,
396 )
397 ( both_endian: false )
398 ]
399 [
400 ( xcore, XCORE, "arch_xcore" )
401 ( mode:
402 Default,
403 )
404 ( extra_modes: )
405 ( syntax: )
406 ( both_endian: false )
407 ]
408 [
409 ( bpf, BPF, "arch_bpf" )
410 ( mode:
411 Cbpf,
412 Ebpf,
413 )
414 ( extra_modes: )
415 ( syntax: )
416 ( both_endian: true )
417 ]
418 );
419 };
420}
421
422pub trait BuildsCapstone<ArchMode> {
424 fn mode(self, mode: ArchMode) -> Self;
426
427 fn detail(self, enable_detail: bool) -> Self;
429
430 fn build(self) -> CsResult<Capstone>;
432}
433
434pub trait BuildsCapstoneExtraMode<ArchMode, ArchExtraMode>: BuildsCapstone<ArchMode> {
436 fn extra_mode<T: Iterator<Item = ArchExtraMode>>(self, extra_mode: T) -> Self;
438}
439
440pub trait BuildsCapstoneSyntax<ArchMode, ArchSyntax>: BuildsCapstone<ArchMode> {
442 fn syntax(self, syntax: ArchSyntax) -> Self;
444}
445
446pub trait BuildsCapstoneEndian<ArchMode>: BuildsCapstone<ArchMode> {
448 fn endian(self, endian: Endian) -> Self;
450}
451
452pub(crate) mod arch_builder {
454 use super::*;
455
456 arch_info_base!(define_arch_builder);
457}
458
459#[derive(Debug)]
461pub struct CapstoneBuilder(
462 PhantomData<()>,
464);
465
466impl CapstoneBuilder {
467 pub(crate) fn new() -> Self {
469 CapstoneBuilder(PhantomData)
470 }
471}
472
473pub trait DetailsArchInsn: PartialEq + Debug {
475 type Operand: Into<ArchOperand> + Default + Clone + Debug + PartialEq;
476 type OperandIterator: Iterator<Item = Self::Operand>;
477
478 fn operands(&self) -> Self::OperandIterator;
479}
480
481macro_rules! impl_PartialEq_repr_fields {
483 (
485 $name:ty [ $( $lifetime:tt ),* ];
486 $( $field:ident),*
487 ) => {
488 impl<$( $lifetime ),*> ::core::cmp::PartialEq for $name {
489 fn eq(&self, other: &Self) -> bool {
490 $(
491 if self.$field() != other.$field() {
492 return false;
493 }
494 )*
495 true
496 }
497 }
498 };
499
500 (
502 $name:ty;
503 $( $field:ident),*
504 ) => {
505 impl_PartialEq_repr_fields!(
506 $name [];
507 $( $field),*
508 );
509 };
510}
511
512macro_rules! detail_arch_base {
514 ($x_macro:ident) => {
515 $x_macro!(
516 [
517 detail = ArmDetail,
518 insn_detail = ArmInsnDetail<'a>,
519 op = ArmOperand,
520 feature = "arch_arm",
521 => arch_name = arm,
523 ]
524 [
525 detail = Arm64Detail,
526 insn_detail = Arm64InsnDetail<'a>,
527 op = Arm64Operand,
528 feature = "arch_arm64",
529 => arch_name = arm64,
531 ]
532 [
533 detail = EvmDetail,
534 insn_detail = EvmInsnDetail<'a>,
535 op = EvmOperand,
536 feature = "arch_evm",
537 => arch_name = evm,
539 ]
540 [
541 detail = M680xDetail,
542 insn_detail = M680xInsnDetail<'a>,
543 op = M680xOperand,
544 feature = "arch_m680x",
545 => arch_name = m680x,
547 ]
548 [
549 detail = M68kDetail,
550 insn_detail = M68kInsnDetail<'a>,
551 op = M68kOperand,
552 feature = "arch_m68k",
553 => arch_name = m68k,
555 ]
556 [
557 detail = MipsDetail,
558 insn_detail = MipsInsnDetail<'a>,
559 op = MipsOperand,
560 feature = "arch_mips",
561 => arch_name = mips,
563 ]
564 [
565 detail = Mos65xxDetail,
566 insn_detail = Mos65xxInsnDetail<'a>,
567 op = Mos65xxOperand,
568 feature = "arch_mos65xx",
569 => arch_name = mos65xx,
571 ]
572 [
573 detail = PpcDetail,
574 insn_detail = PpcInsnDetail<'a>,
575 op = PpcOperand,
576 feature = "arch_powerpc",
577 => arch_name = ppc,
579 ]
580 [
581 detail = RiscVDetail,
582 insn_detail = RiscVInsnDetail<'a>,
583 op = RiscVOperand,
584 feature = "arch_riscv",
585 => arch_name = riscv,
587 ]
588 [
589 detail = ShDetail,
590 insn_detail = ShInsnDetail<'a>,
591 op = ShOperand,
592 feature = "arch_sh",
593 => arch_name = sh,
595 ]
596 [
597 detail = SparcDetail,
598 insn_detail = SparcInsnDetail<'a>,
599 op = SparcOperand,
600 feature = "arch_sparc",
601 => arch_name = sparc,
603 ]
604 [
605 detail = Tms320c64xDetail,
606 insn_detail = Tms320c64xInsnDetail<'a>,
607 op = Tms320c64xOperand,
608 feature = "arch_tms320c64x",
609 => arch_name = tms320c64x,
611 ]
612 [
613 detail = TriCoreDetail,
614 insn_detail = TriCoreInsnDetail<'a>,
615 op = TriCoreOperand,
616 feature = "arch_tricore",
617 => arch_name = tricore,
619 ]
620 [
621 detail = X86Detail,
622 insn_detail = X86InsnDetail<'a>,
623 op = X86Operand,
624 feature = "arch_x86",
625 => arch_name = x86,
627 ]
628 [
629 detail = XcoreDetail,
630 insn_detail = XcoreInsnDetail<'a>,
631 op = XcoreOperand,
632 feature = "arch_xcore",
633 => arch_name = xcore,
635 ]
636 [
637 detail = BpfDetail,
638 insn_detail = BpfInsnDetail<'a>,
639 op = BpfOperand,
640 feature = "arch_bpf",
641 => arch_name = bpf,
643 ]
644 [
645 detail = SysZDetail,
646 insn_detail = SysZInsnDetail<'a>,
647 op = SysZOperand,
648 feature = "arch_sysz",
649 => arch_name = sysz,
651 ]
652 );
653 };
654}
655
656macro_rules! detail_defs {
658 (
659 $( [
660 detail = $Detail:tt,
661 insn_detail = $InsnDetail:ty,
662 op = $Operand:tt,
663 feature = $feature:literal,
664 $( #[$func_attr:meta] )+
665 => arch_name = $arch_name:ident,
666 ] )+
667 ) => {
668 $(
669 #[cfg(feature = $feature)]
670 use self::$arch_name::*;
671 )+
672
673 #[derive(Debug)]
679 pub enum ArchDetail<'a> {
680 $(
681 #[cfg(feature = $feature)]
682 $Detail($InsnDetail),
683 )+
684 }
685
686 #[derive(Clone, Debug, PartialEq)]
688 pub enum ArchOperand {
689 $(
690 #[cfg(feature = $feature)]
691 $Operand($Operand),
692 )+
693 }
694
695 impl<'a> ArchDetail<'a> {
696 pub fn operands(&'a self) -> Vec<ArchOperand> {
698 match *self {
699 $(
700 #[cfg(feature = $feature)]
701 ArchDetail::$Detail(ref detail) => {
702 let ops = detail.operands();
703 let map = ops.map(ArchOperand::from);
704 let vec: Vec<ArchOperand> = map.collect();
705 vec
706 }
707 )+
708 }
709 }
710
711 $(
712 $( #[$func_attr] )+
713 #[cfg(feature = $feature)]
714 pub fn $arch_name(&'a self) -> Option<&'a $InsnDetail> {
715 #[allow(irrefutable_let_patterns)]
717 if let ArchDetail::$Detail(ref arch_detail) = *self {
718 Some(arch_detail)
719 } else {
720 None
721 }
722 }
723 )+
724 }
725
726 $(
727 #[cfg(feature = $feature)]
728 impl From<$Operand> for ArchOperand {
729 fn from(op: $Operand) -> ArchOperand {
730 ArchOperand::$Operand(op)
731 }
732 }
733 )+
734 }
735}
736
737macro_rules! def_arch_details_struct {
739 (
740 InsnDetail = $InsnDetail:ident;
741 Operand = $Operand:ident;
742 OperandIterator = $OperandIterator:ident;
743 OperandIteratorLife = $OperandIteratorLife:ty;
744 [ $iter_struct:item ]
745 cs_arch_op = $cs_arch_op:ty;
746 cs_arch = $cs_arch:ty;
747 ) => {
748 #[derive(Clone)]
750 $iter_struct
751
752 impl<'a> $OperandIteratorLife {
753 fn new(ops: &[$cs_arch_op]) -> $OperandIterator<'_> {
754 $OperandIterator(ops.iter())
755 }
756 }
757
758 impl<'a> Iterator for $OperandIteratorLife {
759 type Item = $Operand;
760
761 fn next(&mut self) -> Option<Self::Item> {
762 self.0.next().map($Operand::from)
763 }
764
765 fn size_hint(&self) -> (usize, Option<usize>) {
766 self.0.size_hint()
767 }
768 }
769
770 impl<'a> ExactSizeIterator for $OperandIteratorLife {
771 fn len(&self) -> usize { self.0.len() }
772 }
773
774 impl<'a> PartialEq for $OperandIteratorLife {
775 fn eq(&self, other: & $OperandIteratorLife) -> bool {
776 self.len() == other.len() && {
777 let self_clone: $OperandIterator = self.clone();
778 let other_clone: $OperandIterator = (*other).clone();
779 self_clone.zip(other_clone).all(|(a, b)| a == b)
780 }
781 }
782 }
783
784 impl<'a> ::core::fmt::Debug for $OperandIteratorLife {
785 fn fmt(&self, fmt: &mut fmt::Formatter) -> ::core::fmt::Result {
786 fmt.debug_struct(stringify!($OperandIterator)).finish()
787 }
788 }
789
790 impl<'a> ::core::fmt::Debug for $InsnDetail<'a> {
791 fn fmt(&self, fmt: &mut fmt::Formatter) -> ::core::fmt::Result {
792 fmt.debug_struct(stringify!($InsnDetail))
793 .field(stringify!($cs_arch), &(self.0 as *const $cs_arch))
794 .finish()
795 }
796 }
797
798 impl<'a> crate::arch::DetailsArchInsn for $InsnDetail<'a> {
799 type OperandIterator = $OperandIteratorLife;
800 type Operand = $Operand;
801
802 fn operands(&self) -> $OperandIteratorLife {
803 $OperandIterator::new(&self.0.operands[..self.0.op_count as usize])
804 }
805 }
806 }
807}
808
809detail_arch_base!(detail_defs);
810
811macro_rules! define_arch_mods {
813 (
814 $( [
815 ( $arch:ident, $arch_variant:ident, $feature:literal )
816 ( mode: $( $mode:ident, )+ )
817 ( extra_modes: $( $extra_mode:ident, )* )
818 ( syntax: $( $syntax:ident, )* )
819 ( both_endian: $( $endian:expr )* )
820 ] )+
821 ) => {
822 $(
823 #[cfg(feature = $feature)]
824 pub mod $arch;
825 )+
826 }
827}
828
829arch_info_base!(define_arch_mods);