blob: 5bae0c1eafd081ab48ffb7e4c89624ccf5c95df6 [file] [log] [blame]
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +08001/* 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// count the number of positive members in @oplist
16#define ARCH_LIST_COUNT(_arch, _optype) \
17static unsigned int _arch ## _list_count(_optype *list, unsigned int max) \
18{ \
19 unsigned int i; \
20 for(i = 0; i < max; i++) \
21 if (list[i].type == 0) \
22 return i; \
23 return max; \
24}
25
26ARCH_LIST_COUNT(arm, cs_arm_op)
27ARCH_LIST_COUNT(arm64, cs_arm64_op)
28ARCH_LIST_COUNT(mips, cs_mips_op)
29ARCH_LIST_COUNT(x86, cs_x86_op)
30
Guillaume Jeannecece24e2014-06-26 15:35:06 +020031
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080032// count the number of positive members in @list
Guillaume Jeannecece24e2014-06-26 15:35:06 +020033static unsigned int list_count(uint8_t *list, unsigned int max)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080034{
35 unsigned int i;
36
37 for(i = 0; i < max; i++)
38 if (list[i] == 0)
39 return i;
40
41 return max;
42}
43
Guillaume Jeannecece24e2014-06-26 15:35:06 +020044CAMLprim value _cs_disasm(cs_arch arch, csh handle, const uint8_t * code, size_t code_len, uint64_t addr, size_t count)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080045{
46 CAMLparam0();
47 CAMLlocal5(list, cons, rec_insn, array, tmp);
48 CAMLlocal4(arch_info, op_info_val, tmp2, tmp3);
49 cs_insn *insn;
50
51 list = Val_emptylist;
52
Guillaume Jeannecece24e2014-06-26 15:35:06 +020053 size_t c = cs_disasm_ex(handle, code, code_len, addr, count, &insn);
54
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080055 if (c) {
56 //printf("Found %lu insn, addr: %lx\n", c, addr);
57 uint64_t j;
58 for (j = c; j > 0; j--) {
59 unsigned int lcount, i;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080060 cons = caml_alloc(2, 0);
61
Guillaume Jeannecece24e2014-06-26 15:35:06 +020062 rec_insn = caml_alloc(13, 0);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080063 Store_field(rec_insn, 0, Val_int(insn[j-1].id));
64 Store_field(rec_insn, 1, Val_int(insn[j-1].address));
65 Store_field(rec_insn, 2, Val_int(insn[j-1].size));
Guillaume Jeannecece24e2014-06-26 15:35:06 +020066
67 Store_field(rec_insn, 4, caml_copy_string(insn[j-1].mnemonic));
68 Store_field(rec_insn, 5, caml_copy_string(insn[j-1].op_str));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080069
Guillaume Jeannecece24e2014-06-26 15:35:06 +020070 // copy raw bytes of instruction
71 lcount = insn[j-1].size;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080072 if (lcount) {
73 array = caml_alloc(lcount, 0);
74 for (i = 0; i < lcount; i++) {
Guillaume Jeannecece24e2014-06-26 15:35:06 +020075 Store_field(array, i, Val_int(insn[j-1].bytes[i]));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080076 }
Guillaume Jeannecece24e2014-06-26 15:35:06 +020077 } else
78 array = Atom(0); // empty list
79 Store_field(rec_insn, 3, array);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080080
Guillaume Jeannecece24e2014-06-26 15:35:06 +020081
82 // copy read registers
83 lcount = (insn[j-1]).detail->regs_read_count;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080084 if (lcount) {
85 array = caml_alloc(lcount, 0);
86 for (i = 0; i < lcount; i++) {
Guillaume Jeannecece24e2014-06-26 15:35:06 +020087 Store_field(array, i, Val_int(insn[j-1].detail->regs_read[i]));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080088 }
89 } else
90 array = Atom(0); // empty list
91 Store_field(rec_insn, 6, array);
Guillaume Jeannecece24e2014-06-26 15:35:06 +020092 Store_field(rec_insn, 7, Val_int(lcount));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080093
Guillaume Jeannecece24e2014-06-26 15:35:06 +020094 lcount = (insn[j-1]).detail->regs_write_count;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080095 if (lcount) {
96 array = caml_alloc(lcount, 0);
97 for (i = 0; i < lcount; i++) {
Guillaume Jeannecece24e2014-06-26 15:35:06 +020098 Store_field(array, i, Val_int(insn[j-1].detail->regs_write[i]));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080099 }
100 } else
101 array = Atom(0); // empty list
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200102 Store_field(rec_insn, 8, array);
103 Store_field(rec_insn, 9, Val_int(lcount));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800104
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200105
106 lcount = (insn[j-1]).detail->groups_count;
107 if (lcount) {
108 array = caml_alloc(lcount, 0);
109 for (i = 0; i < lcount; i++) {
110 Store_field(array, i, Val_int(insn[j-1].detail->groups[i]));
111 }
112 } else
113 array = Atom(0); // empty list
114 Store_field(rec_insn, 10, array);
115 Store_field(rec_insn, 11, Val_int(lcount));
116
117
118
119 if(insn[j-1].detail)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800120 switch(arch) {
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800121 case CS_ARCH_ARM:
122 arch_info = caml_alloc(1, 0);
123
124 op_info_val = caml_alloc(5, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200125 Store_field(op_info_val, 0, Val_int(insn[j-1].detail->arm.cc));
126 Store_field(op_info_val, 1, Val_bool(insn[j-1].detail->arm.update_flags));
127 Store_field(op_info_val, 2, Val_bool(insn[j-1].detail->arm.writeback));
128 Store_field(op_info_val, 3, Val_int(insn[j-1].detail->arm.op_count));
129 lcount = arm_list_count(insn[j - 1].detail->arm.operands, ARR_SIZE(insn[j - 1].detail->arm.operands));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800130 if (lcount > 0) {
131 array = caml_alloc(lcount, 0);
132 for (i = 0; i < lcount; i++) {
133 tmp2 = caml_alloc(2, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200134 switch(insn[j-1].detail->arm.operands[i].type) {
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800135 case ARM_OP_REG:
136 tmp = caml_alloc(1, 1);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200137 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm.operands[i].reg));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800138 break;
139 case ARM_OP_CIMM:
140 tmp = caml_alloc(1, 2);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200141 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm.operands[i].imm));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800142 break;
143 case ARM_OP_PIMM:
144 tmp = caml_alloc(1, 3);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200145 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm.operands[i].imm));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800146 break;
147 case ARM_OP_IMM:
148 tmp = caml_alloc(1, 4);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200149 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm.operands[i].imm));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800150 break;
151 case ARM_OP_FP:
152 tmp = caml_alloc(1, 5);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200153 Store_field(tmp, 0, caml_copy_double(insn[j-1].detail->arm.operands[i].fp));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800154 break;
155 case ARM_OP_MEM:
156 tmp = caml_alloc(1, 6);
157 tmp3 = caml_alloc(4, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200158 Store_field(tmp3, 0, Val_int(insn[j-1].detail->arm.operands[i].mem.base));
159 Store_field(tmp3, 1, Val_int(insn[j-1].detail->arm.operands[i].mem.index));
160 Store_field(tmp3, 2, Val_int(insn[j-1].detail->arm.operands[i].mem.scale));
161 Store_field(tmp3, 3, Val_int(insn[j-1].detail->arm.operands[i].mem.disp));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800162 Store_field(tmp, 0, tmp3);
163 break;
164 default: break;
165 }
166 tmp3 = caml_alloc(2, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200167 Store_field(tmp3, 0, Val_int(insn[j-1].detail->arm.operands[i].shift.type));
168 Store_field(tmp3, 1, Val_int(insn[j-1].detail->arm.operands[i].shift.value));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800169 Store_field(tmp2, 0, tmp3);
170 Store_field(tmp2, 1, tmp);
171 Store_field(array, i, tmp2);
172 }
173 } else // empty list
174 array = Atom(0);
175
176 Store_field(op_info_val, 4, array);
177
178 // finally, insert this into arch_info
179 Store_field(arch_info, 0, op_info_val);
180
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200181 Store_field(rec_insn, 12, arch_info);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800182
183 break;
184 case CS_ARCH_ARM64:
185 arch_info = caml_alloc(1, 1);
186
187 op_info_val = caml_alloc(5, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200188 Store_field(op_info_val, 0, Val_int(insn[j-1].detail->arm64.cc));
189 Store_field(op_info_val, 1, Val_bool(insn[j-1].detail->arm64.update_flags));
190 Store_field(op_info_val, 2, Val_bool(insn[j-1].detail->arm64.writeback));
191 Store_field(op_info_val, 3, Val_int(insn[j-1].detail->arm64.op_count));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800192
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200193 lcount = arm64_list_count(insn[j - 1].detail->arm64.operands, ARR_SIZE(insn[j - 1].detail->arm64.operands));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800194 if (lcount > 0) {
195 array = caml_alloc(lcount, 0);
196 for (i = 0; i < lcount; i++) {
197 tmp2 = caml_alloc(3, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200198 switch(insn[j-1].detail->arm64.operands[i].type) {
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800199 case ARM64_OP_REG:
200 tmp = caml_alloc(1, 1);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200201 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].reg));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800202 break;
203 case ARM64_OP_CIMM:
204 tmp = caml_alloc(1, 2);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200205 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].imm));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800206 break;
207 case ARM64_OP_IMM:
208 tmp = caml_alloc(1, 3);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200209 Store_field(tmp, 0, Val_int(insn[j-1].detail->arm64.operands[i].imm));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800210 break;
211 case ARM64_OP_FP:
212 tmp = caml_alloc(1, 4);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200213 Store_field(tmp, 0, caml_copy_double(insn[j-1].detail->arm64.operands[i].fp));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800214 break;
215 case ARM64_OP_MEM:
216 tmp = caml_alloc(1, 5);
217 tmp3 = caml_alloc(3, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200218 Store_field(tmp3, 0, Val_int(insn[j-1].detail->arm64.operands[i].mem.base));
219 Store_field(tmp3, 1, Val_int(insn[j-1].detail->arm64.operands[i].mem.index));
220 Store_field(tmp3, 2, Val_int(insn[j-1].detail->arm64.operands[i].mem.disp));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800221 Store_field(tmp, 0, tmp3);
222 break;
223 default: break;
224 }
225 tmp3 = caml_alloc(2, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200226 Store_field(tmp3, 0, Val_int(insn[j-1].detail->arm64.operands[i].shift.type));
227 Store_field(tmp3, 1, Val_int(insn[j-1].detail->arm64.operands[i].shift.value));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800228 Store_field(tmp2, 0, tmp3);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200229 Store_field(tmp2, 1, Val_int(insn[j-1].detail->arm64.operands[i].ext));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800230
231 Store_field(tmp2, 2, tmp);
232 Store_field(array, i, tmp2);
233 }
234 } else // empty array
235 array = Atom(0);
236
237 Store_field(op_info_val, 4, array);
238
239 // finally, insert this into arch_info
240 Store_field(arch_info, 0, op_info_val);
241
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200242 Store_field(rec_insn, 12, arch_info);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800243
244 break;
245 case CS_ARCH_MIPS:
246 arch_info = caml_alloc(1, 2);
247
248 op_info_val = caml_alloc(2, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200249 Store_field(op_info_val, 0, Val_int(insn[j-1].detail->mips.op_count));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800250
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200251 lcount = mips_list_count(insn[j - 1].detail->mips.operands, ARR_SIZE(insn[j - 1].detail->mips.operands));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800252 if (lcount > 0) {
253 array = caml_alloc(lcount, 0);
254 for (i = 0; i < lcount; i++) {
255 tmp2 = caml_alloc(1, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200256 switch(insn[j-1].detail->mips.operands[i].type) {
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800257 case MIPS_OP_REG:
258 tmp = caml_alloc(1, 1);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200259 Store_field(tmp, 0, Val_int(insn[j-1].detail->mips.operands[i].reg));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800260 break;
261 case MIPS_OP_IMM:
262 tmp = caml_alloc(1, 2);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200263 Store_field(tmp, 0, Val_int(insn[j-1].detail->mips.operands[i].imm));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800264 break;
265 case MIPS_OP_MEM:
266 tmp = caml_alloc(1, 3);
267 tmp3 = caml_alloc(2, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200268 Store_field(tmp3, 0, Val_int(insn[j-1].detail->mips.operands[i].mem.base));
269 Store_field(tmp3, 1, Val_int(insn[j-1].detail->mips.operands[i].mem.disp));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800270 Store_field(tmp, 0, tmp3);
271 break;
272 default: break;
273 }
274 Store_field(tmp2, 0, tmp);
275 Store_field(array, i, tmp2);
276 }
277 } else // empty array
278 array = Atom(0);
279
280 Store_field(op_info_val, 1, array);
281
282 // finally, insert this into arch_info
283 Store_field(arch_info, 0, op_info_val);
284
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200285 Store_field(rec_insn, 12, arch_info);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800286
287 break;
Guillaume Jeannee002ac72014-06-30 15:46:04 +0200288 case CS_ARCH_PPC:
289
290 arch_info = caml_alloc(1, 3);
291
292 op_info_val = caml_alloc(5, 0);
293
294 Store_field(op_info_val, 0, Val_int(insn[j-1].detail->ppc.bc));
295 Store_field(op_info_val, 1, Val_int(insn[j-1].detail->ppc.bh));
296 Store_field(op_info_val, 2, Val_bool(insn[j-1].detail->ppc.update_cr0));
297
298 lcount = insn[j-1].detail->ppc.op_count;
299
300 Store_field(op_info_val, 3, Val_int(lcount));
301
302 if (lcount > 0) {
303 array = caml_alloc(lcount, 0);
304 for (i = 0; i < lcount; i++) {
305 tmp2 = caml_alloc(1, 0);
306 switch(insn[j-1].detail->ppc.operands[i].type) {
307 case PPC_OP_REG:
308 tmp = caml_alloc(1, 1);
309 Store_field(tmp, 0, Val_int(insn[j-1].detail->ppc.operands[i].reg));
310 break;
311 case PPC_OP_IMM:
312 tmp = caml_alloc(1, 2);
313 Store_field(tmp, 0, Val_int(insn[j-1].detail->ppc.operands[i].imm));
314 break;
315 case PPC_OP_MEM:
316 tmp = caml_alloc(1, 3);
317 tmp3 = caml_alloc(2, 0);
318 Store_field(tmp3, 0, Val_int(insn[j-1].detail->ppc.operands[i].mem.base));
319 Store_field(tmp3, 1, Val_int(insn[j-1].detail->ppc.operands[i].mem.disp));
320 Store_field(tmp, 0, tmp3);
321 break;
322 default: break;
323 }
324 Store_field(tmp2, 0, tmp);
325 Store_field(array, i, tmp2);
326 }
327 } else // empty array
328 array = Atom(0);
329
330 Store_field(op_info_val, 4, array);
331
332 // finally, insert this into arch_info
333 Store_field(arch_info, 0, op_info_val);
334
335 Store_field(rec_insn, 12, arch_info);
336
337 break;
338
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800339 case CS_ARCH_X86:
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200340
Guillaume Jeannee002ac72014-06-30 15:46:04 +0200341 arch_info = caml_alloc(1, 4);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800342
343 op_info_val = caml_alloc(15, 0);
344
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200345 // fill prefix
346 lcount = list_count(insn[j-1].detail->x86.prefix, ARR_SIZE(insn[j-1].detail->x86.prefix));
347 if(lcount) {
348 array = caml_alloc(lcount, 0);
349 for (i = 0; i < lcount; i++) {
350 Store_field(array, i, Val_int(insn[j-1].detail->x86.prefix[i]));
351 }
352 } else
353 array = Atom(0);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800354 Store_field(op_info_val, 0, array);
355
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200356 Store_field(op_info_val, 1, Val_int(insn[j-1].detail->x86.segment));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800357
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200358 // fill opcode
359 lcount = list_count(insn[j-1].detail->x86.opcode, ARR_SIZE(insn[j-1].detail->x86.opcode));
360 if(lcount) {
361 array = caml_alloc(lcount, 0);
362 for (i = 0; i < lcount; i++) {
363 Store_field(array, i, Val_int(insn[j-1].detail->x86.opcode[i]));
364 }
365 } else
366 array = Atom(0);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800367 Store_field(op_info_val, 2, array);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200368 Store_field(op_info_val, 3, Val_int(insn[j-1].detail->x86.op_size));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800369
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200370 Store_field(op_info_val, 4, Val_int(insn[j-1].detail->x86.addr_size));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800371
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200372 Store_field(op_info_val, 5, Val_int(insn[j-1].detail->x86.disp_size));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800373
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200374 Store_field(op_info_val, 6, Val_int(insn[j-1].detail->x86.imm_size));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800375
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200376 Store_field(op_info_val, 7, Val_int(insn[j-1].detail->x86.modrm));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800377
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200378 Store_field(op_info_val, 8, Val_int(insn[j-1].detail->x86.sib));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800379
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200380 Store_field(op_info_val, 9, Val_int(insn[j-1].detail->x86.disp));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800381
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200382 Store_field(op_info_val, 10, Val_int(insn[j-1].detail->x86.sib_index));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800383
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200384 Store_field(op_info_val, 11, Val_int(insn[j-1].detail->x86.sib_scale));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800385
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200386 Store_field(op_info_val, 12, Val_int(insn[j-1].detail->x86.sib_base));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800387
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200388 Store_field(op_info_val, 13, Val_int(insn[j-1].detail->x86.op_count));
389 lcount = x86_list_count(insn[j - 1].detail->x86.operands, ARR_SIZE(insn[j - 1].detail->x86.operands));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800390 if (lcount > 0) {
391 array = caml_alloc(lcount, 0);
392 for (i = 0; i < lcount; i++) {
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200393 switch(insn[j-1].detail->x86.operands[i].type) {
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800394 case X86_OP_REG:
395 tmp = caml_alloc(1, 1);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200396 Store_field(tmp, 0, Val_int(insn[j-1].detail->x86.operands[i].reg));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800397 break;
398 case X86_OP_IMM:
399 tmp = caml_alloc(1, 2);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200400 Store_field(tmp, 0, Val_int(insn[j-1].detail->x86.operands[i].imm));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800401 break;
402 case X86_OP_FP:
403 tmp = caml_alloc(1, 3);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200404 Store_field(tmp, 0, caml_copy_double(insn[j-1].detail->x86.operands[i].fp));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800405 break;
406 case X86_OP_MEM:
407 tmp = caml_alloc(1, 4);
408 tmp2 = caml_alloc(4, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200409 Store_field(tmp2, 0, Val_int(insn[j-1].detail->x86.operands[i].mem.base));
410 Store_field(tmp2, 1, Val_int(insn[j-1].detail->x86.operands[i].mem.index));
411 Store_field(tmp2, 2, Val_int(insn[j-1].detail->x86.operands[i].mem.scale));
412 Store_field(tmp2, 3, Val_int(insn[j-1].detail->x86.operands[i].mem.disp));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800413 Store_field(tmp, 0, tmp2);
414 break;
415 default:
416 break;
417 }
418 Store_field(array, i, tmp);
419 }
420 } else
421 array = Atom(0); // empty array
422
423 Store_field(op_info_val, 14, array);
424
425 // finally, insert this into arch_info
426 Store_field(arch_info, 0, op_info_val);
427
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200428 Store_field(rec_insn, 12, arch_info);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800429 break;
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200430
431 default: break;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800432 }
433
434 Store_field(cons, 0, rec_insn); // head
435 Store_field(cons, 1, list); // tail
436 list = cons;
437 }
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200438 cs_free(insn, count);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800439 }
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200440 // do not free the handle here
441 //cs_close(&handle);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800442 CAMLreturn(list);
443}
444
445CAMLprim value ocaml_cs_disasm_quick(value _arch, value _mode, value _code, value _addr, value _count)
446{
447 CAMLparam5(_arch, _mode, _code, _addr, _count);
448 CAMLlocal1(head);
449 csh handle;
450 cs_arch arch;
451 cs_mode mode = 0;
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200452 const uint8_t *code;
453 uint64_t addr;
454 size_t count, code_len;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800455
456 switch (Int_val(_arch)) {
457 case 0:
458 arch = CS_ARCH_ARM;
459 break;
460 case 1:
461 arch = CS_ARCH_ARM64;
462 break;
463 case 2:
464 arch = CS_ARCH_MIPS;
465 break;
466 case 3:
Guillaume Jeannee002ac72014-06-30 15:46:04 +0200467 arch = CS_ARCH_PPC;
468 break;
469 case 4:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800470 arch = CS_ARCH_X86;
471 break;
472 default:
473 caml_invalid_argument("Error message");
474 return Val_emptylist;
475 }
476
477 while (_mode != Val_emptylist) {
478 head = Field(_mode, 0); /* accessing the head */
479 switch (Int_val(head)) {
480 case 0:
481 mode |= CS_MODE_LITTLE_ENDIAN;
482 break;
483 case 1:
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200484 mode |= CS_OPT_SYNTAX_INTEL;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800485 break;
486 case 2:
487 mode |= CS_MODE_ARM;
488 break;
489 case 3:
490 mode |= CS_MODE_16;
491 break;
492 case 4:
493 mode |= CS_MODE_32;
494 break;
495 case 5:
496 mode |= CS_MODE_64;
497 break;
498 case 6:
499 mode |= CS_MODE_THUMB;
500 break;
501 case 7:
502 mode |= CS_MODE_MICRO;
503 break;
504 case 8:
505 mode |= CS_MODE_N64;
506 break;
507 case 9:
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200508 mode |= CS_OPT_SYNTAX_ATT;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800509 break;
510 case 10:
511 mode |= CS_MODE_BIG_ENDIAN;
512 break;
513 default:
514 caml_invalid_argument("Error message");
515 return Val_emptylist;
516 }
517 _mode = Field(_mode, 1); /* point to the tail for next loop */
518 }
519
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200520 //CS_ERR_OK = 0, // No error: everything was fine
521 if (cs_open(arch, mode, &handle) != 0)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800522 return Val_emptylist;
523
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200524 if (cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON) != 0)
525 CAMLreturn(Val_int(0));
526
527 code = (uint8_t *)String_val(_code);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800528 code_len = caml_string_length(_code);
529 addr = Int64_val(_addr);
530 count = Int64_val(_count);
531
532 CAMLreturn(_cs_disasm(arch, handle, code, code_len, addr, count));
533}
534
535CAMLprim value ocaml_cs_disasm_dyn(value _arch, value _handle, value _code, value _addr, value _count)
536{
537 CAMLparam5(_arch, _handle, _code, _addr, _count);
538 csh handle;
539 cs_arch arch;
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200540 const uint8_t *code;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800541 uint64_t addr, count, code_len;
542
543 handle = Int64_val(_handle);
544
545 arch = Int_val(_arch);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200546 code = (uint8_t *)String_val(_code);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800547 code_len = caml_string_length(_code);
548 addr = Int64_val(_addr);
549 count = Int64_val(_count);
550
551 CAMLreturn(_cs_disasm(arch, handle, code, code_len, addr, count));
552}
553
554CAMLprim value ocaml_cs_open(value _arch, value _mode)
555{
556 CAMLparam2(_arch, _mode);
557 CAMLlocal2(list, head);
558 csh handle;
559 cs_arch arch;
560 cs_mode mode = 0;
561
562 list = Val_emptylist;
563
564 switch (Int_val(_arch)) {
565 case 0:
566 arch = CS_ARCH_ARM;
567 break;
568 case 1:
569 arch = CS_ARCH_ARM64;
570 break;
571 case 2:
572 arch = CS_ARCH_MIPS;
573 break;
574 case 3:
Guillaume Jeannee002ac72014-06-30 15:46:04 +0200575 arch = CS_ARCH_PPC;
576 break;
577 case 4:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800578 arch = CS_ARCH_X86;
579 break;
580 default:
581 caml_invalid_argument("Error message");
582 return Val_emptylist;
583 }
584
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200585
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800586 while (_mode != Val_emptylist) {
587 head = Field(_mode, 0); /* accessing the head */
588 switch (Int_val(head)) {
589 case 0:
590 mode |= CS_MODE_LITTLE_ENDIAN;
591 break;
592 case 1:
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200593 mode |= CS_OPT_SYNTAX_INTEL;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800594 break;
595 case 2:
596 mode |= CS_MODE_ARM;
597 break;
598 case 3:
599 mode |= CS_MODE_16;
600 break;
601 case 4:
602 mode |= CS_MODE_32;
603 break;
604 case 5:
605 mode |= CS_MODE_64;
606 break;
607 case 6:
608 mode |= CS_MODE_THUMB;
609 break;
610 case 7:
611 mode |= CS_MODE_MICRO;
612 break;
613 case 8:
614 mode |= CS_MODE_N64;
615 break;
616 case 9:
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200617 mode |= CS_OPT_SYNTAX_ATT;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800618 break;
619 case 10:
620 mode |= CS_MODE_BIG_ENDIAN;
621 break;
622 default:
623 caml_invalid_argument("Error message");
624 return Val_emptylist;
625 }
626 _mode = Field(_mode, 1); /* point to the tail for next loop */
627 }
628
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200629 if (cs_open(arch, mode, &handle) != 0)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800630 CAMLreturn(Val_int(0));
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200631
632 if (cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON) != 0)
633 CAMLreturn(Val_int(0));
634
635 CAMLlocal1(result);
636 result = caml_alloc(1, 0);
637 Store_field(result, 0, caml_copy_int64(handle));
638 CAMLreturn(result);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800639}
640
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200641CAMLprim value cs_register_name(value _handle, value _reg)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800642{
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200643 const char *name = cs_reg_name(Int64_val(_handle), Int_val(_reg));
644 if(!name) {
645 caml_invalid_argument("invalid reg_id");
646 name = "invalid";
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800647 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800648 return caml_copy_string(name);
649}
650
651CAMLprim value cs_instruction_name(value _handle, value _insn)
652{
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200653 const char *name = cs_insn_name(Int64_val(_handle), Int_val(_insn));
654 if(!name) {
655 caml_invalid_argument("invalid insn_id");
656 name = "invalid";
657 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800658 return caml_copy_string(name);
659}