Coverage Report

Created: 2025-08-29 06:29

/src/capstonenext/cs.c
Line
Count
Source (jump to first uncovered line)
1
/* Capstone Disassembly Engine */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
3
4
#include "SStream.h"
5
#if defined(CAPSTONE_HAS_OSXKERNEL)
6
#include <Availability.h>
7
#include <libkern/libkern.h>
8
#else
9
#include <stddef.h>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#endif
13
14
#include <string.h>
15
#include <capstone/capstone.h>
16
17
#include "utils.h"
18
#include "MCRegisterInfo.h"
19
20
#if defined(_KERNEL_MODE)
21
#include "windows\winkernel_mm.h"
22
#endif
23
24
// Issue #681: Windows kernel does not support formatting float point
25
#if defined(_KERNEL_MODE) && !defined(CAPSTONE_DIET)
26
#if defined(CAPSTONE_HAS_ARM) || defined(CAPSTONE_HAS_AARCH64) || \
27
  defined(CAPSTONE_HAS_M68K)
28
#define CAPSTONE_STR_INTERNAL(x) #x
29
#define CAPSTONE_STR(x) CAPSTONE_STR_INTERNAL(x)
30
#define CAPSTONE_MSVC_WRANING_PREFIX \
31
  __FILE__ "(" CAPSTONE_STR(__LINE__) ") : warning message : "
32
33
#pragma message( \
34
  CAPSTONE_MSVC_WRANING_PREFIX \
35
  "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.")
36
37
#undef CAPSTONE_MSVC_WRANING_PREFIX
38
#undef CAPSTONE_STR
39
#undef CAPSTONE_STR_INTERNAL
40
#endif
41
#endif // defined(_KERNEL_MODE) && !defined(CAPSTONE_DIET)
42
43
#if !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(CAPSTONE_DIET) && \
44
  !defined(_KERNEL_MODE)
45
39.3k
#define INSN_CACHE_SIZE 32
46
#else
47
// reduce stack variable size for kernel/firmware
48
#define INSN_CACHE_SIZE 8
49
#endif
50
51
// default SKIPDATA mnemonic
52
#ifndef CAPSTONE_DIET
53
39.3k
#define SKIPDATA_MNEM ".byte"
54
#else // No printing is available in diet mode
55
#define SKIPDATA_MNEM NULL
56
#endif
57
58
#include "arch/AArch64/AArch64Module.h"
59
#include "arch/ARM/ARMModule.h"
60
#include "arch/EVM/EVMModule.h"
61
#include "arch/WASM/WASMModule.h"
62
#include "arch/M680X/M680XModule.h"
63
#include "arch/M68K/M68KModule.h"
64
#include "arch/Mips/MipsModule.h"
65
#include "arch/PowerPC/PPCModule.h"
66
#include "arch/Sparc/SparcModule.h"
67
#include "arch/SystemZ/SystemZModule.h"
68
#include "arch/TMS320C64x/TMS320C64xModule.h"
69
#include "arch/X86/X86Module.h"
70
#include "arch/XCore/XCoreModule.h"
71
#include "arch/RISCV/RISCVModule.h"
72
#include "arch/MOS65XX/MOS65XXModule.h"
73
#include "arch/BPF/BPFModule.h"
74
#include "arch/SH/SHModule.h"
75
#include "arch/TriCore/TriCoreModule.h"
76
#include "arch/Alpha/AlphaModule.h"
77
#include "arch/HPPA/HPPAModule.h"
78
#include "arch/LoongArch/LoongArchModule.h"
79
#include "arch/Xtensa/XtensaModule.h"
80
#include "arch/ARC/ARCModule.h"
81
82
typedef struct cs_arch_config {
83
  // constructor initialization
84
  cs_err (*arch_init)(cs_struct *);
85
  // support cs_option()
86
  cs_err (*arch_option)(cs_struct *, cs_opt_type, size_t value);
87
  // bitmask for finding disallowed modes for an arch:
88
  // to be called in cs_open()/cs_option()
89
  cs_mode arch_disallowed_mode_mask;
90
} cs_arch_config;
91
92
#define CS_ARCH_CONFIG_ARM \
93
  { \
94
    ARM_global_init, ARM_option, \
95
      ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_ARM | CS_MODE_V8 | \
96
        CS_MODE_MCLASS | CS_MODE_THUMB | \
97
        CS_MODE_BIG_ENDIAN), \
98
  }
99
#define CS_ARCH_CONFIG_AARCH64 \
100
  { \
101
    AArch64_global_init, AArch64_option, \
102
      ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_ARM | \
103
        CS_MODE_BIG_ENDIAN | CS_MODE_APPLE_PROPRIETARY), \
104
  }
105
#define CS_ARCH_CONFIG_MIPS \
106
  { \
107
    Mips_global_init, Mips_option, \
108
      ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_BIG_ENDIAN | \
109
        CS_MODE_MIPS16 | CS_MODE_MIPS32 | CS_MODE_MIPS64 | \
110
        CS_MODE_MICRO | CS_MODE_MIPS1 | CS_MODE_MIPS2 | \
111
        CS_MODE_MIPS32R2 | CS_MODE_MIPS32R3 | \
112
        CS_MODE_MIPS32R5 | CS_MODE_MIPS32R6 | \
113
        CS_MODE_MIPS3 | CS_MODE_MIPS4 | CS_MODE_MIPS5 | \
114
        CS_MODE_MIPS64R2 | CS_MODE_MIPS64R3 | \
115
        CS_MODE_MIPS64R5 | CS_MODE_MIPS64R6 | \
116
        CS_MODE_OCTEON | CS_MODE_OCTEONP | \
117
        CS_MODE_NANOMIPS | CS_MODE_NMS1 | CS_MODE_I7200 | \
118
        CS_MODE_MIPS_NOFLOAT | CS_MODE_MIPS_PTR64), \
119
  }
120
#define CS_ARCH_CONFIG_X86 \
121
  { \
122
    X86_global_init, X86_option, \
123
      ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | \
124
        CS_MODE_16), \
125
  }
126
#define CS_ARCH_CONFIG_PPC \
127
  { \
128
    PPC_global_init, PPC_option, \
129
      ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 | \
130
        CS_MODE_BIG_ENDIAN | CS_MODE_QPX | CS_MODE_PS | \
131
        CS_MODE_BOOKE | CS_MODE_SPE | CS_MODE_AIX_OS | \
132
        CS_MODE_PWR7 | CS_MODE_PWR8 | CS_MODE_PWR9 | \
133
        CS_MODE_PWR10 | CS_MODE_PPC_ISA_FUTURE | \
134
        CS_MODE_MSYNC | CS_MODE_MODERN_AIX_AS), \
135
  }
136
#define CS_ARCH_CONFIG_SPARC \
137
  { \
138
    Sparc_global_init, Sparc_option, \
139
      ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_BIG_ENDIAN | \
140
        CS_MODE_V9 | CS_MODE_64 | CS_MODE_32), \
141
  }
142
#define CS_ARCH_CONFIG_SYSTEMZ \
143
  { \
144
    SystemZ_global_init, SystemZ_option, \
145
      ~(CS_MODE_BIG_ENDIAN | CS_MODE_SYSTEMZ_ARCH8 | \
146
        CS_MODE_SYSTEMZ_ARCH9 | CS_MODE_SYSTEMZ_ARCH10 | \
147
        CS_MODE_SYSTEMZ_ARCH11 | CS_MODE_SYSTEMZ_ARCH12 | \
148
        CS_MODE_SYSTEMZ_ARCH13 | CS_MODE_SYSTEMZ_ARCH14 | \
149
        CS_MODE_SYSTEMZ_Z10 | CS_MODE_SYSTEMZ_Z196 | \
150
        CS_MODE_SYSTEMZ_ZEC12 | CS_MODE_SYSTEMZ_Z13 | \
151
        CS_MODE_SYSTEMZ_Z14 | CS_MODE_SYSTEMZ_Z15 | \
152
        CS_MODE_SYSTEMZ_Z16 | CS_MODE_SYSTEMZ_GENERIC), \
153
  }
154
#define CS_ARCH_CONFIG_XCORE \
155
  { \
156
    XCore_global_init, XCore_option, ~(CS_MODE_BIG_ENDIAN), \
157
  }
158
#define CS_ARCH_CONFIG_M68K \
159
  { \
160
    M68K_global_init, M68K_option, \
161
      ~(CS_MODE_BIG_ENDIAN | CS_MODE_M68K_000 | \
162
        CS_MODE_M68K_010 | CS_MODE_M68K_020 | \
163
        CS_MODE_M68K_030 | CS_MODE_M68K_040 | \
164
        CS_MODE_M68K_060), \
165
  }
166
#define CS_ARCH_CONFIG_TMS320C64X \
167
  { \
168
    TMS320C64x_global_init, TMS320C64x_option, \
169
      ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_BIG_ENDIAN), \
170
  }
171
#define CS_ARCH_CONFIG_M680X \
172
  { \
173
    M680X_global_init, M680X_option, \
174
      ~(CS_MODE_M680X_6301 | CS_MODE_M680X_6309 | \
175
        CS_MODE_M680X_6800 | CS_MODE_M680X_6801 | \
176
        CS_MODE_M680X_6805 | CS_MODE_M680X_6808 | \
177
        CS_MODE_M680X_6809 | CS_MODE_M680X_6811 | \
178
        CS_MODE_M680X_CPU12 | CS_MODE_M680X_HCS08), \
179
  }
180
#define CS_ARCH_CONFIG_EVM \
181
  { \
182
    EVM_global_init, EVM_option, 0, \
183
  }
184
#define CS_ARCH_CONFIG_MOS65XX \
185
  { \
186
    MOS65XX_global_init, MOS65XX_option, \
187
      ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_MOS65XX_6502 | \
188
        CS_MODE_MOS65XX_65C02 | CS_MODE_MOS65XX_W65C02 | \
189
        CS_MODE_MOS65XX_65816_LONG_MX), \
190
  }
191
#define CS_ARCH_CONFIG_WASM \
192
  { \
193
    WASM_global_init, WASM_option, 0, \
194
  }
195
#define CS_ARCH_CONFIG_BPF \
196
  { \
197
    BPF_global_init, BPF_option, \
198
      ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_CLASSIC | \
199
        CS_MODE_BPF_EXTENDED | CS_MODE_BIG_ENDIAN), \
200
  }
201
#define CS_ARCH_CONFIG_RISCV \
202
  { \
203
    RISCV_global_init, RISCV_option, \
204
      ~(CS_MODE_RISCV32 | CS_MODE_RISCV64 | CS_MODE_RISCVC), \
205
  }
206
#define CS_ARCH_CONFIG_SH \
207
  { \
208
    SH_global_init, SH_option, \
209
      ~(CS_MODE_SH2 | CS_MODE_SH2A | CS_MODE_SH3 | \
210
        CS_MODE_SH4 | CS_MODE_SH4A | CS_MODE_SHFPU | \
211
        CS_MODE_SHDSP | CS_MODE_BIG_ENDIAN), \
212
  }
