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