Coverage Report

Created: 2025-07-18 06:56

/src/keystone/llvm/keystone/ks.cpp
Line
Count
Source (jump to first uncovered line)
1
/* Keystone Assembler Engine */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2016 */
3
4
#if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
5
#pragma warning(disable:4996)
6
#endif
7
#if defined(KEYSTONE_HAS_OSXKERNEL)
8
#include <libkern/libkern.h>
9
#else
10
#include <stdio.h>
11
#endif
12
13
#include "llvm/MC/MCObjectFileInfo.h"
14
#include "llvm/MC/MCCodeEmitter.h"
15
16
// FIXME: setup this with CMake
17
#define LLVM_ENABLE_ARCH_EVM
18
#include "EVMMapping.h"
19
20
// DEBUG
21
//#include <iostream>
22
23
#include "ks_priv.h"
24
25
using namespace llvm_ks;
26
27
28
KEYSTONE_EXPORT
29
unsigned int ks_version(unsigned int *major, unsigned int *minor)
30
0
{
31
0
    if (major != NULL && minor != NULL) {
32
0
        *major = KS_API_MAJOR;
33
0
        *minor = KS_API_MINOR;
34
0
    }
35
36
0
    return (KS_API_MAJOR << 8) + KS_API_MINOR;
37
0
}
38
39
40
KEYSTONE_EXPORT
41
ks_err ks_errno(ks_engine *ks)
42
2.52k
{
43
2.52k
    return (ks_err)ks->errnum;
44
2.52k
}
45
46
47
KEYSTONE_EXPORT
48
const char *ks_strerror(ks_err code)
49
0
{
50
0
    switch(code) {
51
0
        default:
52
0
            return "Unknown error";  // FIXME
53
0
        case KS_ERR_OK:
54
0
            return "OK (KS_ERR_OK)";
55
0
        case KS_ERR_NOMEM:
56
0
            return "No memory available or memory not present (KS_ERR_NOMEM)";
57
0
        case KS_ERR_ARCH:
58
0
            return "Invalid/unsupported architecture (KS_ERR_ARCH)";
59
0
        case KS_ERR_HANDLE:
60
0
            return "Invalid handle (KS_ERR_HANDLE)";
61
0
        case KS_ERR_MODE:
62
0
            return "Invalid mode (KS_ERR_MODE)";
63
0
        case KS_ERR_VERSION:
64
0
            return "Different API version between core & binding (KS_ERR_VERSION)";
65
0
        case KS_ERR_OPT_INVALID:
66
0
            return "Invalid option (KS_ERR_OPT_INVALID)";
67
0
        case KS_ERR_ASM_INVALIDOPERAND:
68
0
            return "Invalid operand (KS_ERR_ASM_INVALIDOPERAND)";
69
0
        case KS_ERR_ASM_MISSINGFEATURE:
70
0
            return "Missing CPU feature (KS_ERR_ASM_MISSINGFEATURE)";
71
0
        case KS_ERR_ASM_MNEMONICFAIL:
72
0
            return "Invalid mnemonic (KS_ERR_ASM_MNEMONICFAIL)";
73
74
        // generic input assembly errors - parser specific
75
0
        case KS_ERR_ASM_EXPR_TOKEN:    // unknown token in expression
76
0
            return "Unknown token in expression (KS_ERR_ASM_EXPR_TOKEN)";
77
0
        case KS_ERR_ASM_DIRECTIVE_VALUE_RANGE:   // literal value out of range for directive
78
0
            return "Literal value out of range for directive (KS_ERR_ASM_DIRECTIVE_VALUE_RANGE)";
79
0
        case KS_ERR_ASM_DIRECTIVE_ID:    // expected identifier in directive
80
0
            return "Expected identifier in directive (KS_ERR_ASM_DIRECTIVE_ID)";
81
0
        case KS_ERR_ASM_DIRECTIVE_TOKEN: // unexpected token in directive
82
0
            return "Unexpected token in directive (KS_ERR_ASM_DIRECTIVE_TOKEN)";
83
0
        case KS_ERR_ASM_DIRECTIVE_STR:   // expected string in directive
84
0
            return "Expected string in directive (KS_ERR_ASM_DIRECTIVE_STR)";
85
0
        case KS_ERR_ASM_DIRECTIVE_COMMA: // expected comma in directive
86
0
            return "Expected comma in directive (KS_ERR_ASM_DIRECTIVE_COMMA)";
87
        //case KS_ERR_ASM_DIRECTIVE_RELOC_NAME: // expected relocation name in directive
88
        //    return "Expected relocation name in directive (KS_ERR_ASM_DIRECTIVE_RELOC_NAME)";
89
        //case KS_ERR_ASM_DIRECTIVE_RELOC_TOKEN: // unexpected token in .reloc directive
90
        //    return "Unexpected token in .reloc directive (KS_ERR_ASM_DIRECTIVE_RELOC_TOKEN)";
91
0
        case KS_ERR_ASM_DIRECTIVE_FPOINT:    // invalid floating point in directive
92
0
            return "Invalid floating point in directive (KS_ERR_ASM_DIRECTIVE_FPOINT)";
93
0
        case KS_ERR_ASM_VARIANT_INVALID: // invalid variant
94
0
            return "Invalid variant (KS_ERR_ASM_VARIANT_INVALID)";
95
0
        case KS_ERR_ASM_DIRECTIVE_EQU:
96
0
            return "Invalid equal directive (KS_ERR_ASM_DIRECTIVE_EQU)";
97
0
        case KS_ERR_ASM_EXPR_BRACKET:    // brackets expression not supported on this target
98
0
            return "Brackets expression not supported (KS_ERR_ASM_EXPR_BRACKET)";
99
0
        case KS_ERR_ASM_SYMBOL_MODIFIER: // unexpected symbol modifier following '@'
100
0
            return "Unexpected symbol modifier following '@' (KS_ERR_ASM_SYMBOL_MODIFIER)";
101
0
        case KS_ERR_ASM_SYMBOL_REDEFINED:
102
0
            return "Invalid symbol redefined (KS_ERR_ASM_SYMBOL_REDEFINED)";
103
0
        case KS_ERR_ASM_SYMBOL_MISSING:
104
0
            return "Cannot find a symbol (KS_ERR_ASM_SYMBOL_MISSING)";
105
0
        case KS_ERR_ASM_RPAREN:          // expected ')' in parentheses expression
106
0
            return "Expected ')' (KS_ERR_ASM_RPAREN)";
107
0
        case KS_ERR_ASM_STAT_TOKEN:      // unexpected token at start of statement
108
0
            return "Unexpected token at start of statement (KS_ERR_ASM_STAT_TOKEN)";
109
0
        case KS_ERR_ASM_UNSUPPORTED:     // unsupported token yet
110
0
            return "Unsupported token yet (KS_ERR_ASM_UNSUPPORTED)";
111
0
        case KS_ERR_ASM_MACRO_TOKEN:     // unexpected token in macro instantiation
112
0
            return "Unexpected token in macro instantiation (KS_ERR_ASM_MACRO_TOKEN)";
113
0
        case KS_ERR_ASM_MACRO_PAREN:     // unbalanced parentheses in macro argument
114
0
            return "Unbalanced parentheses in macro argument (KS_ERR_ASM_MACRO_PAREN)";
115
0
        case KS_ERR_ASM_MACRO_EQU:       // expected '=' after formal parameter identifier
116
0
            return "Expected '=' after formal parameter identifier (KS_ERR_ASM_MACRO_EQU)";
117
0
        case KS_ERR_ASM_MACRO_ARGS:      // too many positional arguments
118
0
            return "Too many positional arguments (KS_ERR_ASM_MACRO_ARGS)";
119
0
        case KS_ERR_ASM_MACRO_LEVELS_EXCEED: // macros cannot be nested more than 20 levels deep
120
0
            return "Macros cannot be nested more than 20 levels deep (KS_ERR_ASM_MACRO_LEVELS_EXCEED)";
121
0
        case KS_ERR_ASM_MACRO_STR:         // invalid macro string
122
0
            return "Invalid macro string (KS_ERR_ASM_MACRO_STR)";
123
0
        case KS_ERR_ASM_MACRO_INVALID:         // invalid macro string
124
0
            return "Invalid macro (KS_ERR_ASM_MACRO_INVALID)";
125
0
        case KS_ERR_ASM_ESC_BACKSLASH:   // unexpected backslash at end of escaped string
126
0
            return "Unexpected backslash at end of escaped string (KS_ERR_ASM_ESC_BACKSLASH)";
127
0
        case KS_ERR_ASM_ESC_OCTAL:       // invalid octal escape sequence (out of range)
128
0
            return "Invalid octal escape sequence (KS_ERR_ASM_ESC_OCTAL)";
129
0
        case KS_ERR_ASM_ESC_SEQUENCE:         // invalid escape sequence (unrecognized character)
130
0
            return "Invalid escape sequence (KS_ERR_ASM_ESC_SEQUENCE)";
131
0
        case KS_ERR_ASM_ESC_STR:         // broken escape string
132
0
            return "Invalid escape string (KS_ERR_ASM_ESC_STR)";
133
0
        case KS_ERR_ASM_TOKEN_INVALID:   // invalid token from input assembly
134
0
            return "Invalid input token (KS_ERR_ASM_TOKEN_INVALID)";
135
0
        case KS_ERR_ASM_INSN_UNSUPPORTED:
136
0
            return "Instruction is unsupported in this mode (KS_ERR_ASM_INSN_UNSUPPORTED)";
137
0
        case KS_ERR_ASM_DIRECTIVE_UNKNOWN:
138
0
            return "Unknown directive (KS_ERR_ASM_DIRECTIVE_UNKNOWN)";
139
0
        case KS_ERR_ASM_FIXUP_INVALID:
140
0
            return "Invalid fixup (KS_ERR_ASM_FIXUP_INVALID)";
141
0
        case KS_ERR_ASM_LABEL_INVALID:
142
0
            return "Invalid label (KS_ERR_ASM_LABEL_INVALID)";
143
0
        case KS_ERR_ASM_FRAGMENT_INVALID:
144
0
            return "Invalid fragment (KS_ERR_ASM_FRAGMENT_INVALID)";
145
0
        case KS_ERR_ASM_DIRECTIVE_INVALID:
146
0
            return "Invalid directive (KS_ERR_ASM_DIRECTIVE_INVALID)";
147
0
    }
148
0
}
149
150
151
KEYSTONE_EXPORT
152
bool ks_arch_supported(ks_arch arch)
153
0
{
154
0
    switch (arch) {
155
0
#ifdef LLVM_ENABLE_ARCH_ARM
156
0
        case KS_ARCH_ARM:   return true;
157
0
#endif
158
0
#ifdef LLVM_ENABLE_ARCH_AArch64
159
0
        case KS_ARCH_ARM64: return true;
160
0
#endif
161
0
#ifdef LLVM_ENABLE_ARCH_Mips
162
0
        case KS_ARCH_MIPS:  return true;
163
0
#endif
164
0
#ifdef LLVM_ENABLE_ARCH_PowerPC
165
0
        case KS_ARCH_PPC:   return true;
166
0
#endif
167
0
#ifdef LLVM_ENABLE_ARCH_Sparc
168
0
        case KS_ARCH_SPARC: return true;
169
0
#endif
170
0
#ifdef LLVM_ENABLE_ARCH_X86
171
0
        case KS_ARCH_X86:   return true;
172
0
#endif
173
0
#ifdef LLVM_ENABLE_ARCH_Hexagon
174
0
        case KS_ARCH_HEXAGON:   return true;
175
0
#endif
176
0
#ifdef LLVM_ENABLE_ARCH_SystemZ
177
0
        case KS_ARCH_SYSTEMZ:   return true;
178
0
#endif
179
0
#ifdef LLVM_ENABLE_ARCH_EVM
180
0
        case KS_ARCH_EVM:   return true;
181
0
#endif
182
0
#ifdef LLVM_ENABLE_ARCH_RISCV
183
0
        case KS_ARCH_RISCV: return true;
184
0
#endif
185
        /* Invalid or disabled arch */
186
0
        default:            return false;
187
0
    }
188
0
}
189
190
191
static const Target *GetTarget(std::string TripleName)
192
4.53k
{
193
    // Figure out the target triple.
194
4.53k
    Triple TheTriple(TripleName);
195
196
    // Get the target specific parser.
197
4.53k
    std::string Error;
198
199
4.53k
    return TargetRegistry::lookupTarget("", TheTriple, Error);
200
4.53k
}
201
202
203
static ks_err InitKs(int arch, ks_engine *ks, std::string TripleName)
204
4.53k
{
205
4.53k
    static bool initialized = false;
206
4.53k
    std::string MCPU = "";
207
208
4.53k
    if (!initialized) {
209
1
        initialized = true;
210
        // Initialize targets and assembly parsers.
211
1
        llvm_ks::InitializeAllTargetInfos();
212
1
        llvm_ks::InitializeAllTargetMCs();
213
1
        llvm_ks::InitializeAllAsmParsers();
214
1
    }
215
216
4.53k
    ks->TripleName = Triple::normalize(TripleName);
217
4.53k
    ks->TheTarget = GetTarget(ks->TripleName);
218
4.53k
    if (!ks->TheTarget)
219
0
        return KS_ERR_MODE;   // FIXME
220
221
    // Now that GetTarget() has (potentially) replaced TripleName, it's safe to
222
    // construct the Triple object.
223
4.53k
    Triple TheTriple(ks->TripleName);
224
225
4.53k
    ks->MRI = ks->TheTarget->createMCRegInfo(ks->TripleName);
226
4.53k
    assert(ks->MRI && "Unable to create target register info!");
227
228
    // Package up features to be passed to target/subtarget
229
#if 0
230
    if (MAttrs.size()) {
231
        SubtargetFeatures Features;
232
        for (unsigned i = 0; i != MAttrs.size(); ++i)
233
            Features.AddFeature(MAttrs[i]);
234
        ks->FeaturesStr = Features.getString();
235
    }
236
#endif
237
238
4.53k
    ks->MAI = ks->TheTarget->createMCAsmInfo(*ks->MRI, ks->TripleName);
239
4.53k
    assert(ks->MAI && "Unable to create target asm info!");
240
241
    // enable Knights Landing architecture for X86
242
4.53k
    if (ks->arch == KS_ARCH_X86)
243
0
        MCPU = "knl";
244
245
4.53k
    ks->MCII = ks->TheTarget->createMCInstrInfo();
246
4.53k
    ks->STI = ks->TheTarget->createMCSubtargetInfo(ks->TripleName, MCPU, ks->FeaturesStr);
247
4.53k
    if(ks->TripleName.rfind("riscv",0)==0){
248
0
        ks->MAB = ks->TheTarget->createMCAsmBackend2(*ks->MRI, ks->TripleName, MCPU, *ks->STI, ks->MCOptions);
249
4.53k
    } else {
250
4.53k
        ks->MAB = ks->TheTarget->createMCAsmBackend(*ks->MRI, ks->TripleName, MCPU);
251
4.53k
    }
252
4.53k
    ks->MAB->setArch(arch);
253
4.53k
    ks->MCOptions = InitMCTargetOptionsFromFlags();
254
255
4.53k
    return KS_ERR_OK;
256
4.53k
}
257
258
259
KEYSTONE_EXPORT
260
ks_err ks_open(ks_arch arch, int mode, ks_engine **result)
261
4.53k
{
262
4.53k
    struct ks_struct *ks;
263
4.53k
    std::string TripleName = "";
264
265
4.53k
    if (arch < KS_ARCH_MAX) {
266
        // LLVM-based architectures
267
4.53k
        ks = new (std::nothrow) ks_struct(arch, mode, KS_ERR_OK, KS_OPT_SYNTAX_INTEL);
268
        
269
4.53k
        if (!ks) {
270
            // memory insufficient
271
0
            return KS_ERR_NOMEM;
272
0
        }
273
274
4.53k
        switch(arch) {
275
0
            default: break;
276
277
0
#ifdef LLVM_ENABLE_ARCH_ARM
278
0
            case KS_ARCH_ARM:
279
0
                if (mode & ~KS_MODE_ARM_MASK) {
280
0
                    delete ks;
281
0
                    return KS_ERR_MODE;
282
0
                }
283
284
0
                switch(mode) {
285
0
                    default:
286
0
                        return KS_ERR_MODE;
287
                    // big-endian
288
0
                    case KS_MODE_BIG_ENDIAN | KS_MODE_V8 | KS_MODE_ARM:
289
0
                        TripleName = "armv8eb";
290
0
                        break;
291
0
                    case KS_MODE_BIG_ENDIAN | KS_MODE_V8 | KS_MODE_THUMB:
292
0
                        TripleName = "thumbv8eb";
293
0
                        break;
294
0
                    case KS_MODE_BIG_ENDIAN | KS_MODE_ARM:
295
0
                        TripleName = "armv7eb";
296
0
                        break;
297
0
                    case KS_MODE_BIG_ENDIAN | KS_MODE_THUMB:
298
0
                        TripleName = "thumbebv7";
299
0
                        break;
300
301
                    // little-endian
302
0
                    case KS_MODE_LITTLE_ENDIAN | KS_MODE_V8 | KS_MODE_ARM:
303
0
                        TripleName = "armv8";
304
0
                        break;
305
0
                    case KS_MODE_LITTLE_ENDIAN | KS_MODE_V8 | KS_MODE_THUMB:
306
0
                        TripleName = "thumbv8";
307
0
                        break;
308
0
                    case KS_MODE_LITTLE_ENDIAN | KS_MODE_ARM:
309
0
                        TripleName = "armv7";
310
0
                        break;
311
0
                    case KS_MODE_LITTLE_ENDIAN | KS_MODE_THUMB:
312
0
                        TripleName = "thumbv7";
313
0
                        break;
314
0
                }
315
316
0
                InitKs(arch, ks, TripleName);
317
318
                //ks->init_arch = arm_ks_init;
319
0
                break;
320
0
#endif
321
322
0
#ifdef LLVM_ENABLE_ARCH_AArch64
323
0
            case KS_ARCH_ARM64:
324
0
                if (mode != KS_MODE_LITTLE_ENDIAN) {
325
0
                    delete ks;
326
0
                    return KS_ERR_MODE;
327
0
                }
328
329
0
                TripleName = "aarch64";
330
0
                InitKs(arch, ks, TripleName);
331
332
                //ks->init_arch = arm64_ks_init;
333
0
                break;
334
0
#endif
335
336
0
#ifdef LLVM_ENABLE_ARCH_Hexagon
337
0
            case KS_ARCH_HEXAGON:
338
0
                if (mode & ~KS_MODE_HEXAGON_MASK) {
339
0
                    delete ks;
340
0
                    return KS_ERR_MODE;
341
0
                }
342
343
0
                TripleName = "hexagon";
344
345
0
                InitKs(arch, ks, TripleName);
346
347
                //ks->init_arch = arm_ks_init;
348
0
                break;
349
0
#endif
350
351
0
#ifdef LLVM_ENABLE_ARCH_SystemZ
352
0
            case KS_ARCH_SYSTEMZ:
353
0
                if (mode & ~KS_MODE_SYSTEMZ_MASK) {
354
0
                    delete ks;
355
0
                    return KS_ERR_MODE;
356
0
                }
357
358
0
                TripleName = "s390x";
359
360
0
                InitKs(arch, ks, TripleName);
361
362
                //ks->init_arch = arm_ks_init;
363
0
                break;
364
0
#endif
365
366
0
#ifdef LLVM_ENABLE_ARCH_Sparc
367
0
            case KS_ARCH_SPARC:
368
0
                if ((mode & ~KS_MODE_SPARC_MASK) ||
369
0
                        !(mode & (KS_MODE_SPARC32|KS_MODE_SPARC64))) {
370
0
                    delete ks;
371
0
                    return KS_ERR_MODE;
372
0
                }
373
0
                if (mode & KS_MODE_BIG_ENDIAN) {
374
                    // big endian
375
0
                    if (mode & KS_MODE_SPARC64)
376
0
                        TripleName = "sparc64";
377
0
                    else
378
0
                        TripleName = "sparc";
379
0
                } else {
380
                    // little endian
381
0
                    if (mode & KS_MODE_SPARC64) {
382
                        // TripleName = "sparc64el";
383
                        // FIXME
384
0
                        delete ks;
385
0
                        return KS_ERR_MODE;
386
0
                    } else
387
0
                        TripleName = "sparcel";
388
0
                }
389
390
0
                InitKs(arch, ks, TripleName);
391
392
0
                break;
393
0
#endif
394
395
0
#ifdef LLVM_ENABLE_ARCH_RISCV
396
0
            case KS_ARCH_RISCV: {
397
0
                if ((mode & ~KS_MODE_RISCV_MASK) ||
398
0
                        (mode & KS_MODE_BIG_ENDIAN) ||
399
0
                        !(mode & (KS_MODE_RISCV32|KS_MODE_RISCV64))) {
400
0
                    delete ks;
401
0
                    return KS_ERR_MODE;
402
0
                }
403
404
0
                switch(mode) {
405
0
                    default: break;
406
0
                    case KS_MODE_RISCV32:
407
0
                        TripleName = "riscv32";
408
0
                        break;
409
0
                    case KS_MODE_RISCV64:
410
0
                        TripleName = "riscv64";
411
0
                        break;
412
0
                }
413
414
0
                InitKs(arch, ks, TripleName);
415
416
0
                break;
417
0
            }
418
0
#endif
419
420
0
#ifdef LLVM_ENABLE_ARCH_Mips
421
4.53k
            case KS_ARCH_MIPS:
422
4.53k
                if ((mode & ~KS_MODE_MIPS_MASK) ||
423
4.53k
                        !(mode & (KS_MODE_MIPS32|KS_MODE_MIPS64))) {
424
0
                    delete ks;
425
0
                    return KS_ERR_MODE;
426
0
                }
427
4.53k
                if (mode & KS_MODE_BIG_ENDIAN) {
428
                    // big endian
429
0
                    if (mode & KS_MODE_MIPS32)
430
0
                        TripleName = "mips";
431
0
                    if (mode & KS_MODE_MIPS64)
432
0
                        TripleName = "mips64";
433
4.53k
                } else {    // little endian
434
4.53k
                    if (mode & KS_MODE_MIPS32)
435
0
                        TripleName = "mipsel";
436
4.53k
                    if (mode & KS_MODE_MIPS64)
437
4.53k
                        TripleName = "mips64el";
438
4.53k
                }
439
440
4.53k
                InitKs(arch, ks, TripleName);
441
442
4.53k
                break;
443
0
#endif
444
445
0
#ifdef LLVM_ENABLE_ARCH_PowerPC
446
0
            case KS_ARCH_PPC:
447
0
                if ((mode & ~KS_MODE_PPC_MASK) ||
448
0
                        !(mode & (KS_MODE_PPC32|KS_MODE_PPC64))) {
449
0
                    delete ks;
450
0
                    return KS_ERR_MODE;
451
0
                }
452
453
0
                if (mode & KS_MODE_BIG_ENDIAN) {
454
                    // big endian
455
0
                    if (mode & KS_MODE_PPC32)
456
0
                        TripleName = "ppc32";
457
0
                    if (mode & KS_MODE_PPC64)
458
0
                        TripleName = "ppc64";
459
0
                } else {    // little endian
460
0
                    if (mode & KS_MODE_PPC32) {
461
                        // do not support this mode
462
0
                        delete ks;
463
0
                        return KS_ERR_MODE;
464
0
                    }
465
0
                    if (mode & KS_MODE_MIPS64)
466
0
                        TripleName = "ppc64le";
467
0
                }
468
469
0
                InitKs(arch, ks, TripleName);
470
471
                //ks->init_arch = ppc_ks_init;
472
0
                break;
473
0
#endif
474
475
0
#ifdef LLVM_ENABLE_ARCH_X86
476
0
            case KS_ARCH_X86: {
477
0
                if ((mode & ~KS_MODE_X86_MASK) ||
478
0
                        (mode & KS_MODE_BIG_ENDIAN) ||
479
0
                        !(mode & (KS_MODE_16|KS_MODE_32|KS_MODE_64))) {
480
0
                    delete ks;
481
0
                    return KS_ERR_MODE;
482
0
                }
483
484
0
                switch(mode) {
485
0
                    default: break;
486
0
                    case KS_MODE_16:
487
                        // FIXME
488
0
                        TripleName = "i386-unknown-unknown-code16";
489
0
                        break;
490
0
                    case KS_MODE_32:
491
                        // FIXME
492
0
                        TripleName = "i386";
493
0
                        break;
494
0
                    case KS_MODE_64:
495
                        // FIXME
496
0
                        TripleName = "x86_64";
497
0
                        break;
498
0
                }
499
500
0
                InitKs(arch, ks, TripleName);
501
502
                //ks->init_arch = x86_ks_init;
503
0
                break;
504
0
            }
505
0
#endif
506
0
#ifdef LLVM_ENABLE_ARCH_EVM
507
0
            case KS_ARCH_EVM: {
508
0
                *result = ks;
509
0
                return KS_ERR_OK;
510
0
            }
511
4.53k
#endif
512
4.53k
        }
513
514
4.53k
        if (TripleName.empty()) {
515
            // this arch is not supported
516
0
            delete ks;
517
0
            return KS_ERR_ARCH;
518
0
        }
519
520
4.53k
        *result = ks;
521
522
4.53k
        return KS_ERR_OK;
523
4.53k
    } else
524
0
        return KS_ERR_ARCH;
525
4.53k
}
526
527
528
KEYSTONE_EXPORT
529
ks_err ks_close(ks_engine *ks)
530
4.53k
{
531
4.53k
    if (!ks)
532
0
        return KS_ERR_HANDLE;
533
534
4.53k
    if (ks->arch == KS_ARCH_EVM) {
535
        // handle EVM differently
536
0
        delete ks;
537
0
        return KS_ERR_OK;
538
0
    }
539
540
    // LLVM-based architectures
541
4.53k
    delete ks->STI;
542
4.53k
    delete ks->MCII;
543
4.53k
    delete ks->MAI;
544
4.53k
    delete ks->MRI;
545
4.53k
    delete ks->MAB;
546
547
    // finally, free ks itself.
548
4.53k
    delete ks;
549
550
4.53k
    return KS_ERR_OK;
551
4.53k
}
552
553
554
KEYSTONE_EXPORT
555
ks_err ks_option(ks_engine *ks, ks_opt_type type, size_t value)
556
4.53k
{
557
4.53k
    ks->MAI->setRadix(16);
558
4.53k
    switch(type) {
559
4.53k
        case KS_OPT_SYNTAX:
560
4.53k
            if (ks->arch != KS_ARCH_X86)
561
4.53k
                return KS_ERR_OPT_INVALID;
562
0
            switch(value) {
563
0
                default:
564
0
                    return KS_ERR_OPT_INVALID;
565
0
                case KS_OPT_SYNTAX_RADIX16: // default syntax is Intel
566
0
                case KS_OPT_SYNTAX_NASM | KS_OPT_SYNTAX_RADIX16:
567
0
                case KS_OPT_SYNTAX_INTEL | KS_OPT_SYNTAX_RADIX16:
568
0
                    ks->MAI->setRadix(16);
569
0
                case KS_OPT_SYNTAX_NASM:
570
0
                case KS_OPT_SYNTAX_INTEL:
571
0
                    ks->syntax = (ks_opt_value)value;
572
0
                    ks->MAI->setAssemblerDialect(1);
573
0
                    break;
574
0
                case KS_OPT_SYNTAX_GAS | KS_OPT_SYNTAX_RADIX16:
575
0
                case KS_OPT_SYNTAX_ATT | KS_OPT_SYNTAX_RADIX16:
576
0
                    ks->MAI->setRadix(16);
577
0
                case KS_OPT_SYNTAX_GAS:
578
0
                case KS_OPT_SYNTAX_ATT:
579
0
                    ks->syntax = (ks_opt_value)value;
580
0
                    ks->MAI->setAssemblerDialect(0);
581
0
                    break;
582
0
            }
583
584
0
            return KS_ERR_OK;
585
0
        case KS_OPT_SYM_RESOLVER:
586
0
            ks->sym_resolver = (ks_sym_resolver)value;
587
0
            return KS_ERR_OK;
588
4.53k
    }
589
590
0
    return KS_ERR_OPT_INVALID;
591
4.53k
}
592
593
594
KEYSTONE_EXPORT
595
void ks_free(unsigned char *p)
596
2.01k
{
597
2.01k
    free(p);
598
2.01k
}
599
600
/*
601
 @return: 0 on success, or -1 on failure.
602
 On failure, call ks_errno() for error code.
603
*/
604
KEYSTONE_EXPORT
605
int ks_asm(ks_engine *ks,
606
        const char *assembly,
607
        uint64_t address,
608
        unsigned char **insn, size_t *insn_size,
609
        size_t *stat_count)