213
#define CS_ARCH_CONFIG_TRICORE \
214
  { \
215
    TRICORE_global_init, TRICORE_option, \
216
      ~(CS_MODE_TRICORE_110 | CS_MODE_TRICORE_120 | \
217
        CS_MODE_TRICORE_130 | CS_MODE_TRICORE_131 | \
218
        CS_MODE_TRICORE_160 | CS_MODE_TRICORE_161 | \
219
        CS_MODE_TRICORE_162 | CS_MODE_TRICORE_180 | \
220
        CS_MODE_LITTLE_ENDIAN), \
221
  }
222
#define CS_ARCH_CONFIG_ALPHA \
223
  { \
224
    ALPHA_global_init, ALPHA_option, \
225
      ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_BIG_ENDIAN), \
226
  }
227
#define CS_ARCH_CONFIG_LOONGARCH \
228
  { \
229
    LoongArch_global_init, LoongArch_option, \
230
      ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_LOONGARCH32 | \
231
        CS_MODE_LOONGARCH64), \
232
  }
233
#define CS_ARCH_CONFIG_XTENSA \
234
  { \
235
    Xtensa_global_init, Xtensa_option, \
236
      ~(CS_MODE_XTENSA_ESP32 | CS_MODE_XTENSA_ESP32S2 | \
237
        CS_MODE_XTENSA_ESP8266), \
238
  }
239
240
#define CS_ARCH_CONFIG_ARC \
241
  { \
242
    ARC_global_init, ARC_option, ~(CS_MODE_LITTLE_ENDIAN), \
243
  }
244
245
#ifdef CAPSTONE_USE_ARCH_REGISTRATION
246
static cs_arch_config arch_configs[MAX_ARCH];
247
static uint32_t all_arch;
248
#else
249
static const cs_arch_config arch_configs[MAX_ARCH] = {
250
#ifdef CAPSTONE_HAS_ARM
251
  CS_ARCH_CONFIG_ARM,
252
#else
253
  { NULL, NULL, 0 },
254
#endif
255
#ifdef CAPSTONE_HAS_AARCH64
256
  CS_ARCH_CONFIG_AARCH64,
257
#else
258
  { NULL, NULL, 0 },
259
#endif
260
#ifdef CAPSTONE_HAS_SYSTEMZ
261
  CS_ARCH_CONFIG_SYSTEMZ,
262
#else
263
  { NULL, NULL, 0 },
264
#endif
265
#ifdef CAPSTONE_HAS_MIPS
266
  CS_ARCH_CONFIG_MIPS,
267
#else
268
  { NULL, NULL, 0 },
269
#endif
270
#ifdef CAPSTONE_HAS_X86
271
  CS_ARCH_CONFIG_X86,
272
#else
273
  { NULL, NULL, 0 },
274
#endif
275
#ifdef CAPSTONE_HAS_POWERPC
276
  CS_ARCH_CONFIG_PPC,
277
#else
278
  { NULL, NULL, 0 },
279
#endif
280
#ifdef CAPSTONE_HAS_SPARC
281
  CS_ARCH_CONFIG_SPARC,
282
#else
283
  { NULL, NULL, 0 },
284
#endif
285
#ifdef CAPSTONE_HAS_XCORE
286
  CS_ARCH_CONFIG_XCORE,
287
#else
288
  { NULL, NULL, 0 },
289
#endif
290
#ifdef CAPSTONE_HAS_M68K
291
  CS_ARCH_CONFIG_M68K,
292
#else
293
  { NULL, NULL, 0 },
294
#endif
295
#ifdef CAPSTONE_HAS_TMS320C64X
296
  CS_ARCH_CONFIG_TMS320C64X,
297
#else
298
  { NULL, NULL, 0 },
299
#endif
300
#ifdef CAPSTONE_HAS_M680X
301
  CS_ARCH_CONFIG_M680X,
302
#else
303
  { NULL, NULL, 0 },
304
#endif
305
#ifdef CAPSTONE_HAS_EVM
306
  CS_ARCH_CONFIG_EVM,
307
#else
308
  { NULL, NULL, 0 },
309
#endif
310
#ifdef CAPSTONE_HAS_MOS65XX
311
  CS_ARCH_CONFIG_MOS65XX,
312
#else
313
  { NULL, NULL, 0 },
314
#endif
315
#ifdef CAPSTONE_HAS_WASM
316
  CS_ARCH_CONFIG_WASM,
317
#else
318
  { NULL, NULL, 0 },
319
#endif
320
#ifdef CAPSTONE_HAS_BPF
321
  CS_ARCH_CONFIG_BPF,
322
#else
323
  { NULL, NULL, 0 },
324
#endif
325
#ifdef CAPSTONE_HAS_RISCV
326
  CS_ARCH_CONFIG_RISCV,
327
#else
328
  { NULL, NULL, 0 },
329
#endif
330
#ifdef CAPSTONE_HAS_SH
331
  CS_ARCH_CONFIG_SH,
332
#else
333
  { NULL, NULL, 0 },
334
#endif
335
#ifdef CAPSTONE_HAS_TRICORE
336
  CS_ARCH_CONFIG_TRICORE,
337
#else
338
  { NULL, NULL, 0 },
339
#endif
340
#ifdef CAPSTONE_HAS_ALPHA
341
  CS_ARCH_CONFIG_ALPHA,
342
#else
343
  { NULL, NULL, 0 },
344
#endif
345
#ifdef CAPSTONE_HAS_HPPA
346
  {
347
    HPPA_global_init,
348
    HPPA_option,
349
    ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_BIG_ENDIAN | CS_MODE_HPPA_11 |
350
      CS_MODE_HPPA_20 | CS_MODE_HPPA_20W),
351
  },
352
#else
353
  { NULL, NULL, 0 },
354
#endif
355
#ifdef CAPSTONE_HAS_LOONGARCH
356
  CS_ARCH_CONFIG_LOONGARCH,
357
#else
358
  { NULL, NULL, 0 },
359
#endif
360
#ifdef CAPSTONE_HAS_XTENSA
361
  CS_ARCH_CONFIG_XTENSA,
362
#else
363
  { NULL, NULL, 0 },
364
#endif
365
#ifdef CAPSTONE_HAS_ARC
366
  CS_ARCH_CONFIG_ARC,
367
#else
368
  { NULL, NULL, 0 },
369
#endif
370
};
371
372
// bitmask of enabled architectures
373
static const uint32_t all_arch = 0
374
#ifdef CAPSTONE_HAS_ARM
375
         | (1 << CS_ARCH_ARM)
376
#endif
377
#if defined(CAPSTONE_HAS_AARCH64) || defined(CAPSTONE_HAS_ARM64)
378
         | (1 << CS_ARCH_AARCH64)
379
#endif
380
#ifdef CAPSTONE_HAS_MIPS
381
         | (1 << CS_ARCH_MIPS)
382
#endif
383
#ifdef CAPSTONE_HAS_X86
384
         | (1 << CS_ARCH_X86)
385
#endif
386
#ifdef CAPSTONE_HAS_POWERPC
387
         | (1 << CS_ARCH_PPC)
388
#endif
389
#ifdef CAPSTONE_HAS_SPARC
390
         | (1 << CS_ARCH_SPARC)
391
#endif
392
#ifdef CAPSTONE_HAS_SYSTEMZ
393
         | (1 << CS_ARCH_SYSTEMZ)
394
#endif
395
#ifdef CAPSTONE_HAS_XCORE
396
         | (1 << CS_ARCH_XCORE)
397
#endif
398
#ifdef CAPSTONE_HAS_M68K
399
         | (1 << CS_ARCH_M68K)
400
#endif
401
#ifdef CAPSTONE_HAS_TMS320C64X
402
         | (1 << CS_ARCH_TMS320C64X)
403
#endif
404
#ifdef CAPSTONE_HAS_M680X
405
         | (1 << CS_ARCH_M680X)
406
#endif
407
#ifdef CAPSTONE_HAS_EVM
408
         | (1 << CS_ARCH_EVM)
409
#endif
410
#ifdef CAPSTONE_HAS_MOS65XX
411
         | (1 << CS_ARCH_MOS65XX)
412
#endif
413
#ifdef CAPSTONE_HAS_WASM
414
         | (1 << CS_ARCH_WASM)
415
#endif
416
#ifdef CAPSTONE_HAS_BPF
417
         | (1 << CS_ARCH_BPF)
418
#endif
419
#ifdef CAPSTONE_HAS_RISCV
420
         | (1 << CS_ARCH_RISCV)
421
#endif
422
#ifdef CAPSTONE_HAS_SH
423
         | (1 << CS_ARCH_SH)
424
#endif
425
#ifdef CAPSTONE_HAS_TRICORE
426
         | (1 << CS_ARCH_TRICORE)
427
#endif
428
#ifdef CAPSTONE_HAS_ALPHA
429
         | (1 << CS_ARCH_ALPHA)
430
#endif
431
#ifdef CAPSTONE_HAS_HPPA
432
         | (1 << CS_ARCH_HPPA)
433
#endif
434
#ifdef CAPSTONE_HAS_LOONGARCH
435
         | (1 << CS_ARCH_LOONGARCH)
436
#endif
437
#ifdef CAPSTONE_HAS_XTENSA
438
         | (1 << CS_ARCH_XTENSA)
439
#endif
440
#ifdef CAPSTONE_HAS_ARC
441
         | (1 << CS_ARCH_ARC)
442
#endif
443
  ;
444
#endif
445
446
#if defined(CAPSTONE_USE_SYS_DYN_MEM)
447
#if !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(_KERNEL_MODE)
448
// default
449
cs_malloc_t cs_mem_malloc = malloc;
450
cs_calloc_t cs_mem_calloc = calloc;
451
cs_realloc_t cs_mem_realloc = realloc;
452
cs_free_t cs_mem_free = free;
453
#if defined(_WIN32_WCE)
454
cs_vsnprintf_t cs_vsnprintf = _vsnprintf;
455
#else
456
cs_vsnprintf_t cs_vsnprintf = vsnprintf;
457
#endif // defined(_WIN32_WCE)
458
459
#elif defined(_KERNEL_MODE)
460
// Windows driver
461
cs_malloc_t cs_mem_malloc = cs_winkernel_malloc;
462
cs_calloc_t cs_mem_calloc = cs_winkernel_calloc;
463
cs_realloc_t cs_mem_realloc = cs_winkernel_realloc;
464
cs_free_t cs_mem_free = cs_winkernel_free;
465
cs_vsnprintf_t cs_vsnprintf = cs_winkernel_vsnprintf;
466
#else
467
// OSX kernel
468
extern void *kern_os_malloc(size_t size);
469
extern void kern_os_free(void *addr);
470
extern void *kern_os_realloc(void *addr, size_t nsize);
471
472
static void *cs_kern_os_calloc(size_t num, size_t size)
473
{
474
  return kern_os_malloc(num * size); // malloc bzeroes the buffer
475
}
476
477
cs_malloc_t cs_mem_malloc = kern_os_malloc;
478
cs_calloc_t cs_mem_calloc = cs_kern_os_calloc;
479
cs_realloc_t cs_mem_realloc = kern_os_realloc;
480
cs_free_t cs_mem_free = kern_os_free;
481
cs_vsnprintf_t cs_vsnprintf = vsnprintf;
482
#endif // !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(_KERNEL_MODE)
483
#else
484
// User-defined
485
cs_malloc_t cs_mem_malloc = NULL;
486
cs_calloc_t cs_mem_calloc = NULL;
487
cs_realloc_t cs_mem_realloc = NULL;
488
cs_free_t cs_mem_free = NULL;
489
cs_vsnprintf_t cs_vsnprintf = NULL;
490
491
#endif // defined(CAPSTONE_USE_SYS_DYN_MEM)
492
493
CAPSTONE_EXPORT
494
unsigned int CAPSTONE_API cs_version(int *major, int *minor)
495
0
{
496
0
  if (major != NULL && minor != NULL) {
497
0
    *major = CS_API_MAJOR;
498
0
    *minor = CS_API_MINOR;
499
0
  }
500
501
0
  return (CS_API_MAJOR << 8) + CS_API_MINOR;
502
0
}
503
504
#define CS_ARCH_REGISTER(id) \
505
  cs_arch_config cfg = CS_ARCH_CONFIG_##id; \
