1 /* Capstone Disassembler Engine */
2 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
3
4 #include <stdio.h> // debug
5 #include <string.h>
6 #include <caml/mlvalues.h>
7 #include <caml/memory.h>
8 #include <caml/alloc.h>
9 #include <caml/fail.h>
10
11 #include "../../include/capstone.h"
12
13 #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
14
15
16 // count the number of positive members in @list
list_count(uint8_t * list,unsigned int max)17 static unsigned int list_count(uint8_t *list, unsigned int max)
18 {
19 unsigned int i;
20
21 for(i = 0; i < max; i++)
22 if (list[i] == 0)
23 return i;
24
25 return max;
26 }
27
_cs_disasm(cs_arch arch,csh handle,const uint8_t * code,size_t code_len,uint64_t addr,size_t count)28 CAMLprim value _cs_disasm(cs_arch arch, csh handle, const uint8_t * code, size_t code_len, uint64_t addr, size_t count)
29 {
30 CAMLparam0();
31 CAMLlocal5(list, cons, rec_insn, array, tmp);
32 CAMLlocal4(arch_info, op_info_val, tmp2, tmp3);
33 cs_insn *insn;
34 size_t c;
35
36 list = Val_emptylist;
37
38 c = cs_disasm(handle, code, code_len, addr, count, &insn);
39 if (c) {
40 //printf("Found %lu insn, addr: %lx\n", c, addr);
41 uint64_t j;
42 for (j = c; j > 0; j--) {
43 unsigned int lcount, i;
44 cons = caml_alloc(2, 0);
45
46 rec_insn = caml_alloc(10, 0);
47 Store_field(rec_insn, 0, Val_int(insn[j-1].id));
48 Store_field(rec_insn, 1, Val_int(insn[j-1].address));
49 Store_field(rec_insn, 2, Val_int(insn[j-1].size));
50
51 // copy raw bytes of instruction
52 lcount = insn[j-1].size;
53 if (lcount) {
54 array = caml_alloc(lcount, 0);
55 for (i = 0; i < lcount; i++) {
56 Store_field(array, i, Val_int(insn[j-1].bytes[i]));
57 }
58 } else
59 array = Atom(0); // empty list
60 Store_field(rec_insn, 3, array);
61
62 Store_field(rec_insn, 4, caml_copy_string(insn[j-1].mnemonic));
63 Store_field(rec_insn, 5, caml_copy_string(insn[j-1].op_str));
64
65 // copy read registers
66 if (insn[0].detail) {
67 lcount = (insn[j-1]).detail->regs_read_count;
68 if (lcount) {
69 array = caml_alloc(lcount, 0);
70 for (i = 0; i < lcount; i++) {
71 Store_field(array, i, Val_int(insn[j-1].detail->regs_read[i]));
72 }
73 } else
74 array = Atom(0); // empty list
75 } else
76 array = Atom(0); // empty list
77 Store_field(rec_insn, 6, array);
78
79 if (insn[0].detail) {
80 lcount = (insn[j-1]).detail->regs_write_count;
81 if (lcount) {
82 array = caml_alloc(lcount, 0);
83 for (i = 0; i < lcount; i++) {
84 Store_field(array, i, Val_int(insn[j-1].detail->regs_write[i]));
85 }
86 } else
87 array = Atom(0); // empty list
88 } else
89 array = Atom(0); // empty list
90 Store_field(rec_insn, 7, array);
91
92 if (insn[0].detail) {
93 lcount = (insn[j-1]).detail->groups_count;
94 if (lcount) {
95 array = caml_alloc(lcount, 0);
96 for (i = 0; i < lcount; i++) {
97 Store_field(array, i, Val_int(insn[j-1].detail->groups[i]));
98 }
99 } else
100 array = Atom(0); // empty list
101 } else
102 array = Atom(0); // empty list
103 Store_field(rec_insn, 8, array);
104
105 if (insn[j-1].detail) {
106 switch(arch) {
107 case CS_ARCH_ARM:
108 arch_info = caml_alloc(1, 0);
109
110 op_info_val = caml_alloc(10, 0);
111 Store_field(op_info_val, 0, Val_bool(insn[j-1].detail->arm.usermode));
112 Store_field(op_info_val, 1, Val_int(insn[j-1].detail->arm.vector_size));
113 Store_field(op_info_val, 2, Val_int(insn[j-1].detail->arm.vector_data));
114 Store_field(op_info_val, 3, Val_int(insn[j-1].detail->arm.cps_mode));
115 Store_field(op_info_val, 4, Val_int(insn[j-1].detail->arm.cps_flag));
116 Store_field(op_info_val, 5, Val_int(insn[j-1].detail->arm.cc));
117 Store_field(op_info_val, 6, Val_bool(insn[j-1].detail->arm.update_flags));
118 Store_field(op_info_val, 7, Val_bool(insn[j-1].detail->arm.writeback));
119 Store_field(op_info_val, 8, Val_int(insn[j-1].detail->arm.mem_barrier));
120
121 lcount = insn[j-1].detail->arm.op_count;
122 if (lcount > 0) {
123 array = caml_alloc(lcount, 0);
124 for (i = 0; i < lcount; i++) {
125 tmp2 = caml_alloc(4, 0);
126 switch(insn[j-1].detail->arm.operands[i].type) {
127 case ARM_OP_REG:
128 case ARM_OP_SYSREG:
129 tmp = caml_alloc(1, 1);
130 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm.operands[i].reg));
131 break;
132 case ARM_OP_CIMM:
133 tmp = caml_alloc(1, 2);
134 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm.operands[i].imm));
135 break;
136 case ARM_OP_PIMM:
137 tmp = caml_alloc(1, 3);
138 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm.operands[i].imm));
139 break;
140 case ARM_OP_IMM:
141 tmp = caml_alloc(1, 4);
142 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm.operands[i].imm));
143 break;
144 case ARM_OP_FP:
145 tmp = caml_alloc(1, 5);
146 Store_field(tmp, 0, caml_copy_double(insn[j-1].detail->arm.operands[i].fp));
147 break;
148 case ARM_OP_MEM:
149 tmp = caml_alloc(1, 6);
150 tmp3 = caml_alloc(4, 0);
151 Store_field(tmp3, 0, Val_int(insn[j-1].detail->arm.operands[i].mem.base));
152 Store_field(tmp3, 1, Val_int(insn[j-1].detail->arm.operands[i].mem.index));
153 Store_field(tmp3, 2, Val_int(insn[j-1].detail->arm.operands[i].mem.scale));
154 Store_field(tmp3, 3, Val_int(insn[j-1].detail->arm.operands[i].mem.disp));
155 Store_field(tmp, 0, tmp3);
156 break;
157 case ARM_OP_SETEND:
158 tmp = caml_alloc(1, 7);
159 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm.operands[i].setend));
160 break;
161 default: break;
162 }
163 tmp3 = caml_alloc(2, 0);
164 Store_field(tmp3, 0, Val_int(insn[j-1].detail->arm.operands[i].shift.type));
165 Store_field(tmp3, 1, Val_int(insn[j-1].detail->arm.operands[i].shift.value));
166 Store_field(tmp2, 0, Val_int(insn[j-1].detail->arm.operands[i].vector_index));
167 Store_field(tmp2, 1, tmp3);
168 Store_field(tmp2, 2, tmp);
169 Store_field(tmp2, 3, Val_bool(insn[j-1].detail->arm.operands[i].subtracted));
170 Store_field(array, i, tmp2);
171 }
172 } else // empty list
173 array = Atom(0);
174
175 Store_field(op_info_val, 9, array);
176
177 // finally, insert this into arch_info
178 Store_field(arch_info, 0, op_info_val);
179
180 Store_field(rec_insn, 9, arch_info);
181
182 break;
183 case CS_ARCH_ARM64:
184 arch_info = caml_alloc(1, 1);
185
186 op_info_val = caml_alloc(4, 0);
187 Store_field(op_info_val, 0, Val_int(insn[j-1].detail->arm64.cc));
188 Store_field(op_info_val, 1, Val_bool(insn[j-1].detail->arm64.update_flags));
189 Store_field(op_info_val, 2, Val_bool(insn[j-1].detail->arm64.writeback));
190
191 lcount = insn[j-1].detail->arm64.op_count;
192 if (lcount > 0) {
193 array = caml_alloc(lcount, 0);
194 for (i = 0; i < lcount; i++) {
195 tmp2 = caml_alloc(6, 0);
196 switch(insn[j-1].detail->arm64.operands[i].type) {
197 case ARM64_OP_REG:
198 tmp = caml_alloc(1, 1);
199 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].reg));
200 break;
201 case ARM64_OP_CIMM:
202 tmp = caml_alloc(1, 2);
203 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].imm));
204 break;
205 case ARM64_OP_IMM:
206 tmp = caml_alloc(1, 3);
207 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].imm));
208 break;
209 case ARM64_OP_FP:
210 tmp = caml_alloc(1, 4);
211 Store_field(tmp, 0, caml_copy_double(insn[j-1].detail->arm64.operands[i].fp));
212 break;
213 case ARM64_OP_MEM:
214 tmp = caml_alloc(1, 5);
215 tmp3 = caml_alloc(3, 0);
216 Store_field(tmp3, 0, Val_int(insn[j-1].detail->arm64.operands[i].mem.base));
217 Store_field(tmp3, 1, Val_int(insn[j-1].detail->arm64.operands[i].mem.index));
218 Store_field(tmp3, 2, Val_int(insn[j-1].detail->arm64.operands[i].mem.disp));
219 Store_field(tmp, 0, tmp3);
220 break;
221 case ARM64_OP_REG_MRS:
222 tmp = caml_alloc(1, 6);
223 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].reg));
224 break;
225 case ARM64_OP_REG_MSR:
226 tmp = caml_alloc(1, 7);
227 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].reg));
228 break;
229 case ARM64_OP_PSTATE:
230 tmp = caml_alloc(1, 8);
231 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].pstate));
232 break;
233 case ARM64_OP_SYS:
234 tmp = caml_alloc(1, 9);
235 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].sys));
236 break;
237 case ARM64_OP_PREFETCH:
238 tmp = caml_alloc(1, 10);
239 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].prefetch));
240 break;
241 case ARM64_OP_BARRIER:
242 tmp = caml_alloc(1, 11);
243 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].barrier));
244 break;
245 default: break;
246 }
247 tmp3 = caml_alloc(2, 0);
248 Store_field(tmp3, 0, Val_int(insn[j-1].detail->arm64.operands[i].shift.type));
249 Store_field(tmp3, 1, Val_int(insn[j-1].detail->arm64.operands[i].shift.value));
250
251 Store_field(tmp2, 0, Val_int(insn[j-1].detail->arm64.operands[i].vector_index));
252 Store_field(tmp2, 1, Val_int(insn[j-1].detail->arm64.operands[i].vas));
253 Store_field(tmp2, 2, Val_int(insn[j-1].detail->arm64.operands[i].vess));
254 Store_field(tmp2, 3, tmp3);
255 Store_field(tmp2, 4, Val_int(insn[j-1].detail->arm64.operands[i].ext));
256 Store_field(tmp2, 5, tmp);
257
258 Store_field(array, i, tmp2);
259 }
260 } else // empty array
261 array = Atom(0);
262
263 Store_field(op_info_val, 3, array);
264
265 // finally, insert this into arch_info
266 Store_field(arch_info, 0, op_info_val);
267
268 Store_field(rec_insn, 9, arch_info);
269
270 break;
271 case CS_ARCH_MIPS:
272 arch_info = caml_alloc(1, 2);
273
274 op_info_val = caml_alloc(1, 0);
275
276 lcount = insn[j-1].detail->mips.op_count;
277 if (lcount > 0) {
278 array = caml_alloc(lcount, 0);
279 for (i = 0; i < lcount; i++) {
280 tmp2 = caml_alloc(1, 0);
281 switch(insn[j-1].detail->mips.operands[i].type) {
282 case MIPS_OP_REG:
283 tmp = caml_alloc(1, 1);
284 Store_field(tmp, 0, Val_int(insn[j-1].detail->mips.operands[i].reg));
285 break;
286 case MIPS_OP_IMM:
287 tmp = caml_alloc(1, 2);
288 Store_field(tmp, 0, Val_int(insn[j-1].detail->mips.operands[i].imm));
289 break;
290 case MIPS_OP_MEM:
291 tmp = caml_alloc(1, 3);
292 tmp3 = caml_alloc(2, 0);
293 Store_field(tmp3, 0, Val_int(insn[j-1].detail->mips.operands[i].mem.base));
294 Store_field(tmp3, 1, Val_int(insn[j-1].detail->mips.operands[i].mem.disp));
295 Store_field(tmp, 0, tmp3);
296 break;
297 default: break;
298 }
299 Store_field(tmp2, 0, tmp);
300 Store_field(array, i, tmp2);
301 }
302 } else // empty array
303 array = Atom(0);
304
305 Store_field(op_info_val, 0, array);
306
307 // finally, insert this into arch_info
308 Store_field(arch_info, 0, op_info_val);
309
310 Store_field(rec_insn, 9, arch_info);
311
312 break;
313 case CS_ARCH_X86:
314 arch_info = caml_alloc(1, 3);
315
316 op_info_val = caml_alloc(15, 0);
317
318 // fill prefix
319 lcount = list_count(insn[j-1].detail->x86.prefix, ARR_SIZE(insn[j-1].detail->x86.prefix));
320 if (lcount) {
321 array = caml_alloc(lcount, 0);
322 for (i = 0; i < lcount; i++) {
323 Store_field(array, i, Val_int(insn[j-1].detail->x86.prefix[i]));
324 }
325 } else
326 array = Atom(0);
327 Store_field(op_info_val, 0, array);
328
329 // fill opcode
330 lcount = list_count(insn[j-1].detail->x86.opcode, ARR_SIZE(insn[j-1].detail->x86.opcode));
331 if (lcount) {
332 array = caml_alloc(lcount, 0);
333 for (i = 0; i < lcount; i++) {
334 Store_field(array, i, Val_int(insn[j-1].detail->x86.opcode[i]));
335 }
336 } else
337 array = Atom(0);
338 Store_field(op_info_val, 1, array);
339
340 Store_field(op_info_val, 2, Val_int(insn[j-1].detail->x86.rex));
341
342 Store_field(op_info_val, 3, Val_int(insn[j-1].detail->x86.addr_size));
343
344 Store_field(op_info_val, 4, Val_int(insn[j-1].detail->x86.modrm));
345
346 Store_field(op_info_val, 5, Val_int(insn[j-1].detail->x86.sib));
347
348 Store_field(op_info_val, 6, Val_int(insn[j-1].detail->x86.disp));
349
350 Store_field(op_info_val, 7, Val_int(insn[j-1].detail->x86.sib_index));
351
352 Store_field(op_info_val, 8, Val_int(insn[j-1].detail->x86.sib_scale));
353
354 Store_field(op_info_val, 9, Val_int(insn[j-1].detail->x86.sib_base));
355
356 Store_field(op_info_val, 10, Val_int(insn[j-1].detail->x86.sse_cc));
357 Store_field(op_info_val, 11, Val_int(insn[j-1].detail->x86.avx_cc));
358 Store_field(op_info_val, 12, Val_int(insn[j-1].detail->x86.avx_sae));
359 Store_field(op_info_val, 13, Val_int(insn[j-1].detail->x86.avx_rm));
360
361 lcount = insn[j-1].detail->x86.op_count;
362 if (lcount > 0) {
363 array = caml_alloc(lcount, 0);
364 for (i = 0; i < lcount; i++) {
365 switch(insn[j-1].detail->x86.operands[i].type) {
366 case X86_OP_REG:
367 tmp = caml_alloc(4, 1);
368 Store_field(tmp, 0, Val_int(insn[j-1].detail->x86.operands[i].reg));
369 break;
370 case X86_OP_IMM:
371 tmp = caml_alloc(4, 2);
372 Store_field(tmp, 0, Val_int(insn[j-1].detail->x86.operands[i].imm));
373 break;
374 case X86_OP_FP:
375 tmp = caml_alloc(4, 3);
376 Store_field(tmp, 0, caml_copy_double(insn[j-1].detail->x86.operands[i].fp));
377 break;
378 case X86_OP_MEM:
379 tmp = caml_alloc(4, 4);
380 tmp2 = caml_alloc(5, 0);
381 Store_field(tmp2, 0, Val_int(insn[j-1].detail->x86.operands[i].mem.segment));
382 Store_field(tmp2, 1, Val_int(insn[j-1].detail->x86.operands[i].mem.base));
383 Store_field(tmp2, 2, Val_int(insn[j-1].detail->x86.operands[i].mem.index));
384 Store_field(tmp2, 3, Val_int(insn[j-1].detail->x86.operands[i].mem.scale));
385 Store_field(tmp2, 4, Val_int(insn[j-1].detail->x86.operands[i].mem.disp));
386
387 Store_field(tmp, 0, tmp2);
388 break;
389 default:
390 break;
391 }
392 Store_field(tmp, 1, Val_int(insn[j-1].detail->x86.operands[i].size));
393 Store_field(tmp, 2, Val_int(insn[j-1].detail->x86.operands[i].avx_bcast));
394 Store_field(tmp, 3, Val_int(insn[j-1].detail->x86.operands[i].avx_zero_opmask));
395 tmp2 = caml_alloc(1, 0);
396 Store_field(tmp2, 0, tmp);
397 Store_field(array, i, tmp2);
398 }
399 } else // empty array
400 array = Atom(0);
401 Store_field(op_info_val, 14, array);
402
403 // finally, insert this into arch_info
404 Store_field(arch_info, 0, op_info_val);
405
406 Store_field(rec_insn, 9, arch_info);
407 break;
408
409 case CS_ARCH_PPC:
410 arch_info = caml_alloc(1, 4);
411
412 op_info_val = caml_alloc(4, 0);
413
414 Store_field(op_info_val, 0, Val_int(insn[j-1].detail->ppc.bc));
415 Store_field(op_info_val, 1, Val_int(insn[j-1].detail->ppc.bh));
416 Store_field(op_info_val, 2, Val_bool(insn[j-1].detail->ppc.update_cr0));
417
418 lcount = insn[j-1].detail->ppc.op_count;
419 if (lcount > 0) {
420 array = caml_alloc(lcount, 0);
421 for (i = 0; i < lcount; i++) {
422 tmp2 = caml_alloc(1, 0);
423 switch(insn[j-1].detail->ppc.operands[i].type) {
424 case PPC_OP_REG:
425 tmp = caml_alloc(1, 1);
426 Store_field(tmp, 0, Val_int(insn[j-1].detail->ppc.operands[i].reg));
427 break;
428 case PPC_OP_IMM:
429 tmp = caml_alloc(1, 2);
430 Store_field(tmp, 0, Val_int(insn[j-1].detail->ppc.operands[i].imm));
431 break;
432 case PPC_OP_MEM:
433 tmp = caml_alloc(1, 3);
434 tmp3 = caml_alloc(2, 0);
435 Store_field(tmp3, 0, Val_int(insn[j-1].detail->ppc.operands[i].mem.base));
436 Store_field(tmp3, 1, Val_int(insn[j-1].detail->ppc.operands[i].mem.disp));
437 Store_field(tmp, 0, tmp3);
438 break;
439 case PPC_OP_CRX:
440 tmp = caml_alloc(1, 4);
441 tmp3 = caml_alloc(3, 0);
442 Store_field(tmp3, 0, Val_int(insn[j-1].detail->ppc.operands[i].crx.scale));
443 Store_field(tmp3, 1, Val_int(insn[j-1].detail->ppc.operands[i].crx.reg));
444 Store_field(tmp3, 2, Val_int(insn[j-1].detail->ppc.operands[i].crx.cond));
445 Store_field(tmp, 0, tmp3);
446 break;
447 default: break;
448 }
449 Store_field(tmp2, 0, tmp);
450 Store_field(array, i, tmp2);
451 }
452 } else // empty array
453 array = Atom(0);
454
455 Store_field(op_info_val, 3, array);
456
457 // finally, insert this into arch_info
458 Store_field(arch_info, 0, op_info_val);
459
460 Store_field(rec_insn, 9, arch_info);
461
462 break;
463
464 case CS_ARCH_SPARC:
465 arch_info = caml_alloc(1, 5);
466
467 op_info_val = caml_alloc(3, 0);
468
469 Store_field(op_info_val, 0, Val_int(insn[j-1].detail->sparc.cc));
470 Store_field(op_info_val, 1, Val_int(insn[j-1].detail->sparc.hint));
471
472 lcount = insn[j-1].detail->sparc.op_count;
473 if (lcount > 0) {
474 array = caml_alloc(lcount, 0);
475 for (i = 0; i < lcount; i++) {
476 tmp2 = caml_alloc(1, 0);
477 switch(insn[j-1].detail->sparc.operands[i].type) {
478 case SPARC_OP_REG:
479 tmp = caml_alloc(1, 1);
480 Store_field(tmp, 0, Val_int(insn[j-1].detail->sparc.operands[i].reg));
481 break;
482 case SPARC_OP_IMM:
483 tmp = caml_alloc(1, 2);
484 Store_field(tmp, 0, Val_int(insn[j-1].detail->sparc.operands[i].imm));
485 break;
486 case SPARC_OP_MEM:
487 tmp = caml_alloc(1, 3);
488 tmp3 = caml_alloc(3, 0);
489 Store_field(tmp3, 0, Val_int(insn[j-1].detail->sparc.operands[i].mem.base));
490 Store_field(tmp3, 1, Val_int(insn[j-1].detail->sparc.operands[i].mem.index));
491 Store_field(tmp3, 2, Val_int(insn[j-1].detail->sparc.operands[i].mem.disp));
492 Store_field(tmp, 0, tmp3);
493 break;
494 default: break;
495 }
496 Store_field(tmp2, 0, tmp);
497 Store_field(array, i, tmp2);
498 }
499 } else // empty array
500 array = Atom(0);
501
502 Store_field(op_info_val, 2, array);
503
504 // finally, insert this into arch_info
505 Store_field(arch_info, 0, op_info_val);
506
507 Store_field(rec_insn, 9, arch_info);
508
509 break;
510
511 case CS_ARCH_SYSZ:
512 arch_info = caml_alloc(1, 6);
513
514 op_info_val = caml_alloc(2, 0);
515
516 Store_field(op_info_val, 0, Val_int(insn[j-1].detail->sysz.cc));
517
518 lcount = insn[j-1].detail->sysz.op_count;
519 if (lcount > 0) {
520 array = caml_alloc(lcount, 0);
521 for (i = 0; i < lcount; i++) {
522 tmp2 = caml_alloc(1, 0);
523 switch(insn[j-1].detail->sysz.operands[i].type) {
524 case SYSZ_OP_REG:
525 tmp = caml_alloc(1, 1);
526 Store_field(tmp, 0, Val_int(insn[j-1].detail->sysz.operands[i].reg));
527 break;
528 case SYSZ_OP_ACREG:
529 tmp = caml_alloc(1, 2);
530 Store_field(tmp, 0, Val_int(insn[j-1].detail->sysz.operands[i].reg));
531 break;
532 case SYSZ_OP_IMM:
533 tmp = caml_alloc(1, 3);
534 Store_field(tmp, 0, Val_int(insn[j-1].detail->sysz.operands[i].imm));
535 break;
536 case SYSZ_OP_MEM:
537 tmp = caml_alloc(1, 4);
538 tmp3 = caml_alloc(4, 0);
539 Store_field(tmp3, 0, Val_int(insn[j-1].detail->sysz.operands[i].mem.base));
540 Store_field(tmp3, 1, Val_int(insn[j-1].detail->sysz.operands[i].mem.index));
541 Store_field(tmp3, 2, caml_copy_int64(insn[j-1].detail->sysz.operands[i].mem.length));
542 Store_field(tmp3, 3, caml_copy_int64(insn[j-1].detail->sysz.operands[i].mem.disp));
543 Store_field(tmp, 0, tmp3);
544 break;
545 default: break;
546 }
547 Store_field(tmp2, 0, tmp);
548 Store_field(array, i, tmp2);
549 }
550 } else // empty array
551 array = Atom(0);
552
553 Store_field(op_info_val, 1, array);
554
555 // finally, insert this into arch_info
556 Store_field(arch_info, 0, op_info_val);
557
558 Store_field(rec_insn, 9, arch_info);
559
560 break;
561
562 case CS_ARCH_XCORE:
563 arch_info = caml_alloc(1, 7);
564
565 op_info_val = caml_alloc(1, 0);
566
567 lcount = insn[j-1].detail->xcore.op_count;
568 if (lcount > 0) {
569 array = caml_alloc(lcount, 0);
570 for (i = 0; i < lcount; i++) {
571 tmp2 = caml_alloc(1, 0);
572 switch(insn[j-1].detail->xcore.operands[i].type) {
573 case XCORE_OP_REG:
574 tmp = caml_alloc(1, 1);
575 Store_field(tmp, 0, Val_int(insn[j-1].detail->xcore.operands[i].reg));
576 break;
577 case XCORE_OP_IMM:
578 tmp = caml_alloc(1, 2);
579 Store_field(tmp, 0, Val_int(insn[j-1].detail->xcore.operands[i].imm));
580 break;
581 case XCORE_OP_MEM:
582 tmp = caml_alloc(1, 3);
583 tmp3 = caml_alloc(4, 0);
584 Store_field(tmp3, 0, Val_int(insn[j-1].detail->xcore.operands[i].mem.base));
585 Store_field(tmp3, 1, Val_int(insn[j-1].detail->xcore.operands[i].mem.index));
586 Store_field(tmp3, 2, caml_copy_int64(insn[j-1].detail->xcore.operands[i].mem.disp));
587 Store_field(tmp3, 3, caml_copy_int64(insn[j-1].detail->xcore.operands[i].mem.direct));
588 Store_field(tmp, 0, tmp3);
589 break;
590 default: break;
591 }
592 Store_field(tmp2, 0, tmp);
593 Store_field(array, i, tmp2);
594 }
595 } else // empty array
596 array = Atom(0);
597
598 Store_field(op_info_val, 0, array);
599
600 // finally, insert this into arch_info
601 Store_field(arch_info, 0, op_info_val);
602
603 Store_field(rec_insn, 9, arch_info);
604
605 break;
606
607 default: break;
608 }
609 }
610
611 Store_field(cons, 0, rec_insn); // head
612 Store_field(cons, 1, list); // tail
613 list = cons;
614 }
615 cs_free(insn, count);
616 }
617
618 // do not free the handle here
619 //cs_close(&handle);
620 CAMLreturn(list);
621 }
622
ocaml_cs_disasm(value _arch,value _mode,value _code,value _addr,value _count)623 CAMLprim value ocaml_cs_disasm(value _arch, value _mode, value _code, value _addr, value _count)
624 {
625 CAMLparam5(_arch, _mode, _code, _addr, _count);
626 CAMLlocal1(head);
627 csh handle;
628 cs_arch arch;
629 cs_mode mode = 0;
630 const uint8_t *code;
631 uint64_t addr;
632 size_t count, code_len;
633
634 switch (Int_val(_arch)) {
635 case 0:
636 arch = CS_ARCH_ARM;
637 break;
638 case 1:
639 arch = CS_ARCH_ARM64;
640 break;
641 case 2:
642 arch = CS_ARCH_MIPS;
643 break;
644 case 3:
645 arch = CS_ARCH_X86;
646 break;
647 case 4:
648 arch = CS_ARCH_PPC;
649 break;
650 case 5:
651 arch = CS_ARCH_SPARC;
652 break;
653 case 6:
654 arch = CS_ARCH_SYSZ;
655 break;
656 case 7:
657 arch = CS_ARCH_XCORE;
658 break;
659 default:
660 caml_invalid_argument("Invalid arch");
661 return Val_emptylist;
662 }
663
664 while (_mode != Val_emptylist) {
665 head = Field(_mode, 0); /* accessing the head */
666 switch (Int_val(head)) {
667 case 0:
668 mode |= CS_MODE_LITTLE_ENDIAN;
669 break;
670 case 1:
671 mode |= CS_MODE_ARM;
672 break;
673 case 2:
674 mode |= CS_MODE_16;
675 break;
676 case 3:
677 mode |= CS_MODE_32;
678 break;
679 case 4:
680 mode |= CS_MODE_64;
681 break;
682 case 5:
683 mode |= CS_MODE_THUMB;
684 break;
685 case 6:
686 mode |= CS_MODE_MCLASS;
687 break;
688 case 7:
689 mode |= CS_MODE_V8;
690 break;
691 case 8:
692 mode |= CS_MODE_MICRO;
693 break;
694 case 9:
695 mode |= CS_MODE_MIPS3;
696 break;
697 case 10:
698 mode |= CS_MODE_MIPS32R6;
699 break;
700 case 11:
701 mode |= CS_MODE_MIPSGP64;
702 break;
703 case 12:
704 mode |= CS_MODE_V9;
705 break;
706 case 13:
707 mode |= CS_MODE_BIG_ENDIAN;
708 break;
709 case 14:
710 mode |= CS_MODE_MIPS32;
711 break;
712 case 15:
713 mode |= CS_MODE_MIPS64;
714 break;
715 default:
716 caml_invalid_argument("Invalid mode");
717 return Val_emptylist;
718 }
719 _mode = Field(_mode, 1); /* point to the tail for next loop */
720 }
721
722 cs_err ret = cs_open(arch, mode, &handle);
723 if (ret != CS_ERR_OK) {
724 return Val_emptylist;
725 }
726
727 code = (uint8_t *)String_val(_code);
728 code_len = caml_string_length(_code);
729 addr = Int64_val(_addr);
730 count = Int64_val(_count);
731
732 CAMLreturn(_cs_disasm(arch, handle, code, code_len, addr, count));
733 }
734
ocaml_cs_disasm_internal(value _arch,value _handle,value _code,value _addr,value _count)735 CAMLprim value ocaml_cs_disasm_internal(value _arch, value _handle, value _code, value _addr, value _count)
736 {
737 CAMLparam5(_arch, _handle, _code, _addr, _count);
738 csh handle;
739 cs_arch arch;
740 const uint8_t *code;
741 uint64_t addr, count, code_len;
742
743 handle = Int64_val(_handle);
744
745 arch = Int_val(_arch);
746 code = (uint8_t *)String_val(_code);
747 code_len = caml_string_length(_code);
748 addr = Int64_val(_addr);
749 count = Int64_val(_count);
750
751 CAMLreturn(_cs_disasm(arch, handle, code, code_len, addr, count));
752 }
753
ocaml_open(value _arch,value _mode)754 CAMLprim value ocaml_open(value _arch, value _mode)
755 {
756 CAMLparam2(_arch, _mode);
757 CAMLlocal2(list, head);
758 csh handle;
759 cs_arch arch;
760 cs_mode mode = 0;
761
762 list = Val_emptylist;
763
764 switch (Int_val(_arch)) {
765 case 0:
766 arch = CS_ARCH_ARM;
767 break;
768 case 1:
769 arch = CS_ARCH_ARM64;
770 break;
771 case 2:
772 arch = CS_ARCH_MIPS;
773 break;
774 case 3:
775 arch = CS_ARCH_X86;
776 break;
777 case 4:
778 arch = CS_ARCH_PPC;
779 break;
780 case 5:
781 arch = CS_ARCH_SPARC;
782 break;
783 case 6:
784 arch = CS_ARCH_SYSZ;
785 break;
786 case 7:
787 arch = CS_ARCH_XCORE;
788 break;
789 default:
790 caml_invalid_argument("Invalid arch");
791 return Val_emptylist;
792 }
793
794
795 while (_mode != Val_emptylist) {
796 head = Field(_mode, 0); /* accessing the head */
797 switch (Int_val(head)) {
798 case 0:
799 mode |= CS_MODE_LITTLE_ENDIAN;
800 break;
801 case 1:
802 mode |= CS_MODE_ARM;
803 break;
804 case 2:
805 mode |= CS_MODE_16;
806 break;
807 case 3:
808 mode |= CS_MODE_32;
809 break;
810 case 4:
811 mode |= CS_MODE_64;
812 break;
813 case 5:
814 mode |= CS_MODE_THUMB;
815 break;
816 case 6:
817 mode |= CS_MODE_MCLASS;
818 break;
819 case 7:
820 mode |= CS_MODE_V8;
821 break;
822 case 8:
823 mode |= CS_MODE_MICRO;
824 break;
825 case 9:
826 mode |= CS_MODE_MIPS3;
827 break;
828 case 10:
829 mode |= CS_MODE_MIPS32R6;
830 break;
831 case 11:
832 mode |= CS_MODE_MIPSGP64;
833 break;
834 case 12:
835 mode |= CS_MODE_V9;
836 break;
837 case 13:
838 mode |= CS_MODE_BIG_ENDIAN;
839 break;
840 case 14:
841 mode |= CS_MODE_MIPS32;
842 break;
843 case 15:
844 mode |= CS_MODE_MIPS64;
845 break;
846 default:
847 caml_invalid_argument("Invalid mode");
848 return Val_emptylist;
849 }
850 _mode = Field(_mode, 1); /* point to the tail for next loop */
851 }
852
853 if (cs_open(arch, mode, &handle) != 0)
854 CAMLreturn(Val_int(0));
855
856 CAMLlocal1(result);
857 result = caml_alloc(1, 0);
858 Store_field(result, 0, caml_copy_int64(handle));
859 CAMLreturn(result);
860 }
861
ocaml_option(value _handle,value _opt,value _value)862 CAMLprim value ocaml_option(value _handle, value _opt, value _value)
863 {
864 CAMLparam3(_handle, _opt, _value);
865 cs_opt_type opt;
866 int err;
867
868 switch (Int_val(_opt)) {
869 case 0:
870 opt = CS_OPT_SYNTAX;
871 break;
872 case 1:
873 opt = CS_OPT_DETAIL;
874 break;
875 case 2:
876 opt = CS_OPT_MODE;
877 break;
878 case 3:
879 opt = CS_OPT_MEM;
880 break;
881 case 4:
882 opt = CS_OPT_SKIPDATA;
883 break;
884 case 5:
885 opt = CS_OPT_SKIPDATA_SETUP;
886 break;
887 default:
888 caml_invalid_argument("Invalid option");
889 CAMLreturn(Val_int(CS_ERR_OPTION));
890 }
891
892 err = cs_option(Int64_val(_handle), opt, Int64_val(_value));
893
894 CAMLreturn(Val_int(err));
895 }
896
ocaml_register_name(value _handle,value _reg)897 CAMLprim value ocaml_register_name(value _handle, value _reg)
898 {
899 const char *name = cs_reg_name(Int64_val(_handle), Int_val(_reg));
900 if (!name) {
901 caml_invalid_argument("invalid reg_id");
902 name = "invalid";
903 }
904
905 return caml_copy_string(name);
906 }
907
ocaml_instruction_name(value _handle,value _insn)908 CAMLprim value ocaml_instruction_name(value _handle, value _insn)
909 {
910 const char *name = cs_insn_name(Int64_val(_handle), Int_val(_insn));
911 if (!name) {
912 caml_invalid_argument("invalid insn_id");
913 name = "invalid";
914 }
915
916 return caml_copy_string(name);
917 }
918
ocaml_group_name(value _handle,value _insn)919 CAMLprim value ocaml_group_name(value _handle, value _insn)
920 {
921 const char *name = cs_group_name(Int64_val(_handle), Int_val(_insn));
922 if (!name) {
923 caml_invalid_argument("invalid insn_id");
924 name = "invalid";
925 }
926
927 return caml_copy_string(name);
928 }
929
ocaml_version(void)930 CAMLprim value ocaml_version(void)
931 {
932 int version = cs_version(NULL, NULL);
933 return Val_int(version);
934 }
935
ocaml_close(value _handle)936 CAMLprim value ocaml_close(value _handle)
937 {
938 CAMLparam1(_handle);
939 csh h;
940
941 h = Int64_val(_handle);
942
943 CAMLreturn(Val_int(cs_close(&h)));
944 }
945