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