Coverage Report

Created: 2024-08-21 06:24

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