Coverage Report

Created: 2025-07-01 07:03

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