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