1 /* Capstone Disassembler Engine */ 2 /* By Nguyen Anh Quynh <aquynh (at) 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 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 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 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 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 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 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 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 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 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 930 CAMLprim value ocaml_version(void) 931 { 932 int version = cs_version(NULL, NULL); 933 return Val_int(version); 934 } 935 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