506
  arch_configs[CS_ARCH_##id] = cfg; \
507
  all_arch |= 1 << CS_ARCH_##id
508
509
CAPSTONE_EXPORT
510
void CAPSTONE_API cs_arch_register_arm(void)
511
0
{
512
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_ARM)
513
  CS_ARCH_REGISTER(ARM);
514
#endif
515
0
}
516
517
CAPSTONE_EXPORT
518
void CAPSTONE_API cs_arch_register_aarch64(void)
519
0
{
520
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_AARCH64)
521
  CS_ARCH_REGISTER(AARCH64);
522
#endif
523
0
}
524
525
CAPSTONE_EXPORT
526
void CAPSTONE_API cs_arch_register_mips(void)
527
0
{
528
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_MIPS)
529
  CS_ARCH_REGISTER(MIPS);
530
#endif
531
0
}
532
533
CAPSTONE_EXPORT
534
void CAPSTONE_API cs_arch_register_x86(void)
535
0
{
536
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_X86)
537
  CS_ARCH_REGISTER(X86);
538
#endif
539
0
}
540
541
CAPSTONE_EXPORT
542
void CAPSTONE_API cs_arch_register_powerpc(void)
543
0
{
544
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_POWERPC)
545
  CS_ARCH_REGISTER(PPC);
546
#endif
547
0
}
548
549
CAPSTONE_EXPORT
550
void CAPSTONE_API cs_arch_register_sparc(void)
551
0
{
552
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_SPARC)
553
  CS_ARCH_REGISTER(SPARC);
554
#endif
555
0
}
556
557
CAPSTONE_EXPORT
558
void CAPSTONE_API cs_arch_register_systemz(void)
559
0
{
560
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_SYSTEMZ)
561
  CS_ARCH_REGISTER(SYSTEMZ);
562
#endif
563
0
}
564
565
CAPSTONE_EXPORT
566
void CAPSTONE_API cs_arch_register_xcore(void)
567
0
{
568
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_XCORE)
569
  CS_ARCH_REGISTER(XCORE);
570
#endif
571
0
}
572
573
CAPSTONE_EXPORT
574
void CAPSTONE_API cs_arch_register_m68k(void)
575
0
{
576
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_M68K)
577
  CS_ARCH_REGISTER(M68K);
578
#endif
579
0
}
580
581
CAPSTONE_EXPORT
582
void CAPSTONE_API cs_arch_register_tms320c64x(void)
583
0
{
584
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_TMS320C64X)
585
  CS_ARCH_REGISTER(TMS320C64X);
586
#endif
587
0
}
588
589
CAPSTONE_EXPORT
590
void CAPSTONE_API cs_arch_register_m680x(void)
591
0
{
592
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_M680X)
593
  CS_ARCH_REGISTER(M680X);
594
#endif
595
0
}
596
597
CAPSTONE_EXPORT
598
void CAPSTONE_API cs_arch_register_evm(void)
599
0
{
600
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_EVM)
601
  CS_ARCH_REGISTER(EVM);
602
#endif
603
0
}
604
605
CAPSTONE_EXPORT
606
void CAPSTONE_API cs_arch_register_mos65xx(void)
607
0
{
608
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_MOS65XX)
609
  CS_ARCH_REGISTER(MOS65XX);
610
#endif
611
0
}
612
613
CAPSTONE_EXPORT
614
void CAPSTONE_API cs_arch_register_wasm(void)
615
0
{
616
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_WASM)
617
  CS_ARCH_REGISTER(WASM);
618
#endif
619
0
}
620
621
CAPSTONE_EXPORT
622
void CAPSTONE_API cs_arch_register_bpf(void)
623
0
{
624
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_BPF)
625
  CS_ARCH_REGISTER(BPF);
626
#endif
627
0
}
628
629
CAPSTONE_EXPORT
630
void CAPSTONE_API cs_arch_register_riscv(void)
631
0
{
632
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_RISCV)
633
  CS_ARCH_REGISTER(RISCV);
634
#endif
635
0
}
636
637
CAPSTONE_EXPORT
638
void CAPSTONE_API cs_arch_register_sh(void)
639
0
{
640
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_SH)
641
  CS_ARCH_REGISTER(SH);
642
#endif
643
0
}
644
645
CAPSTONE_EXPORT
646
void CAPSTONE_API cs_arch_register_tricore(void)
647
0
{
648
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_TRICORE)
649
  CS_ARCH_REGISTER(TRICORE);
650
#endif
651
0
}
652
653
CAPSTONE_EXPORT
654
void CAPSTONE_API cs_arch_register_alpha(void)
655
0
{
656
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_ALPHA)
657
  CS_ARCH_REGISTER(ALPHA);
658
#endif
659
0
}
660
661
CAPSTONE_EXPORT
662
void CAPSTONE_API cs_arch_register_loongarch(void)
663
0
{
664
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_LOONGARCH)
665
  CS_ARCH_REGISTER(LOONGARCH);
666
#endif
667
0
}
668
669
CAPSTONE_EXPORT
670
void CAPSTONE_API cs_arch_register_arc(void)
671
0
{
672
#if defined(CAPSTONE_USE_ARCH_REGISTRATION) && defined(CAPSTONE_HAS_ARC)
673
  CS_ARCH_REGISTER(ARC);
674
#endif
675
0
}
676
677
CAPSTONE_EXPORT
678
bool CAPSTONE_API cs_support(int query)
679
0
{
680
0
  if (query == CS_ARCH_ALL)
681
0
    return all_arch ==
682
0
           ((1 << CS_ARCH_ARM) | (1 << CS_ARCH_AARCH64) |
683
0
      (1 << CS_ARCH_MIPS) | (1 << CS_ARCH_X86) |
684
0
      (1 << CS_ARCH_PPC) | (1 << CS_ARCH_SPARC) |
685
0
      (1 << CS_ARCH_SYSTEMZ) | (1 << CS_ARCH_XCORE) |
686
0
      (1 << CS_ARCH_M68K) | (1 << CS_ARCH_TMS320C64X) |
687
0
      (1 << CS_ARCH_M680X) | (1 << CS_ARCH_EVM) |
688
0
      (1 << CS_ARCH_RISCV) | (1 << CS_ARCH_MOS65XX) |
689
0
      (1 << CS_ARCH_WASM) | (1 << CS_ARCH_BPF) |
690
0
      (1 << CS_ARCH_SH) | (1 << CS_ARCH_TRICORE) |
691
0
      (1 << CS_ARCH_ALPHA) | (1 << CS_ARCH_HPPA) |
692
0
      (1 << CS_ARCH_LOONGARCH) | (1 << CS_ARCH_XTENSA) |
693
0
      (1 << CS_ARCH_ARC));
694
695
0
  if ((unsigned int)query < CS_ARCH_MAX)
696
0
    return all_arch & (1 << query);
697
698
0
  if (query == CS_SUPPORT_DIET) {
699
#ifdef CAPSTONE_DIET
700
    return true;
701
#else
702
0
    return false;
703
0
#endif
704
0
  }
705
706
0
  if (query == CS_SUPPORT_X86_REDUCE) {
707
#if defined(CAPSTONE_HAS_X86) && defined(CAPSTONE_X86_REDUCE)
708
    return true;
709
#else
710
0
    return false;
711
0
#endif
712
0
  }
713
714
  // unsupported query
715
0
  return false;
716
0
}
717
718
CAPSTONE_EXPORT
719
cs_err CAPSTONE_API cs_errno(csh handle)
720
0
{
721
0
  struct cs_struct *ud;
722
0
  if (!handle)
723
0
    return CS_ERR_CSH;
724
725
0
  ud = (struct cs_struct *)(uintptr_t)handle;
726
727
0
  return ud->errnum;
728
0
}
729
730
CAPSTONE_EXPORT
731
const char *CAPSTONE_API cs_strerror(cs_err code)
732
0
{
733
0
  switch (code) {
734
0
  default:
735
0
    return "Unknown error code";
736
0
  case CS_ERR_OK:
737
0
    return "OK (CS_ERR_OK)";
738
0
  case CS_ERR_MEM:
739
0
    return "Out of memory (CS_ERR_MEM)";
740
0
  case CS_ERR_ARCH:
741
0
    return "Invalid/unsupported architecture(CS_ERR_ARCH)";
742
0
  case CS_ERR_HANDLE:
743
0
    return "Invalid handle (CS_ERR_HANDLE)";
744
0
  case CS_ERR_CSH:
745
0
    return "Invalid csh (CS_ERR_CSH)";
746
0
  case CS_ERR_MODE:
747
0
    return "Invalid mode (CS_ERR_MODE)";
748
0
  case CS_ERR_OPTION:
749
0
    return "Invalid option (CS_ERR_OPTION)";
750
0
  case CS_ERR_DETAIL:
751
0
    return "Details are unavailable (CS_ERR_DETAIL)";
752
0
  case CS_ERR_MEMSETUP:
753
0
    return "Dynamic memory management uninitialized (CS_ERR_MEMSETUP)";
754
0
  case CS_ERR_VERSION:
755
0
    return "Different API version between core & binding (CS_ERR_VERSION)";
756
0
  case CS_ERR_DIET:
757
0
    return "Information irrelevant in diet engine (CS_ERR_DIET)";
758
0
  case CS_ERR_SKIPDATA:
759
0
    return "Information irrelevant for 'data' instruction in SKIPDATA mode (CS_ERR_SKIPDATA)";
760
0
  case CS_ERR_X86_ATT:
761
0
    return "AT&T syntax is unavailable (CS_ERR_X86_ATT)";
762
0
  case CS_ERR_X86_INTEL:
763
0
    return "INTEL syntax is unavailable (CS_ERR_X86_INTEL)";
764
0
  case CS_ERR_X86_MASM:
765
0
    return "MASM syntax is unavailable (CS_ERR_X86_MASM)";
766
0
  }
767
0
}
768
769
CAPSTONE_EXPORT
770
cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
771
39.3k
{
772
39.3k
  cs_err err;
773
39.3k
  struct cs_struct *ud = NULL;
774
39.3k
  if (!cs_mem_malloc || !cs_mem_calloc || !cs_mem_realloc ||
775
39.3k
      !cs_mem_free || !cs_vsnprintf)
776
    // Error: before cs_open(), dynamic memory management must be initialized
777
    // with cs_option(CS_OPT_MEM)
778
0
    return CS_ERR_MEMSETUP;
779
780
39.3k
  if (arch < CS_ARCH_MAX && arch_configs[arch].arch_init) {
781
    // verify if requested mode is valid
782
39.3k
    if (mode & arch_configs[arch].arch_disallowed_mode_mask) {
783
7
      *handle = 0;
784
7
      return CS_ERR_MODE;
785
7
    }
786
787
39.3k
    ud = cs_mem_calloc(1, sizeof(*ud));
788
39.3k
    if (!ud) {
789
      // memory insufficient
790
0
      return CS_ERR_MEM;
791
0
    }
792
793
39.3k
    ud->errnum = CS_ERR_OK;
794
39.3k
    ud->arch = arch;
795
39.3k
    ud->mode = mode;
796
    // by default, do not break instruction into details
797
39.3k
    ud->detail_opt = CS_OPT_OFF;
798
39.3k
    ud->PrintBranchImmAsAddress = true;
799
800
    // default skipdata setup
801
39.3k
    ud->skipdata_setup.mnemonic = SKIPDATA_MNEM;
802
803
39.3k
    err = arch_configs[ud->arch].arch_init(ud);
804
39.3k
    if (err) {
805
0
      cs_mem_free(ud);
806
0
      *handle = 0;
807
0
      return err;
808
0
    }
809
810
39.3k
    *handle = (uintptr_t)ud;
811
812
39.3k
    return CS_ERR_OK;
813
39.3k
  } else {
814
0
    cs_mem_free(ud);
815
0
    *handle = 0;
816
0
    return CS_ERR_ARCH;
817
0
  }
818
39.3k
}
819
820
CAPSTONE_EXPORT
821
cs_err CAPSTONE_API cs_close(csh *handle)
822
39.3k
{
823
39.3k
  struct cs_struct *ud = NULL;
824
39.3k
  struct insn_mnem *next = NULL, *tmp = NULL;
825
826
39.3k
  if (*handle == 0)
827
    // invalid handle
828
0
    return CS_ERR_CSH;
829
830
39.3k
  ud = (struct cs_struct *)(*handle);
831
832
39.3k
  if (ud->printer_info)
833
37.2k
    cs_mem_free(ud->printer_info);
834
835
  // free the linked list of customized mnemonic
836
39.3k
  tmp = ud->mnem_list;
837
39.3k
  while (tmp) {
838
0
    next = tmp->next;
839
0
    cs_mem_free(tmp);
840
0
    tmp = next;
841
0
  }
842
843
39.3k
  cs_mem_free(ud->insn_cache);
844
845
39.3k
  memset(ud, 0, sizeof(*ud));
846
39.3k
  cs_mem_free(ud);
847
848
  // invalidate this handle by ZERO out its value.
849
  // this is to make sure it is unusable after cs_close()
850
39.3k
  *handle = 0;
851
852
39.3k
  return CS_ERR_OK;
853
39.3k
}
854
855
/// replace str1 in target with str2; target starts with str1
856
/// output is put into result (which is array of char with size CS_MNEMONIC_SIZE)
857
/// return 0 on success, -1 on failure
858
#ifndef CAPSTONE_DIET
859
static int str_replace(char *result, char *target, const char *str1, char *str2)
860
0
{
861
0
  size_t target_len = strlen(target);
862
0
  size_t str1_len = strlen(str1);
863
0
  if (target_len < str1_len) {
864
0
    return -1;
865
0
  }
866
867
  // only perform replacement if the output fits into result
868
0
  if (target_len - str1_len + strlen(str2) <= CS_MNEMONIC_SIZE - 1) {
869
    // copy str2 to beginning of result
870
    // skip str1 - already replaced by str2
871
0
    snprintf(result, CS_MNEMONIC_SIZE, "%s%s", str2,
872
0
       target + str1_len);
873
874
0
    return 0;
875
0
  } else
876
0
    return -1;
877
0
}
878
#endif
879
880
// fill insn with mnemonic & operands info
881
static void fill_insn(struct cs_struct *handle, cs_insn *insn, SStream *OS,
882
          MCInst *mci, PostPrinter_t postprinter,
883
          const uint8_t *code)
