Coverage Report

Created: 2024-09-08 06:22

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