1*9a0e4156SSadaf Ebrahimi /* Capstone Disassembly Engine */
2*9a0e4156SSadaf Ebrahimi /* By Nguyen Anh Quynh <[email protected]>, 2013-2015 */
3*9a0e4156SSadaf Ebrahimi #if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
4*9a0e4156SSadaf Ebrahimi #pragma warning(disable:4996) // disable MSVC's warning on strcpy()
5*9a0e4156SSadaf Ebrahimi #pragma warning(disable:28719) // disable MSVC's warning on strcpy()
6*9a0e4156SSadaf Ebrahimi #endif
7*9a0e4156SSadaf Ebrahimi #if defined(CAPSTONE_HAS_OSXKERNEL)
8*9a0e4156SSadaf Ebrahimi #include <Availability.h>
9*9a0e4156SSadaf Ebrahimi #include <libkern/libkern.h>
10*9a0e4156SSadaf Ebrahimi #else
11*9a0e4156SSadaf Ebrahimi #include <stddef.h>
12*9a0e4156SSadaf Ebrahimi #include <stdio.h>
13*9a0e4156SSadaf Ebrahimi #include <stdlib.h>
14*9a0e4156SSadaf Ebrahimi #endif
15*9a0e4156SSadaf Ebrahimi
16*9a0e4156SSadaf Ebrahimi #include <string.h>
17*9a0e4156SSadaf Ebrahimi #include <capstone/capstone.h>
18*9a0e4156SSadaf Ebrahimi
19*9a0e4156SSadaf Ebrahimi #include "utils.h"
20*9a0e4156SSadaf Ebrahimi #include "MCRegisterInfo.h"
21*9a0e4156SSadaf Ebrahimi
22*9a0e4156SSadaf Ebrahimi #if defined(_KERNEL_MODE)
23*9a0e4156SSadaf Ebrahimi #include "windows\winkernel_mm.h"
24*9a0e4156SSadaf Ebrahimi #endif
25*9a0e4156SSadaf Ebrahimi
26*9a0e4156SSadaf Ebrahimi // Issue #681: Windows kernel does not support formatting float point
27*9a0e4156SSadaf Ebrahimi #if defined(_KERNEL_MODE) && !defined(CAPSTONE_DIET)
28*9a0e4156SSadaf Ebrahimi #if defined(CAPSTONE_HAS_ARM) || defined(CAPSTONE_HAS_ARM64) || defined(CAPSTONE_HAS_M68K)
29*9a0e4156SSadaf Ebrahimi #define CAPSTONE_STR_INTERNAL(x) #x
30*9a0e4156SSadaf Ebrahimi #define CAPSTONE_STR(x) CAPSTONE_STR_INTERNAL(x)
31*9a0e4156SSadaf Ebrahimi #define CAPSTONE_MSVC_WRANING_PREFIX __FILE__ "("CAPSTONE_STR(__LINE__)") : warning message : "
32*9a0e4156SSadaf Ebrahimi
33*9a0e4156SSadaf Ebrahimi #pragma message(CAPSTONE_MSVC_WRANING_PREFIX "Windows driver does not support full features for selected architecture(s). Define CAPSTONE_DIET to compile Capstone with only supported features. See issue #681 for details.")
34*9a0e4156SSadaf Ebrahimi
35*9a0e4156SSadaf Ebrahimi #undef CAPSTONE_MSVC_WRANING_PREFIX
36*9a0e4156SSadaf Ebrahimi #undef CAPSTONE_STR
37*9a0e4156SSadaf Ebrahimi #undef CAPSTONE_STR_INTERNAL
38*9a0e4156SSadaf Ebrahimi #endif
39*9a0e4156SSadaf Ebrahimi #endif // defined(_KERNEL_MODE) && !defined(CAPSTONE_DIET)
40*9a0e4156SSadaf Ebrahimi
41*9a0e4156SSadaf Ebrahimi #if !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(CAPSTONE_DIET) && !defined(_KERNEL_MODE)
42*9a0e4156SSadaf Ebrahimi #define INSN_CACHE_SIZE 32
43*9a0e4156SSadaf Ebrahimi #else
44*9a0e4156SSadaf Ebrahimi // reduce stack variable size for kernel/firmware
45*9a0e4156SSadaf Ebrahimi #define INSN_CACHE_SIZE 8
46*9a0e4156SSadaf Ebrahimi #endif
47*9a0e4156SSadaf Ebrahimi
48*9a0e4156SSadaf Ebrahimi // default SKIPDATA mnemonic
49*9a0e4156SSadaf Ebrahimi #ifndef CAPSTONE_DIET
50*9a0e4156SSadaf Ebrahimi #define SKIPDATA_MNEM ".byte"
51*9a0e4156SSadaf Ebrahimi #else // No printing is available in diet mode
52*9a0e4156SSadaf Ebrahimi #define SKIPDATA_MNEM NULL
53*9a0e4156SSadaf Ebrahimi #endif
54*9a0e4156SSadaf Ebrahimi
55*9a0e4156SSadaf Ebrahimi #include "arch/AArch64/AArch64Module.h"
56*9a0e4156SSadaf Ebrahimi #include "arch/ARM/ARMModule.h"
57*9a0e4156SSadaf Ebrahimi #include "arch/EVM/EVMModule.h"
58*9a0e4156SSadaf Ebrahimi #include "arch/M680X/M680XModule.h"
59*9a0e4156SSadaf Ebrahimi #include "arch/M68K/M68KModule.h"
60*9a0e4156SSadaf Ebrahimi #include "arch/Mips/MipsModule.h"
61*9a0e4156SSadaf Ebrahimi #include "arch/PowerPC/PPCModule.h"
62*9a0e4156SSadaf Ebrahimi #include "arch/Sparc/SparcModule.h"
63*9a0e4156SSadaf Ebrahimi #include "arch/SystemZ/SystemZModule.h"
64*9a0e4156SSadaf Ebrahimi #include "arch/TMS320C64x/TMS320C64xModule.h"
65*9a0e4156SSadaf Ebrahimi #include "arch/X86/X86Module.h"
66*9a0e4156SSadaf Ebrahimi #include "arch/XCore/XCoreModule.h"
67*9a0e4156SSadaf Ebrahimi #include "arch/MOS65XX/MOS65XXModule.h"
68*9a0e4156SSadaf Ebrahimi
69*9a0e4156SSadaf Ebrahimi // constructor initialization for all archs
70*9a0e4156SSadaf Ebrahimi static cs_err (*cs_arch_init[MAX_ARCH])(cs_struct *) = {
71*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_ARM
72*9a0e4156SSadaf Ebrahimi ARM_global_init,
73*9a0e4156SSadaf Ebrahimi #else
74*9a0e4156SSadaf Ebrahimi NULL,
75*9a0e4156SSadaf Ebrahimi #endif
76*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_ARM64
77*9a0e4156SSadaf Ebrahimi AArch64_global_init,
78*9a0e4156SSadaf Ebrahimi #else
79*9a0e4156SSadaf Ebrahimi NULL,
80*9a0e4156SSadaf Ebrahimi #endif
81*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_MIPS
82*9a0e4156SSadaf Ebrahimi Mips_global_init,
83*9a0e4156SSadaf Ebrahimi #else
84*9a0e4156SSadaf Ebrahimi NULL,
85*9a0e4156SSadaf Ebrahimi #endif
86*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_X86
87*9a0e4156SSadaf Ebrahimi X86_global_init,
88*9a0e4156SSadaf Ebrahimi #else
89*9a0e4156SSadaf Ebrahimi NULL,
90*9a0e4156SSadaf Ebrahimi #endif
91*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_POWERPC
92*9a0e4156SSadaf Ebrahimi PPC_global_init,
93*9a0e4156SSadaf Ebrahimi #else
94*9a0e4156SSadaf Ebrahimi NULL,
95*9a0e4156SSadaf Ebrahimi #endif
96*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_SPARC
97*9a0e4156SSadaf Ebrahimi Sparc_global_init,
98*9a0e4156SSadaf Ebrahimi #else
99*9a0e4156SSadaf Ebrahimi NULL,
100*9a0e4156SSadaf Ebrahimi #endif
101*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_SYSZ
102*9a0e4156SSadaf Ebrahimi SystemZ_global_init,
103*9a0e4156SSadaf Ebrahimi #else
104*9a0e4156SSadaf Ebrahimi NULL,
105*9a0e4156SSadaf Ebrahimi #endif
106*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_XCORE
107*9a0e4156SSadaf Ebrahimi XCore_global_init,
108*9a0e4156SSadaf Ebrahimi #else
109*9a0e4156SSadaf Ebrahimi NULL,
110*9a0e4156SSadaf Ebrahimi #endif
111*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_M68K
112*9a0e4156SSadaf Ebrahimi M68K_global_init,
113*9a0e4156SSadaf Ebrahimi #else
114*9a0e4156SSadaf Ebrahimi NULL,
115*9a0e4156SSadaf Ebrahimi #endif
116*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_TMS320C64X
117*9a0e4156SSadaf Ebrahimi TMS320C64x_global_init,
118*9a0e4156SSadaf Ebrahimi #else
119*9a0e4156SSadaf Ebrahimi NULL,
120*9a0e4156SSadaf Ebrahimi #endif
121*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_M680X
122*9a0e4156SSadaf Ebrahimi M680X_global_init,
123*9a0e4156SSadaf Ebrahimi #else
124*9a0e4156SSadaf Ebrahimi NULL,
125*9a0e4156SSadaf Ebrahimi #endif
126*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_EVM
127*9a0e4156SSadaf Ebrahimi EVM_global_init,
128*9a0e4156SSadaf Ebrahimi #else
129*9a0e4156SSadaf Ebrahimi NULL,
130*9a0e4156SSadaf Ebrahimi #endif
131*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_MOS65XX
132*9a0e4156SSadaf Ebrahimi MOS65XX_global_init,
133*9a0e4156SSadaf Ebrahimi #else
134*9a0e4156SSadaf Ebrahimi NULL,
135*9a0e4156SSadaf Ebrahimi #endif
136*9a0e4156SSadaf Ebrahimi };
137*9a0e4156SSadaf Ebrahimi
138*9a0e4156SSadaf Ebrahimi // support cs_option() for all archs
139*9a0e4156SSadaf Ebrahimi static cs_err (*cs_arch_option[MAX_ARCH]) (cs_struct *, cs_opt_type, size_t value) = {
140*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_ARM
141*9a0e4156SSadaf Ebrahimi ARM_option,
142*9a0e4156SSadaf Ebrahimi #else
143*9a0e4156SSadaf Ebrahimi NULL,
144*9a0e4156SSadaf Ebrahimi #endif
145*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_ARM64
146*9a0e4156SSadaf Ebrahimi AArch64_option,
147*9a0e4156SSadaf Ebrahimi #else
148*9a0e4156SSadaf Ebrahimi NULL,
149*9a0e4156SSadaf Ebrahimi #endif
150*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_MIPS
151*9a0e4156SSadaf Ebrahimi Mips_option,
152*9a0e4156SSadaf Ebrahimi #else
153*9a0e4156SSadaf Ebrahimi NULL,
154*9a0e4156SSadaf Ebrahimi #endif
155*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_X86
156*9a0e4156SSadaf Ebrahimi X86_option,
157*9a0e4156SSadaf Ebrahimi #else
158*9a0e4156SSadaf Ebrahimi NULL,
159*9a0e4156SSadaf Ebrahimi #endif
160*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_POWERPC
161*9a0e4156SSadaf Ebrahimi PPC_option,
162*9a0e4156SSadaf Ebrahimi #else
163*9a0e4156SSadaf Ebrahimi NULL,
164*9a0e4156SSadaf Ebrahimi #endif
165*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_SPARC
166*9a0e4156SSadaf Ebrahimi Sparc_option,
167*9a0e4156SSadaf Ebrahimi #else
168*9a0e4156SSadaf Ebrahimi NULL,
169*9a0e4156SSadaf Ebrahimi #endif
170*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_SYSZ
171*9a0e4156SSadaf Ebrahimi SystemZ_option,
172*9a0e4156SSadaf Ebrahimi #else
173*9a0e4156SSadaf Ebrahimi NULL,
174*9a0e4156SSadaf Ebrahimi #endif
175*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_XCORE
176*9a0e4156SSadaf Ebrahimi XCore_option,
177*9a0e4156SSadaf Ebrahimi #else
178*9a0e4156SSadaf Ebrahimi NULL,
179*9a0e4156SSadaf Ebrahimi #endif
180*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_M68K
181*9a0e4156SSadaf Ebrahimi M68K_option,
182*9a0e4156SSadaf Ebrahimi #else
183*9a0e4156SSadaf Ebrahimi NULL,
184*9a0e4156SSadaf Ebrahimi #endif
185*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_TMS320C64X
186*9a0e4156SSadaf Ebrahimi TMS320C64x_option,
187*9a0e4156SSadaf Ebrahimi #else
188*9a0e4156SSadaf Ebrahimi NULL,
189*9a0e4156SSadaf Ebrahimi #endif
190*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_M680X
191*9a0e4156SSadaf Ebrahimi M680X_option,
192*9a0e4156SSadaf Ebrahimi #else
193*9a0e4156SSadaf Ebrahimi NULL,
194*9a0e4156SSadaf Ebrahimi #endif
195*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_EVM
196*9a0e4156SSadaf Ebrahimi EVM_option,
197*9a0e4156SSadaf Ebrahimi #else
198*9a0e4156SSadaf Ebrahimi NULL,
199*9a0e4156SSadaf Ebrahimi #endif
200*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_MOS65XX
201*9a0e4156SSadaf Ebrahimi MOS65XX_option,
202*9a0e4156SSadaf Ebrahimi #else
203*9a0e4156SSadaf Ebrahimi NULL,
204*9a0e4156SSadaf Ebrahimi #endif
205*9a0e4156SSadaf Ebrahimi
206*9a0e4156SSadaf Ebrahimi };
207*9a0e4156SSadaf Ebrahimi
208*9a0e4156SSadaf Ebrahimi // bitmask for finding disallowed modes for an arch:
209*9a0e4156SSadaf Ebrahimi // to be called in cs_open()/cs_option()
210*9a0e4156SSadaf Ebrahimi static cs_mode cs_arch_disallowed_mode_mask[MAX_ARCH] = {
211*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_ARM
212*9a0e4156SSadaf Ebrahimi ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_ARM | CS_MODE_V8 | CS_MODE_MCLASS
213*9a0e4156SSadaf Ebrahimi | CS_MODE_THUMB | CS_MODE_BIG_ENDIAN),
214*9a0e4156SSadaf Ebrahimi #else
215*9a0e4156SSadaf Ebrahimi 0,
216*9a0e4156SSadaf Ebrahimi #endif
217*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_ARM64
218*9a0e4156SSadaf Ebrahimi ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_ARM | CS_MODE_BIG_ENDIAN),
219*9a0e4156SSadaf Ebrahimi #else
220*9a0e4156SSadaf Ebrahimi 0,
221*9a0e4156SSadaf Ebrahimi #endif
222*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_MIPS
223*9a0e4156SSadaf Ebrahimi ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | CS_MODE_MICRO
224*9a0e4156SSadaf Ebrahimi | CS_MODE_MIPS32R6 | CS_MODE_BIG_ENDIAN | CS_MODE_MIPS2 | CS_MODE_MIPS3),
225*9a0e4156SSadaf Ebrahimi #else
226*9a0e4156SSadaf Ebrahimi 0,
227*9a0e4156SSadaf Ebrahimi #endif
228*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_X86
229*9a0e4156SSadaf Ebrahimi ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | CS_MODE_16),
230*9a0e4156SSadaf Ebrahimi #else
231*9a0e4156SSadaf Ebrahimi 0,
232*9a0e4156SSadaf Ebrahimi #endif
233*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_POWERPC
234*9a0e4156SSadaf Ebrahimi ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | CS_MODE_BIG_ENDIAN
235*9a0e4156SSadaf Ebrahimi | CS_MODE_QPX),
236*9a0e4156SSadaf Ebrahimi #else
237*9a0e4156SSadaf Ebrahimi 0,
238*9a0e4156SSadaf Ebrahimi #endif
239*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_SPARC
240*9a0e4156SSadaf Ebrahimi ~(CS_MODE_BIG_ENDIAN | CS_MODE_V9),
241*9a0e4156SSadaf Ebrahimi #else
242*9a0e4156SSadaf Ebrahimi 0,
243*9a0e4156SSadaf Ebrahimi #endif
244*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_SYSZ
245*9a0e4156SSadaf Ebrahimi ~(CS_MODE_BIG_ENDIAN),
246*9a0e4156SSadaf Ebrahimi #else
247*9a0e4156SSadaf Ebrahimi 0,
248*9a0e4156SSadaf Ebrahimi #endif
249*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_XCORE
250*9a0e4156SSadaf Ebrahimi ~(CS_MODE_BIG_ENDIAN),
251*9a0e4156SSadaf Ebrahimi #else
252*9a0e4156SSadaf Ebrahimi 0,
253*9a0e4156SSadaf Ebrahimi #endif
254*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_M68K
255*9a0e4156SSadaf Ebrahimi ~(CS_MODE_BIG_ENDIAN | CS_MODE_M68K_000 | CS_MODE_M68K_010 | CS_MODE_M68K_020
256*9a0e4156SSadaf Ebrahimi | CS_MODE_M68K_030 | CS_MODE_M68K_040 | CS_MODE_M68K_060),
257*9a0e4156SSadaf Ebrahimi #else
258*9a0e4156SSadaf Ebrahimi 0,
259*9a0e4156SSadaf Ebrahimi #endif
260*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_TMS320C64X
261*9a0e4156SSadaf Ebrahimi ~(CS_MODE_BIG_ENDIAN),
262*9a0e4156SSadaf Ebrahimi #else
263*9a0e4156SSadaf Ebrahimi 0,
264*9a0e4156SSadaf Ebrahimi #endif
265*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_M680X
266*9a0e4156SSadaf Ebrahimi ~(CS_MODE_M680X_6301 | CS_MODE_M680X_6309 | CS_MODE_M680X_6800
267*9a0e4156SSadaf Ebrahimi | CS_MODE_M680X_6801 | CS_MODE_M680X_6805 | CS_MODE_M680X_6808
268*9a0e4156SSadaf Ebrahimi | CS_MODE_M680X_6809 | CS_MODE_M680X_6811 | CS_MODE_M680X_CPU12
269*9a0e4156SSadaf Ebrahimi | CS_MODE_M680X_HCS08),
270*9a0e4156SSadaf Ebrahimi #else
271*9a0e4156SSadaf Ebrahimi 0,
272*9a0e4156SSadaf Ebrahimi #endif
273*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_EVM
274*9a0e4156SSadaf Ebrahimi 0,
275*9a0e4156SSadaf Ebrahimi #else
276*9a0e4156SSadaf Ebrahimi 0,
277*9a0e4156SSadaf Ebrahimi #endif
278*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_MOS65XX
279*9a0e4156SSadaf Ebrahimi ~(CS_MODE_BIG_ENDIAN),
280*9a0e4156SSadaf Ebrahimi #else
281*9a0e4156SSadaf Ebrahimi 0,
282*9a0e4156SSadaf Ebrahimi #endif
283*9a0e4156SSadaf Ebrahimi };
284*9a0e4156SSadaf Ebrahimi
285*9a0e4156SSadaf Ebrahimi // bitmask of enabled architectures
286*9a0e4156SSadaf Ebrahimi static uint32_t all_arch = 0
287*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_ARM
288*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_ARM)
289*9a0e4156SSadaf Ebrahimi #endif
290*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_ARM64
291*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_ARM64)
292*9a0e4156SSadaf Ebrahimi #endif
293*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_MIPS
294*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_MIPS)
295*9a0e4156SSadaf Ebrahimi #endif
296*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_X86
297*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_X86)
298*9a0e4156SSadaf Ebrahimi #endif
299*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_POWERPC
300*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_PPC)
301*9a0e4156SSadaf Ebrahimi #endif
302*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_SPARC
303*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_SPARC)
304*9a0e4156SSadaf Ebrahimi #endif
305*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_SYSZ
306*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_SYSZ)
307*9a0e4156SSadaf Ebrahimi #endif
308*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_XCORE
309*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_XCORE)
310*9a0e4156SSadaf Ebrahimi #endif
311*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_M68K
312*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_M68K)
313*9a0e4156SSadaf Ebrahimi #endif
314*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_TMS320C64X
315*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_TMS320C64X)
316*9a0e4156SSadaf Ebrahimi #endif
317*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_M680X
318*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_M680X)
319*9a0e4156SSadaf Ebrahimi #endif
320*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_EVM
321*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_EVM)
322*9a0e4156SSadaf Ebrahimi #endif
323*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_HAS_MOS65XX
324*9a0e4156SSadaf Ebrahimi | (1 << CS_ARCH_MOS65XX)
325*9a0e4156SSadaf Ebrahimi #endif
326*9a0e4156SSadaf Ebrahimi ;
327*9a0e4156SSadaf Ebrahimi
328*9a0e4156SSadaf Ebrahimi
329*9a0e4156SSadaf Ebrahimi #if defined(CAPSTONE_USE_SYS_DYN_MEM)
330*9a0e4156SSadaf Ebrahimi #if !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(_KERNEL_MODE)
331*9a0e4156SSadaf Ebrahimi // default
332*9a0e4156SSadaf Ebrahimi cs_malloc_t cs_mem_malloc = malloc;
333*9a0e4156SSadaf Ebrahimi cs_calloc_t cs_mem_calloc = calloc;
334*9a0e4156SSadaf Ebrahimi cs_realloc_t cs_mem_realloc = realloc;
335*9a0e4156SSadaf Ebrahimi cs_free_t cs_mem_free = free;
336*9a0e4156SSadaf Ebrahimi #if defined(_WIN32_WCE)
337*9a0e4156SSadaf Ebrahimi cs_vsnprintf_t cs_vsnprintf = _vsnprintf;
338*9a0e4156SSadaf Ebrahimi #else
339*9a0e4156SSadaf Ebrahimi cs_vsnprintf_t cs_vsnprintf = vsnprintf;
340*9a0e4156SSadaf Ebrahimi #endif // defined(_WIN32_WCE)
341*9a0e4156SSadaf Ebrahimi
342*9a0e4156SSadaf Ebrahimi #elif defined(_KERNEL_MODE)
343*9a0e4156SSadaf Ebrahimi // Windows driver
344*9a0e4156SSadaf Ebrahimi cs_malloc_t cs_mem_malloc = cs_winkernel_malloc;
345*9a0e4156SSadaf Ebrahimi cs_calloc_t cs_mem_calloc = cs_winkernel_calloc;
346*9a0e4156SSadaf Ebrahimi cs_realloc_t cs_mem_realloc = cs_winkernel_realloc;
347*9a0e4156SSadaf Ebrahimi cs_free_t cs_mem_free = cs_winkernel_free;
348*9a0e4156SSadaf Ebrahimi cs_vsnprintf_t cs_vsnprintf = cs_winkernel_vsnprintf;
349*9a0e4156SSadaf Ebrahimi #else
350*9a0e4156SSadaf Ebrahimi // OSX kernel
351*9a0e4156SSadaf Ebrahimi extern void* kern_os_malloc(size_t size);
352*9a0e4156SSadaf Ebrahimi extern void kern_os_free(void* addr);
353*9a0e4156SSadaf Ebrahimi extern void* kern_os_realloc(void* addr, size_t nsize);
354*9a0e4156SSadaf Ebrahimi
cs_kern_os_calloc(size_t num,size_t size)355*9a0e4156SSadaf Ebrahimi static void* cs_kern_os_calloc(size_t num, size_t size)
356*9a0e4156SSadaf Ebrahimi {
357*9a0e4156SSadaf Ebrahimi return kern_os_malloc(num * size); // malloc bzeroes the buffer
358*9a0e4156SSadaf Ebrahimi }
359*9a0e4156SSadaf Ebrahimi
360*9a0e4156SSadaf Ebrahimi cs_malloc_t cs_mem_malloc = kern_os_malloc;
361*9a0e4156SSadaf Ebrahimi cs_calloc_t cs_mem_calloc = cs_kern_os_calloc;
362*9a0e4156SSadaf Ebrahimi cs_realloc_t cs_mem_realloc = kern_os_realloc;
363*9a0e4156SSadaf Ebrahimi cs_free_t cs_mem_free = kern_os_free;
364*9a0e4156SSadaf Ebrahimi cs_vsnprintf_t cs_vsnprintf = vsnprintf;
365*9a0e4156SSadaf Ebrahimi #endif // !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(_KERNEL_MODE)
366*9a0e4156SSadaf Ebrahimi #else
367*9a0e4156SSadaf Ebrahimi // User-defined
368*9a0e4156SSadaf Ebrahimi cs_malloc_t cs_mem_malloc = NULL;
369*9a0e4156SSadaf Ebrahimi cs_calloc_t cs_mem_calloc = NULL;
370*9a0e4156SSadaf Ebrahimi cs_realloc_t cs_mem_realloc = NULL;
371*9a0e4156SSadaf Ebrahimi cs_free_t cs_mem_free = NULL;
372*9a0e4156SSadaf Ebrahimi cs_vsnprintf_t cs_vsnprintf = NULL;
373*9a0e4156SSadaf Ebrahimi
374*9a0e4156SSadaf Ebrahimi #endif // defined(CAPSTONE_USE_SYS_DYN_MEM)
375*9a0e4156SSadaf Ebrahimi
376*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_version(int * major,int * minor)377*9a0e4156SSadaf Ebrahimi unsigned int CAPSTONE_API cs_version(int *major, int *minor)
378*9a0e4156SSadaf Ebrahimi {
379*9a0e4156SSadaf Ebrahimi if (major != NULL && minor != NULL) {
380*9a0e4156SSadaf Ebrahimi *major = CS_API_MAJOR;
381*9a0e4156SSadaf Ebrahimi *minor = CS_API_MINOR;
382*9a0e4156SSadaf Ebrahimi }
383*9a0e4156SSadaf Ebrahimi
384*9a0e4156SSadaf Ebrahimi return (CS_API_MAJOR << 8) + CS_API_MINOR;
385*9a0e4156SSadaf Ebrahimi }
386*9a0e4156SSadaf Ebrahimi
387*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_support(int query)388*9a0e4156SSadaf Ebrahimi bool CAPSTONE_API cs_support(int query)
389*9a0e4156SSadaf Ebrahimi {
390*9a0e4156SSadaf Ebrahimi if (query == CS_ARCH_ALL)
391*9a0e4156SSadaf Ebrahimi return all_arch == ((1 << CS_ARCH_ARM) | (1 << CS_ARCH_ARM64) |
392*9a0e4156SSadaf Ebrahimi (1 << CS_ARCH_MIPS) | (1 << CS_ARCH_X86) |
393*9a0e4156SSadaf Ebrahimi (1 << CS_ARCH_PPC) | (1 << CS_ARCH_SPARC) |
394*9a0e4156SSadaf Ebrahimi (1 << CS_ARCH_SYSZ) | (1 << CS_ARCH_XCORE) |
395*9a0e4156SSadaf Ebrahimi (1 << CS_ARCH_M68K) | (1 << CS_ARCH_TMS320C64X) |
396*9a0e4156SSadaf Ebrahimi (1 << CS_ARCH_M680X) | (1 << CS_ARCH_EVM) |
397*9a0e4156SSadaf Ebrahimi (1 << CS_ARCH_MOS65XX));
398*9a0e4156SSadaf Ebrahimi
399*9a0e4156SSadaf Ebrahimi if ((unsigned int)query < CS_ARCH_MAX)
400*9a0e4156SSadaf Ebrahimi return all_arch & (1 << query);
401*9a0e4156SSadaf Ebrahimi
402*9a0e4156SSadaf Ebrahimi if (query == CS_SUPPORT_DIET) {
403*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_DIET
404*9a0e4156SSadaf Ebrahimi return true;
405*9a0e4156SSadaf Ebrahimi #else
406*9a0e4156SSadaf Ebrahimi return false;
407*9a0e4156SSadaf Ebrahimi #endif
408*9a0e4156SSadaf Ebrahimi }
409*9a0e4156SSadaf Ebrahimi
410*9a0e4156SSadaf Ebrahimi if (query == CS_SUPPORT_X86_REDUCE) {
411*9a0e4156SSadaf Ebrahimi #if defined(CAPSTONE_HAS_X86) && defined(CAPSTONE_X86_REDUCE)
412*9a0e4156SSadaf Ebrahimi return true;
413*9a0e4156SSadaf Ebrahimi #else
414*9a0e4156SSadaf Ebrahimi return false;
415*9a0e4156SSadaf Ebrahimi #endif
416*9a0e4156SSadaf Ebrahimi }
417*9a0e4156SSadaf Ebrahimi
418*9a0e4156SSadaf Ebrahimi // unsupported query
419*9a0e4156SSadaf Ebrahimi return false;
420*9a0e4156SSadaf Ebrahimi }
421*9a0e4156SSadaf Ebrahimi
422*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_errno(csh handle)423*9a0e4156SSadaf Ebrahimi cs_err CAPSTONE_API cs_errno(csh handle)
424*9a0e4156SSadaf Ebrahimi {
425*9a0e4156SSadaf Ebrahimi struct cs_struct *ud;
426*9a0e4156SSadaf Ebrahimi if (!handle)
427*9a0e4156SSadaf Ebrahimi return CS_ERR_CSH;
428*9a0e4156SSadaf Ebrahimi
429*9a0e4156SSadaf Ebrahimi ud = (struct cs_struct *)(uintptr_t)handle;
430*9a0e4156SSadaf Ebrahimi
431*9a0e4156SSadaf Ebrahimi return ud->errnum;
432*9a0e4156SSadaf Ebrahimi }
433*9a0e4156SSadaf Ebrahimi
434*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_strerror(cs_err code)435*9a0e4156SSadaf Ebrahimi const char * CAPSTONE_API cs_strerror(cs_err code)
436*9a0e4156SSadaf Ebrahimi {
437*9a0e4156SSadaf Ebrahimi switch(code) {
438*9a0e4156SSadaf Ebrahimi default:
439*9a0e4156SSadaf Ebrahimi return "Unknown error code";
440*9a0e4156SSadaf Ebrahimi case CS_ERR_OK:
441*9a0e4156SSadaf Ebrahimi return "OK (CS_ERR_OK)";
442*9a0e4156SSadaf Ebrahimi case CS_ERR_MEM:
443*9a0e4156SSadaf Ebrahimi return "Out of memory (CS_ERR_MEM)";
444*9a0e4156SSadaf Ebrahimi case CS_ERR_ARCH:
445*9a0e4156SSadaf Ebrahimi return "Invalid/unsupported architecture(CS_ERR_ARCH)";
446*9a0e4156SSadaf Ebrahimi case CS_ERR_HANDLE:
447*9a0e4156SSadaf Ebrahimi return "Invalid handle (CS_ERR_HANDLE)";
448*9a0e4156SSadaf Ebrahimi case CS_ERR_CSH:
449*9a0e4156SSadaf Ebrahimi return "Invalid csh (CS_ERR_CSH)";
450*9a0e4156SSadaf Ebrahimi case CS_ERR_MODE:
451*9a0e4156SSadaf Ebrahimi return "Invalid mode (CS_ERR_MODE)";
452*9a0e4156SSadaf Ebrahimi case CS_ERR_OPTION:
453*9a0e4156SSadaf Ebrahimi return "Invalid option (CS_ERR_OPTION)";
454*9a0e4156SSadaf Ebrahimi case CS_ERR_DETAIL:
455*9a0e4156SSadaf Ebrahimi return "Details are unavailable (CS_ERR_DETAIL)";
456*9a0e4156SSadaf Ebrahimi case CS_ERR_MEMSETUP:
457*9a0e4156SSadaf Ebrahimi return "Dynamic memory management uninitialized (CS_ERR_MEMSETUP)";
458*9a0e4156SSadaf Ebrahimi case CS_ERR_VERSION:
459*9a0e4156SSadaf Ebrahimi return "Different API version between core & binding (CS_ERR_VERSION)";
460*9a0e4156SSadaf Ebrahimi case CS_ERR_DIET:
461*9a0e4156SSadaf Ebrahimi return "Information irrelevant in diet engine (CS_ERR_DIET)";
462*9a0e4156SSadaf Ebrahimi case CS_ERR_SKIPDATA:
463*9a0e4156SSadaf Ebrahimi return "Information irrelevant for 'data' instruction in SKIPDATA mode (CS_ERR_SKIPDATA)";
464*9a0e4156SSadaf Ebrahimi case CS_ERR_X86_ATT:
465*9a0e4156SSadaf Ebrahimi return "AT&T syntax is unavailable (CS_ERR_X86_ATT)";
466*9a0e4156SSadaf Ebrahimi case CS_ERR_X86_INTEL:
467*9a0e4156SSadaf Ebrahimi return "INTEL syntax is unavailable (CS_ERR_X86_INTEL)";
468*9a0e4156SSadaf Ebrahimi case CS_ERR_X86_MASM:
469*9a0e4156SSadaf Ebrahimi return "MASM syntax is unavailable (CS_ERR_X86_MASM)";
470*9a0e4156SSadaf Ebrahimi }
471*9a0e4156SSadaf Ebrahimi }
472*9a0e4156SSadaf Ebrahimi
473*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_open(cs_arch arch,cs_mode mode,csh * handle)474*9a0e4156SSadaf Ebrahimi cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
475*9a0e4156SSadaf Ebrahimi {
476*9a0e4156SSadaf Ebrahimi cs_err err;
477*9a0e4156SSadaf Ebrahimi struct cs_struct *ud;
478*9a0e4156SSadaf Ebrahimi if (!cs_mem_malloc || !cs_mem_calloc || !cs_mem_realloc || !cs_mem_free || !cs_vsnprintf)
479*9a0e4156SSadaf Ebrahimi // Error: before cs_open(), dynamic memory management must be initialized
480*9a0e4156SSadaf Ebrahimi // with cs_option(CS_OPT_MEM)
481*9a0e4156SSadaf Ebrahimi return CS_ERR_MEMSETUP;
482*9a0e4156SSadaf Ebrahimi
483*9a0e4156SSadaf Ebrahimi if (arch < CS_ARCH_MAX && cs_arch_init[arch]) {
484*9a0e4156SSadaf Ebrahimi // verify if requested mode is valid
485*9a0e4156SSadaf Ebrahimi if (mode & cs_arch_disallowed_mode_mask[arch]) {
486*9a0e4156SSadaf Ebrahimi *handle = 0;
487*9a0e4156SSadaf Ebrahimi return CS_ERR_MODE;
488*9a0e4156SSadaf Ebrahimi }
489*9a0e4156SSadaf Ebrahimi
490*9a0e4156SSadaf Ebrahimi ud = cs_mem_calloc(1, sizeof(*ud));
491*9a0e4156SSadaf Ebrahimi if (!ud) {
492*9a0e4156SSadaf Ebrahimi // memory insufficient
493*9a0e4156SSadaf Ebrahimi return CS_ERR_MEM;
494*9a0e4156SSadaf Ebrahimi }
495*9a0e4156SSadaf Ebrahimi
496*9a0e4156SSadaf Ebrahimi ud->errnum = CS_ERR_OK;
497*9a0e4156SSadaf Ebrahimi ud->arch = arch;
498*9a0e4156SSadaf Ebrahimi ud->mode = mode;
499*9a0e4156SSadaf Ebrahimi // by default, do not break instruction into details
500*9a0e4156SSadaf Ebrahimi ud->detail = CS_OPT_OFF;
501*9a0e4156SSadaf Ebrahimi
502*9a0e4156SSadaf Ebrahimi // default skipdata setup
503*9a0e4156SSadaf Ebrahimi ud->skipdata_setup.mnemonic = SKIPDATA_MNEM;
504*9a0e4156SSadaf Ebrahimi
505*9a0e4156SSadaf Ebrahimi err = cs_arch_init[ud->arch](ud);
506*9a0e4156SSadaf Ebrahimi if (err) {
507*9a0e4156SSadaf Ebrahimi cs_mem_free(ud);
508*9a0e4156SSadaf Ebrahimi *handle = 0;
509*9a0e4156SSadaf Ebrahimi return err;
510*9a0e4156SSadaf Ebrahimi }
511*9a0e4156SSadaf Ebrahimi
512*9a0e4156SSadaf Ebrahimi *handle = (uintptr_t)ud;
513*9a0e4156SSadaf Ebrahimi
514*9a0e4156SSadaf Ebrahimi return CS_ERR_OK;
515*9a0e4156SSadaf Ebrahimi } else {
516*9a0e4156SSadaf Ebrahimi *handle = 0;
517*9a0e4156SSadaf Ebrahimi return CS_ERR_ARCH;
518*9a0e4156SSadaf Ebrahimi }
519*9a0e4156SSadaf Ebrahimi }
520*9a0e4156SSadaf Ebrahimi
521*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_close(csh * handle)522*9a0e4156SSadaf Ebrahimi cs_err CAPSTONE_API cs_close(csh *handle)
523*9a0e4156SSadaf Ebrahimi {
524*9a0e4156SSadaf Ebrahimi struct cs_struct *ud;
525*9a0e4156SSadaf Ebrahimi struct insn_mnem *next, *tmp;
526*9a0e4156SSadaf Ebrahimi
527*9a0e4156SSadaf Ebrahimi if (*handle == 0)
528*9a0e4156SSadaf Ebrahimi // invalid handle
529*9a0e4156SSadaf Ebrahimi return CS_ERR_CSH;
530*9a0e4156SSadaf Ebrahimi
531*9a0e4156SSadaf Ebrahimi ud = (struct cs_struct *)(*handle);
532*9a0e4156SSadaf Ebrahimi
533*9a0e4156SSadaf Ebrahimi if (ud->printer_info)
534*9a0e4156SSadaf Ebrahimi cs_mem_free(ud->printer_info);
535*9a0e4156SSadaf Ebrahimi
536*9a0e4156SSadaf Ebrahimi // free the linked list of customized mnemonic
537*9a0e4156SSadaf Ebrahimi tmp = ud->mnem_list;
538*9a0e4156SSadaf Ebrahimi while(tmp) {
539*9a0e4156SSadaf Ebrahimi next = tmp->next;
540*9a0e4156SSadaf Ebrahimi cs_mem_free(tmp);
541*9a0e4156SSadaf Ebrahimi tmp = next;
542*9a0e4156SSadaf Ebrahimi }
543*9a0e4156SSadaf Ebrahimi
544*9a0e4156SSadaf Ebrahimi cs_mem_free(ud->insn_cache);
545*9a0e4156SSadaf Ebrahimi
546*9a0e4156SSadaf Ebrahimi memset(ud, 0, sizeof(*ud));
547*9a0e4156SSadaf Ebrahimi cs_mem_free(ud);
548*9a0e4156SSadaf Ebrahimi
549*9a0e4156SSadaf Ebrahimi // invalidate this handle by ZERO out its value.
550*9a0e4156SSadaf Ebrahimi // this is to make sure it is unusable after cs_close()
551*9a0e4156SSadaf Ebrahimi *handle = 0;
552*9a0e4156SSadaf Ebrahimi
553*9a0e4156SSadaf Ebrahimi return CS_ERR_OK;
554*9a0e4156SSadaf Ebrahimi }
555*9a0e4156SSadaf Ebrahimi
556*9a0e4156SSadaf Ebrahimi // fill insn with mnemonic & operands info
fill_insn(struct cs_struct * handle,cs_insn * insn,char * buffer,MCInst * mci,PostPrinter_t postprinter,const uint8_t * code)557*9a0e4156SSadaf Ebrahimi static void fill_insn(struct cs_struct *handle, cs_insn *insn, char *buffer, MCInst *mci,
558*9a0e4156SSadaf Ebrahimi PostPrinter_t postprinter, const uint8_t *code)
559*9a0e4156SSadaf Ebrahimi {
560*9a0e4156SSadaf Ebrahimi #ifndef CAPSTONE_DIET
561*9a0e4156SSadaf Ebrahimi char *sp, *mnem;
562*9a0e4156SSadaf Ebrahimi #endif
563*9a0e4156SSadaf Ebrahimi uint16_t copy_size = MIN(sizeof(insn->bytes), insn->size);
564*9a0e4156SSadaf Ebrahimi
565*9a0e4156SSadaf Ebrahimi // fill the instruction bytes.
566*9a0e4156SSadaf Ebrahimi // we might skip some redundant bytes in front in the case of X86
567*9a0e4156SSadaf Ebrahimi memcpy(insn->bytes, code + insn->size - copy_size, copy_size);
568*9a0e4156SSadaf Ebrahimi insn->size = copy_size;
569*9a0e4156SSadaf Ebrahimi
570*9a0e4156SSadaf Ebrahimi // alias instruction might have ID saved in OpcodePub
571*9a0e4156SSadaf Ebrahimi if (MCInst_getOpcodePub(mci))
572*9a0e4156SSadaf Ebrahimi insn->id = MCInst_getOpcodePub(mci);
573*9a0e4156SSadaf Ebrahimi
574*9a0e4156SSadaf Ebrahimi // post printer handles some corner cases (hacky)
575*9a0e4156SSadaf Ebrahimi if (postprinter)
576*9a0e4156SSadaf Ebrahimi postprinter((csh)handle, insn, buffer, mci);
577*9a0e4156SSadaf Ebrahimi
578*9a0e4156SSadaf Ebrahimi #ifndef CAPSTONE_DIET
579*9a0e4156SSadaf Ebrahimi // fill in mnemonic & operands
580*9a0e4156SSadaf Ebrahimi // find first space or tab
581*9a0e4156SSadaf Ebrahimi mnem = insn->mnemonic;
582*9a0e4156SSadaf Ebrahimi for (sp = buffer; *sp; sp++) {
583*9a0e4156SSadaf Ebrahimi if (*sp == ' '|| *sp == '\t')
584*9a0e4156SSadaf Ebrahimi break;
585*9a0e4156SSadaf Ebrahimi if (*sp == '|') // lock|rep prefix for x86
586*9a0e4156SSadaf Ebrahimi *sp = ' ';
587*9a0e4156SSadaf Ebrahimi // copy to @mnemonic
588*9a0e4156SSadaf Ebrahimi *mnem = *sp;
589*9a0e4156SSadaf Ebrahimi mnem++;
590*9a0e4156SSadaf Ebrahimi }
591*9a0e4156SSadaf Ebrahimi
592*9a0e4156SSadaf Ebrahimi *mnem = '\0';
593*9a0e4156SSadaf Ebrahimi
594*9a0e4156SSadaf Ebrahimi // we might have customized mnemonic
595*9a0e4156SSadaf Ebrahimi if (handle->mnem_list) {
596*9a0e4156SSadaf Ebrahimi struct insn_mnem *tmp = handle->mnem_list;
597*9a0e4156SSadaf Ebrahimi while(tmp) {
598*9a0e4156SSadaf Ebrahimi if (tmp->insn.id == insn->id) {
599*9a0e4156SSadaf Ebrahimi // found this instruction, so copy its mnemonic
600*9a0e4156SSadaf Ebrahimi (void)strncpy(insn->mnemonic, tmp->insn.mnemonic, sizeof(insn->mnemonic) - 1);
601*9a0e4156SSadaf Ebrahimi insn->mnemonic[sizeof(insn->mnemonic) - 1] = '\0';
602*9a0e4156SSadaf Ebrahimi break;
603*9a0e4156SSadaf Ebrahimi }
604*9a0e4156SSadaf Ebrahimi tmp = tmp->next;
605*9a0e4156SSadaf Ebrahimi }
606*9a0e4156SSadaf Ebrahimi }
607*9a0e4156SSadaf Ebrahimi
608*9a0e4156SSadaf Ebrahimi // copy @op_str
609*9a0e4156SSadaf Ebrahimi if (*sp) {
610*9a0e4156SSadaf Ebrahimi // find the next non-space char
611*9a0e4156SSadaf Ebrahimi sp++;
612*9a0e4156SSadaf Ebrahimi for (; ((*sp == ' ') || (*sp == '\t')); sp++);
613*9a0e4156SSadaf Ebrahimi strncpy(insn->op_str, sp, sizeof(insn->op_str) - 1);
614*9a0e4156SSadaf Ebrahimi insn->op_str[sizeof(insn->op_str) - 1] = '\0';
615*9a0e4156SSadaf Ebrahimi } else
616*9a0e4156SSadaf Ebrahimi insn->op_str[0] = '\0';
617*9a0e4156SSadaf Ebrahimi #endif
618*9a0e4156SSadaf Ebrahimi }
619*9a0e4156SSadaf Ebrahimi
620*9a0e4156SSadaf Ebrahimi // how many bytes will we skip when encountering data (CS_OPT_SKIPDATA)?
621*9a0e4156SSadaf Ebrahimi // this very much depends on instruction alignment requirement of each arch.
skipdata_size(cs_struct * handle)622*9a0e4156SSadaf Ebrahimi static uint8_t skipdata_size(cs_struct *handle)
623*9a0e4156SSadaf Ebrahimi {
624*9a0e4156SSadaf Ebrahimi switch(handle->arch) {
625*9a0e4156SSadaf Ebrahimi default:
626*9a0e4156SSadaf Ebrahimi // should never reach
627*9a0e4156SSadaf Ebrahimi return (uint8_t)-1;
628*9a0e4156SSadaf Ebrahimi case CS_ARCH_ARM:
629*9a0e4156SSadaf Ebrahimi // skip 2 bytes on Thumb mode.
630*9a0e4156SSadaf Ebrahimi if (handle->mode & CS_MODE_THUMB)
631*9a0e4156SSadaf Ebrahimi return 2;
632*9a0e4156SSadaf Ebrahimi // otherwise, skip 4 bytes
633*9a0e4156SSadaf Ebrahimi return 4;
634*9a0e4156SSadaf Ebrahimi case CS_ARCH_ARM64:
635*9a0e4156SSadaf Ebrahimi case CS_ARCH_MIPS:
636*9a0e4156SSadaf Ebrahimi case CS_ARCH_PPC:
637*9a0e4156SSadaf Ebrahimi case CS_ARCH_SPARC:
638*9a0e4156SSadaf Ebrahimi // skip 4 bytes
639*9a0e4156SSadaf Ebrahimi return 4;
640*9a0e4156SSadaf Ebrahimi case CS_ARCH_SYSZ:
641*9a0e4156SSadaf Ebrahimi // SystemZ instruction's length can be 2, 4 or 6 bytes,
642*9a0e4156SSadaf Ebrahimi // so we just skip 2 bytes
643*9a0e4156SSadaf Ebrahimi return 2;
644*9a0e4156SSadaf Ebrahimi case CS_ARCH_X86:
645*9a0e4156SSadaf Ebrahimi // X86 has no restriction on instruction alignment
646*9a0e4156SSadaf Ebrahimi return 1;
647*9a0e4156SSadaf Ebrahimi case CS_ARCH_XCORE:
648*9a0e4156SSadaf Ebrahimi // XCore instruction's length can be 2 or 4 bytes,
649*9a0e4156SSadaf Ebrahimi // so we just skip 2 bytes
650*9a0e4156SSadaf Ebrahimi return 2;
651*9a0e4156SSadaf Ebrahimi case CS_ARCH_M68K:
652*9a0e4156SSadaf Ebrahimi // M68K has 2 bytes instruction alignment but contain multibyte instruction so we skip 2 bytes
653*9a0e4156SSadaf Ebrahimi return 2;
654*9a0e4156SSadaf Ebrahimi case CS_ARCH_TMS320C64X:
655*9a0e4156SSadaf Ebrahimi // TMS320C64x alignment is 4.
656*9a0e4156SSadaf Ebrahimi return 4;
657*9a0e4156SSadaf Ebrahimi case CS_ARCH_M680X:
658*9a0e4156SSadaf Ebrahimi // M680X alignment is 1.
659*9a0e4156SSadaf Ebrahimi return 1;
660*9a0e4156SSadaf Ebrahimi case CS_ARCH_EVM:
661*9a0e4156SSadaf Ebrahimi // EVM alignment is 1.
662*9a0e4156SSadaf Ebrahimi return 1;
663*9a0e4156SSadaf Ebrahimi case CS_ARCH_MOS65XX:
664*9a0e4156SSadaf Ebrahimi // MOS65XX alignment is 1.
665*9a0e4156SSadaf Ebrahimi return 1;
666*9a0e4156SSadaf Ebrahimi }
667*9a0e4156SSadaf Ebrahimi }
668*9a0e4156SSadaf Ebrahimi
669*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_option(csh ud,cs_opt_type type,size_t value)670*9a0e4156SSadaf Ebrahimi cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
671*9a0e4156SSadaf Ebrahimi {
672*9a0e4156SSadaf Ebrahimi struct cs_struct *handle;
673*9a0e4156SSadaf Ebrahimi cs_opt_mnem *opt;
674*9a0e4156SSadaf Ebrahimi
675*9a0e4156SSadaf Ebrahimi // cs_option() can be called with NULL handle just for CS_OPT_MEM
676*9a0e4156SSadaf Ebrahimi // This is supposed to be executed before all other APIs (even cs_open())
677*9a0e4156SSadaf Ebrahimi if (type == CS_OPT_MEM) {
678*9a0e4156SSadaf Ebrahimi cs_opt_mem *mem = (cs_opt_mem *)value;
679*9a0e4156SSadaf Ebrahimi
680*9a0e4156SSadaf Ebrahimi cs_mem_malloc = mem->malloc;
681*9a0e4156SSadaf Ebrahimi cs_mem_calloc = mem->calloc;
682*9a0e4156SSadaf Ebrahimi cs_mem_realloc = mem->realloc;
683*9a0e4156SSadaf Ebrahimi cs_mem_free = mem->free;
684*9a0e4156SSadaf Ebrahimi cs_vsnprintf = mem->vsnprintf;
685*9a0e4156SSadaf Ebrahimi
686*9a0e4156SSadaf Ebrahimi return CS_ERR_OK;
687*9a0e4156SSadaf Ebrahimi }
688*9a0e4156SSadaf Ebrahimi
689*9a0e4156SSadaf Ebrahimi handle = (struct cs_struct *)(uintptr_t)ud;
690*9a0e4156SSadaf Ebrahimi if (!handle)
691*9a0e4156SSadaf Ebrahimi return CS_ERR_CSH;
692*9a0e4156SSadaf Ebrahimi
693*9a0e4156SSadaf Ebrahimi switch(type) {
694*9a0e4156SSadaf Ebrahimi default:
695*9a0e4156SSadaf Ebrahimi break;
696*9a0e4156SSadaf Ebrahimi
697*9a0e4156SSadaf Ebrahimi case CS_OPT_UNSIGNED:
698*9a0e4156SSadaf Ebrahimi handle->imm_unsigned = (cs_opt_value)value;
699*9a0e4156SSadaf Ebrahimi return CS_ERR_OK;
700*9a0e4156SSadaf Ebrahimi
701*9a0e4156SSadaf Ebrahimi case CS_OPT_DETAIL:
702*9a0e4156SSadaf Ebrahimi handle->detail = (cs_opt_value)value;
703*9a0e4156SSadaf Ebrahimi return CS_ERR_OK;
704*9a0e4156SSadaf Ebrahimi
705*9a0e4156SSadaf Ebrahimi case CS_OPT_SKIPDATA:
706*9a0e4156SSadaf Ebrahimi handle->skipdata = (value == CS_OPT_ON);
707*9a0e4156SSadaf Ebrahimi if (handle->skipdata) {
708*9a0e4156SSadaf Ebrahimi if (handle->skipdata_size == 0) {
709*9a0e4156SSadaf Ebrahimi // set the default skipdata size
710*9a0e4156SSadaf Ebrahimi handle->skipdata_size = skipdata_size(handle);
711*9a0e4156SSadaf Ebrahimi }
712*9a0e4156SSadaf Ebrahimi }
713*9a0e4156SSadaf Ebrahimi return CS_ERR_OK;
714*9a0e4156SSadaf Ebrahimi
715*9a0e4156SSadaf Ebrahimi case CS_OPT_SKIPDATA_SETUP:
716*9a0e4156SSadaf Ebrahimi if (value)
717*9a0e4156SSadaf Ebrahimi handle->skipdata_setup = *((cs_opt_skipdata *)value);
718*9a0e4156SSadaf Ebrahimi return CS_ERR_OK;
719*9a0e4156SSadaf Ebrahimi
720*9a0e4156SSadaf Ebrahimi case CS_OPT_MNEMONIC:
721*9a0e4156SSadaf Ebrahimi opt = (cs_opt_mnem *)value;
722*9a0e4156SSadaf Ebrahimi if (opt->id) {
723*9a0e4156SSadaf Ebrahimi if (opt->mnemonic) {
724*9a0e4156SSadaf Ebrahimi struct insn_mnem *tmp;
725*9a0e4156SSadaf Ebrahimi
726*9a0e4156SSadaf Ebrahimi // add new instruction, or replace existing instruction
727*9a0e4156SSadaf Ebrahimi // 1. find if we already had this insn in the linked list
728*9a0e4156SSadaf Ebrahimi tmp = handle->mnem_list;
729*9a0e4156SSadaf Ebrahimi while(tmp) {
730*9a0e4156SSadaf Ebrahimi if (tmp->insn.id == opt->id) {
731*9a0e4156SSadaf Ebrahimi // found this instruction, so replace its mnemonic
732*9a0e4156SSadaf Ebrahimi (void)strncpy(tmp->insn.mnemonic, opt->mnemonic, sizeof(tmp->insn.mnemonic) - 1);
733*9a0e4156SSadaf Ebrahimi tmp->insn.mnemonic[sizeof(tmp->insn.mnemonic) - 1] = '\0';
734*9a0e4156SSadaf Ebrahimi break;
735*9a0e4156SSadaf Ebrahimi }
736*9a0e4156SSadaf Ebrahimi tmp = tmp->next;
737*9a0e4156SSadaf Ebrahimi }
738*9a0e4156SSadaf Ebrahimi
739*9a0e4156SSadaf Ebrahimi // 2. add this instruction if we have not had it yet
740*9a0e4156SSadaf Ebrahimi if (!tmp) {
741*9a0e4156SSadaf Ebrahimi tmp = cs_mem_malloc(sizeof(*tmp));
742*9a0e4156SSadaf Ebrahimi tmp->insn.id = opt->id;
743*9a0e4156SSadaf Ebrahimi (void)strncpy(tmp->insn.mnemonic, opt->mnemonic, sizeof(tmp->insn.mnemonic) - 1);
744*9a0e4156SSadaf Ebrahimi tmp->insn.mnemonic[sizeof(tmp->insn.mnemonic) - 1] = '\0';
745*9a0e4156SSadaf Ebrahimi // this new instruction is heading the list
746*9a0e4156SSadaf Ebrahimi tmp->next = handle->mnem_list;
747*9a0e4156SSadaf Ebrahimi handle->mnem_list = tmp;
748*9a0e4156SSadaf Ebrahimi }
749*9a0e4156SSadaf Ebrahimi return CS_ERR_OK;
750*9a0e4156SSadaf Ebrahimi } else {
751*9a0e4156SSadaf Ebrahimi struct insn_mnem *prev, *tmp;
752*9a0e4156SSadaf Ebrahimi
753*9a0e4156SSadaf Ebrahimi // we want to delete an existing instruction
754*9a0e4156SSadaf Ebrahimi // iterate the list to find the instruction to remove it
755*9a0e4156SSadaf Ebrahimi tmp = handle->mnem_list;
756*9a0e4156SSadaf Ebrahimi prev = tmp;
757*9a0e4156SSadaf Ebrahimi while(tmp) {
758*9a0e4156SSadaf Ebrahimi if (tmp->insn.id == opt->id) {
759*9a0e4156SSadaf Ebrahimi // delete this instruction
760*9a0e4156SSadaf Ebrahimi if (tmp == prev) {
761*9a0e4156SSadaf Ebrahimi // head of the list
762*9a0e4156SSadaf Ebrahimi handle->mnem_list = tmp->next;
763*9a0e4156SSadaf Ebrahimi } else {
764*9a0e4156SSadaf Ebrahimi prev->next = tmp->next;
765*9a0e4156SSadaf Ebrahimi }
766*9a0e4156SSadaf Ebrahimi cs_mem_free(tmp);
767*9a0e4156SSadaf Ebrahimi break;
768*9a0e4156SSadaf Ebrahimi }
769*9a0e4156SSadaf Ebrahimi prev = tmp;
770*9a0e4156SSadaf Ebrahimi tmp = tmp->next;
771*9a0e4156SSadaf Ebrahimi }
772*9a0e4156SSadaf Ebrahimi }
773*9a0e4156SSadaf Ebrahimi }
774*9a0e4156SSadaf Ebrahimi return CS_ERR_OK;
775*9a0e4156SSadaf Ebrahimi
776*9a0e4156SSadaf Ebrahimi case CS_OPT_MODE:
777*9a0e4156SSadaf Ebrahimi // verify if requested mode is valid
778*9a0e4156SSadaf Ebrahimi if (value & cs_arch_disallowed_mode_mask[handle->arch]) {
779*9a0e4156SSadaf Ebrahimi return CS_ERR_OPTION;
780*9a0e4156SSadaf Ebrahimi }
781*9a0e4156SSadaf Ebrahimi break;
782*9a0e4156SSadaf Ebrahimi }
783*9a0e4156SSadaf Ebrahimi
784*9a0e4156SSadaf Ebrahimi return cs_arch_option[handle->arch](handle, type, value);
785*9a0e4156SSadaf Ebrahimi }
786*9a0e4156SSadaf Ebrahimi
787*9a0e4156SSadaf Ebrahimi // generate @op_str for data instruction of SKIPDATA
788*9a0e4156SSadaf Ebrahimi #ifndef CAPSTONE_DIET
skipdata_opstr(char * opstr,const uint8_t * buffer,size_t size)789*9a0e4156SSadaf Ebrahimi static void skipdata_opstr(char *opstr, const uint8_t *buffer, size_t size)
790*9a0e4156SSadaf Ebrahimi {
791*9a0e4156SSadaf Ebrahimi char *p = opstr;
792*9a0e4156SSadaf Ebrahimi int len;
793*9a0e4156SSadaf Ebrahimi size_t i;
794*9a0e4156SSadaf Ebrahimi size_t available = sizeof(((cs_insn*)NULL)->op_str);
795*9a0e4156SSadaf Ebrahimi
796*9a0e4156SSadaf Ebrahimi if (!size) {
797*9a0e4156SSadaf Ebrahimi opstr[0] = '\0';
798*9a0e4156SSadaf Ebrahimi return;
799*9a0e4156SSadaf Ebrahimi }
800*9a0e4156SSadaf Ebrahimi
801*9a0e4156SSadaf Ebrahimi len = cs_snprintf(p, available, "0x%02x", buffer[0]);
802*9a0e4156SSadaf Ebrahimi p+= len;
803*9a0e4156SSadaf Ebrahimi available -= len;
804*9a0e4156SSadaf Ebrahimi
805*9a0e4156SSadaf Ebrahimi for(i = 1; i < size; i++) {
806*9a0e4156SSadaf Ebrahimi len = cs_snprintf(p, available, ", 0x%02x", buffer[i]);
807*9a0e4156SSadaf Ebrahimi if (len < 0) {
808*9a0e4156SSadaf Ebrahimi break;
809*9a0e4156SSadaf Ebrahimi }
810*9a0e4156SSadaf Ebrahimi if ((size_t)len > available - 1) {
811*9a0e4156SSadaf Ebrahimi break;
812*9a0e4156SSadaf Ebrahimi }
813*9a0e4156SSadaf Ebrahimi p+= len;
814*9a0e4156SSadaf Ebrahimi available -= len;
815*9a0e4156SSadaf Ebrahimi }
816*9a0e4156SSadaf Ebrahimi }
817*9a0e4156SSadaf Ebrahimi #endif
818*9a0e4156SSadaf Ebrahimi
819*9a0e4156SSadaf Ebrahimi // dynamicly allocate memory to contain disasm insn
820*9a0e4156SSadaf Ebrahimi // NOTE: caller must free() the allocated memory itself to avoid memory leaking
821*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_disasm(csh ud,const uint8_t * buffer,size_t size,uint64_t offset,size_t count,cs_insn ** insn)822*9a0e4156SSadaf Ebrahimi size_t CAPSTONE_API cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn)
823*9a0e4156SSadaf Ebrahimi {
824*9a0e4156SSadaf Ebrahimi struct cs_struct *handle;
825*9a0e4156SSadaf Ebrahimi MCInst mci;
826*9a0e4156SSadaf Ebrahimi uint16_t insn_size;
827*9a0e4156SSadaf Ebrahimi size_t c = 0, i;
828*9a0e4156SSadaf Ebrahimi unsigned int f = 0; // index of the next instruction in the cache
829*9a0e4156SSadaf Ebrahimi cs_insn *insn_cache; // cache contains disassembled instructions
830*9a0e4156SSadaf Ebrahimi void *total = NULL;
831*9a0e4156SSadaf Ebrahimi size_t total_size = 0; // total size of output buffer containing all insns
832*9a0e4156SSadaf Ebrahimi bool r;
833*9a0e4156SSadaf Ebrahimi void *tmp;
834*9a0e4156SSadaf Ebrahimi size_t skipdata_bytes;
835*9a0e4156SSadaf Ebrahimi uint64_t offset_org; // save all the original info of the buffer
836*9a0e4156SSadaf Ebrahimi size_t size_org;
837*9a0e4156SSadaf Ebrahimi const uint8_t *buffer_org;
838*9a0e4156SSadaf Ebrahimi unsigned int cache_size = INSN_CACHE_SIZE;
839*9a0e4156SSadaf Ebrahimi size_t next_offset;
840*9a0e4156SSadaf Ebrahimi
841*9a0e4156SSadaf Ebrahimi handle = (struct cs_struct *)(uintptr_t)ud;
842*9a0e4156SSadaf Ebrahimi if (!handle) {
843*9a0e4156SSadaf Ebrahimi // FIXME: how to handle this case:
844*9a0e4156SSadaf Ebrahimi // handle->errnum = CS_ERR_HANDLE;
845*9a0e4156SSadaf Ebrahimi return 0;
846*9a0e4156SSadaf Ebrahimi }
847*9a0e4156SSadaf Ebrahimi
848*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_OK;
849*9a0e4156SSadaf Ebrahimi
850*9a0e4156SSadaf Ebrahimi // reset IT block of ARM structure
851*9a0e4156SSadaf Ebrahimi if (handle->arch == CS_ARCH_ARM)
852*9a0e4156SSadaf Ebrahimi handle->ITBlock.size = 0;
853*9a0e4156SSadaf Ebrahimi
854*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_USE_SYS_DYN_MEM
855*9a0e4156SSadaf Ebrahimi if (count > 0 && count <= INSN_CACHE_SIZE)
856*9a0e4156SSadaf Ebrahimi cache_size = (unsigned int) count;
857*9a0e4156SSadaf Ebrahimi #endif
858*9a0e4156SSadaf Ebrahimi
859*9a0e4156SSadaf Ebrahimi // save the original offset for SKIPDATA
860*9a0e4156SSadaf Ebrahimi buffer_org = buffer;
861*9a0e4156SSadaf Ebrahimi offset_org = offset;
862*9a0e4156SSadaf Ebrahimi size_org = size;
863*9a0e4156SSadaf Ebrahimi
864*9a0e4156SSadaf Ebrahimi total_size = sizeof(cs_insn) * cache_size;
865*9a0e4156SSadaf Ebrahimi total = cs_mem_malloc(total_size);
866*9a0e4156SSadaf Ebrahimi if (total == NULL) {
867*9a0e4156SSadaf Ebrahimi // insufficient memory
868*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_MEM;
869*9a0e4156SSadaf Ebrahimi return 0;
870*9a0e4156SSadaf Ebrahimi }
871*9a0e4156SSadaf Ebrahimi
872*9a0e4156SSadaf Ebrahimi insn_cache = total;
873*9a0e4156SSadaf Ebrahimi
874*9a0e4156SSadaf Ebrahimi while (size > 0) {
875*9a0e4156SSadaf Ebrahimi MCInst_Init(&mci);
876*9a0e4156SSadaf Ebrahimi mci.csh = handle;
877*9a0e4156SSadaf Ebrahimi
878*9a0e4156SSadaf Ebrahimi // relative branches need to know the address & size of current insn
879*9a0e4156SSadaf Ebrahimi mci.address = offset;
880*9a0e4156SSadaf Ebrahimi
881*9a0e4156SSadaf Ebrahimi if (handle->detail) {
882*9a0e4156SSadaf Ebrahimi // allocate memory for @detail pointer
883*9a0e4156SSadaf Ebrahimi insn_cache->detail = cs_mem_malloc(sizeof(cs_detail));
884*9a0e4156SSadaf Ebrahimi } else {
885*9a0e4156SSadaf Ebrahimi insn_cache->detail = NULL;
886*9a0e4156SSadaf Ebrahimi }
887*9a0e4156SSadaf Ebrahimi
888*9a0e4156SSadaf Ebrahimi // save all the information for non-detailed mode
889*9a0e4156SSadaf Ebrahimi mci.flat_insn = insn_cache;
890*9a0e4156SSadaf Ebrahimi mci.flat_insn->address = offset;
891*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_DIET
892*9a0e4156SSadaf Ebrahimi // zero out mnemonic & op_str
893*9a0e4156SSadaf Ebrahimi mci.flat_insn->mnemonic[0] = '\0';
894*9a0e4156SSadaf Ebrahimi mci.flat_insn->op_str[0] = '\0';
895*9a0e4156SSadaf Ebrahimi #endif
896*9a0e4156SSadaf Ebrahimi
897*9a0e4156SSadaf Ebrahimi r = handle->disasm(ud, buffer, size, &mci, &insn_size, offset, handle->getinsn_info);
898*9a0e4156SSadaf Ebrahimi if (r) {
899*9a0e4156SSadaf Ebrahimi SStream ss;
900*9a0e4156SSadaf Ebrahimi SStream_Init(&ss);
901*9a0e4156SSadaf Ebrahimi
902*9a0e4156SSadaf Ebrahimi mci.flat_insn->size = insn_size;
903*9a0e4156SSadaf Ebrahimi
904*9a0e4156SSadaf Ebrahimi // map internal instruction opcode to public insn ID
905*9a0e4156SSadaf Ebrahimi
906*9a0e4156SSadaf Ebrahimi handle->insn_id(handle, insn_cache, mci.Opcode);
907*9a0e4156SSadaf Ebrahimi
908*9a0e4156SSadaf Ebrahimi handle->printer(&mci, &ss, handle->printer_info);
909*9a0e4156SSadaf Ebrahimi fill_insn(handle, insn_cache, ss.buffer, &mci, handle->post_printer, buffer);
910*9a0e4156SSadaf Ebrahimi
911*9a0e4156SSadaf Ebrahimi // adjust for pseudo opcode (X86)
912*9a0e4156SSadaf Ebrahimi if (handle->arch == CS_ARCH_X86)
913*9a0e4156SSadaf Ebrahimi insn_cache->id += mci.popcode_adjust;
914*9a0e4156SSadaf Ebrahimi
915*9a0e4156SSadaf Ebrahimi next_offset = insn_size;
916*9a0e4156SSadaf Ebrahimi } else {
917*9a0e4156SSadaf Ebrahimi // encounter a broken instruction
918*9a0e4156SSadaf Ebrahimi
919*9a0e4156SSadaf Ebrahimi // free memory of @detail pointer
920*9a0e4156SSadaf Ebrahimi if (handle->detail) {
921*9a0e4156SSadaf Ebrahimi cs_mem_free(insn_cache->detail);
922*9a0e4156SSadaf Ebrahimi }
923*9a0e4156SSadaf Ebrahimi
924*9a0e4156SSadaf Ebrahimi // if there is no request to skip data, or remaining data is too small,
925*9a0e4156SSadaf Ebrahimi // then bail out
926*9a0e4156SSadaf Ebrahimi if (!handle->skipdata || handle->skipdata_size > size)
927*9a0e4156SSadaf Ebrahimi break;
928*9a0e4156SSadaf Ebrahimi
929*9a0e4156SSadaf Ebrahimi if (handle->skipdata_setup.callback) {
930*9a0e4156SSadaf Ebrahimi skipdata_bytes = handle->skipdata_setup.callback(buffer_org, size_org,
931*9a0e4156SSadaf Ebrahimi (size_t)(offset - offset_org), handle->skipdata_setup.user_data);
932*9a0e4156SSadaf Ebrahimi if (skipdata_bytes > size)
933*9a0e4156SSadaf Ebrahimi // remaining data is not enough
934*9a0e4156SSadaf Ebrahimi break;
935*9a0e4156SSadaf Ebrahimi
936*9a0e4156SSadaf Ebrahimi if (!skipdata_bytes)
937*9a0e4156SSadaf Ebrahimi // user requested not to skip data, so bail out
938*9a0e4156SSadaf Ebrahimi break;
939*9a0e4156SSadaf Ebrahimi } else
940*9a0e4156SSadaf Ebrahimi skipdata_bytes = handle->skipdata_size;
941*9a0e4156SSadaf Ebrahimi
942*9a0e4156SSadaf Ebrahimi // we have to skip some amount of data, depending on arch & mode
943*9a0e4156SSadaf Ebrahimi insn_cache->id = 0; // invalid ID for this "data" instruction
944*9a0e4156SSadaf Ebrahimi insn_cache->address = offset;
945*9a0e4156SSadaf Ebrahimi insn_cache->size = (uint16_t)skipdata_bytes;
946*9a0e4156SSadaf Ebrahimi memcpy(insn_cache->bytes, buffer, skipdata_bytes);
947*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_DIET
948*9a0e4156SSadaf Ebrahimi insn_cache->mnemonic[0] = '\0';
949*9a0e4156SSadaf Ebrahimi insn_cache->op_str[0] = '\0';
950*9a0e4156SSadaf Ebrahimi #else
951*9a0e4156SSadaf Ebrahimi strncpy(insn_cache->mnemonic, handle->skipdata_setup.mnemonic,
952*9a0e4156SSadaf Ebrahimi sizeof(insn_cache->mnemonic) - 1);
953*9a0e4156SSadaf Ebrahimi skipdata_opstr(insn_cache->op_str, buffer, skipdata_bytes);
954*9a0e4156SSadaf Ebrahimi #endif
955*9a0e4156SSadaf Ebrahimi insn_cache->detail = NULL;
956*9a0e4156SSadaf Ebrahimi
957*9a0e4156SSadaf Ebrahimi next_offset = skipdata_bytes;
958*9a0e4156SSadaf Ebrahimi }
959*9a0e4156SSadaf Ebrahimi
960*9a0e4156SSadaf Ebrahimi // one more instruction entering the cache
961*9a0e4156SSadaf Ebrahimi f++;
962*9a0e4156SSadaf Ebrahimi
963*9a0e4156SSadaf Ebrahimi // one more instruction disassembled
964*9a0e4156SSadaf Ebrahimi c++;
965*9a0e4156SSadaf Ebrahimi if (count > 0 && c == count)
966*9a0e4156SSadaf Ebrahimi // already got requested number of instructions
967*9a0e4156SSadaf Ebrahimi break;
968*9a0e4156SSadaf Ebrahimi
969*9a0e4156SSadaf Ebrahimi if (f == cache_size) {
970*9a0e4156SSadaf Ebrahimi // full cache, so expand the cache to contain incoming insns
971*9a0e4156SSadaf Ebrahimi cache_size = cache_size * 8 / 5; // * 1.6 ~ golden ratio
972*9a0e4156SSadaf Ebrahimi total_size += (sizeof(cs_insn) * cache_size);
973*9a0e4156SSadaf Ebrahimi tmp = cs_mem_realloc(total, total_size);
974*9a0e4156SSadaf Ebrahimi if (tmp == NULL) { // insufficient memory
975*9a0e4156SSadaf Ebrahimi if (handle->detail) {
976*9a0e4156SSadaf Ebrahimi insn_cache = (cs_insn *)total;
977*9a0e4156SSadaf Ebrahimi for (i = 0; i < c; i++, insn_cache++)
978*9a0e4156SSadaf Ebrahimi cs_mem_free(insn_cache->detail);
979*9a0e4156SSadaf Ebrahimi }
980*9a0e4156SSadaf Ebrahimi
981*9a0e4156SSadaf Ebrahimi cs_mem_free(total);
982*9a0e4156SSadaf Ebrahimi *insn = NULL;
983*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_MEM;
984*9a0e4156SSadaf Ebrahimi return 0;
985*9a0e4156SSadaf Ebrahimi }
986*9a0e4156SSadaf Ebrahimi
987*9a0e4156SSadaf Ebrahimi total = tmp;
988*9a0e4156SSadaf Ebrahimi // continue to fill in the cache after the last instruction
989*9a0e4156SSadaf Ebrahimi insn_cache = (cs_insn *)((char *)total + sizeof(cs_insn) * c);
990*9a0e4156SSadaf Ebrahimi
991*9a0e4156SSadaf Ebrahimi // reset f back to 0, so we fill in the cache from begining
992*9a0e4156SSadaf Ebrahimi f = 0;
993*9a0e4156SSadaf Ebrahimi } else
994*9a0e4156SSadaf Ebrahimi insn_cache++;
995*9a0e4156SSadaf Ebrahimi
996*9a0e4156SSadaf Ebrahimi buffer += next_offset;
997*9a0e4156SSadaf Ebrahimi size -= next_offset;
998*9a0e4156SSadaf Ebrahimi offset += next_offset;
999*9a0e4156SSadaf Ebrahimi }
1000*9a0e4156SSadaf Ebrahimi
1001*9a0e4156SSadaf Ebrahimi if (!c) {
1002*9a0e4156SSadaf Ebrahimi // we did not disassemble any instruction
1003*9a0e4156SSadaf Ebrahimi cs_mem_free(total);
1004*9a0e4156SSadaf Ebrahimi total = NULL;
1005*9a0e4156SSadaf Ebrahimi } else if (f != cache_size) {
1006*9a0e4156SSadaf Ebrahimi // total did not fully use the last cache, so downsize it
1007*9a0e4156SSadaf Ebrahimi tmp = cs_mem_realloc(total, total_size - (cache_size - f) * sizeof(*insn_cache));
1008*9a0e4156SSadaf Ebrahimi if (tmp == NULL) { // insufficient memory
1009*9a0e4156SSadaf Ebrahimi // free all detail pointers
1010*9a0e4156SSadaf Ebrahimi if (handle->detail) {
1011*9a0e4156SSadaf Ebrahimi insn_cache = (cs_insn *)total;
1012*9a0e4156SSadaf Ebrahimi for (i = 0; i < c; i++, insn_cache++)
1013*9a0e4156SSadaf Ebrahimi cs_mem_free(insn_cache->detail);
1014*9a0e4156SSadaf Ebrahimi }
1015*9a0e4156SSadaf Ebrahimi
1016*9a0e4156SSadaf Ebrahimi cs_mem_free(total);
1017*9a0e4156SSadaf Ebrahimi *insn = NULL;
1018*9a0e4156SSadaf Ebrahimi
1019*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_MEM;
1020*9a0e4156SSadaf Ebrahimi return 0;
1021*9a0e4156SSadaf Ebrahimi }
1022*9a0e4156SSadaf Ebrahimi
1023*9a0e4156SSadaf Ebrahimi total = tmp;
1024*9a0e4156SSadaf Ebrahimi }
1025*9a0e4156SSadaf Ebrahimi
1026*9a0e4156SSadaf Ebrahimi *insn = total;
1027*9a0e4156SSadaf Ebrahimi
1028*9a0e4156SSadaf Ebrahimi return c;
1029*9a0e4156SSadaf Ebrahimi }
1030*9a0e4156SSadaf Ebrahimi
1031*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
1032*9a0e4156SSadaf Ebrahimi CAPSTONE_DEPRECATED
cs_disasm_ex(csh ud,const uint8_t * buffer,size_t size,uint64_t offset,size_t count,cs_insn ** insn)1033*9a0e4156SSadaf Ebrahimi size_t CAPSTONE_API cs_disasm_ex(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn)
1034*9a0e4156SSadaf Ebrahimi {
1035*9a0e4156SSadaf Ebrahimi return cs_disasm(ud, buffer, size, offset, count, insn);
1036*9a0e4156SSadaf Ebrahimi }
1037*9a0e4156SSadaf Ebrahimi
1038*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_free(cs_insn * insn,size_t count)1039*9a0e4156SSadaf Ebrahimi void CAPSTONE_API cs_free(cs_insn *insn, size_t count)
1040*9a0e4156SSadaf Ebrahimi {
1041*9a0e4156SSadaf Ebrahimi size_t i;
1042*9a0e4156SSadaf Ebrahimi
1043*9a0e4156SSadaf Ebrahimi // free all detail pointers
1044*9a0e4156SSadaf Ebrahimi for (i = 0; i < count; i++)
1045*9a0e4156SSadaf Ebrahimi cs_mem_free(insn[i].detail);
1046*9a0e4156SSadaf Ebrahimi
1047*9a0e4156SSadaf Ebrahimi // then free pointer to cs_insn array
1048*9a0e4156SSadaf Ebrahimi cs_mem_free(insn);
1049*9a0e4156SSadaf Ebrahimi }
1050*9a0e4156SSadaf Ebrahimi
1051*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_malloc(csh ud)1052*9a0e4156SSadaf Ebrahimi cs_insn * CAPSTONE_API cs_malloc(csh ud)
1053*9a0e4156SSadaf Ebrahimi {
1054*9a0e4156SSadaf Ebrahimi cs_insn *insn;
1055*9a0e4156SSadaf Ebrahimi struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
1056*9a0e4156SSadaf Ebrahimi
1057*9a0e4156SSadaf Ebrahimi insn = cs_mem_malloc(sizeof(cs_insn));
1058*9a0e4156SSadaf Ebrahimi if (!insn) {
1059*9a0e4156SSadaf Ebrahimi // insufficient memory
1060*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_MEM;
1061*9a0e4156SSadaf Ebrahimi return NULL;
1062*9a0e4156SSadaf Ebrahimi } else {
1063*9a0e4156SSadaf Ebrahimi if (handle->detail) {
1064*9a0e4156SSadaf Ebrahimi // allocate memory for @detail pointer
1065*9a0e4156SSadaf Ebrahimi insn->detail = cs_mem_malloc(sizeof(cs_detail));
1066*9a0e4156SSadaf Ebrahimi if (insn->detail == NULL) { // insufficient memory
1067*9a0e4156SSadaf Ebrahimi cs_mem_free(insn);
1068*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_MEM;
1069*9a0e4156SSadaf Ebrahimi return NULL;
1070*9a0e4156SSadaf Ebrahimi }
1071*9a0e4156SSadaf Ebrahimi } else
1072*9a0e4156SSadaf Ebrahimi insn->detail = NULL;
1073*9a0e4156SSadaf Ebrahimi }
1074*9a0e4156SSadaf Ebrahimi
1075*9a0e4156SSadaf Ebrahimi return insn;
1076*9a0e4156SSadaf Ebrahimi }
1077*9a0e4156SSadaf Ebrahimi
1078*9a0e4156SSadaf Ebrahimi // iterator for instruction "single-stepping"
1079*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_disasm_iter(csh ud,const uint8_t ** code,size_t * size,uint64_t * address,cs_insn * insn)1080*9a0e4156SSadaf Ebrahimi bool CAPSTONE_API cs_disasm_iter(csh ud, const uint8_t **code, size_t *size,
1081*9a0e4156SSadaf Ebrahimi uint64_t *address, cs_insn *insn)
1082*9a0e4156SSadaf Ebrahimi {
1083*9a0e4156SSadaf Ebrahimi struct cs_struct *handle;
1084*9a0e4156SSadaf Ebrahimi uint16_t insn_size;
1085*9a0e4156SSadaf Ebrahimi MCInst mci;
1086*9a0e4156SSadaf Ebrahimi bool r;
1087*9a0e4156SSadaf Ebrahimi
1088*9a0e4156SSadaf Ebrahimi handle = (struct cs_struct *)(uintptr_t)ud;
1089*9a0e4156SSadaf Ebrahimi if (!handle) {
1090*9a0e4156SSadaf Ebrahimi return false;
1091*9a0e4156SSadaf Ebrahimi }
1092*9a0e4156SSadaf Ebrahimi
1093*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_OK;
1094*9a0e4156SSadaf Ebrahimi
1095*9a0e4156SSadaf Ebrahimi MCInst_Init(&mci);
1096*9a0e4156SSadaf Ebrahimi mci.csh = handle;
1097*9a0e4156SSadaf Ebrahimi
1098*9a0e4156SSadaf Ebrahimi // relative branches need to know the address & size of current insn
1099*9a0e4156SSadaf Ebrahimi mci.address = *address;
1100*9a0e4156SSadaf Ebrahimi
1101*9a0e4156SSadaf Ebrahimi // save all the information for non-detailed mode
1102*9a0e4156SSadaf Ebrahimi mci.flat_insn = insn;
1103*9a0e4156SSadaf Ebrahimi mci.flat_insn->address = *address;
1104*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_DIET
1105*9a0e4156SSadaf Ebrahimi // zero out mnemonic & op_str
1106*9a0e4156SSadaf Ebrahimi mci.flat_insn->mnemonic[0] = '\0';
1107*9a0e4156SSadaf Ebrahimi mci.flat_insn->op_str[0] = '\0';
1108*9a0e4156SSadaf Ebrahimi #endif
1109*9a0e4156SSadaf Ebrahimi
1110*9a0e4156SSadaf Ebrahimi r = handle->disasm(ud, *code, *size, &mci, &insn_size, *address, handle->getinsn_info);
1111*9a0e4156SSadaf Ebrahimi if (r) {
1112*9a0e4156SSadaf Ebrahimi SStream ss;
1113*9a0e4156SSadaf Ebrahimi SStream_Init(&ss);
1114*9a0e4156SSadaf Ebrahimi
1115*9a0e4156SSadaf Ebrahimi mci.flat_insn->size = insn_size;
1116*9a0e4156SSadaf Ebrahimi
1117*9a0e4156SSadaf Ebrahimi // map internal instruction opcode to public insn ID
1118*9a0e4156SSadaf Ebrahimi handle->insn_id(handle, insn, mci.Opcode);
1119*9a0e4156SSadaf Ebrahimi
1120*9a0e4156SSadaf Ebrahimi handle->printer(&mci, &ss, handle->printer_info);
1121*9a0e4156SSadaf Ebrahimi
1122*9a0e4156SSadaf Ebrahimi fill_insn(handle, insn, ss.buffer, &mci, handle->post_printer, *code);
1123*9a0e4156SSadaf Ebrahimi
1124*9a0e4156SSadaf Ebrahimi // adjust for pseudo opcode (X86)
1125*9a0e4156SSadaf Ebrahimi if (handle->arch == CS_ARCH_X86)
1126*9a0e4156SSadaf Ebrahimi insn->id += mci.popcode_adjust;
1127*9a0e4156SSadaf Ebrahimi
1128*9a0e4156SSadaf Ebrahimi *code += insn_size;
1129*9a0e4156SSadaf Ebrahimi *size -= insn_size;
1130*9a0e4156SSadaf Ebrahimi *address += insn_size;
1131*9a0e4156SSadaf Ebrahimi } else { // encounter a broken instruction
1132*9a0e4156SSadaf Ebrahimi size_t skipdata_bytes;
1133*9a0e4156SSadaf Ebrahimi
1134*9a0e4156SSadaf Ebrahimi // if there is no request to skip data, or remaining data is too small,
1135*9a0e4156SSadaf Ebrahimi // then bail out
1136*9a0e4156SSadaf Ebrahimi if (!handle->skipdata || handle->skipdata_size > *size)
1137*9a0e4156SSadaf Ebrahimi return false;
1138*9a0e4156SSadaf Ebrahimi
1139*9a0e4156SSadaf Ebrahimi if (handle->skipdata_setup.callback) {
1140*9a0e4156SSadaf Ebrahimi skipdata_bytes = handle->skipdata_setup.callback(*code, *size,
1141*9a0e4156SSadaf Ebrahimi 0, handle->skipdata_setup.user_data);
1142*9a0e4156SSadaf Ebrahimi if (skipdata_bytes > *size)
1143*9a0e4156SSadaf Ebrahimi // remaining data is not enough
1144*9a0e4156SSadaf Ebrahimi return false;
1145*9a0e4156SSadaf Ebrahimi
1146*9a0e4156SSadaf Ebrahimi if (!skipdata_bytes)
1147*9a0e4156SSadaf Ebrahimi // user requested not to skip data, so bail out
1148*9a0e4156SSadaf Ebrahimi return false;
1149*9a0e4156SSadaf Ebrahimi } else
1150*9a0e4156SSadaf Ebrahimi skipdata_bytes = handle->skipdata_size;
1151*9a0e4156SSadaf Ebrahimi
1152*9a0e4156SSadaf Ebrahimi // we have to skip some amount of data, depending on arch & mode
1153*9a0e4156SSadaf Ebrahimi insn->id = 0; // invalid ID for this "data" instruction
1154*9a0e4156SSadaf Ebrahimi insn->address = *address;
1155*9a0e4156SSadaf Ebrahimi insn->size = (uint16_t)skipdata_bytes;
1156*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_DIET
1157*9a0e4156SSadaf Ebrahimi insn->mnemonic[0] = '\0';
1158*9a0e4156SSadaf Ebrahimi insn->op_str[0] = '\0';
1159*9a0e4156SSadaf Ebrahimi #else
1160*9a0e4156SSadaf Ebrahimi memcpy(insn->bytes, *code, skipdata_bytes);
1161*9a0e4156SSadaf Ebrahimi strncpy(insn->mnemonic, handle->skipdata_setup.mnemonic,
1162*9a0e4156SSadaf Ebrahimi sizeof(insn->mnemonic) - 1);
1163*9a0e4156SSadaf Ebrahimi skipdata_opstr(insn->op_str, *code, skipdata_bytes);
1164*9a0e4156SSadaf Ebrahimi #endif
1165*9a0e4156SSadaf Ebrahimi
1166*9a0e4156SSadaf Ebrahimi *code += skipdata_bytes;
1167*9a0e4156SSadaf Ebrahimi *size -= skipdata_bytes;
1168*9a0e4156SSadaf Ebrahimi *address += skipdata_bytes;
1169*9a0e4156SSadaf Ebrahimi }
1170*9a0e4156SSadaf Ebrahimi
1171*9a0e4156SSadaf Ebrahimi return true;
1172*9a0e4156SSadaf Ebrahimi }
1173*9a0e4156SSadaf Ebrahimi
1174*9a0e4156SSadaf Ebrahimi // return friendly name of regiser in a string
1175*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_reg_name(csh ud,unsigned int reg)1176*9a0e4156SSadaf Ebrahimi const char * CAPSTONE_API cs_reg_name(csh ud, unsigned int reg)
1177*9a0e4156SSadaf Ebrahimi {
1178*9a0e4156SSadaf Ebrahimi struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
1179*9a0e4156SSadaf Ebrahimi
1180*9a0e4156SSadaf Ebrahimi if (!handle || handle->reg_name == NULL) {
1181*9a0e4156SSadaf Ebrahimi return NULL;
1182*9a0e4156SSadaf Ebrahimi }
1183*9a0e4156SSadaf Ebrahimi
1184*9a0e4156SSadaf Ebrahimi return handle->reg_name(ud, reg);
1185*9a0e4156SSadaf Ebrahimi }
1186*9a0e4156SSadaf Ebrahimi
1187*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_insn_name(csh ud,unsigned int insn)1188*9a0e4156SSadaf Ebrahimi const char * CAPSTONE_API cs_insn_name(csh ud, unsigned int insn)
1189*9a0e4156SSadaf Ebrahimi {
1190*9a0e4156SSadaf Ebrahimi struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
1191*9a0e4156SSadaf Ebrahimi
1192*9a0e4156SSadaf Ebrahimi if (!handle || handle->insn_name == NULL) {
1193*9a0e4156SSadaf Ebrahimi return NULL;
1194*9a0e4156SSadaf Ebrahimi }
1195*9a0e4156SSadaf Ebrahimi
1196*9a0e4156SSadaf Ebrahimi return handle->insn_name(ud, insn);
1197*9a0e4156SSadaf Ebrahimi }
1198*9a0e4156SSadaf Ebrahimi
1199*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_group_name(csh ud,unsigned int group)1200*9a0e4156SSadaf Ebrahimi const char * CAPSTONE_API cs_group_name(csh ud, unsigned int group)
1201*9a0e4156SSadaf Ebrahimi {
1202*9a0e4156SSadaf Ebrahimi struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
1203*9a0e4156SSadaf Ebrahimi
1204*9a0e4156SSadaf Ebrahimi if (!handle || handle->group_name == NULL) {
1205*9a0e4156SSadaf Ebrahimi return NULL;
1206*9a0e4156SSadaf Ebrahimi }
1207*9a0e4156SSadaf Ebrahimi
1208*9a0e4156SSadaf Ebrahimi return handle->group_name(ud, group);
1209*9a0e4156SSadaf Ebrahimi }
1210*9a0e4156SSadaf Ebrahimi
1211*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_insn_group(csh ud,const cs_insn * insn,unsigned int group_id)1212*9a0e4156SSadaf Ebrahimi bool CAPSTONE_API cs_insn_group(csh ud, const cs_insn *insn, unsigned int group_id)
1213*9a0e4156SSadaf Ebrahimi {
1214*9a0e4156SSadaf Ebrahimi struct cs_struct *handle;
1215*9a0e4156SSadaf Ebrahimi if (!ud)
1216*9a0e4156SSadaf Ebrahimi return false;
1217*9a0e4156SSadaf Ebrahimi
1218*9a0e4156SSadaf Ebrahimi handle = (struct cs_struct *)(uintptr_t)ud;
1219*9a0e4156SSadaf Ebrahimi
1220*9a0e4156SSadaf Ebrahimi if (!handle->detail) {
1221*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1222*9a0e4156SSadaf Ebrahimi return false;
1223*9a0e4156SSadaf Ebrahimi }
1224*9a0e4156SSadaf Ebrahimi
1225*9a0e4156SSadaf Ebrahimi if (!insn->id) {
1226*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_SKIPDATA;
1227*9a0e4156SSadaf Ebrahimi return false;
1228*9a0e4156SSadaf Ebrahimi }
1229*9a0e4156SSadaf Ebrahimi
1230*9a0e4156SSadaf Ebrahimi if (!insn->detail) {
1231*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1232*9a0e4156SSadaf Ebrahimi return false;
1233*9a0e4156SSadaf Ebrahimi }
1234*9a0e4156SSadaf Ebrahimi
1235*9a0e4156SSadaf Ebrahimi return arr_exist8(insn->detail->groups, insn->detail->groups_count, group_id);
1236*9a0e4156SSadaf Ebrahimi }
1237*9a0e4156SSadaf Ebrahimi
1238*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_reg_read(csh ud,const cs_insn * insn,unsigned int reg_id)1239*9a0e4156SSadaf Ebrahimi bool CAPSTONE_API cs_reg_read(csh ud, const cs_insn *insn, unsigned int reg_id)
1240*9a0e4156SSadaf Ebrahimi {
1241*9a0e4156SSadaf Ebrahimi struct cs_struct *handle;
1242*9a0e4156SSadaf Ebrahimi if (!ud)
1243*9a0e4156SSadaf Ebrahimi return false;
1244*9a0e4156SSadaf Ebrahimi
1245*9a0e4156SSadaf Ebrahimi handle = (struct cs_struct *)(uintptr_t)ud;
1246*9a0e4156SSadaf Ebrahimi
1247*9a0e4156SSadaf Ebrahimi if (!handle->detail) {
1248*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1249*9a0e4156SSadaf Ebrahimi return false;
1250*9a0e4156SSadaf Ebrahimi }
1251*9a0e4156SSadaf Ebrahimi
1252*9a0e4156SSadaf Ebrahimi if (!insn->id) {
1253*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_SKIPDATA;
1254*9a0e4156SSadaf Ebrahimi return false;
1255*9a0e4156SSadaf Ebrahimi }
1256*9a0e4156SSadaf Ebrahimi
1257*9a0e4156SSadaf Ebrahimi if (!insn->detail) {
1258*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1259*9a0e4156SSadaf Ebrahimi return false;
1260*9a0e4156SSadaf Ebrahimi }
1261*9a0e4156SSadaf Ebrahimi
1262*9a0e4156SSadaf Ebrahimi return arr_exist(insn->detail->regs_read, insn->detail->regs_read_count, reg_id);
1263*9a0e4156SSadaf Ebrahimi }
1264*9a0e4156SSadaf Ebrahimi
1265*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_reg_write(csh ud,const cs_insn * insn,unsigned int reg_id)1266*9a0e4156SSadaf Ebrahimi bool CAPSTONE_API cs_reg_write(csh ud, const cs_insn *insn, unsigned int reg_id)
1267*9a0e4156SSadaf Ebrahimi {
1268*9a0e4156SSadaf Ebrahimi struct cs_struct *handle;
1269*9a0e4156SSadaf Ebrahimi if (!ud)
1270*9a0e4156SSadaf Ebrahimi return false;
1271*9a0e4156SSadaf Ebrahimi
1272*9a0e4156SSadaf Ebrahimi handle = (struct cs_struct *)(uintptr_t)ud;
1273*9a0e4156SSadaf Ebrahimi
1274*9a0e4156SSadaf Ebrahimi if (!handle->detail) {
1275*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1276*9a0e4156SSadaf Ebrahimi return false;
1277*9a0e4156SSadaf Ebrahimi }
1278*9a0e4156SSadaf Ebrahimi
1279*9a0e4156SSadaf Ebrahimi if (!insn->id) {
1280*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_SKIPDATA;
1281*9a0e4156SSadaf Ebrahimi return false;
1282*9a0e4156SSadaf Ebrahimi }
1283*9a0e4156SSadaf Ebrahimi
1284*9a0e4156SSadaf Ebrahimi if (!insn->detail) {
1285*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1286*9a0e4156SSadaf Ebrahimi return false;
1287*9a0e4156SSadaf Ebrahimi }
1288*9a0e4156SSadaf Ebrahimi
1289*9a0e4156SSadaf Ebrahimi return arr_exist(insn->detail->regs_write, insn->detail->regs_write_count, reg_id);
1290*9a0e4156SSadaf Ebrahimi }
1291*9a0e4156SSadaf Ebrahimi
1292*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_op_count(csh ud,const cs_insn * insn,unsigned int op_type)1293*9a0e4156SSadaf Ebrahimi int CAPSTONE_API cs_op_count(csh ud, const cs_insn *insn, unsigned int op_type)
1294*9a0e4156SSadaf Ebrahimi {
1295*9a0e4156SSadaf Ebrahimi struct cs_struct *handle;
1296*9a0e4156SSadaf Ebrahimi unsigned int count = 0, i;
1297*9a0e4156SSadaf Ebrahimi if (!ud)
1298*9a0e4156SSadaf Ebrahimi return -1;
1299*9a0e4156SSadaf Ebrahimi
1300*9a0e4156SSadaf Ebrahimi handle = (struct cs_struct *)(uintptr_t)ud;
1301*9a0e4156SSadaf Ebrahimi
1302*9a0e4156SSadaf Ebrahimi if (!handle->detail) {
1303*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1304*9a0e4156SSadaf Ebrahimi return -1;
1305*9a0e4156SSadaf Ebrahimi }
1306*9a0e4156SSadaf Ebrahimi
1307*9a0e4156SSadaf Ebrahimi if (!insn->id) {
1308*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_SKIPDATA;
1309*9a0e4156SSadaf Ebrahimi return -1;
1310*9a0e4156SSadaf Ebrahimi }
1311*9a0e4156SSadaf Ebrahimi
1312*9a0e4156SSadaf Ebrahimi if (!insn->detail) {
1313*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1314*9a0e4156SSadaf Ebrahimi return -1;
1315*9a0e4156SSadaf Ebrahimi }
1316*9a0e4156SSadaf Ebrahimi
1317*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_OK;
1318*9a0e4156SSadaf Ebrahimi
1319*9a0e4156SSadaf Ebrahimi switch (handle->arch) {
1320*9a0e4156SSadaf Ebrahimi default:
1321*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_HANDLE;
1322*9a0e4156SSadaf Ebrahimi return -1;
1323*9a0e4156SSadaf Ebrahimi case CS_ARCH_ARM:
1324*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->arm.op_count; i++)
1325*9a0e4156SSadaf Ebrahimi if (insn->detail->arm.operands[i].type == (arm_op_type)op_type)
1326*9a0e4156SSadaf Ebrahimi count++;
1327*9a0e4156SSadaf Ebrahimi break;
1328*9a0e4156SSadaf Ebrahimi case CS_ARCH_ARM64:
1329*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->arm64.op_count; i++)
1330*9a0e4156SSadaf Ebrahimi if (insn->detail->arm64.operands[i].type == (arm64_op_type)op_type)
1331*9a0e4156SSadaf Ebrahimi count++;
1332*9a0e4156SSadaf Ebrahimi break;
1333*9a0e4156SSadaf Ebrahimi case CS_ARCH_X86:
1334*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->x86.op_count; i++)
1335*9a0e4156SSadaf Ebrahimi if (insn->detail->x86.operands[i].type == (x86_op_type)op_type)
1336*9a0e4156SSadaf Ebrahimi count++;
1337*9a0e4156SSadaf Ebrahimi break;
1338*9a0e4156SSadaf Ebrahimi case CS_ARCH_MIPS:
1339*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->mips.op_count; i++)
1340*9a0e4156SSadaf Ebrahimi if (insn->detail->mips.operands[i].type == (mips_op_type)op_type)
1341*9a0e4156SSadaf Ebrahimi count++;
1342*9a0e4156SSadaf Ebrahimi break;
1343*9a0e4156SSadaf Ebrahimi case CS_ARCH_PPC:
1344*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->ppc.op_count; i++)
1345*9a0e4156SSadaf Ebrahimi if (insn->detail->ppc.operands[i].type == (ppc_op_type)op_type)
1346*9a0e4156SSadaf Ebrahimi count++;
1347*9a0e4156SSadaf Ebrahimi break;
1348*9a0e4156SSadaf Ebrahimi case CS_ARCH_SPARC:
1349*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->sparc.op_count; i++)
1350*9a0e4156SSadaf Ebrahimi if (insn->detail->sparc.operands[i].type == (sparc_op_type)op_type)
1351*9a0e4156SSadaf Ebrahimi count++;
1352*9a0e4156SSadaf Ebrahimi break;
1353*9a0e4156SSadaf Ebrahimi case CS_ARCH_SYSZ:
1354*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->sysz.op_count; i++)
1355*9a0e4156SSadaf Ebrahimi if (insn->detail->sysz.operands[i].type == (sysz_op_type)op_type)
1356*9a0e4156SSadaf Ebrahimi count++;
1357*9a0e4156SSadaf Ebrahimi break;
1358*9a0e4156SSadaf Ebrahimi case CS_ARCH_XCORE:
1359*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->xcore.op_count; i++)
1360*9a0e4156SSadaf Ebrahimi if (insn->detail->xcore.operands[i].type == (xcore_op_type)op_type)
1361*9a0e4156SSadaf Ebrahimi count++;
1362*9a0e4156SSadaf Ebrahimi break;
1363*9a0e4156SSadaf Ebrahimi case CS_ARCH_M68K:
1364*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->m68k.op_count; i++)
1365*9a0e4156SSadaf Ebrahimi if (insn->detail->m68k.operands[i].type == (m68k_op_type)op_type)
1366*9a0e4156SSadaf Ebrahimi count++;
1367*9a0e4156SSadaf Ebrahimi break;
1368*9a0e4156SSadaf Ebrahimi case CS_ARCH_TMS320C64X:
1369*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->tms320c64x.op_count; i++)
1370*9a0e4156SSadaf Ebrahimi if (insn->detail->tms320c64x.operands[i].type == (tms320c64x_op_type)op_type)
1371*9a0e4156SSadaf Ebrahimi count++;
1372*9a0e4156SSadaf Ebrahimi break;
1373*9a0e4156SSadaf Ebrahimi case CS_ARCH_M680X:
1374*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->m680x.op_count; i++)
1375*9a0e4156SSadaf Ebrahimi if (insn->detail->m680x.operands[i].type == (m680x_op_type)op_type)
1376*9a0e4156SSadaf Ebrahimi count++;
1377*9a0e4156SSadaf Ebrahimi break;
1378*9a0e4156SSadaf Ebrahimi case CS_ARCH_EVM:
1379*9a0e4156SSadaf Ebrahimi #if 0
1380*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->evm.op_count; i++)
1381*9a0e4156SSadaf Ebrahimi if (insn->detail->evm.operands[i].type == (evm_op_type)op_type)
1382*9a0e4156SSadaf Ebrahimi count++;
1383*9a0e4156SSadaf Ebrahimi #endif
1384*9a0e4156SSadaf Ebrahimi break;
1385*9a0e4156SSadaf Ebrahimi case CS_ARCH_MOS65XX:
1386*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->mos65xx.op_count; i++)
1387*9a0e4156SSadaf Ebrahimi if (insn->detail->mos65xx.operands[i].type == (mos65xx_op_type)op_type)
1388*9a0e4156SSadaf Ebrahimi count++;
1389*9a0e4156SSadaf Ebrahimi break;
1390*9a0e4156SSadaf Ebrahimi }
1391*9a0e4156SSadaf Ebrahimi
1392*9a0e4156SSadaf Ebrahimi return count;
1393*9a0e4156SSadaf Ebrahimi }
1394*9a0e4156SSadaf Ebrahimi
1395*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_op_index(csh ud,const cs_insn * insn,unsigned int op_type,unsigned int post)1396*9a0e4156SSadaf Ebrahimi int CAPSTONE_API cs_op_index(csh ud, const cs_insn *insn, unsigned int op_type,
1397*9a0e4156SSadaf Ebrahimi unsigned int post)
1398*9a0e4156SSadaf Ebrahimi {
1399*9a0e4156SSadaf Ebrahimi struct cs_struct *handle;
1400*9a0e4156SSadaf Ebrahimi unsigned int count = 0, i;
1401*9a0e4156SSadaf Ebrahimi if (!ud)
1402*9a0e4156SSadaf Ebrahimi return -1;
1403*9a0e4156SSadaf Ebrahimi
1404*9a0e4156SSadaf Ebrahimi handle = (struct cs_struct *)(uintptr_t)ud;
1405*9a0e4156SSadaf Ebrahimi
1406*9a0e4156SSadaf Ebrahimi if (!handle->detail) {
1407*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1408*9a0e4156SSadaf Ebrahimi return -1;
1409*9a0e4156SSadaf Ebrahimi }
1410*9a0e4156SSadaf Ebrahimi
1411*9a0e4156SSadaf Ebrahimi if (!insn->id) {
1412*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_SKIPDATA;
1413*9a0e4156SSadaf Ebrahimi return -1;
1414*9a0e4156SSadaf Ebrahimi }
1415*9a0e4156SSadaf Ebrahimi
1416*9a0e4156SSadaf Ebrahimi if (!insn->detail) {
1417*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1418*9a0e4156SSadaf Ebrahimi return -1;
1419*9a0e4156SSadaf Ebrahimi }
1420*9a0e4156SSadaf Ebrahimi
1421*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_OK;
1422*9a0e4156SSadaf Ebrahimi
1423*9a0e4156SSadaf Ebrahimi switch (handle->arch) {
1424*9a0e4156SSadaf Ebrahimi default:
1425*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_HANDLE;
1426*9a0e4156SSadaf Ebrahimi return -1;
1427*9a0e4156SSadaf Ebrahimi case CS_ARCH_ARM:
1428*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->arm.op_count; i++) {
1429*9a0e4156SSadaf Ebrahimi if (insn->detail->arm.operands[i].type == (arm_op_type)op_type)
1430*9a0e4156SSadaf Ebrahimi count++;
1431*9a0e4156SSadaf Ebrahimi if (count == post)
1432*9a0e4156SSadaf Ebrahimi return i;
1433*9a0e4156SSadaf Ebrahimi }
1434*9a0e4156SSadaf Ebrahimi break;
1435*9a0e4156SSadaf Ebrahimi case CS_ARCH_ARM64:
1436*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->arm64.op_count; i++) {
1437*9a0e4156SSadaf Ebrahimi if (insn->detail->arm64.operands[i].type == (arm64_op_type)op_type)
1438*9a0e4156SSadaf Ebrahimi count++;
1439*9a0e4156SSadaf Ebrahimi if (count == post)
1440*9a0e4156SSadaf Ebrahimi return i;
1441*9a0e4156SSadaf Ebrahimi }
1442*9a0e4156SSadaf Ebrahimi break;
1443*9a0e4156SSadaf Ebrahimi case CS_ARCH_X86:
1444*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->x86.op_count; i++) {
1445*9a0e4156SSadaf Ebrahimi if (insn->detail->x86.operands[i].type == (x86_op_type)op_type)
1446*9a0e4156SSadaf Ebrahimi count++;
1447*9a0e4156SSadaf Ebrahimi if (count == post)
1448*9a0e4156SSadaf Ebrahimi return i;
1449*9a0e4156SSadaf Ebrahimi }
1450*9a0e4156SSadaf Ebrahimi break;
1451*9a0e4156SSadaf Ebrahimi case CS_ARCH_MIPS:
1452*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->mips.op_count; i++) {
1453*9a0e4156SSadaf Ebrahimi if (insn->detail->mips.operands[i].type == (mips_op_type)op_type)
1454*9a0e4156SSadaf Ebrahimi count++;
1455*9a0e4156SSadaf Ebrahimi if (count == post)
1456*9a0e4156SSadaf Ebrahimi return i;
1457*9a0e4156SSadaf Ebrahimi }
1458*9a0e4156SSadaf Ebrahimi break;
1459*9a0e4156SSadaf Ebrahimi case CS_ARCH_PPC:
1460*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->ppc.op_count; i++) {
1461*9a0e4156SSadaf Ebrahimi if (insn->detail->ppc.operands[i].type == (ppc_op_type)op_type)
1462*9a0e4156SSadaf Ebrahimi count++;
1463*9a0e4156SSadaf Ebrahimi if (count == post)
1464*9a0e4156SSadaf Ebrahimi return i;
1465*9a0e4156SSadaf Ebrahimi }
1466*9a0e4156SSadaf Ebrahimi break;
1467*9a0e4156SSadaf Ebrahimi case CS_ARCH_SPARC:
1468*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->sparc.op_count; i++) {
1469*9a0e4156SSadaf Ebrahimi if (insn->detail->sparc.operands[i].type == (sparc_op_type)op_type)
1470*9a0e4156SSadaf Ebrahimi count++;
1471*9a0e4156SSadaf Ebrahimi if (count == post)
1472*9a0e4156SSadaf Ebrahimi return i;
1473*9a0e4156SSadaf Ebrahimi }
1474*9a0e4156SSadaf Ebrahimi break;
1475*9a0e4156SSadaf Ebrahimi case CS_ARCH_SYSZ:
1476*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->sysz.op_count; i++) {
1477*9a0e4156SSadaf Ebrahimi if (insn->detail->sysz.operands[i].type == (sysz_op_type)op_type)
1478*9a0e4156SSadaf Ebrahimi count++;
1479*9a0e4156SSadaf Ebrahimi if (count == post)
1480*9a0e4156SSadaf Ebrahimi return i;
1481*9a0e4156SSadaf Ebrahimi }
1482*9a0e4156SSadaf Ebrahimi break;
1483*9a0e4156SSadaf Ebrahimi case CS_ARCH_XCORE:
1484*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->xcore.op_count; i++) {
1485*9a0e4156SSadaf Ebrahimi if (insn->detail->xcore.operands[i].type == (xcore_op_type)op_type)
1486*9a0e4156SSadaf Ebrahimi count++;
1487*9a0e4156SSadaf Ebrahimi if (count == post)
1488*9a0e4156SSadaf Ebrahimi return i;
1489*9a0e4156SSadaf Ebrahimi }
1490*9a0e4156SSadaf Ebrahimi break;
1491*9a0e4156SSadaf Ebrahimi case CS_ARCH_M68K:
1492*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->m68k.op_count; i++) {
1493*9a0e4156SSadaf Ebrahimi if (insn->detail->m68k.operands[i].type == (m68k_op_type)op_type)
1494*9a0e4156SSadaf Ebrahimi count++;
1495*9a0e4156SSadaf Ebrahimi if (count == post)
1496*9a0e4156SSadaf Ebrahimi return i;
1497*9a0e4156SSadaf Ebrahimi }
1498*9a0e4156SSadaf Ebrahimi break;
1499*9a0e4156SSadaf Ebrahimi case CS_ARCH_TMS320C64X:
1500*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->tms320c64x.op_count; i++) {
1501*9a0e4156SSadaf Ebrahimi if (insn->detail->tms320c64x.operands[i].type == (tms320c64x_op_type)op_type)
1502*9a0e4156SSadaf Ebrahimi count++;
1503*9a0e4156SSadaf Ebrahimi if (count == post)
1504*9a0e4156SSadaf Ebrahimi return i;
1505*9a0e4156SSadaf Ebrahimi }
1506*9a0e4156SSadaf Ebrahimi break;
1507*9a0e4156SSadaf Ebrahimi case CS_ARCH_M680X:
1508*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->m680x.op_count; i++) {
1509*9a0e4156SSadaf Ebrahimi if (insn->detail->m680x.operands[i].type == (m680x_op_type)op_type)
1510*9a0e4156SSadaf Ebrahimi count++;
1511*9a0e4156SSadaf Ebrahimi if (count == post)
1512*9a0e4156SSadaf Ebrahimi return i;
1513*9a0e4156SSadaf Ebrahimi }
1514*9a0e4156SSadaf Ebrahimi break;
1515*9a0e4156SSadaf Ebrahimi case CS_ARCH_EVM:
1516*9a0e4156SSadaf Ebrahimi #if 0
1517*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->evm.op_count; i++) {
1518*9a0e4156SSadaf Ebrahimi if (insn->detail->evm.operands[i].type == (evm_op_type)op_type)
1519*9a0e4156SSadaf Ebrahimi count++;
1520*9a0e4156SSadaf Ebrahimi if (count == post)
1521*9a0e4156SSadaf Ebrahimi return i;
1522*9a0e4156SSadaf Ebrahimi }
1523*9a0e4156SSadaf Ebrahimi #endif
1524*9a0e4156SSadaf Ebrahimi break;
1525*9a0e4156SSadaf Ebrahimi case CS_ARCH_MOS65XX:
1526*9a0e4156SSadaf Ebrahimi for (i = 0; i < insn->detail->mos65xx.op_count; i++) {
1527*9a0e4156SSadaf Ebrahimi if (insn->detail->mos65xx.operands[i].type == (mos65xx_op_type)op_type)
1528*9a0e4156SSadaf Ebrahimi count++;
1529*9a0e4156SSadaf Ebrahimi if (count == post)
1530*9a0e4156SSadaf Ebrahimi return i;
1531*9a0e4156SSadaf Ebrahimi }
1532*9a0e4156SSadaf Ebrahimi break;
1533*9a0e4156SSadaf Ebrahimi }
1534*9a0e4156SSadaf Ebrahimi
1535*9a0e4156SSadaf Ebrahimi return -1;
1536*9a0e4156SSadaf Ebrahimi }
1537*9a0e4156SSadaf Ebrahimi
1538*9a0e4156SSadaf Ebrahimi CAPSTONE_EXPORT
cs_regs_access(csh ud,const cs_insn * insn,cs_regs regs_read,uint8_t * regs_read_count,cs_regs regs_write,uint8_t * regs_write_count)1539*9a0e4156SSadaf Ebrahimi cs_err CAPSTONE_API cs_regs_access(csh ud, const cs_insn *insn,
1540*9a0e4156SSadaf Ebrahimi cs_regs regs_read, uint8_t *regs_read_count,
1541*9a0e4156SSadaf Ebrahimi cs_regs regs_write, uint8_t *regs_write_count)
1542*9a0e4156SSadaf Ebrahimi {
1543*9a0e4156SSadaf Ebrahimi struct cs_struct *handle;
1544*9a0e4156SSadaf Ebrahimi
1545*9a0e4156SSadaf Ebrahimi if (!ud)
1546*9a0e4156SSadaf Ebrahimi return -1;
1547*9a0e4156SSadaf Ebrahimi
1548*9a0e4156SSadaf Ebrahimi handle = (struct cs_struct *)(uintptr_t)ud;
1549*9a0e4156SSadaf Ebrahimi
1550*9a0e4156SSadaf Ebrahimi #ifdef CAPSTONE_DIET
1551*9a0e4156SSadaf Ebrahimi // This API does not work in DIET mode
1552*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DIET;
1553*9a0e4156SSadaf Ebrahimi return CS_ERR_DIET;
1554*9a0e4156SSadaf Ebrahimi #else
1555*9a0e4156SSadaf Ebrahimi if (!handle->detail) {
1556*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1557*9a0e4156SSadaf Ebrahimi return CS_ERR_DETAIL;
1558*9a0e4156SSadaf Ebrahimi }
1559*9a0e4156SSadaf Ebrahimi
1560*9a0e4156SSadaf Ebrahimi if (!insn->id) {
1561*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_SKIPDATA;
1562*9a0e4156SSadaf Ebrahimi return CS_ERR_SKIPDATA;
1563*9a0e4156SSadaf Ebrahimi }
1564*9a0e4156SSadaf Ebrahimi
1565*9a0e4156SSadaf Ebrahimi if (!insn->detail) {
1566*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_DETAIL;
1567*9a0e4156SSadaf Ebrahimi return CS_ERR_DETAIL;
1568*9a0e4156SSadaf Ebrahimi }
1569*9a0e4156SSadaf Ebrahimi
1570*9a0e4156SSadaf Ebrahimi if (handle->reg_access) {
1571*9a0e4156SSadaf Ebrahimi handle->reg_access(insn, regs_read, regs_read_count, regs_write, regs_write_count);
1572*9a0e4156SSadaf Ebrahimi } else {
1573*9a0e4156SSadaf Ebrahimi // this arch is unsupported yet
1574*9a0e4156SSadaf Ebrahimi handle->errnum = CS_ERR_ARCH;
1575*9a0e4156SSadaf Ebrahimi return CS_ERR_ARCH;
1576*9a0e4156SSadaf Ebrahimi }
1577*9a0e4156SSadaf Ebrahimi
1578*9a0e4156SSadaf Ebrahimi return CS_ERR_OK;
1579*9a0e4156SSadaf Ebrahimi #endif
1580*9a0e4156SSadaf Ebrahimi }
1581