884
2.05M
{
885
2.05M
#ifndef CAPSTONE_DIET
886
2.05M
  char *sp;
887
2.05M
#endif
888
2.05M
  SStream_trimls(OS);
889
2.05M
  uint16_t copy_size = MIN(sizeof(insn->bytes), insn->size);
890
891
  // fill the instruction bytes.
892
  // we might skip some redundant bytes in front in the case of X86
893
2.05M
  memcpy(insn->bytes, code + insn->size - copy_size, copy_size);
894
2.05M
  insn->op_str[0] = '\0';
895
2.05M
  insn->size = copy_size;
896
897
  // alias instruction might have ID saved in OpcodePub
898
2.05M
  if (MCInst_getOpcodePub(mci))
899
74.2k
    insn->id = MCInst_getOpcodePub(mci);
900
901
  // post printer handles some corner cases (hacky)
902
2.05M
  if (postprinter)
903
513k
    postprinter((csh)handle, insn, OS, mci);
904
905
2.05M
#ifndef CAPSTONE_DIET
906
2.05M
  memset(insn->mnemonic, '\0', sizeof(insn->mnemonic));
907
2.05M
  memset(insn->op_str, '\0', sizeof(insn->op_str));
908
2.05M
  SStream_extract_mnem_opstr(OS, insn->mnemonic, sizeof(insn->mnemonic),
909
2.05M
           insn->op_str, sizeof(insn->op_str));
910
11.8M
  for (sp = insn->mnemonic; *sp; sp++) {
911
9.75M
    if (*sp == '|') // lock|rep prefix for x86
912
53.4k
      *sp = ' ';
913
9.75M
  }
914
915
  // we might have customized mnemonic
916
2.05M
  if (handle->mnem_list) {
917
0
    struct insn_mnem *tmp = handle->mnem_list;
918
0
    while (tmp) {
919
0
      if (tmp->insn.id == insn->id) {
920
0
        char str[CS_MNEMONIC_SIZE] = { 0 };
921
922
0
        if (!str_replace(str, insn->mnemonic,
923
0
             cs_insn_name((csh)handle,
924
0
                    insn->id),
925
0
             tmp->insn.mnemonic)) {
926
          // copy result to mnemonic
927
0
          CS_ASSERT_RET(sizeof(insn->mnemonic) ==
928
0
                  sizeof(str));
929
0
          (void)memcpy(insn->mnemonic, str,
930
0
                 sizeof(insn->mnemonic));
931
0
          insn->mnemonic[sizeof(insn->mnemonic) -
932
0
                   1] = '\0';
933
0
        }
934
935
0
        break;
936
0
      }
937
0
      tmp = tmp->next;
938
0
    }
939
0
  }
940
2.05M
#endif
941
2.05M
}
942
943
// how many bytes will we skip when encountering data (CS_OPT_SKIPDATA)?
944
// this very much depends on instruction alignment requirement of each arch.
945
static uint8_t skipdata_size(cs_struct *handle)
946
0
{
947
0
  switch (handle->arch) {
948
0
  default:
949
    // should never reach
950
0
    return (uint8_t)-1;
951
0
  case CS_ARCH_ARM:
952
    // skip 2 bytes on Thumb mode.
953
0
    if (handle->mode & CS_MODE_THUMB)
954
0
      return 2;
955
    // otherwise, skip 4 bytes
956
0
    return 4;
957
0
  case CS_ARCH_AARCH64:
958
0
  case CS_ARCH_MIPS:
959
0
  case CS_ARCH_PPC:
960
0
  case CS_ARCH_SPARC:
961
    // skip 4 bytes
962
0
    return 4;
963
0
  case CS_ARCH_SYSTEMZ:
964
    // SystemZ instruction's length can be 2, 4 or 6 bytes,
965
    // so we just skip 2 bytes
966
0
    return 2;
967
0
  case CS_ARCH_X86:
968
    // X86 has no restriction on instruction alignment
969
0
    return 1;
970
0
  case CS_ARCH_XCORE:
971
    // XCore instruction's length can be 2 or 4 bytes,
972
    // so we just skip 2 bytes
973
0
    return 2;
974
0
  case CS_ARCH_M68K:
975
    // M68K has 2 bytes instruction alignment but contain multibyte instruction so we skip 2 bytes
976
0
    return 2;
977
0
  case CS_ARCH_TMS320C64X:
978
    // TMS320C64x alignment is 4.
979
0
    return 4;
980
0
  case CS_ARCH_M680X:
981
    // M680X alignment is 1.
982
0
    return 1;
983
0
  case CS_ARCH_EVM:
984
    // EVM alignment is 1.
985
0
    return 1;
986
0
  case CS_ARCH_WASM:
987
    //WASM alignment is 1
988
0
    return 1;
989
0
  case CS_ARCH_MOS65XX:
990
    // MOS65XX alignment is 1.
991
0
    return 1;
992
0
  case CS_ARCH_BPF:
993
    // both classic and extended BPF have alignment 8.
994
0
    return 8;
995
0
  case CS_ARCH_RISCV:
996
    // special compress mode
997
0
    if (handle->mode & CS_MODE_RISCVC)
998
0
      return 2;
999
0
    return 4;
1000
0
  case CS_ARCH_SH:
1001
0
    return 2;
1002
0
  case CS_ARCH_TRICORE:
1003
    // TriCore instruction's length can be 2 or 4 bytes,
1004
    // so we just skip 2 bytes
1005
0
    return 2;
1006
0
  case CS_ARCH_ALPHA:
1007
    // Alpha alignment is 4.
1008
0
    return 4;
1009
0
  case CS_ARCH_HPPA:
1010
    // Hppa alignment is 4.
1011
0
    return 4;
1012
0
  case CS_ARCH_LOONGARCH:
1013
    // LoongArch alignment is 4.
1014
0
    return 4;
1015
0
  case CS_ARCH_ARC:
1016
    // ARC instruction's length can be 2, 4, 6 or 8 bytes,
1017
    // therefore, skip 2 bytes
1018
0
    return 2;
1019
0
  }
1020
0
}
1021
1022
CAPSTONE_EXPORT
1023
cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
1024
49.7k
{
1025
49.7k
  struct cs_struct *handle;
1026
49.7k
  cs_opt_mnem *opt;
1027
1028
  // cs_option() can be called with NULL handle just for CS_OPT_MEM
1029
  // This is supposed to be executed before all other APIs (even cs_open())
1030
49.7k
  if (type == CS_OPT_MEM) {
1031
0
    cs_opt_mem *mem = (cs_opt_mem *)value;
1032
1033
0
    cs_mem_malloc = mem->malloc;
1034
0
    cs_mem_calloc = mem->calloc;
1035
0
    cs_mem_realloc = mem->realloc;
1036
0
    cs_mem_free = mem->free;
1037
0
    cs_vsnprintf = mem->vsnprintf;
1038
1039
0
    return CS_ERR_OK;
1040
0
  }
1041
1042
49.7k
  handle = (struct cs_struct *)(uintptr_t)ud;
1043
49.7k
  if (!handle)
1044
0
    return CS_ERR_CSH;
1045
1046
49.7k
  switch (type) {
1047
10.4k
  default:
1048
10.4k
    break;
1049
1050
10.4k
  case CS_OPT_UNSIGNED:
1051
0
    handle->imm_unsigned = (cs_opt_value)value;
1052
0
    return CS_ERR_OK;
1053
1054
39.3k
  case CS_OPT_DETAIL:
1055
39.3k
    handle->detail_opt |= (cs_opt_value)value;
1056
39.3k
    return CS_ERR_OK;
1057
1058
0
  case CS_OPT_SKIPDATA:
1059
0
    handle->skipdata = (value == CS_OPT_ON);
1060
0
    if (handle->skipdata) {
1061
0
      if (handle->skipdata_size == 0) {
1062
        // set the default skipdata size
1063
0
        handle->skipdata_size = skipdata_size(handle);
1064
0
      }
1065
0
    }
1066
0
    return CS_ERR_OK;
1067
1068
0
  case CS_OPT_SKIPDATA_SETUP:
1069
0
    if (value) {
1070
0
      handle->skipdata_setup = *((cs_opt_skipdata *)value);
1071
0
      if (handle->skipdata_setup.mnemonic == NULL) {
1072
0
        handle->skipdata_setup.mnemonic = SKIPDATA_MNEM;
1073
0
      }
1074
0
    }
1075
0
    return CS_ERR_OK;
1076
1077
0
  case CS_OPT_MNEMONIC:
1078
0
    opt = (cs_opt_mnem *)value;
1079
0
    if (opt->id) {
1080
0
      if (opt->mnemonic) {
1081
0
        struct insn_mnem *tmp;
1082
1083
        // add new instruction, or replace existing instruction
1084
        // 1. find if we already had this insn in the linked list
1085
0
        tmp = handle->mnem_list;
1086
0
        while (tmp) {
1087
0
          if (tmp->insn.id == opt->id) {
1088
            // found this instruction, so replace its mnemonic
1089
0
            (void)strncpy(
1090
0
              tmp->insn.mnemonic,
1091
0
              opt->mnemonic,
1092
0
              sizeof(tmp->insn
1093
0
                       .mnemonic) -
1094
0
                1);
1095
0
            tmp->insn.mnemonic
1096
0
              [sizeof(tmp->insn.mnemonic) -
1097
0
               1] = '\0';
1098
0
            break;
1099
0
          }
1100
0
          tmp = tmp->next;
1101
0
        }
1102
1103
        // 2. add this instruction if we have not had it yet
1104
0
        if (!tmp) {
1105
0
          tmp = cs_mem_malloc(sizeof(*tmp));
1106
0
          tmp->insn.id = opt->id;
1107
0
          (void)strncpy(
1108
0
            tmp->insn.mnemonic,
1109
0
            opt->mnemonic,
1110
0
            sizeof(tmp->insn.mnemonic) - 1);
1111
0
          tmp->insn.mnemonic
1112
0
            [sizeof(tmp->insn.mnemonic) - 1] =
1113
0
            '\0';
1114
          // this new instruction is heading the list
1115
0
          tmp->next = handle->mnem_list;
1116
0
          handle->mnem_list = tmp;
1117
0
        }
1118
0
        return CS_ERR_OK;
1119
0
      } else {
1120
0
        struct insn_mnem *prev, *tmp;
1121
1122
        // we want to delete an existing instruction
1123
        // iterate the list to find the instruction to remove it
1124
0
        tmp = handle->mnem_list;
1125
0
        prev = tmp;
1126
0
        while (tmp) {
1127
0
          if (tmp->insn.id == opt->id) {
1128
            // delete this instruction
1129
0
            if (tmp == prev) {
1130
              // head of the list
1131
0
              handle->mnem_list =
1132
0
                tmp->next;
1133
0
            } else {
1134
0
              prev->next = tmp->next;
1135
0
            }
1136
0
            cs_mem_free(tmp);
1137
0
            break;
1138
0
          }
1139
0
          prev = tmp;
1140
0
          tmp = tmp->next;
1141
0
        }
1142
0
      }
1143
0
    }
1144
0
    return CS_ERR_OK;
1145
1146
0
  case CS_OPT_MODE:
1147
    // verify if requested mode is valid
1148
0
    if (value &
1149
0
        arch_configs[handle->arch].arch_disallowed_mode_mask) {
1150
0
      return CS_ERR_OPTION;
1151
0
    }
1152
0
    break;
1153
0
  case CS_OPT_ONLY_OFFSET_BRANCH:
1154
0
    handle->PrintBranchImmAsAddress = value == CS_OPT_ON ? false :
1155
0
                       true;
1156
0
    return CS_ERR_OK;
1157
49.7k
  }
1158
1159
10.4k
  if (!arch_configs[handle->arch].arch_option)
1160
0
    return CS_ERR_ARCH;
1161
1162
10.4k
  return arch_configs[handle->arch].arch_option(handle, type, value);
1163
10.4k
}
1164
1165
// generate @op_str for data instruction of SKIPDATA
1166
#ifndef CAPSTONE_DIET
1167
static void skipdata_opstr(char *opstr, const uint8_t *buffer, size_t size)
1168
0
{
1169
0
  char *p = opstr;
1170
0
  int len;
1171
0
  size_t i;
1172
0
  size_t available = sizeof(((cs_insn *)NULL)->op_str);
1173
1174
0
  if (!size) {
1175
0
    opstr[0] = '\0';
1176
0
    return;
1177
0
  }
1178
1179
0
  len = cs_snprintf(p, available, "0x%02x", buffer[0]);
1180
0
  p += len;
1181
0
  available -= len;
1182
1183
0
  for (i = 1; i < size; i++) {
1184
0
    len = cs_snprintf(p, available, ", 0x%02x", buffer[i]);
1185
0
    if (len < 0) {
1186
0
      break;
1187
0
    }
1188
0
    if ((size_t)len > available - 1) {
1189
0
      break;
1190
0
    }
1191
0
    p += len;
1192
0
    available -= len;
1193
0
  }
1194
0
}
1195
#endif
1196
1197
// dynamically allocate memory to contain disasm insn
1198
// NOTE: caller must free() the allocated memory itself to avoid memory leaking
1199
CAPSTONE_EXPORT
1200
size_t CAPSTONE_API cs_disasm(csh ud, const uint8_t *buffer, size_t size,
1201
            uint64_t offset, size_t count, cs_insn **insn)