610
4.53k
{
611
4.53k
    MCCodeEmitter *CE;
612
4.53k
    MCStreamer *Streamer;
613
4.53k
    unsigned char *encoding;
614
4.53k
    SmallString<1024> Msg;
615
4.53k
    raw_svector_ostream OS(Msg);
616
617
4.53k
    if (ks->arch == KS_ARCH_EVM) {
618
        // handle EVM differently
619
0
        unsigned short opcode = EVM_opcode(assembly);
620
0
        if (opcode == (unsigned short)-1) {
621
            // invalid instruction
622
0
            return -1;
623
0
        }
624
625
0
        *insn_size = 1;
626
0
        *stat_count = 1;
627
0
        encoding = (unsigned char *)malloc(*insn_size);
628
0
        encoding[0] = opcode;
629
0
        *insn = encoding;
630
0
        return 0;
631
0
    }
632
633
4.53k
    *insn = NULL;
634
4.53k
    *insn_size = 0;
635
636
4.53k
    MCContext Ctx(ks->MAI, ks->MRI, &ks->MOFI, &ks->SrcMgr, true, address);
637
4.53k
    ks->MOFI.InitMCObjectFileInfo(Triple(ks->TripleName), Ctx);
638
4.53k
    CE = ks->TheTarget->createMCCodeEmitter(*ks->MCII, *ks->MRI, Ctx);
639
4.53k
    if (!CE) {
640
        // memory insufficient
641
0
        return KS_ERR_NOMEM;
642
0
    }
643
4.53k
    Streamer = ks->TheTarget->createMCObjectStreamer(
644
4.53k
            Triple(ks->TripleName), Ctx, *ks->MAB, OS, CE, *ks->STI, ks->MCOptions.MCRelaxAll,
645
4.53k
            /*DWARFMustBeAtTheEnd*/ false);
646
            
647
4.53k
    if (!Streamer) {
648
        // memory insufficient
649
0
        delete CE;
650
0
        return KS_ERR_NOMEM;
651
0
    }
652
653
    // Tell SrcMgr about this buffer, which is what the parser will pick up.
654
4.53k
    ErrorOr<std::unique_ptr<MemoryBuffer>> BufferPtr = MemoryBuffer::getMemBuffer(assembly);
655
4.53k
    if (BufferPtr.getError()) {
656
0
        delete Streamer;
657
0
        delete CE;
658
0
        return KS_ERR_NOMEM;
659
0
    }
660
661
4.53k
    ks->SrcMgr.clearBuffers();
662
4.53k
    ks->SrcMgr.AddNewSourceBuffer(std::move(*BufferPtr), SMLoc());
663
664
4.53k
    Streamer->setSymResolver((void *)(ks->sym_resolver));
665
666
4.53k
    MCAsmParser *Parser = createMCAsmParser(ks->SrcMgr, Ctx, *Streamer, *ks->MAI);
667
4.53k
    if (!Parser) {
668
0
        delete Streamer;
669
0
        delete CE;
670
        // memory insufficient
671
0
        return KS_ERR_NOMEM;
672
0
    }
673
4.53k
    MCTargetAsmParser *TAP = ks->TheTarget->createMCAsmParser(*ks->STI, *Parser, *ks->MCII, ks->MCOptions);
674
4.53k
    if (!TAP) { 
675
        // memory insufficient
676
0
        delete Parser;
677
0
        delete Streamer;
678
0
        delete CE;
679
0
        return KS_ERR_NOMEM;
680
0
    }
681
4.53k
    TAP->KsSyntax = ks->syntax;
682
683
4.53k
    Parser->setTargetParser(*TAP);
684
685
    // TODO: optimize this to avoid setting up NASM every time we call ks_asm()
686
4.53k
    if (ks->arch == KS_ARCH_X86 && ks->syntax == KS_OPT_SYNTAX_NASM) {
687
0
        Parser->initializeDirectiveKindMap(KS_OPT_SYNTAX_NASM);
688
0
        ks->MAI->setCommentString(";");
689
0
    }
690
691
4.53k
    *stat_count = Parser->Run(false, address);
692
693
    // PPC counts empty statement
694
4.53k
    if (ks->arch == KS_ARCH_PPC)
695
0
        *stat_count = *stat_count / 2;
696
697
4.53k
    ks->errnum = Parser->KsError;
698
699
4.53k
    delete TAP;
700
4.53k
    delete Parser;
701
4.53k
    delete CE;
702
4.53k
    delete Streamer;
703
704
4.53k
    if (ks->errnum >= KS_ERR_ASM)
705
2.52k
        return -1;
706
2.01k
    else {
707
2.01k
        *insn_size = Msg.size();
708
2.01k
        encoding = (unsigned char *)malloc(*insn_size);
709
2.01k
        if (!encoding) {
710
0
            return KS_ERR_NOMEM;
711
0
        }
712
2.01k
        memcpy(encoding, Msg.data(), *insn_size);
713
2.01k
        *insn = encoding;
714
2.01k
        return 0;
715
2.01k
    }
716
4.53k
}