capstone_git/
constants.rs

1use capstone_sys::cs_arch::*;
2use capstone_sys::cs_opt_value::*;
3use capstone_sys::*;
4use core::convert::From;
5use core::fmt::{self, Display};
6use core::str::FromStr;
7
8/// A C-like enum can list its variants
9pub trait EnumList
10where
11    Self: Sized,
12{
13    /// Slice of available variants
14    fn variants() -> &'static [Self];
15}
16
17/// Define the rust enum
18macro_rules! define_cs_rust_enum {
19    ( [
20        $( #[$enum_attr:meta] )*
21        => $rust_enum:ident = $cs_enum:ty
22      ]
23      $( $( #[$attr:meta] )*
24      => $rust_variant:ident = $cs_variant:tt; )* ) => {
25        $( #[$enum_attr] )*
26        #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
27        pub enum $rust_enum {
28            $(
29                $( #[$attr] )*
30                $rust_variant,
31            )*
32        }
33    }
34}
35
36/// Define an `enum` that corresponds to a capstone enum
37///
38/// The different `From` implementations can be disabled by using the cfg attribute
39macro_rules! define_cs_enum_wrapper {
40    ( [
41        $( #[$enum_attr:meta] )*
42        => $rust_enum:ident = $cs_enum:ty
43      ]
44      $( $( #[$attr:meta] )*
45      => $rust_variant:ident = $cs_variant:tt; )* ) => {
46
47        define_cs_rust_enum!(
48            [
49                $( #[$enum_attr] )*
50                => $rust_enum = $cs_enum
51            ]
52            $( $( #[$attr] )*
53            => $rust_variant = $cs_variant; )*
54        );
55
56        impl ::core::convert::From<$rust_enum> for $cs_enum {
57            fn from(other: $rust_enum) -> Self {
58                match other {
59                    $(
60                        $rust_enum::$rust_variant => $cs_variant,
61                    )*
62                }
63            }
64        }
65
66        impl EnumList for $rust_enum {
67            fn variants() -> &'static [Self] {
68                &[
69                    $(
70                        $rust_enum::$rust_variant,
71                    )*
72                ]
73            }
74        }
75
76        impl FromStr for $rust_enum {
77            type Err = &'static str;
78
79            fn from_str(s: &str) -> Result<Self, Self::Err> {
80                let s = s.to_lowercase();
81
82                $(
83                    if s == stringify!($rust_variant).to_lowercase() {
84                        return Ok($rust_enum::$rust_variant);
85                    }
86                )*
87                Err(concat!("Failed to parse ", stringify!($rust_enum)))
88            }
89        }
90
91        impl Display for $rust_enum {
92            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
93                match *self {
94                    $(
95                        $rust_enum::$rust_variant => write!(f, "{}", stringify!($rust_variant)),
96                    )*
97                }
98
99            }
100        }
101    }
102}
103
104/// Define Rust enum that is created from C enum
105#[macro_export]
106macro_rules! define_cs_enum_wrapper_reverse {
107    ( [
108        $( #[$enum_attr:meta] )*
109        => $rust_enum:ident = $cs_enum:ident,
110        $( from_u32 = $gen_from_u32:ident,)*
111      ]
112      $( $( #[$attr:meta] )*
113      => $rust_variant:ident = $cs_variant:tt; )* ) => {
114
115        define_cs_rust_enum!(
116            [
117                $( #[$enum_attr] )*
118                => $rust_enum = $cs_enum
119            ]
120            $( $( #[$attr] )*
121            => $rust_variant = $cs_variant; )*
122        );
123
124        impl ::core::convert::From<$cs_enum> for $rust_enum {
125            fn from(other: $cs_enum) -> Self {
126                match other {
127                    $(
128                        $cs_enum::$cs_variant => $rust_enum::$rust_variant,
129                    )*
130                }
131            }
132        }
133
134        impl $rust_enum {
135            /// Construct from a `u32`
136            #[allow(dead_code)]
137            pub(crate) fn from_u32(other: u32) -> Option<$rust_enum> {
138                match other {
139                    $(
140                        x if x == ($cs_enum::$cs_variant as u32) => Some($rust_enum::$rust_variant),
141                    )*
142                    _ => None,
143                }
144            }
145        }
146    }
147}
148
149/// Defines getters for a bitmask
150///
151/// mask_constants must be unsigned integers with exactly one bit set to 1
152#[macro_export]
153macro_rules! define_impl_bitmask {
154    (
155        impl $struct:ident < $($impl_lifetime:lifetime),* > ;
156        $mask_getter:ident : $mask_getter_ty:ty = { $get_mask:expr }
157        test_mod = $test_mod:ident;
158        $(
159            $( #[$attr:meta] )*
160            => $getter:ident = $mask_constant:ident;
161        )*
162    ) => {
163        #[allow(clippy::redundant_closure_call)]
164        impl < $($impl_lifetime),* > $struct < $($impl_lifetime),* > {
165            /// Raw mask from Capstone
166            pub(crate) fn $mask_getter(&self) -> $mask_getter_ty {
167                $get_mask(self)
168            }
169
170            $(
171                $( #[$attr] )*
172                pub fn $getter(&self) -> bool {
173                    ($get_mask(self) & $mask_constant) != 0
174                }
175            )*
176        }
177
178        /// Test that masks have exactly one 1 bit set
179        #[allow(non_snake_case)]
180        #[cfg(test)]
181        mod $test_mod {
182            use super::*;
183
184            $(
185                #[test]
186                fn $getter() {
187                    assert_eq!($mask_constant.count_ones(), 1);
188                }
189            )*
190        }
191    }
192}
193
194define_cs_enum_wrapper!(
195    [
196        /// Architectures for the disassembler
197        => Arch = cs_arch
198    ]
199    /// ARM (Advanced RISC Machine)
200    => ARM = CS_ARCH_ARM;
201    /// ARM 64-bit (also known as AArch64)
202    => ARM64 = CS_ARCH_ARM64;
203    /// MIPS
204    => MIPS = CS_ARCH_MIPS;
205    /// x86 family (includes 16, 32, and 64 bit modes)
206    => X86 = CS_ARCH_X86;
207    /// PowerPC
208    => PPC = CS_ARCH_PPC;
209    /// SH
210    => SH = CS_ARCH_SH;
211    /// SPARC
212    => SPARC = CS_ARCH_SPARC;
213    /// System z
214    => SYSZ = CS_ARCH_SYSZ;
215    /// XCore
216    => XCORE = CS_ARCH_XCORE;
217    /// Motorolla 68K
218    => M68K = CS_ARCH_M68K;
219    /// MOS65XX architecture (including MOS6502)
220    => MOS65XX = CS_ARCH_MOS65XX;
221    /// Texas Instruments TMS320C64x
222    => TMS320C64X = CS_ARCH_TMS320C64X;
223    /// TriCore
224    => TRICORE = CS_ARCH_TRICORE;
225    /// Motorola 68000
226    => M680X = CS_ARCH_M680X;
227    /// EVM
228    => EVM = CS_ARCH_EVM;
229    /// RISC-V
230    => RISCV = CS_ARCH_RISCV;
231    /// BPF
232    => BPF = CS_ARCH_BPF;
233);
234
235define_cs_enum_wrapper!(
236    [
237        /// Disassembler modes
238        => Mode = cs_mode
239    ]
240    /// 32-bit ARM
241    => Arm = { cs_mode::CS_MODE_ARM };
242    /// 16-bit mode (X86)
243    => Mode16 = { cs_mode::CS_MODE_16 };
244    /// 32-bit mode (X86)
245    => Mode32 = { cs_mode::CS_MODE_32 };
246    /// 64-bit mode (X86, PPC)
247    => Mode64 = { cs_mode::CS_MODE_64 };
248    /// ARM's Thumb mode, including Thumb-2
249    => Thumb = { cs_mode::CS_MODE_THUMB };
250    /// Mips II ISA
251    => Mips2 = { cs_mode::CS_MODE_MIPS2 };
252    /// Mips III ISA
253    => Mips3 = { cs_mode::CS_MODE_MIPS3 };
254    /// Mips32r6 ISA
255    => Mips32R6 = { cs_mode::CS_MODE_MIPS32R6 };
256    /// Mips32 ISA (Mips)
257    => Mips32 = { cs_mode::CS_MODE_MIPS32 };
258    /// Mips64 ISA (Mips)
259    => Mips64 = { cs_mode::CS_MODE_MIPS64 };
260    /// SparcV9 mode (Sparc)
261    => V9 = { cs_mode::CS_MODE_V9 };
262    /// Quad Processing eXtensions mode (PPC)
263    => Qpx = { cs_mode::CS_MODE_QPX };
264    /// M68K 68000 mode
265    => M68k000 = { cs_mode::CS_MODE_M68K_000 };
266    /// M68K 68010 mode
267    => M68k010 = { cs_mode::CS_MODE_M68K_010 };
268    /// M68K 68020 mode
269    => M68k020 = { cs_mode::CS_MODE_M68K_020 };
270    /// M68K 68030 mode
271    => M68k030 = { cs_mode::CS_MODE_M68K_030 };
272    /// M68K 68040 mode
273    => M68k040 = { cs_mode::CS_MODE_M68K_040 };
274    /// M680X Hitachi 6301,6303 mode
275    => M680x6301 = { cs_mode::CS_MODE_M680X_6301 };
276    /// M680X Hitachi 6309 mode
277    => M680x6309 = { cs_mode::CS_MODE_M680X_6309 };
278    /// M680X Motorola 6800,6802 mode
279    => M680x6800 = { cs_mode::CS_MODE_M680X_6800 };
280    /// M680X Motorola 6801,6803 mode
281    => M680x6801 = { cs_mode::CS_MODE_M680X_6801 };
282    /// M680X Motorola/Freescale 6805 mode
283    => M680x6805 = { cs_mode::CS_MODE_M680X_6805 };
284    /// M680X Motorola/Freescale/NXP 68HC08 mode
285    => M680x6808 = { cs_mode::CS_MODE_M680X_6808 };
286    /// M680X Motorola 6809 mode
287    => M680x6809 = { cs_mode::CS_MODE_M680X_6809 };
288    /// M680X Motorola/Freescale/NXP 68HC11 mode
289    => M680x6811 = { cs_mode::CS_MODE_M680X_6811 };
290    /// M680X Motorola/Freescale/NXP CPU12
291    => M680xCpu12 = { cs_mode::CS_MODE_M680X_CPU12 };
292    /// M680X Freescale/NXP HCS08 mode
293    => M680xHcs08 = { cs_mode::CS_MODE_M680X_HCS08 };
294    /// MOS65XXX MOS 6502
295    => Mos65xx6502 = { cs_mode::CS_MODE_MOS65XX_6502 };
296    /// MOS65XXX WDC 65c02
297    => Mos65xx65c02 = { cs_mode::CS_MODE_MOS65XX_65C02 };
298    /// MOS65XXX WDC W65c02
299    => Mos65xxW65c02 = { cs_mode::CS_MODE_MOS65XX_W65C02 };
300    /// MOS65XXX WDC 65816, 8-bit m/x
301    => Mos65xx65816 = { cs_mode::CS_MODE_MOS65XX_65816 };
302    /// MOS65XXX WDC 65816, 16-bit m, 8-bit x
303    => Mos65xx65816LongM = { cs_mode::CS_MODE_MOS65XX_65816_LONG_M };
304    /// MOS65XXX WDC 65816, 8-bit m, 16-bit x
305    => Mos65xx65816LongX = { cs_mode::CS_MODE_MOS65XX_65816_LONG_M };
306    /// MOS65XXX WDC 65816, 16-bit m, 16-bit x
307    => Mos65xx65816LongMx = { cs_mode::CS_MODE_MOS65XX_65816_LONG_MX };
308    /// SH2
309    => Sh2 = { cs_mode::CS_MODE_SH2 };
310    /// SH2A
311    => Sh2a = { cs_mode::CS_MODE_SH2A };
312    /// SH3
313    => Sh3 = { cs_mode::CS_MODE_SH3 };
314    /// SH4
315    => Sh4 = { cs_mode::CS_MODE_SH4 };
316    /// SH4A
317    => Sh4a = { cs_mode::CS_MODE_SH4A };
318    /// SH w/ FPU
319    => ShFpu = { cs_mode::CS_MODE_SHFPU };
320    /// SH w/ DSP
321    => ShDsp = { cs_mode::CS_MODE_SHDSP };
322    /// RISC-V 32-bit mode
323    => RiscV32 = { cs_mode::CS_MODE_RISCV32 };
324    /// RISC-V 64-bit mode
325    => RiscV64 = { cs_mode::CS_MODE_RISCV64 };
326    /// Classic BPF mode
327    => Cbpf = { cs_mode::CS_MODE_BPF_CLASSIC };
328    /// Extended BPF mode
329    => Ebpf = { cs_mode::CS_MODE_BPF_EXTENDED };
330    /// TriCore 1.1
331    => TriCore110 = { cs_mode::CS_MODE_TRICORE_110 };
332    /// TriCore 1.2
333    => TriCore120 = { cs_mode::CS_MODE_TRICORE_120 };
334    /// TriCore 1.3
335    => TriCore130 = { cs_mode::CS_MODE_TRICORE_130 };
336    /// TriCore 1.3.1
337    => TriCore131 = { cs_mode::CS_MODE_TRICORE_131 };
338    /// TriCore 1.6
339    => TriCore160 = { cs_mode::CS_MODE_TRICORE_160 };
340    /// TriCore 1.6.1
341    => TriCore161 = { cs_mode::CS_MODE_TRICORE_161 };
342    /// TriCore 1.6.2
343    => TriCore162 = { cs_mode::CS_MODE_TRICORE_162 };
344    /// Default mode for little-endian
345    => Default = { cs_mode::CS_MODE_LITTLE_ENDIAN };
346);
347
348define_cs_enum_wrapper!(
349    [
350        /// Extra modes or features that can be enabled with some modes
351        => ExtraMode = cs_mode
352    ]
353    /// ARM's Cortex-M series. Works with `Arm` mode.
354    => MClass = { cs_mode::CS_MODE_MCLASS };
355    /// ARMv8 A32 encodings for ARM. Works with `Arm` and `Thumb` modes.
356    => V8 = { cs_mode::CS_MODE_V8 };
357    /// MicroMips mode. Works in `MIPS` mode.
358    => Micro = { cs_mode::CS_MODE_MICRO };
359    /// RISC-V compressed instruction mode
360    => RiscVC = { cs_mode::CS_MODE_RISCVC };
361);
362
363define_cs_enum_wrapper!(
364    [
365        /// Disassembler endianness
366        => Endian = cs_mode
367    ]
368    /// Little-endian mode
369    => Little = { cs_mode::CS_MODE_LITTLE_ENDIAN };
370    /// Big-endian mode
371    => Big = { cs_mode::CS_MODE_BIG_ENDIAN };
372);
373
374define_cs_enum_wrapper!(
375    [
376        /// Disassembly syntax
377        => Syntax = cs_opt_value::Type
378    ]
379    /// Intel syntax
380    => Intel = CS_OPT_SYNTAX_INTEL;
381    /// AT&T syntax (also known as GNU assembler/GAS syntax)
382    => Att = CS_OPT_SYNTAX_ATT;
383    /// MASM syntax
384    => Masm = CS_OPT_SYNTAX_MASM;
385    /// No register name
386    => NoRegName = CS_OPT_SYNTAX_NOREGNAME;
387);
388
389pub(crate) struct OptValue(pub cs_opt_value::Type);
390
391impl From<bool> for OptValue {
392    fn from(value: bool) -> Self {
393        if value {
394            OptValue(cs_opt_value::CS_OPT_ON)
395        } else {
396            OptValue(cs_opt_value::CS_OPT_OFF)
397        }
398    }
399}
400
401#[cfg(test)]
402mod test {
403    use super::*;
404
405    #[test]
406    fn parse_arch() {
407        assert_eq!(Arch::from_str("x86"), Ok(Arch::X86));
408        assert_eq!(Arch::from_str("X86"), Ok(Arch::X86));
409    }
410}