1202
39.3k
{
1203
39.3k
  struct cs_struct *handle;
1204
39.3k
  MCInst mci;
1205
39.3k
  uint16_t insn_size;
1206
39.3k
  size_t c = 0, i;
1207
39.3k
  unsigned int f = 0; // index of the next instruction in the cache
1208
39.3k
  cs_insn *insn_cache; // cache contains disassembled instructions
1209
39.3k
  void *total = NULL;
1210
39.3k
  size_t total_size =
1211
39.3k
    0; // total size of output buffer containing all insns
1212
39.3k
  bool r;
1213
39.3k
  void *tmp;
1214
39.3k
  size_t skipdata_bytes;
1215
39.3k
  uint64_t offset_org; // save all the original info of the buffer
1216
39.3k
  size_t size_org;
1217
39.3k
  const uint8_t *buffer_org;
1218
39.3k
  unsigned int cache_size = INSN_CACHE_SIZE;
1219
39.3k
  size_t next_offset;
1220
1221
39.3k
  handle = (struct cs_struct *)(uintptr_t)ud;
1222
39.3k
  if (!handle) {
1223
    // FIXME: how to handle this case:
1224
    // handle->errnum = CS_ERR_HANDLE;
1225
0
    return 0;
1226
0
  }
1227
1228
39.3k
  handle->errnum = CS_ERR_OK;
1229
1230
39.3k
#ifdef CAPSTONE_USE_SYS_DYN_MEM
1231
39.3k
  if (count > 0 && count <= INSN_CACHE_SIZE)
1232
0
    cache_size = (unsigned int)count;
1233
39.3k
#endif
1234
1235
  // save the original offset for SKIPDATA
1236
39.3k
  buffer_org = buffer;
1237
39.3k
  offset_org = offset;
1238
39.3k
  size_org = size;
1239
1240
39.3k
  total_size = sizeof(cs_insn) * cache_size;
1241
39.3k
  total = cs_mem_calloc(sizeof(cs_insn), cache_size);
1242
39.3k
  if (total == NULL) {
1243
    // insufficient memory
1244
0
    handle->errnum = CS_ERR_MEM;
1245
0
    return 0;
1246
0
  }
1247
1248
39.3k
  insn_cache = total;
1249
1250
2.09M
  while (size > 0) {
1251
2.07M
    MCInst_Init(&mci, handle->arch);
1252
2.07M
    mci.csh = handle;
1253
1254
    // relative branches need to know the address & size of current insn
1255
2.07M
    mci.address = offset;
1256
1257
2.07M
    if (handle->detail_opt) {
1258
      // allocate memory for @detail pointer
1259
2.07M
      insn_cache->detail =
1260
2.07M
        cs_mem_calloc(1, sizeof(cs_detail));
1261
2.07M
    } else {
1262
0
      insn_cache->detail = NULL;
1263
0
    }
1264
1265
    // save all the information for non-detailed mode
1266
2.07M
    mci.flat_insn = insn_cache;
1267
2.07M
    mci.flat_insn->address = offset;
1268
#ifdef CAPSTONE_DIET
1269
    // zero out mnemonic & op_str
1270
    mci.flat_insn->mnemonic[0] = '\0';
1271
    mci.flat_insn->op_str[0] = '\0';
1272
#endif
1273
1274
2.07M
    r = handle->disasm(ud, buffer, size, &mci, &insn_size, offset,
1275
2.07M
           handle->getinsn_info);
1276
2.07M
    if (r) {
1277
2.05M
      SStream ss;
1278
2.05M
      SStream_Init(&ss);
1279
1280
2.05M
      mci.flat_insn->size = insn_size;
1281
1282
      // map internal instruction opcode to public insn ID
1283
1284
2.05M
      handle->insn_id(handle, insn_cache, mci.Opcode);
1285
1286
2.05M
      SStream_opt_unum(&ss, handle->imm_unsigned);
1287
2.05M
      handle->printer(&mci, &ss, handle->printer_info);
1288
2.05M
      fill_insn(handle, insn_cache, &ss, &mci,
1289
2.05M
          handle->post_printer, buffer);
1290
1291
      // adjust for pseudo opcode (X86)
1292
2.05M
      if (handle->arch == CS_ARCH_X86 &&
1293
2.05M
          insn_cache->id != X86_INS_VCMP)
1294
464k
        insn_cache->id += mci.popcode_adjust;
1295
1296
2.05M
      next_offset = insn_size;
1297
2.05M
    } else {
1298
      // encounter a broken instruction
1299
1300
      // free memory of @detail pointer
1301
19.9k
      if (handle->detail_opt) {
1302
19.9k
        cs_mem_free(insn_cache->detail);
1303
19.9k
      }
1304
1305
      // if there is no request to skip data, or remaining data is too small,
1306
      // then bail out
1307
19.9k
      if (!handle->skipdata || handle->skipdata_size > size)
1308
19.9k
        break;
1309
1310
0
      if (handle->skipdata_setup.callback) {
1311
0
        skipdata_bytes = handle->skipdata_setup.callback(
1312
0
          buffer_org, size_org,
1313
0
          (size_t)(offset - offset_org),
1314
0
          handle->skipdata_setup.user_data);
1315
0
        if (skipdata_bytes > size)
1316
          // remaining data is not enough
1317
0
          break;
1318
1319
0
        if (!skipdata_bytes)
1320
          // user requested not to skip data, so bail out
1321
0
          break;
1322
0
      } else
1323
0
        skipdata_bytes = handle->skipdata_size;
1324
1325
      // we have to skip some amount of data, depending on arch & mode
1326
0
      insn_cache->id =
1327
0
        0; // invalid ID for this "data" instruction
1328
0
      insn_cache->address = offset;
1329
0
      insn_cache->size = (uint16_t)skipdata_bytes;
1330
0
      memcpy(insn_cache->bytes, buffer, skipdata_bytes);
1331
#ifdef CAPSTONE_DIET
1332
      insn_cache->mnemonic[0] = '\0';
1333
      insn_cache->op_str[0] = '\0';
1334
#else
1335
0
      strncpy(insn_cache->mnemonic,
1336
0
        handle->skipdata_setup.mnemonic,
1337
0
        sizeof(insn_cache->mnemonic) - 1);
1338
0
      skipdata_opstr(insn_cache->op_str, buffer,
1339
0
               skipdata_bytes);
1340
0
#endif
1341
0
      insn_cache->detail = NULL;
1342
1343
0
      next_offset = skipdata_bytes;
1344
0
    }
1345
1346
    // one more instruction entering the cache
1347
2.05M
    f++;
1348
1349
    // one more instruction disassembled
1350
2.05M
    c++;
1351
2.05M
    if (count > 0 && c == count)
1352
      // already got requested number of instructions
1353
0
      break;
1354
1355
2.05M
    if (f == cache_size) {
1356
      // full cache, so expand the cache to contain incoming insns
1357
20.8k
      cache_size = cache_size * 8 / 5; // * 1.6 ~ golden ratio
1358
20.8k
      total_size += (sizeof(cs_insn) * cache_size);
1359
20.8k
      tmp = cs_mem_realloc(total, total_size);
1360
20.8k
      if (tmp == NULL) { // insufficient memory
1361
0
        if (handle->detail_opt) {
1362
0
          insn_cache = (cs_insn *)total;
1363
0
          for (i = 0; i < c; i++, insn_cache++)
1364
0
            cs_mem_free(insn_cache->detail);
1365
0
        }
1366
1367
0
        cs_mem_free(total);
1368
0
        *insn = NULL;
1369
0
        handle->errnum = CS_ERR_MEM;
1370
0
        return 0;
1371
0
      }
1372
1373
20.8k
      total = tmp;
1374
      // continue to fill in the cache after the last instruction
1375
20.8k
      insn_cache = (cs_insn *)((char *)total +
1376
20.8k
             sizeof(cs_insn) * c);
1377
1378
      // reset f back to 0, so we fill in the cache from beginning
1379
20.8k
      f = 0;
1380
20.8k
    } else
1381
2.03M
      insn_cache++;
1382
1383
2.05M
    buffer += next_offset;
1384
2.05M
    size -= next_offset;
1385
2.05M
    offset += next_offset;
1386
2.05M
  }
1387
1388
39.3k
  if (!c) {
1389
    // we did not disassemble any instruction
1390
1.00k
    cs_mem_free(total);
1391
1.00k
    total = NULL;
1392
38.3k
  } else if (f != cache_size) {
1393
    // total did not fully use the last cache, so downsize it
1394
38.3k
    tmp = cs_mem_realloc(total,
1395
38.3k
             total_size - (cache_size - f) *
1396
38.3k
                sizeof(*insn_cache));
1397
38.3k
    if (tmp == NULL) { // insufficient memory
1398
      // free all detail pointers
1399
0
      if (handle->detail_opt) {
1400
0
        insn_cache = (cs_insn *)total;
1401
0
        for (i = 0; i < c; i++, insn_cache++)
1402
0
          cs_mem_free(insn_cache->detail);
1403
0
      }
1404
1405
0
      cs_mem_free(total);
1406
0
      *insn = NULL;
1407
1408
0
      handle->errnum = CS_ERR_MEM;
1409
0
      return 0;
1410
0
    }
1411
1412
38.3k
    total = tmp;
1413
38.3k
  }
1414
1415
39.3k
  *insn = total;
1416
1417
39.3k
  return c;
1418
39.3k
}
1419
1420
CAPSTONE_EXPORT
1421
void CAPSTONE_API cs_free(cs_insn *insn, size_t count)
1422
38.3k
{
1423
38.3k
  size_t i;
1424
1425
  // free all detail pointers
1426
2.09M
  for (i = 0; i < count; i++)
1427
2.05M
    cs_mem_free(insn[i].detail);
1428
1429
  // then free pointer to cs_insn array
1430
38.3k
  cs_mem_free(insn);
1431
38.3k
}
1432
1433
CAPSTONE_EXPORT
1434
cs_insn *CAPSTONE_API cs_malloc(csh ud)
1435
0
{
1436
0
  cs_insn *insn;
1437
0
  struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
1438
1439
0
  insn = cs_mem_malloc(sizeof(cs_insn));
1440
0
  if (!insn) {
1441
    // insufficient memory
1442
0
    handle->errnum = CS_ERR_MEM;
1443
0
    return NULL;
1444
0
  } else {
1445
0
    if (handle->detail_opt) {
1446
      // allocate memory for @detail pointer
1447
0
      insn->detail = cs_mem_malloc(sizeof(cs_detail));
1448
0
      if (insn->detail == NULL) { // insufficient memory
1449
0
        cs_mem_free(insn);
1450
0
        handle->errnum = CS_ERR_MEM;
1451
0
        return NULL;
1452
0
      }
1453
0
    } else
1454
0
      insn->detail = NULL;
1455
0
  }
1456
1457
0
  return insn;
1458
0
}
1459
1460
// iterator for instruction "single-stepping"
1461
CAPSTONE_EXPORT
1462
bool CAPSTONE_API cs_disasm_iter(csh ud, const uint8_t **code, size_t *size,
1463
         uint64_t *address, cs_insn *insn)
