blob: dded8a1fe69b197643df3d717d0f176d5d118314 [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
Guillaume Jeannecece24e2014-06-26 15:35:06 +020015
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080016// count the number of positive members in @list
Guillaume Jeannecece24e2014-06-26 15:35:06 +020017static unsigned int list_count(uint8_t *list, unsigned int max)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080018{
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
Guillaume Jeannecece24e2014-06-26 15:35:06 +020028CAMLprim 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 +080029{
30 CAMLparam0();
31 CAMLlocal5(list, cons, rec_insn, array, tmp);
32 CAMLlocal4(arch_info, op_info_val, tmp2, tmp3);
33 cs_insn *insn;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +080034 size_t c;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080035
36 list = Val_emptylist;
37
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +080038 c = cs_disasm(handle, code, code_len, addr, count, &insn);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080039 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;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080044 cons = caml_alloc(2, 0);
45
Nguyen Anh Quynh6dc1dd52014-09-27 00:40:34 +080046 rec_insn = caml_alloc(10, 0);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080047 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));
Jay Oster79e253c2014-10-12 16:03:12 -070050
Guillaume Jeannecece24e2014-06-26 15:35:06 +020051 // copy raw bytes of instruction
52 lcount = insn[j-1].size;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080053 if (lcount) {
54 array = caml_alloc(lcount, 0);
55 for (i = 0; i < lcount; i++) {
Guillaume Jeannecece24e2014-06-26 15:35:06 +020056 Store_field(array, i, Val_int(insn[j-1].bytes[i]));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080057 }
Guillaume Jeannecece24e2014-06-26 15:35:06 +020058 } else
59 array = Atom(0); // empty list
60 Store_field(rec_insn, 3, array);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080061
Nguyen Anh Quynh443af142014-09-26 00:48:05 +080062 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));
Guillaume Jeannecece24e2014-06-26 15:35:06 +020064
65 // copy read registers
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +080066 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
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080075 } else
76 array = Atom(0); // empty list
77 Store_field(rec_insn, 6, array);
78
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +080079 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
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080088 } else
89 array = Atom(0); // empty list
Nguyen Anh Quynh6dc1dd52014-09-27 00:40:34 +080090 Store_field(rec_insn, 7, array);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +080091
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +080092 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
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200101 } else
102 array = Atom(0); // empty list
Nguyen Anh Quynh6dc1dd52014-09-27 00:40:34 +0800103 Store_field(rec_insn, 8, array);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200104
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +0800105 if (insn[j-1].detail) {
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800106 switch(arch) {
107 case CS_ARCH_ARM:
108 arch_info = caml_alloc(1, 0);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200109
Nguyen Anh Quynh0b3d95e2014-11-11 23:00:35 +0800110 op_info_val = caml_alloc(10, 0);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800111 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));
Nguyen Anh Quynh0b3d95e2014-11-11 23:00:35 +0800119 Store_field(op_info_val, 8, Val_int(insn[j-1].detail->arm.mem_barrier));
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200120
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800121 lcount = insn[j-1].detail->arm.op_count;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800122 if (lcount > 0) {
123 array = caml_alloc(lcount, 0);
124 for (i = 0; i < lcount; i++) {
Nguyen Anh Quynhb0cc71d2014-10-06 21:01:32 +0800125 tmp2 = caml_alloc(4, 0);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800126 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);
Nguyen Anh Quynhb0cc71d2014-10-06 21:01:32 +0800169 Store_field(tmp2, 3, Val_bool(insn[j-1].detail->arm.operands[i].subtracted));
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800170 Store_field(array, i, tmp2);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800171 }
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800172 } else // empty list
173 array = Atom(0);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800174
Nguyen Anh Quynh0b3d95e2014-11-11 23:00:35 +0800175 Store_field(op_info_val, 9, array);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800176
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800177 // finally, insert this into arch_info
178 Store_field(arch_info, 0, op_info_val);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800179
Nguyen Anh Quynh6dc1dd52014-09-27 00:40:34 +0800180 Store_field(rec_insn, 9, arch_info);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800181
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800182 break;
183 case CS_ARCH_ARM64:
184 arch_info = caml_alloc(1, 1);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800185
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800186 op_info_val = caml_alloc(4, 0);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800187 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));
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800190
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800191 lcount = insn[j-1].detail->arm64.op_count;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800192 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));
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800250
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800251 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);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800257
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800258 Store_field(array, i, tmp2);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800259 }
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800260 } else // empty array
261 array = Atom(0);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800262
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800263 Store_field(op_info_val, 3, array);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800264
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800265 // finally, insert this into arch_info
266 Store_field(arch_info, 0, op_info_val);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800267
Nguyen Anh Quynh6dc1dd52014-09-27 00:40:34 +0800268 Store_field(rec_insn, 9, arch_info);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200269
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800270 break;
271 case CS_ARCH_MIPS:
272 arch_info = caml_alloc(1, 2);
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200273
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800274 op_info_val = caml_alloc(1, 0);
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200275
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800276 lcount = insn[j-1].detail->mips.op_count;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800277 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);
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200304
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800305 Store_field(op_info_val, 0, array);
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200306
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800307 // finally, insert this into arch_info
308 Store_field(arch_info, 0, op_info_val);
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200309
Nguyen Anh Quynh6dc1dd52014-09-27 00:40:34 +0800310 Store_field(rec_insn, 9, arch_info);
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200311
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800312 break;
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800313 case CS_ARCH_X86:
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800314 arch_info = caml_alloc(1, 3);
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200315
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800316 op_info_val = caml_alloc(15, 0);
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200317
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800318 // fill prefix
319 lcount = list_count(insn[j-1].detail->x86.prefix, ARR_SIZE(insn[j-1].detail->x86.prefix));
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800320 if (lcount) {
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800321 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);
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200328
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800329 // fill opcode
330 lcount = list_count(insn[j-1].detail->x86.opcode, ARR_SIZE(insn[j-1].detail->x86.opcode));
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +0800331 if (lcount) {
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800332 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);
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200339
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800340 Store_field(op_info_val, 2, Val_int(insn[j-1].detail->x86.rex));
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200341
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800342 Store_field(op_info_val, 3, Val_int(insn[j-1].detail->x86.addr_size));
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200343
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800344 Store_field(op_info_val, 4, Val_int(insn[j-1].detail->x86.modrm));
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200345
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800346 Store_field(op_info_val, 5, Val_int(insn[j-1].detail->x86.sib));
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200347
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800348 Store_field(op_info_val, 6, Val_int(insn[j-1].detail->x86.disp));
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200349
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800350 Store_field(op_info_val, 7, Val_int(insn[j-1].detail->x86.sib_index));
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200351
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800352 Store_field(op_info_val, 8, Val_int(insn[j-1].detail->x86.sib_scale));
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200353
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800354 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;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800362 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));
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800386
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800387 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));
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800395 tmp2 = caml_alloc(1, 0);
396 Store_field(tmp2, 0, tmp);
397 Store_field(array, i, tmp2);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800398 }
399 } else // empty array
400 array = Atom(0);
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800401 Store_field(op_info_val, 14, array);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800402
403 // finally, insert this into arch_info
404 Store_field(arch_info, 0, op_info_val);
405
Nguyen Anh Quynh6dc1dd52014-09-27 00:40:34 +0800406 Store_field(rec_insn, 9, arch_info);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800407 break;
408
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800409 case CS_ARCH_PPC:
410 arch_info = caml_alloc(1, 4);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800411
412 op_info_val = caml_alloc(4, 0);
413
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800414 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;
Nguyen Anh Quynh9dbb2f02014-10-17 22:27:26 +0800439 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;
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800447 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
Nguyen Anh Quynh6dc1dd52014-09-27 00:40:34 +0800460 Store_field(rec_insn, 9, arch_info);
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800461
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
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800469 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;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800473 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
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800502 Store_field(op_info_val, 2, array);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800503
504 // finally, insert this into arch_info
505 Store_field(arch_info, 0, op_info_val);
506
Nguyen Anh Quynh6dc1dd52014-09-27 00:40:34 +0800507 Store_field(rec_insn, 9, arch_info);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800508
509 break;
510
511 case CS_ARCH_SYSZ:
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800512 arch_info = caml_alloc(1, 6);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800513
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800514 op_info_val = caml_alloc(2, 0);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800515
516 Store_field(op_info_val, 0, Val_int(insn[j-1].detail->sysz.cc));
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800517
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800518 lcount = insn[j-1].detail->sysz.op_count;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800519 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;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800528 case SYSZ_OP_ACREG:
529 tmp = caml_alloc(1, 2);
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800530 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));
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800535 break;
536 case SYSZ_OP_MEM:
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800537 tmp = caml_alloc(1, 4);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800538 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
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800553 Store_field(op_info_val, 1, array);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800554
555 // finally, insert this into arch_info
556 Store_field(arch_info, 0, op_info_val);
557
Nguyen Anh Quynh6dc1dd52014-09-27 00:40:34 +0800558 Store_field(rec_insn, 9, arch_info);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800559
560 break;
561
562 case CS_ARCH_XCORE:
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800563 arch_info = caml_alloc(1, 7);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800564
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800565 op_info_val = caml_alloc(1, 0);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800566
567 lcount = insn[j-1].detail->xcore.op_count;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800568 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
Nguyen Anh Quynh81a97c62014-09-26 23:38:53 +0800598 Store_field(op_info_val, 0, array);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800599
600 // finally, insert this into arch_info
601 Store_field(arch_info, 0, op_info_val);
602
Nguyen Anh Quynh6dc1dd52014-09-27 00:40:34 +0800603 Store_field(rec_insn, 9, arch_info);
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800604
605 break;
606
607 default: break;
608 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800609 }
610
611 Store_field(cons, 0, rec_insn); // head
612 Store_field(cons, 1, list); // tail
613 list = cons;
614 }
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200615 cs_free(insn, count);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800616 }
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800617
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200618 // do not free the handle here
619 //cs_close(&handle);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800620 CAMLreturn(list);
621}
622
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800623CAMLprim value ocaml_cs_disasm(value _arch, value _mode, value _code, value _addr, value _count)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800624{
625 CAMLparam5(_arch, _mode, _code, _addr, _count);
626 CAMLlocal1(head);
627 csh handle;
628 cs_arch arch;
629 cs_mode mode = 0;
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200630 const uint8_t *code;
631 uint64_t addr;
632 size_t count, code_len;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800633
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:
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200645 arch = CS_ARCH_X86;
Guillaume Jeannee002ac72014-06-30 15:46:04 +0200646 break;
647 case 4:
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200648 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;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800659 default:
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800660 caml_invalid_argument("Invalid arch");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800661 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:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800671 mode |= CS_MODE_ARM;
672 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200673 case 2:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800674 mode |= CS_MODE_16;
675 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200676 case 3:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800677 mode |= CS_MODE_32;
678 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200679 case 4:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800680 mode |= CS_MODE_64;
681 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200682 case 5:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800683 mode |= CS_MODE_THUMB;
684 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200685 case 6:
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800686 mode |= CS_MODE_MCLASS;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800687 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200688 case 7:
Nguyen Anh Quynh8e538902014-11-10 22:06:23 +0800689 mode |= CS_MODE_V8;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800690 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200691 case 8:
Nguyen Anh Quynh8e538902014-11-10 22:06:23 +0800692 mode |= CS_MODE_MICRO;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800693 break;
Jay Oster79e253c2014-10-12 16:03:12 -0700694 case 9:
Nguyen Anh Quynh8e538902014-11-10 22:06:23 +0800695 mode |= CS_MODE_MIPS3;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800696 break;
Jay Oster79e253c2014-10-12 16:03:12 -0700697 case 10:
Nguyen Anh Quynh8e538902014-11-10 22:06:23 +0800698 mode |= CS_MODE_MIPS32R6;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800699 break;
Jay Oster79e253c2014-10-12 16:03:12 -0700700 case 11:
Nguyen Anh Quynh8e538902014-11-10 22:06:23 +0800701 mode |= CS_MODE_MIPSGP64;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800702 break;
Jay Oster79e253c2014-10-12 16:03:12 -0700703 case 12:
Nguyen Anh Quynh8e538902014-11-10 22:06:23 +0800704 mode |= CS_MODE_V9;
705 break;
706 case 13:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800707 mode |= CS_MODE_BIG_ENDIAN;
708 break;
Nguyen Anh Quynhff9a5742014-11-13 12:09:49 +0800709 case 14:
710 mode |= CS_MODE_MIPS32;
711 break;
712 case 15:
713 mode |= CS_MODE_MIPS64;
714 break;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800715 default:
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800716 caml_invalid_argument("Invalid mode");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800717 return Val_emptylist;
718 }
719 _mode = Field(_mode, 1); /* point to the tail for next loop */
720 }
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800721
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200722 cs_err ret = cs_open(arch, mode, &handle);
723 if (ret != CS_ERR_OK) {
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800724 return Val_emptylist;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200725 }
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800726
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200727 code = (uint8_t *)String_val(_code);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800728 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
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800735CAMLprim value ocaml_cs_disasm_internal(value _arch, value _handle, value _code, value _addr, value _count)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800736{
737 CAMLparam5(_arch, _handle, _code, _addr, _count);
738 csh handle;
739 cs_arch arch;
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200740 const uint8_t *code;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800741 uint64_t addr, count, code_len;
742
743 handle = Int64_val(_handle);
Jay Oster79e253c2014-10-12 16:03:12 -0700744
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800745 arch = Int_val(_arch);
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200746 code = (uint8_t *)String_val(_code);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800747 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
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +0800754CAMLprim value ocaml_open(value _arch, value _mode)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800755{
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:
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200775 arch = CS_ARCH_X86;
Guillaume Jeannee002ac72014-06-30 15:46:04 +0200776 break;
777 case 4:
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200778 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;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800789 default:
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800790 caml_invalid_argument("Invalid arch");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800791 return Val_emptylist;
792 }
793
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200794
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800795 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:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800802 mode |= CS_MODE_ARM;
803 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200804 case 2:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800805 mode |= CS_MODE_16;
806 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200807 case 3:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800808 mode |= CS_MODE_32;
809 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200810 case 4:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800811 mode |= CS_MODE_64;
812 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200813 case 5:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800814 mode |= CS_MODE_THUMB;
815 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200816 case 6:
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800817 mode |= CS_MODE_MCLASS;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800818 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200819 case 7:
Nguyen Anh Quynh7b7d7452014-11-12 10:26:17 +0800820 mode |= CS_MODE_V8;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800821 break;
Guillaume Jeanneae48c972014-08-19 14:46:06 +0200822 case 8:
Nguyen Anh Quynh7b7d7452014-11-12 10:26:17 +0800823 mode |= CS_MODE_MICRO;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800824 break;
Jay Oster79e253c2014-10-12 16:03:12 -0700825 case 9:
Nguyen Anh Quynh7b7d7452014-11-12 10:26:17 +0800826 mode |= CS_MODE_MIPS3;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800827 break;
Jay Oster79e253c2014-10-12 16:03:12 -0700828 case 10:
Nguyen Anh Quynh7b7d7452014-11-12 10:26:17 +0800829 mode |= CS_MODE_MIPS32R6;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800830 break;
Jay Oster79e253c2014-10-12 16:03:12 -0700831 case 11:
Nguyen Anh Quynh7b7d7452014-11-12 10:26:17 +0800832 mode |= CS_MODE_MIPSGP64;
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800833 break;
Jay Oster79e253c2014-10-12 16:03:12 -0700834 case 12:
Nguyen Anh Quynh7b7d7452014-11-12 10:26:17 +0800835 mode |= CS_MODE_V9;
836 break;
837 case 13:
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800838 mode |= CS_MODE_BIG_ENDIAN;
839 break;
Nguyen Anh Quynhff9a5742014-11-13 12:09:49 +0800840 case 14:
841 mode |= CS_MODE_MIPS32;
842 break;
843 case 15:
844 mode |= CS_MODE_MIPS64;
845 break;
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800846 default:
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800847 caml_invalid_argument("Invalid mode");
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800848 return Val_emptylist;
849 }
850 _mode = Field(_mode, 1); /* point to the tail for next loop */
851 }
852
Jay Oster79e253c2014-10-12 16:03:12 -0700853 if (cs_open(arch, mode, &handle) != 0)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800854 CAMLreturn(Val_int(0));
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200855
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200856 CAMLlocal1(result);
857 result = caml_alloc(1, 0);
858 Store_field(result, 0, caml_copy_int64(handle));
859 CAMLreturn(result);
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800860}
861
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +0800862CAMLprim 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
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800897CAMLprim value ocaml_register_name(value _handle, value _reg)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800898{
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200899 const char *name = cs_reg_name(Int64_val(_handle), Int_val(_reg));
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +0800900 if (!name) {
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200901 caml_invalid_argument("invalid reg_id");
902 name = "invalid";
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800903 }
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +0800904
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800905 return caml_copy_string(name);
906}
907
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800908CAMLprim value ocaml_instruction_name(value _handle, value _insn)
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800909{
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200910 const char *name = cs_insn_name(Int64_val(_handle), Int_val(_insn));
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +0800911 if (!name) {
Guillaume Jeannecece24e2014-06-26 15:35:06 +0200912 caml_invalid_argument("invalid insn_id");
913 name = "invalid";
914 }
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +0800915
Nguyen Anh Quynh26ee41a2013-11-27 12:11:31 +0800916 return caml_copy_string(name);
917}
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800918
919CAMLprim value ocaml_group_name(value _handle, value _insn)
920{
921 const char *name = cs_group_name(Int64_val(_handle), Int_val(_insn));
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +0800922 if (!name) {
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800923 caml_invalid_argument("invalid insn_id");
924 name = "invalid";
925 }
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +0800926
Nguyen Anh Quynh77d93e92014-09-25 23:03:36 +0800927 return caml_copy_string(name);
928}
929
930CAMLprim value ocaml_version(void)
931{
932 int version = cs_version(NULL, NULL);
933 return Val_int(version);
934}
Nguyen Anh Quynhfe4822c2014-10-04 16:30:02 +0800935
936CAMLprim 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}