/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 | } |