1464
0
{
1465
0
  struct cs_struct *handle;
1466
0
  uint16_t insn_size;
1467
0
  MCInst mci;
1468
0
  bool r;
1469
1470
0
  handle = (struct cs_struct *)(uintptr_t)ud;
1471
0
  if (!handle) {
1472
0
    return false;
1473
0
  }
1474
1475
0
  handle->errnum = CS_ERR_OK;
1476
1477
0
  MCInst_Init(&mci, handle->arch);
1478
0
  mci.csh = handle;
1479
1480
  // relative branches need to know the address & size of current insn
1481
0
  mci.address = *address;
1482
1483
  // save all the information for non-detailed mode
1484
0
  mci.flat_insn = insn;
1485
0
  mci.flat_insn->address = *address;
1486
#ifdef CAPSTONE_DIET
1487
  // zero out mnemonic & op_str
1488
  mci.flat_insn->mnemonic[0] = '\0';
1489
  mci.flat_insn->op_str[0] = '\0';
1490
#endif
1491
1492
0
  r = handle->disasm(ud, *code, *size, &mci, &insn_size, *address,
1493
0
         handle->getinsn_info);
1494
0
  if (r) {
1495
0
    SStream ss;
1496
0
    SStream_Init(&ss);
1497
1498
0
    mci.flat_insn->size = insn_size;
1499
1500
    // map internal instruction opcode to public insn ID
1501
0
    handle->insn_id(handle, insn, mci.Opcode);
1502
1503
0
    SStream_opt_unum(&ss, handle->imm_unsigned);
1504
0
    handle->printer(&mci, &ss, handle->printer_info);
1505
1506
0
    fill_insn(handle, insn, &ss, &mci, handle->post_printer, *code);
1507
1508
    // adjust for pseudo opcode (X86)
1509
0
    if (handle->arch == CS_ARCH_X86)
1510
0
      insn->id += mci.popcode_adjust;
1511
1512
0
    *code += insn_size;
1513
0
    *size -= insn_size;
1514
0
    *address += insn_size;
1515
0
  } else { // encounter a broken instruction
1516
0
    size_t skipdata_bytes;
1517
1518
    // if there is no request to skip data, or remaining data is too small,
1519
    // then bail out
1520
0
    if (!handle->skipdata || handle->skipdata_size > *size)
1521
0
      return false;
1522
1523
0
    if (handle->skipdata_setup.callback) {
1524
0
      skipdata_bytes = handle->skipdata_setup.callback(
1525
0
        *code, *size, 0,
1526
0
        handle->skipdata_setup.user_data);
1527
0
      if (skipdata_bytes > *size)
1528
        // remaining data is not enough
1529
0
        return false;
1530
1531
0
      if (!skipdata_bytes)
1532
        // user requested not to skip data, so bail out
1533
0
        return false;
1534
0
    } else
1535
0
      skipdata_bytes = handle->skipdata_size;
1536
1537
    // we have to skip some amount of data, depending on arch & mode
1538
0
    insn->id = 0; // invalid ID for this "data" instruction
1539
0
    insn->address = *address;
1540
0
    insn->size = (uint16_t)skipdata_bytes;
1541
#ifdef CAPSTONE_DIET
1542
    insn->mnemonic[0] = '\0';
1543
    insn->op_str[0] = '\0';
1544
#else
1545
0
    memcpy(insn->bytes, *code, skipdata_bytes);
1546
0
    strncpy(insn->mnemonic, handle->skipdata_setup.mnemonic,
1547
0
      sizeof(insn->mnemonic) - 1);
1548
0
    skipdata_opstr(insn->op_str, *code, skipdata_bytes);
1549
0
#endif
1550
1551
0
    *code += skipdata_bytes;
1552
0
    *size -= skipdata_bytes;
1553
0
    *address += skipdata_bytes;
1554
0
  }
1555
1556
0
  return true;
1557
0
}
1558
1559
// return friendly name of register in a string
1560
CAPSTONE_EXPORT
1561
const char *CAPSTONE_API cs_reg_name(csh ud, unsigned int reg)
1562
1.89M
{
1563
1.89M
  struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
1564
1565
1.89M
  if (!handle || handle->reg_name == NULL) {
1566
0
    return NULL;
1567
0
  }
1568
1569
1.89M
  return handle->reg_name(ud, reg);
1570
1.89M
}
1571
1572
CAPSTONE_EXPORT
1573
const char *CAPSTONE_API cs_insn_name(csh ud, unsigned int insn)
1574
2.05M
{
1575
2.05M
  struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
1576
1577
2.05M
  if (!handle || handle->insn_name == NULL) {
1578
0
    return NULL;
1579
0
  }
1580
1581
2.05M
  return handle->insn_name(ud, insn);
1582
2.05M
}
1583
1584
CAPSTONE_EXPORT
1585
const char *CAPSTONE_API cs_group_name(csh ud, unsigned int group)
1586
1.73M
{
1587
1.73M
  struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
1588
1589
1.73M
  if (!handle || handle->group_name == NULL) {
1590
0
    return NULL;
1591
0
  }
1592
1593
1.73M
  return handle->group_name(ud, group);
1594
1.73M
}
1595
1596
CAPSTONE_EXPORT
1597
bool CAPSTONE_API cs_insn_group(csh ud, const cs_insn *insn,
1598
        unsigned int group_id)
