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