1599
0
{
1600
0
  struct cs_struct *handle;
1601
0
  if (!ud)
1602
0
    return false;
1603
1604
0
  handle = (struct cs_struct *)(uintptr_t)ud;
1605
1606
0
  if (!handle->detail_opt) {
1607
0
    handle->errnum = CS_ERR_DETAIL;
1608
0
    return false;
1609
0
  }
1610
1611
0
  if (!insn->id) {
1612
0
    handle->errnum = CS_ERR_SKIPDATA;
1613
0
    return false;
1614
0
  }
1615
1616
0
  if (!insn->detail) {
1617
0
    handle->errnum = CS_ERR_DETAIL;
1618
0
    return false;
1619
0
  }
1620
1621
0
  return arr_exist8(insn->detail->groups, insn->detail->groups_count,
1622
0
        group_id);
1623
0
}
1624
1625
CAPSTONE_EXPORT
1626
bool CAPSTONE_API cs_reg_read(csh ud, const cs_insn *insn, unsigned int reg_id)
1627
0
{
1628
0
  struct cs_struct *handle;
1629
0
  if (!ud)
1630
0
    return false;
1631
1632
0
  handle = (struct cs_struct *)(uintptr_t)ud;
1633
1634
0
  if (!handle->detail_opt) {
1635
0
    handle->errnum = CS_ERR_DETAIL;
1636
0
    return false;
1637
0
  }
1638
1639
0
  if (!insn->id) {
1640
0
    handle->errnum = CS_ERR_SKIPDATA;
1641
0
    return false;
1642
0
  }
1643
1644
0
  if (!insn->detail) {
1645
0
    handle->errnum = CS_ERR_DETAIL;
1646
0
    return false;
1647
0
  }
1648
1649
0
  return arr_exist(insn->detail->regs_read, insn->detail->regs_read_count,
1650
0
       reg_id);
1651
0
}
1652
1653
CAPSTONE_EXPORT
1654
bool CAPSTONE_API cs_reg_write(csh ud, const cs_insn *insn, unsigned int reg_id)
1655
0
{
1656
0
  struct cs_struct *handle;
1657
0
  if (!ud)
1658
0
    return false;
1659
1660
0
  handle = (struct cs_struct *)(uintptr_t)ud;
1661
1662
0
  if (!handle->detail_opt) {
1663
0
    handle->errnum = CS_ERR_DETAIL;
1664
0
    return false;
1665
0
  }
1666
1667
0
  if (!insn->id) {
1668
0
    handle->errnum = CS_ERR_SKIPDATA;
1669
0
    return false;
1670
0
  }
1671
1672
0
  if (!insn->detail) {
1673
0
    handle->errnum = CS_ERR_DETAIL;
1674
0
    return false;
1675
0
  }
1676
1677
0
  return arr_exist(insn->detail->regs_write,
1678
0
       insn->detail->regs_write_count, reg_id);
1679
0
}
1680
1681
CAPSTONE_EXPORT
1682
int CAPSTONE_API cs_op_count(csh ud, const cs_insn *insn, unsigned int op_type)
1683
0
{
1684
0
  struct cs_struct *handle;
1685
0
  unsigned int count = 0, i;
1686
0
  if (!ud)
1687
0
    return -1;
1688
1689
0
  handle = (struct cs_struct *)(uintptr_t)ud;
1690
1691
0
  if (!handle->detail_opt) {
1692
0
    handle->errnum = CS_ERR_DETAIL;
1693
0
    return -1;
1694
0
  }
1695
1696
0
  if (!insn->id) {
1697
0
    handle->errnum = CS_ERR_SKIPDATA;
1698
0
    return -1;
1699
0
  }
1700
1701
0
  if (!insn->detail) {
1702
0
    handle->errnum = CS_ERR_DETAIL;
1703
0
    return -1;
1704
0
  }
1705
1706
0
  handle->errnum = CS_ERR_OK;
1707
1708
0
  switch (handle->arch) {
1709
0
  default:
1710
0
    handle->errnum = CS_ERR_HANDLE;
1711
0
    return -1;
1712
0
  case CS_ARCH_ARM:
1713
0
    for (i = 0; i < insn->detail->arm.op_count; i++)
1714
0
      if (insn->detail->arm.operands[i].type ==
1715
0
          (arm_op_type)op_type)
1716
0
        count++;
1717
0
    break;
1718
0
  case CS_ARCH_AARCH64:
1719
0
    for (i = 0; i < insn->detail->aarch64.op_count; i++)
1720
0
      if (insn->detail->aarch64.operands[i].type ==
1721
0
          (aarch64_op_type)op_type)
1722
0
        count++;
1723
0
    break;
1724
0
  case CS_ARCH_X86:
1725
0
    for (i = 0; i < insn->detail->x86.op_count; i++)
1726
0
      if (insn->detail->x86.operands[i].type ==
1727
0
          (x86_op_type)op_type)
1728
0
        count++;
1729
0
    break;
1730
0
  case CS_ARCH_MIPS:
1731
0
    for (i = 0; i < insn->detail->mips.op_count; i++)
1732
0
      if (insn->detail->mips.operands[i].type ==
1733
0
          (mips_op_type)op_type)
1734
0
        count++;
1735
0
    break;
1736
0
  case CS_ARCH_PPC:
1737
0
    for (i = 0; i < insn->detail->ppc.op_count; i++)
1738
0
      if (insn->detail->ppc.operands[i].type ==
1739
0
          (ppc_op_type)op_type)
1740
0
        count++;
1741
0
    break;
1742
0
  case CS_ARCH_SPARC:
1743
0
    for (i = 0; i < insn->detail->sparc.op_count; i++)
1744
0
      if (insn->detail->sparc.operands[i].type ==
1745
0
          (sparc_op_type)op_type)
1746
0
        count++;
1747
0
    break;
1748
0
  case CS_ARCH_SYSTEMZ:
1749
0
    for (i = 0; i < insn->detail->systemz.op_count; i++)
1750
0
      if (insn->detail->systemz.operands[i].type ==
1751
0
          (systemz_op_type)op_type)
1752
0
        count++;
1753
0
    break;
1754
0
  case CS_ARCH_XCORE:
1755
0
    for (i = 0; i < insn->detail->xcore.op_count; i++)
1756
0
      if (insn->detail->xcore.operands[i].type ==
1757
0
          (xcore_op_type)op_type)
1758
0
        count++;
1759
0
    break;
1760
0
  case CS_ARCH_M68K:
1761
0
    for (i = 0; i < insn->detail->m68k.op_count; i++)
1762
0
      if (insn->detail->m68k.operands[i].type ==
1763
0
          (m68k_op_type)op_type)
1764
0
        count++;
1765
0
    break;
1766
0
  case CS_ARCH_TMS320C64X:
1767
0
    for (i = 0; i < insn->detail->tms320c64x.op_count; i++)
1768
0
      if (insn->detail->tms320c64x.operands[i].type ==
1769
0
          (tms320c64x_op_type)op_type)
1770
0
        count++;
1771
0
    break;
1772
0
  case CS_ARCH_M680X:
1773
0
    for (i = 0; i < insn->detail->m680x.op_count; i++)
1774
0
      if (insn->detail->m680x.operands[i].type ==
1775
0
          (m680x_op_type)op_type)
1776
0
        count++;
1777
0
    break;
1778
0
  case CS_ARCH_EVM:
1779
0
    break;
1780
0
  case CS_ARCH_MOS65XX:
1781
0
    for (i = 0; i < insn->detail->mos65xx.op_count; i++)
1782
0
      if (insn->detail->mos65xx.operands[i].type ==
1783
0
          (mos65xx_op_type)op_type)
1784
0
        count++;
1785
0
    break;
1786
0
  case CS_ARCH_WASM:
1787
0
    for (i = 0; i < insn->detail->wasm.op_count; i++)
1788
0
      if (insn->detail->wasm.operands[i].type ==
1789
0
          (wasm_op_type)op_type)
1790
0
        count++;
1791
0
    break;
1792
0
  case CS_ARCH_BPF:
1793
0
    for (i = 0; i < insn->detail->bpf.op_count; i++)
1794
0
      if (insn->detail->bpf.operands[i].type ==
1795
0
          (bpf_op_type)op_type)
1796
0
        count++;
1797
0
    break;
1798
0
  case CS_ARCH_RISCV:
1799
0
    for (i = 0; i < insn->detail->riscv.op_count; i++)
1800
0
      if (insn->detail->riscv.operands[i].type ==
1801
0
          (riscv_op_type)op_type)
1802
0
        count++;
1803
0
    break;
1804
0
  case CS_ARCH_TRICORE:
1805
0
    for (i = 0; i < insn->detail->tricore.op_count; i++)
1806
0
      if (insn->detail->tricore.operands[i].type ==
1807
0
          (tricore_op_type)op_type)
1808
0
        count++;
1809
0
    break;
1810
0
  case CS_ARCH_ALPHA:
1811
0
    for (i = 0; i < insn->detail->alpha.op_count; i++)
1812
0
      if (insn->detail->alpha.operands[i].type ==
1813
0
          (alpha_op_type)op_type)
1814
0
        count++;
1815
0
    break;
1816
0
  case CS_ARCH_HPPA:
1817
0
    for (i = 0; i < insn->detail->hppa.op_count; i++)
1818
0
      if (insn->detail->hppa.operands[i].type ==
1819
0
          (hppa_op_type)op_type)
1820
0
        count++;
1821
0
    break;
1822
0
  case CS_ARCH_LOONGARCH:
1823
0
    for (i = 0; i < insn->detail->loongarch.op_count; i++)
1824
0
      if (insn->detail->loongarch.operands[i].type ==
1825
0
          (loongarch_op_type)op_type)
1826
0
        count++;
1827
0
    break;
1828
0
  case CS_ARCH_ARC:
1829
0
    for (i = 0; i < insn->detail->arc.op_count; i++)
1830
0
      if (insn->detail->arc.operands[i].type ==
1831
0
          (arc_op_type)op_type)
1832
0
        count++;
1833
0
    break;
1834
0
  }
1835
1836
0
  return count;
1837
0
}
1838
1839
CAPSTONE_EXPORT
1840
int CAPSTONE_API cs_op_index(csh ud, const cs_insn *insn, unsigned int op_type,
1841
           unsigned int post)
1842
0
{
1843
0
  struct cs_struct *handle;
1844
0
  unsigned int count = 0, i;
1845
0
  if (!ud)
1846
0
    return -1;
1847
1848
0
  handle = (struct cs_struct *)(uintptr_t)ud;
1849
1850
0
  if (!handle->detail_opt) {
1851
0
    handle->errnum = CS_ERR_DETAIL;
1852
0
    return -1;
1853
0
  }
1854
1855
0
  if (!insn->id) {
1856
0
    handle->errnum = CS_ERR_SKIPDATA;
1857
0
    return -1;
1858
0
  }
1859
1860
0
  if (!insn->detail) {
1861
0
    handle->errnum = CS_ERR_DETAIL;
1862
0
    return -1;
1863
0
  }
1864
1865
0
  handle->errnum = CS_ERR_OK;
1866
1867
0
  switch (handle->arch) {
1868
0
  default:
1869
0
    handle->errnum = CS_ERR_HANDLE;
1870
0
    return -1;
1871
0
  case CS_ARCH_ARM:
1872
0
    for (i = 0; i < insn->detail->arm.op_count; i++) {
1873
0
      if (insn->detail->arm.operands[i].type ==
1874
0
          (arm_op_type)op_type)
1875
0
        count++;
1876
0
      if (count == post)
1877
0
        return i;
1878
0
    }
1879
0
    break;
1880
0
  case CS_ARCH_AARCH64:
1881
0
    for (i = 0; i < insn->detail->aarch64.op_count; i++) {
1882
0
      if (insn->detail->aarch64.operands[i].type ==
1883
0
          (aarch64_op_type)op_type)
1884
0
        count++;
1885
0
      if (count == post)
1886
0
        return i;
1887
0
    }
1888
0
    break;
1889
0
  case CS_ARCH_X86:
1890
0
    for (i = 0; i < insn->detail->x86.op_count; i++) {
1891
0
      if (insn->detail->x86.operands[i].type ==
1892
0
          (x86_op_type)op_type)
1893
0
        count++;
1894
0
      if (count == post)
1895
0
        return i;
1896
0
    }
1897
0
    break;
1898
0
  case CS_ARCH_MIPS:
1899
0
    for (i = 0; i < insn->detail->mips.op_count; i++) {
1900
0
      if (insn->detail->mips.operands[i].type ==
1901
0
          (mips_op_type)op_type)
1902
0
        count++;
1903
0
      if (count == post)
1904
0
        return i;
1905
0
    }
1906
0
    break;
1907
0
  case CS_ARCH_PPC:
1908
0
    for (i = 0; i < insn->detail->ppc.op_count; i++) {
1909
0
      if (insn->detail->ppc.operands[i].type ==
1910
0
          (ppc_op_type)op_type)
1911
0
        count++;
1912
0
      if (count == post)
1913
0
        return i;
1914
0
    }
1915
0
    break;
1916
0
  case CS_ARCH_SPARC:
1917
0
    for (i = 0; i < insn->detail->sparc.op_count; i++) {
1918
0
      if (insn->detail->sparc.operands[i].type ==
1919
0
          (sparc_op_type)op_type)
1920
0
        count++;
1921
0
      if (count == post)
1922
0
        return i;
1923
0
    }
1924
0
    break;
1925
0
  case CS_ARCH_SYSTEMZ:
1926
0
    for (i = 0; i < insn->detail->systemz.op_count; i++) {
1927
0
      if (insn->detail->systemz.operands[i].type ==
1928
0
          (systemz_op_type)op_type)
1929
0
        count++;
1930
0
      if (count == post)
1931
0
        return i;
1932
0
    }
1933
0
    break;
1934
0
  case CS_ARCH_XCORE:
1935
0
    for (i = 0; i < insn->detail->xcore.op_count; i++) {
1936
0
      if (insn->detail->xcore.operands[i].type ==
1937
0
          (xcore_op_type)op_type)
1938
0
        count++;
1939
0
      if (count == post)
1940
0
        return i;
1941
0
    }
1942
0
    break;
1943
0
  case CS_ARCH_TRICORE:
1944
0
    for (i = 0; i < insn->detail->tricore.op_count; i++) {
1945
0
      if (insn->detail->tricore.operands[i].type ==
1946
0
          (tricore_op_type)op_type)
1947
0
        count++;
1948
0
      if (count == post)
1949
0
        return i;
1950
0
    }
1951
0
    break;
1952
0
  case CS_ARCH_M68K:
1953
0
    for (i = 0; i < insn->detail->m68k.op_count; i++) {
1954
0
      if (insn->detail->m68k.operands[i].type ==
1955
0
          (m68k_op_type)op_type)
1956
0
        count++;
1957
0
      if (count == post)
1958
0
        return i;
1959
0
    }
1960
0
    break;
1961
0
  case CS_ARCH_TMS320C64X:
1962
0
    for (i = 0; i < insn->detail->tms320c64x.op_count; i++) {
1963
0
      if (insn->detail->tms320c64x.operands[i].type ==
1964
0
          (tms320c64x_op_type)op_type)
1965
0
        count++;
1966
0
      if (count == post)
1967
0
        return i;
1968
0
    }
1969
0
    break;
1970
0
  case CS_ARCH_M680X:
1971
0
    for (i = 0; i < insn->detail->m680x.op_count; i++) {
1972
0
      if (insn->detail->m680x.operands[i].type ==
1973
0
          (m680x_op_type)op_type)
1974
0
        count++;
1975
0
      if (count == post)
1976
0
        return i;
1977
0
    }
1978
0
    break;
1979
0
  case CS_ARCH_EVM:
1980
#if 0
1981
      for (i = 0; i < insn->detail->evm.op_count; i++) {
1982
        if (insn->detail->evm.operands[i].type == (evm_op_type)op_type)
1983
          count++;
1984
        if (count == post)
1985
          return i;
1986
      }
1987
#endif
1988
0
    break;
1989
0
  case CS_ARCH_MOS65XX:
1990
0
    for (i = 0; i < insn->detail->mos65xx.op_count; i++) {
1991
0
      if (insn->detail->mos65xx.operands[i].type ==
1992
0
          (mos65xx_op_type)op_type)
1993
0
        count++;
1994
0
      if (count == post)
1995
0
        return i;
1996
0
    }
1997
0
    break;
1998
0
  case CS_ARCH_WASM:
1999
0
    for (i = 0; i < insn->detail->wasm.op_count; i++) {
2000
0
      if (insn->detail->wasm.operands[i].type ==
2001
0
          (wasm_op_type)op_type)
2002
0
        count++;
2003
0
      if (count == post)
2004
0
        return i;
2005
0
    }
2006
0
    break;
2007
0
  case CS_ARCH_BPF:
2008
0
    for (i = 0; i < insn->detail->bpf.op_count; i++) {
2009
0
      if (insn->detail->bpf.operands[i].type ==
2010
0
          (bpf_op_type)op_type)
2011
0
        count++;
2012
0
      if (count == post)
2013
0
        return i;
2014
0
    }
2015
0
    break;
2016
0
  case CS_ARCH_RISCV:
2017
0
    for (i = 0; i < insn->detail->riscv.op_count; i++) {
2018
0
      if (insn->detail->riscv.operands[i].type ==
2019
0
          (riscv_op_type)op_type)
2020
0
        count++;
2021
0
      if (count == post)
2022
0
        return i;
2023
0
    }
2024
0
    break;
2025
0
  case CS_ARCH_SH:
2026
0
    for (i = 0; i < insn->detail->sh.op_count; i++) {
2027
0
      if (insn->detail->sh.operands[i].type ==
2028
0
          (sh_op_type)op_type)
2029
0
        count++;
2030
0
      if (count == post)
2031
0
        return i;
2032
0
    }
2033
0
    break;
2034
0
  case CS_ARCH_ALPHA:
2035
0
    for (i = 0; i < insn->detail->alpha.op_count; i++) {
2036
0
      if (insn->detail->alpha.operands[i].type ==
2037
0
          (alpha_op_type)op_type)
2038
0
        count++;
2039
0
      if (count == post)
2040
0
        return i;
2041
0
    }
2042
0
    break;
2043
0
  case CS_ARCH_HPPA:
2044
0
    for (i = 0; i < insn->detail->hppa.op_count; i++) {
2045
0
      if (insn->detail->hppa.operands[i].type ==
2046
0
          (hppa_op_type)op_type)
2047
0
        count++;
2048
0
      if (count == post)
2049
0
        return i;
2050
0
    }
2051
0
    break;
2052
0
  case CS_ARCH_LOONGARCH:
2053
0
    for (i = 0; i < insn->detail->loongarch.op_count; i++) {
2054
0
      if (insn->detail->loongarch.operands[i].type ==
2055
0
          (loongarch_op_type)op_type)
2056
0
        count++;
2057
0
      if (count == post)
2058
0
        return i;
2059
0
    }
2060
0
    break;
2061
0
  case CS_ARCH_ARC:
2062
0
    for (i = 0; i < insn->detail->arc.op_count; i++) {
2063
0
      if (insn->detail->arc.operands[i].type ==
2064
0
          (arc_op_type)op_type)
2065
0
        count++;
2066
0
      if (count == post)
2067
0
        return i;
2068
0
    }
2069
0
    break;
2070
0
  }
2071
2072
0
  return -1;
2073
0
}
2074
2075
CAPSTONE_EXPORT
2076
cs_err CAPSTONE_API cs_regs_access(csh ud, const cs_insn *insn,
2077
           cs_regs regs_read, uint8_t *regs_read_count,
2078
           cs_regs regs_write,
2079
           uint8_t *regs_write_count)
2080
0
{
2081
0
  struct cs_struct *handle;
2082
2083
0
  if (!ud)
2084
0
    return CS_ERR_CSH;
2085
2086
0
  handle = (struct cs_struct *)(uintptr_t)ud;
2087
2088
#ifdef CAPSTONE_DIET
2089
  // This API does not work in DIET mode
2090
  handle->errnum = CS_ERR_DIET;
2091
  return CS_ERR_DIET;
2092
#else
2093
0
  if (!handle->detail_opt) {
2094
0
    handle->errnum = CS_ERR_DETAIL;
2095
0
    return CS_ERR_DETAIL;
2096
0
  }
2097
2098
0
  if (!insn->id) {
2099
0
    handle->errnum = CS_ERR_SKIPDATA;
2100
0
    return CS_ERR_SKIPDATA;
2101
0
  }
2102
2103
0
  if (!insn->detail) {
2104
0
    handle->errnum = CS_ERR_DETAIL;
2105
0
    return CS_ERR_DETAIL;
2106
0
  }
2107
2108
0
  if (handle->reg_access) {
2109
0
    handle->reg_access(insn, regs_read, regs_read_count, regs_write,
2110
0
           regs_write_count);
2111
0
  } else {
2112
    // this arch is unsupported yet
2113
0
    handle->errnum = CS_ERR_ARCH;
2114
0
    return CS_ERR_ARCH;
2115
0
  }
2116
2117
0
  return CS_ERR_OK;
2118
0
#endif
2119
0
}