Merge branch 'next' of git://github.com/aquynh/capstone into xcodeproj

test2
Félix Cloutier 10 years ago
commit 1dcd737f34
  1. 3
      .gitignore
  2. 4
      CMakeLists.txt
  3. 2
      COMPILE.TXT
  4. 3
      CREDITS.TXT
  5. 116
      arch/ARM/ARMInstPrinter.c
  6. 8
      arch/Mips/MipsDisassembler.c
  7. 3
      arch/Mips/MipsMapping.c
  8. 2
      arch/Mips/MipsModule.c
  9. 4
      arch/PowerPC/PPCInstPrinter.c
  10. 2
      bindings/java/TestArm.java
  11. 4
      bindings/java/capstone/Arm.java
  12. 8
      bindings/java/capstone/Capstone.java
  13. 15
      bindings/java/capstone/Mips_const.java
  14. 1
      bindings/ocaml/arm.ml
  15. 79
      bindings/ocaml/capstone.ml
  16. 15
      bindings/ocaml/mips_const.ml
  17. 143
      bindings/ocaml/ocaml.c
  18. 65
      bindings/ocaml/test.ml
  19. 94
      bindings/ocaml/test_arm.ml
  20. 92
      bindings/ocaml/test_arm64.ml
  21. 66
      bindings/ocaml/test_detail.ml
  22. 75
      bindings/ocaml/test_mips.ml
  23. 74
      bindings/ocaml/test_ppc.ml
  24. 74
      bindings/ocaml/test_sparc.ml
  25. 75
      bindings/ocaml/test_systemz.ml
  26. 144
      bindings/ocaml/test_x86.ml
  27. 72
      bindings/ocaml/test_xcore.ml
  28. 8
      bindings/python/capstone/__init__.py
  29. 1
      bindings/python/capstone/arm.py
  30. 15
      bindings/python/capstone/mips_const.py
  31. 4
      bindings/python/test_arm.py
  32. 116
      cs.c
  33. 4
      docs/README
  34. 3
      include/arm.h
  35. 135
      include/capstone.h
  36. 1
      include/mips.h
  37. 2
      suite/MC/Mips/nabi-regs.s.cs
  38. 2
      tests/Makefile
  39. 9
      tests/README
  40. 5
      tests/test_arm.c
  41. 3
      tests/test_detail.c
  42. 264
      tests/test_iter.c

3
.gitignore vendored

@ -47,6 +47,7 @@ bindings/ocaml/test_xcore
# test binaries
tests/test
tests/test_detail
tests/test_iter
tests/test_arm
tests/test_arm64
tests/test_mips
@ -85,3 +86,5 @@ xcode/Capstone.xcodeproj/xcuserdata
# suite/
test_arm_regression
test_arm_regression.o
*.s

@ -22,7 +22,7 @@ option(CAPSTONE_SYSZ_SUPPORT "SystemZ support" ON)
option(CAPSTONE_XCORE_SUPPORT "XCore support" ON)
option(CAPSTONE_X86_SUPPORT "x86 support" ON)
option(CAPSTONE_X86_REDUCE "x86 with reduce instruction sets to minimize library" OFF)
option(CAPSTONE_X86_ATT_DISABLE, "Disable x86 AT&T syntax" OFF)
option(CAPSTONE_X86_ATT_DISABLE "Disable x86 AT&T syntax" OFF)
if (CAPSTONE_BUILD_DIET)
add_definitions(-DCAPSTONE_DIET)
@ -50,7 +50,7 @@ set(SOURCES
utils.c
)
set(TEST_SOURCES test.c test_detail.c test_skipdata.c)
set(TEST_SOURCES test.c test_detail.c test_skipdata.c test_iter.c)
## architecture support
if (CAPSTONE_ARM_SUPPORT)

@ -5,6 +5,8 @@ To natively compile for Windows using Microsoft Visual Studio, see COMPILE_MSVC.
To compile using CMake, see COMPILE_CMAKE.TXT.
To compile using XCode on MacOSX, see xcode/README.md.
*-*-*-*-*-*
Capstone requires no prerequisite packages, so it is easy to compile & install.

@ -50,3 +50,6 @@ Daniel Pistelli: Cmake support.
Peter Hlavaty: integrate Capstone for Windows kernel drivers.
Guillaume Jeanne: Ocaml binding.
Martin Tofall, Obsidium Software: Optimize X86 performance & size.
David Martínez Moreno: Debian package.
Félix Cloutier: Xcode project.
Benoit Lecocq: OpenBSD package.

@ -49,7 +49,6 @@ static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned OpNum, SStream *O);
static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
static void printAddrMode3Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
static void printAM3PostIndexOp(MCInst *MI, unsigned Op, SStream *O);
static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O, bool AlwaysPrintImm0);
static void printPostIdxImm8Operand(MCInst *MI, unsigned OpNum, SStream *O);
static void printPostIdxRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
@ -758,6 +757,7 @@ static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O)
MCOperand *MO1 = MCInst_getOperand(MI, Op);
MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
MCOperand *MO3 = MCInst_getOperand(MI, Op + 2);
ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO3));
SStream_concat0(O, "[");
set_mem_access(MI, true);
@ -770,14 +770,17 @@ static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O)
if (!MCOperand_getReg(MO2)) {
unsigned tmp = getAM2Offset((unsigned int)MCOperand_getImm(MO3));
if (tmp) { // Don't print +0.
subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO3));
SStream_concat0(O, ", ");
if (tmp > HEX_THRESHOLD)
SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO3))), tmp);
SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), tmp);
else
SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO3))), tmp);
SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), tmp);
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (arm_shifter)getAM2Op((unsigned int)MCOperand_getImm(MO3));
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = tmp;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
}
}
SStream_concat0(O, "]");
@ -786,10 +789,11 @@ static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O)
}
SStream_concat0(O, ", ");
SStream_concat0(O, ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO3))));
SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
printRegName(MI->csh, O, MCOperand_getReg(MO2));
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
}
printRegImmShift(MI, O, getAM2ShiftOpc((unsigned int)MCOperand_getImm(MO3)),
@ -852,28 +856,31 @@ static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
{
MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO2));
if (!MCOperand_getReg(MO1)) {
unsigned ImmOffs = getAM2Offset((unsigned int)MCOperand_getImm(MO2));
if (ImmOffs > HEX_THRESHOLD)
SStream_concat(O, "#%s0x%x",
ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO2))), ImmOffs);
ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
else
SStream_concat(O, "#%s%u",
ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO2))), ImmOffs);
ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
MI->flat_insn->detail->arm.op_count++;
}
return;
}
SStream_concat0(O, ARM_AM_getAddrOpcStr(getAM2Op((unsigned int)MCOperand_getImm(MO2))));
SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
printRegName(MI->csh, O, MCOperand_getReg(MO1));
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
MI->flat_insn->detail->arm.op_count++;
}
@ -885,58 +892,13 @@ static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
// Addressing Mode #3
//===--------------------------------------------------------------------===//
static void printAM3PostIndexOp(MCInst *MI, unsigned Op, SStream *O)
{
MCOperand *MO1 = MCInst_getOperand(MI, Op);
MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
MCOperand *MO3 = MCInst_getOperand(MI, Op+2);
ARM_AM_AddrOpc op = getAM3Op((unsigned int)MCOperand_getImm(MO3));
unsigned ImmOffs;
SStream_concat0(O, "[");
set_mem_access(MI, true);
printRegName(MI->csh, O, MCOperand_getReg(MO1));
if (MI->csh->detail)
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
SStream_concat0(O, "], ");
set_mem_access(MI, false);
if (MCOperand_getReg(MO2)) {
SStream_concat(O, "%c", (char)op);
printRegName(MI->csh, O, MCOperand_getReg(MO2));
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO2);
MI->flat_insn->detail->arm.op_count++;
}
return;
}
ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO3));
if (ImmOffs > HEX_THRESHOLD)
SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(op), ImmOffs);
else
SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(op), ImmOffs);
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
if (op)
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
else
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = -(int)ImmOffs;
MI->flat_insn->detail->arm.op_count++;
}
}
static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,
bool AlwaysPrintImm0)
{
MCOperand *MO1 = MCInst_getOperand(MI, Op);
MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
MCOperand *MO3 = MCInst_getOperand(MI, Op+2);
ARM_AM_AddrOpc op = getAM3Op((unsigned int)MCOperand_getImm(MO3));
ARM_AM_AddrOpc subtracted = getAM3Op((unsigned int)MCOperand_getImm(MO3));
unsigned ImmOffs;
SStream_concat0(O, "[");
@ -947,12 +909,14 @@ static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,
if (MCOperand_getReg(MO2)) {
SStream_concat0(O, ", ");
SStream_concat0(O, ARM_AM_getAddrOpcStr(op));
SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
printRegName(MI->csh, O, MCOperand_getReg(MO2));
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
if (op)
if (subtracted) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = -1;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
}
}
SStream_concat0(O, "]");
set_mem_access(MI, false);
@ -962,17 +926,18 @@ static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,
//If the op is sub we have to print the immediate even if it is 0
ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO3));
if (AlwaysPrintImm0 || ImmOffs || (op == ARM_AM_sub)) {
if (AlwaysPrintImm0 || ImmOffs || (subtracted == ARM_AM_sub)) {
if (ImmOffs > HEX_THRESHOLD)
SStream_concat(O, ", #%s0x%x", ARM_AM_getAddrOpcStr(op), ImmOffs);
SStream_concat(O, ", #%s0x%x", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
else
SStream_concat(O, ", #%s%u", ARM_AM_getAddrOpcStr(op), ImmOffs);
SStream_concat(O, ", #%s%u", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
}
if (MI->csh->detail) {
if (op)
if (subtracted) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = (int)MCOperand_getImm(MO3);
else
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
} else
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = (int)-MCOperand_getImm(MO3);
}
@ -983,22 +948,12 @@ static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,
static void printAddrMode3Operand(MCInst *MI, unsigned Op, SStream *O,
bool AlwaysPrintImm0)
{
unsigned IdxMode;
MCOperand *MO3;
MCOperand *MO1 = MCInst_getOperand(MI, Op);
if (!MCOperand_isReg(MO1)) { // For label symbolic references.
printOperand(MI, Op, O);
return;
}
MO3 = MCInst_getOperand(MI, Op+2);
IdxMode = getAM3IdxMode((unsigned int)MCOperand_getImm(MO3));
if (IdxMode == ARMII_IndexModePost) {
printAM3PostIndexOp(MI, Op, O);
return;
}
printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);
}
@ -1006,15 +961,16 @@ static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
{
MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
ARM_AM_AddrOpc op = getAM3Op((unsigned int)MCOperand_getImm(MO2));
ARM_AM_AddrOpc subtracted = getAM3Op((unsigned int)MCOperand_getImm(MO2));
unsigned ImmOffs;
if (MCOperand_getReg(MO1)) {
SStream_concat0(O, ARM_AM_getAddrOpcStr(op));
SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
printRegName(MI->csh, O, MCOperand_getReg(MO1));
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
MI->flat_insn->detail->arm.op_count++;
}
return;
@ -1022,15 +978,16 @@ static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO2));
if (ImmOffs > HEX_THRESHOLD)
SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(op), ImmOffs);
SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
else
SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(op), ImmOffs);
SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
if (op)
if (subtracted) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
else
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
} else
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = -(int)ImmOffs;
MI->flat_insn->detail->arm.op_count++;
@ -1081,7 +1038,9 @@ static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O,
{
MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO2));
unsigned ImmOffs, Op;
if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
printOperand(MI, OpNum, O);
return;
@ -1103,14 +1062,15 @@ static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O,
if (AlwaysPrintImm0 || ImmOffs || Op == ARM_AM_sub) {
if (ImmOffs * 4 > HEX_THRESHOLD)
SStream_concat(O, ", #%s0x%x",
ARM_AM_getAddrOpcStr(ARM_AM_getAM5Op((unsigned int)MCOperand_getImm(MO2))),
ARM_AM_getAddrOpcStr(subtracted),
ImmOffs * 4);
else
SStream_concat(O, ", #%s%u",
ARM_AM_getAddrOpcStr(ARM_AM_getAM5Op((unsigned int)MCOperand_getImm(MO2))),
ARM_AM_getAddrOpcStr(subtracted),
ImmOffs * 4);
if (MI->csh->detail) {
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = ImmOffs * 4;
MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
}
}
SStream_concat0(O, "]");

@ -265,11 +265,11 @@ void Mips_init(MCRegisterInfo *MRI)
// MipsRegEncodingTable);
MCRegisterInfo_InitMCRegisterInfo(MRI, MipsRegDesc, 394,
0, 0,
0, 0,
MipsMCRegisterClasses, 48,
0, 0,
0, 0,
MipsRegDiffLists,
0,
0,
MipsSubRegIdxLists, 12,
0);
}
@ -767,7 +767,7 @@ static DecodeStatus DecodeGPR32RegisterClass(MCInst *Inst,
static DecodeStatus DecodePtrRegisterClass(MCInst *Inst,
unsigned RegNo, uint64_t Address, MCRegisterInfo *Decoder)
{
if (Inst->csh->mode & CS_MODE_N64)
if (Inst->csh->mode & CS_MODE_64)
return DecodeGPR64RegisterClass(Inst, RegNo, Address, Decoder);
return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder);

@ -185,7 +185,6 @@ static name_map reg_name_maps[] = {
{ MIPS_REG_HI, "hi"},
{ MIPS_REG_LO, "lo"},
{ MIPS_REG_PC, "pc"},
{ MIPS_REG_P0, "p0"},
{ MIPS_REG_P1, "p1"},
@ -9972,7 +9971,7 @@ mips_reg Mips_map_register(unsigned int r)
MIPS_REG_AT, MIPS_REG_DSPCCOND, MIPS_REG_DSPCARRY, MIPS_REG_DSPEFI, MIPS_REG_DSPOUTFLAG,
MIPS_REG_DSPPOS, MIPS_REG_DSPSCOUNT, MIPS_REG_FP, MIPS_REG_GP, MIPS_REG_2,
MIPS_REG_1, MIPS_REG_0, MIPS_REG_6, MIPS_REG_4, MIPS_REG_5,
MIPS_REG_3, MIPS_REG_7, MIPS_REG_PC, MIPS_REG_RA, MIPS_REG_SP,
MIPS_REG_3, MIPS_REG_7, 0, MIPS_REG_RA, MIPS_REG_SP,
MIPS_REG_ZERO, MIPS_REG_A0, MIPS_REG_A1, MIPS_REG_A2, MIPS_REG_A3,
MIPS_REG_AC0, MIPS_REG_AC1, MIPS_REG_AC2, MIPS_REG_AC3, MIPS_REG_AT,
MIPS_REG_CC0, MIPS_REG_CC1, MIPS_REG_CC2, MIPS_REG_CC3, MIPS_REG_CC4,

@ -15,7 +15,7 @@ static cs_err init(cs_struct *ud)
// verify if requested mode is valid
if (ud->mode & ~(CS_MODE_LITTLE_ENDIAN | CS_MODE_32 | CS_MODE_64 |
CS_MODE_MICRO | CS_MODE_N64 | CS_MODE_BIG_ENDIAN))
CS_MODE_MICRO | CS_MODE_BIG_ENDIAN))
return CS_ERR_MODE;
mri = cs_mem_malloc(sizeof(*mri));

@ -907,7 +907,9 @@ static char *printAliasInstrEx(MCInst *MI, SStream *OS, void *info)
(MCOperand_getImm(MCInst_getOperand(MI, 0)) < 16)) {
int cr = getBICR(MCOperand_getReg(MCInst_getOperand(MI, 1)));
op_addReg(MI, PPC_REG_CR0 + cr - PPC_CR0);
if (cr != PPC_CR0) {
op_addReg(MI, PPC_REG_CR0 + cr - PPC_CR0);
}
if (decCtr) {
needComma = true;

@ -75,6 +75,8 @@ public class TestArm {
System.out.printf("\t\t\toperands[%d].vector_index = %d\n", c, (i.vector_index));
if (i.shift.type != ARM_SFT_INVALID && i.shift.value > 0)
System.out.printf("\t\t\tShift: %d = %d\n", i.shift.type, i.shift.value);
if (i.subtracted)
System.out.printf("\t\t\toperands[%d].subtracted = True\n", c);
}
}
if (operands.writeback)

@ -53,6 +53,7 @@ public class Arm {
public OpShift shift;
public int type;
public OpValue value;
public boolean subtracted;
public void read() {
readField("vector_index");
@ -69,11 +70,12 @@ public class Arm {
return;
readField("value");
readField("shift");
readField("subtracted");
}
@Override
public List getFieldOrder() {
return Arrays.asList("vector_index", "shift", "type", "value");
return Arrays.asList("vector_index", "shift", "type", "value", "subtracted");
}
}

@ -297,10 +297,9 @@ public class Capstone {
public static final int CS_MODE_THUMB = 1 << 4; // ARM's Thumb mode, including Thumb-2
public static final int CS_MODE_MCLASS = 1 << 5; // ARM's Cortex-M series
public static final int CS_MODE_MICRO = 1 << 4; // MicroMips mode (Mips arch)
public static final int CS_MODE_N64 = 1 << 5; // Nintendo-64 mode (Mips arch)
public static final int CS_MODE_MIPS3 = 1 << 6; // Mips III ISA
public static final int CS_MODE_MIPS32R6 = 1 << 7; // Mips32r6 ISA
public static final int CS_MODE_MIPSGP64 = 1 << 8; // General Purpose Registers are 64-bit wide (MIPS arch)
public static final int CS_MODE_MIPS3 = 1 << 5; // Mips III ISA
public static final int CS_MODE_MIPS32R6 = 1 << 6; // Mips32r6 ISA
public static final int CS_MODE_MIPSGP64 = 1 << 7; // General Purpose Registers are 64-bit wide (MIPS arch)
public static final int CS_MODE_BIG_ENDIAN = 1 << 31;
public static final int CS_MODE_V9 = 1 << 4; // SparcV9 mode (Sparc arch)
@ -427,4 +426,3 @@ public class Capstone {
return allInsn;
}
}

@ -154,14 +154,13 @@ public class Mips_const {
public static final int MIPS_REG_W31 = 127;
public static final int MIPS_REG_HI = 128;
public static final int MIPS_REG_LO = 129;
public static final int MIPS_REG_PC = 130;
public static final int MIPS_REG_P0 = 131;
public static final int MIPS_REG_P1 = 132;
public static final int MIPS_REG_P2 = 133;
public static final int MIPS_REG_MPL0 = 134;
public static final int MIPS_REG_MPL1 = 135;
public static final int MIPS_REG_MPL2 = 136;
public static final int MIPS_REG_ENDING = 137;
public static final int MIPS_REG_P0 = 130;
public static final int MIPS_REG_P1 = 131;
public static final int MIPS_REG_P2 = 132;
public static final int MIPS_REG_MPL0 = 133;
public static final int MIPS_REG_MPL1 = 134;
public static final int MIPS_REG_MPL2 = 135;
public static final int MIPS_REG_ENDING = 136;
public static final int MIPS_REG_ZERO = MIPS_REG_0;
public static final int MIPS_REG_AT = MIPS_REG_1;
public static final int MIPS_REG_V0 = MIPS_REG_2;

@ -35,6 +35,7 @@ type arm_op = {
vector_index: int;
shift: arm_op_shift;
value: arm_op_value;
subtracted: bool;
}
type cs_arm = {

@ -30,7 +30,6 @@ type mode =
| CS_MODE_THUMB (* ARM's Thumb mode, including Thumb-2 *)
| CS_MODE_MCLASS (* ARM's MClass mode *)
| CS_MODE_MICRO (* MicroMips mode (MIPS architecture) *)
| CS_MODE_N64 (* Nintendo-64 mode (MIPS architecture) *)
| CS_MODE_MIPS3 (* Mips3 mode (MIPS architecture) *)
| CS_MODE_MIPS32R6 (* Mips32-R6 mode (MIPS architecture) *)
| CS_MODE_MIPSGP64 (* MipsGP64 mode (MIPS architecture) *)
@ -47,16 +46,15 @@ type opt_type =
| CS_OPT_SKIPDATA_SETUP (* Setup user-defined function for SKIPDATA option *)
type opt_value =
| CS_OPT_OFF (* Turn OFF an option - default option of CS_OPT_DETAIL, CS_OPT_SKIPDATA. *)
| CS_OPT_ON (* Turn ON an option (CS_OPT_DETAIL, CS_OPT_SKIPDATA). *)
| CS_OPT_SYNTAX_DEFAULT (* Default asm syntax (CS_OPT_SYNTAX). *)
| CS_OPT_SYNTAX_INTEL (* X86 Intel asm syntax - default on X86 (CS_OPT_SYNTAX). *)
| CS_OPT_SYNTAX_ATT (* X86 ATT asm syntax (CS_OPT_SYNTAX). *)
| CS_OPT_SYNTAX_NOREGNAME (* Prints register name with only number (CS_OPT_SYNTAX) *)
let _CS_OPT_OFF = 0L;; (* Turn OFF an option - default option of CS_OPT_DETAIL, CS_OPT_SKIPDATA. *)
let _CS_OPT_ON = 3L;; (* Turn ON an option (CS_OPT_DETAIL, CS_OPT_SKIPDATA). *)
let _CS_OPT_SYNTAX_DEFAULT = 0L;; (* Default asm syntax (CS_OPT_SYNTAX). *)
let _CS_OPT_SYNTAX_INTEL = 1L;; (* X86 Intel asm syntax - default on X86 (CS_OPT_SYNTAX). *)
let _CS_OPT_SYNTAX_ATT = 2L;; (* X86 ATT asm syntax (CS_OPT_SYNTAX). *)
let _CS_OPT_SYNTAX_NOREGNAME = 3L;; (* Prints register name with only number (CS_OPT_SYNTAX) *)
type cs_arch =
type cs_arch =
| CS_INFO_ARM of cs_arm
| CS_INFO_ARM64 of cs_arm64
| CS_INFO_MIPS of cs_mips
@ -67,6 +65,11 @@ type cs_arch =
| CS_INFO_XCORE of cs_xcore
type csh = {
h: Int64.t;
a: arch;
}
type cs_insn0 = {
id: int;
address: int;
@ -80,13 +83,48 @@ type cs_insn0 = {
arch: cs_arch;
}
external cs_open: arch -> mode list -> Int64.t option = "ocaml_cs_open"
external _cs_open: arch -> mode list -> Int64.t option = "ocaml_open"
external cs_disasm_quick: arch -> mode list -> string -> Int64.t -> Int64.t -> cs_insn0 list = "ocaml_cs_disasm"
external _cs_disasm_internal: arch -> Int64.t -> string -> Int64.t -> Int64.t -> cs_insn0 list = "ocaml_cs_disasm_internal"
external cs_reg_name: Int64.t -> int -> string = "ocaml_register_name"
external cs_insn_name: Int64.t -> int -> string = "ocaml_instruction_name"
external cs_group_name: Int64.t -> int -> string = "ocaml_group_name"
external _cs_reg_name: Int64.t -> int -> string = "ocaml_register_name"
external _cs_insn_name: Int64.t -> int -> string = "ocaml_instruction_name"
external _cs_group_name: Int64.t -> int -> string = "ocaml_group_name"
external cs_version: unit -> int = "ocaml_version"
external _cs_option: Int64.t -> opt_type -> Int64.t -> int = "ocaml_option"
external _cs_close: Int64.t -> int = "ocaml_close"
let cs_open _arch _mode: csh = (
let _handle = _cs_open _arch _mode in (
match _handle with
| None -> { h = 0L; a = _arch }
| Some v -> { h = v; a = _arch }
);
);;
let cs_close handle = (
_cs_close handle.h;
)
let cs_option handle opt value = (
_cs_option handle.h opt value;
);;
let cs_disasm handle code address count = (
_cs_disasm_internal handle.a handle.h code address count;
);;
let cs_reg_name handle id = (
_cs_reg_name handle.h id;
);;
let cs_insn_name handle id = (
_cs_insn_name handle.h id;
);;
let cs_group_name handle id = (
_cs_group_name handle.h id;
);;
class cs_insn c a =
let csh = c in
@ -105,7 +143,9 @@ class cs_insn c a =
method regs_write = regs_write;
method groups = groups;
method arch = arch;
method insn_name = cs_insn_name csh id;
method reg_name id = _cs_reg_name csh.h id;
method insn_name id = _cs_insn_name csh.h id;
method group_name id = _cs_group_name csh.h id;
end;;
let cs_insn_group handle insn group_id =
@ -120,17 +160,10 @@ let cs_reg_write handle insn reg_id =
class cs a m =
let mode = m and arch = a in
let csh = cs_open arch mode in
let handle = cs_open arch mode in
object
val handle = match csh with
| None -> failwith "impossible to open an handle"
| Some v -> v
method get_csh = handle
method disasm code offset count =
let insns = (_cs_disasm_internal arch handle code offset count) in
let insns = (_cs_disasm_internal arch handle.h code offset count) in
List.map (fun x -> new cs_insn handle x) insns;
end;;

@ -151,14 +151,13 @@ let _MIPS_REG_W30 = 126;;
let _MIPS_REG_W31 = 127;;
let _MIPS_REG_HI = 128;;
let _MIPS_REG_LO = 129;;
let _MIPS_REG_PC = 130;;
let _MIPS_REG_P0 = 131;;
let _MIPS_REG_P1 = 132;;
let _MIPS_REG_P2 = 133;;
let _MIPS_REG_MPL0 = 134;;
let _MIPS_REG_MPL1 = 135;;
let _MIPS_REG_MPL2 = 136;;
let _MIPS_REG_ENDING = 137;;
let _MIPS_REG_P0 = 130;;
let _MIPS_REG_P1 = 131;;
let _MIPS_REG_P2 = 132;;
let _MIPS_REG_MPL0 = 133;;
let _MIPS_REG_MPL1 = 134;;
let _MIPS_REG_MPL2 = 135;;
let _MIPS_REG_ENDING = 136;;
let _MIPS_REG_ZERO = _MIPS_REG_0;;
let _MIPS_REG_AT = _MIPS_REG_1;;
let _MIPS_REG_V0 = _MIPS_REG_2;;

@ -47,7 +47,7 @@ CAMLprim value _cs_disasm(cs_arch arch, csh handle, const uint8_t * code, size_t
Store_field(rec_insn, 0, Val_int(insn[j-1].id));
Store_field(rec_insn, 1, Val_int(insn[j-1].address));
Store_field(rec_insn, 2, Val_int(insn[j-1].size));
// copy raw bytes of instruction
lcount = insn[j-1].size;
if (lcount) {
@ -63,38 +63,46 @@ CAMLprim value _cs_disasm(cs_arch arch, csh handle, const uint8_t * code, size_t
Store_field(rec_insn, 5, caml_copy_string(insn[j-1].op_str));
// copy read registers
lcount = (insn[j-1]).detail->regs_read_count;
if (lcount) {
array = caml_alloc(lcount, 0);
for (i = 0; i < lcount; i++) {
Store_field(array, i, Val_int(insn[j-1].detail->regs_read[i]));
}
if (insn[0].detail) {
lcount = (insn[j-1]).detail->regs_read_count;
if (lcount) {
array = caml_alloc(lcount, 0);
for (i = 0; i < lcount; i++) {
Store_field(array, i, Val_int(insn[j-1].detail->regs_read[i]));
}
} else
array = Atom(0); // empty list
} else
array = Atom(0); // empty list
Store_field(rec_insn, 6, array);
lcount = (insn[j-1]).detail->regs_write_count;
if (lcount) {
array = caml_alloc(lcount, 0);
for (i = 0; i < lcount; i++) {
Store_field(array, i, Val_int(insn[j-1].detail->regs_write[i]));
}
if (insn[0].detail) {
lcount = (insn[j-1]).detail->regs_write_count;
if (lcount) {
array = caml_alloc(lcount, 0);
for (i = 0; i < lcount; i++) {
Store_field(array, i, Val_int(insn[j-1].detail->regs_write[i]));
}
} else
array = Atom(0); // empty list
} else
array = Atom(0); // empty list
Store_field(rec_insn, 7, array);
lcount = (insn[j-1]).detail->groups_count;
if (lcount) {
array = caml_alloc(lcount, 0);
for (i = 0; i < lcount; i++) {
Store_field(array, i, Val_int(insn[j-1].detail->groups[i]));
}
if (insn[0].detail) {
lcount = (insn[j-1]).detail->groups_count;
if (lcount) {
array = caml_alloc(lcount, 0);
for (i = 0; i < lcount; i++) {
Store_field(array, i, Val_int(insn[j-1].detail->groups[i]));
}
} else
array = Atom(0); // empty list
} else
array = Atom(0); // empty list
Store_field(rec_insn, 8, array);
if(insn[j-1].detail) {
if (insn[j-1].detail) {
switch(arch) {
case CS_ARCH_ARM:
arch_info = caml_alloc(1, 0);
@ -113,7 +121,7 @@ CAMLprim value _cs_disasm(cs_arch arch, csh handle, const uint8_t * code, size_t
if (lcount > 0) {
array = caml_alloc(lcount, 0);
for (i = 0; i < lcount; i++) {
tmp2 = caml_alloc(3, 0);
tmp2 = caml_alloc(4, 0);
switch(insn[j-1].detail->arm.operands[i].type) {
case ARM_OP_REG:
case ARM_OP_SYSREG:
@ -157,6 +165,7 @@ CAMLprim value _cs_disasm(cs_arch arch, csh handle, const uint8_t * code, size_t
Store_field(tmp2, 0, Val_int(insn[j-1].detail->arm.operands[i].vector_index));
Store_field(tmp2, 1, tmp3);
Store_field(tmp2, 2, tmp);
Store_field(tmp2, 3, Val_bool(insn[j-1].detail->arm.operands[i].subtracted));
Store_field(array, i, tmp2);
}
} else // empty list
@ -318,7 +327,7 @@ CAMLprim value _cs_disasm(cs_arch arch, csh handle, const uint8_t * code, size_t
// fill opcode
lcount = list_count(insn[j-1].detail->x86.opcode, ARR_SIZE(insn[j-1].detail->x86.opcode));
if(lcount) {
if (lcount) {
array = caml_alloc(lcount, 0);
for (i = 0; i < lcount; i++) {
Store_field(array, i, Val_int(insn[j-1].detail->x86.opcode[i]));
@ -671,21 +680,18 @@ CAMLprim value ocaml_cs_disasm(value _arch, value _mode, value _code, value _add
mode |= CS_MODE_MICRO;
break;
case 8:
mode |= CS_MODE_N64;
break;
case 9:
mode |= CS_MODE_MIPS3;
break;
case 10:
case 9:
mode |= CS_MODE_MIPS32R6;
break;
case 11:
case 10:
mode |= CS_MODE_MIPSGP64;
break;
case 12:
case 11:
mode |= CS_MODE_V9;
break;
case 13:
case 12:
mode |= CS_MODE_BIG_ENDIAN;
break;
default:
@ -700,9 +706,6 @@ CAMLprim value ocaml_cs_disasm(value _arch, value _mode, value _code, value _add
return Val_emptylist;
}
if (cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON) != CS_ERR_OK)
CAMLreturn(Val_int(0));
code = (uint8_t *)String_val(_code);
code_len = caml_string_length(_code);
addr = Int64_val(_addr);
@ -720,7 +723,7 @@ CAMLprim value ocaml_cs_disasm_internal(value _arch, value _handle, value _code,
uint64_t addr, count, code_len;
handle = Int64_val(_handle);
arch = Int_val(_arch);
code = (uint8_t *)String_val(_code);
code_len = caml_string_length(_code);
@ -730,7 +733,7 @@ CAMLprim value ocaml_cs_disasm_internal(value _arch, value _handle, value _code,
CAMLreturn(_cs_disasm(arch, handle, code, code_len, addr, count));
}
CAMLprim value ocaml_cs_open(value _arch, value _mode)
CAMLprim value ocaml_open(value _arch, value _mode)
{
CAMLparam2(_arch, _mode);
CAMLlocal2(list, head);
@ -799,21 +802,18 @@ CAMLprim value ocaml_cs_open(value _arch, value _mode)
mode |= CS_MODE_MICRO;
break;
case 8:
mode |= CS_MODE_N64;
break;
case 9:
mode |= CS_MODE_MIPS3;
break;
case 10:
case 9:
mode |= CS_MODE_MIPS32R6;
break;
case 11:
case 10:
mode |= CS_MODE_MIPSGP64;
break;
case 12:
case 11:
mode |= CS_MODE_V9;
break;
case 13:
case 12:
mode |= CS_MODE_BIG_ENDIAN;
break;
default:
@ -823,10 +823,7 @@ CAMLprim value ocaml_cs_open(value _arch, value _mode)
_mode = Field(_mode, 1); /* point to the tail for next loop */
}
if (cs_open(arch, mode, &handle) != 0)
CAMLreturn(Val_int(0));
if (cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON) != 0)
if (cs_open(arch, mode, &handle) != 0)
CAMLreturn(Val_int(0));
CAMLlocal1(result);
@ -835,33 +832,71 @@ CAMLprim value ocaml_cs_open(value _arch, value _mode)
CAMLreturn(result);
}
CAMLprim value ocaml_option(value _handle, value _opt, value _value)
{
CAMLparam3(_handle, _opt, _value);
cs_opt_type opt;
int err;
switch (Int_val(_opt)) {
case 0:
opt = CS_OPT_SYNTAX;
break;
case 1:
opt = CS_OPT_DETAIL;
break;
case 2:
opt = CS_OPT_MODE;
break;
case 3:
opt = CS_OPT_MEM;
break;
case 4:
opt = CS_OPT_SKIPDATA;
break;
case 5:
opt = CS_OPT_SKIPDATA_SETUP;
break;
default:
caml_invalid_argument("Invalid option");
CAMLreturn(Val_int(CS_ERR_OPTION));
}
err = cs_option(Int64_val(_handle), opt, Int64_val(_value));
CAMLreturn(Val_int(err));
}
CAMLprim value ocaml_register_name(value _handle, value _reg)
{
const char *name = cs_reg_name(Int64_val(_handle), Int_val(_reg));
if(!name) {
if (!name) {
caml_invalid_argument("invalid reg_id");
name = "invalid";
}
return caml_copy_string(name);
}
CAMLprim value ocaml_instruction_name(value _handle, value _insn)
{
const char *name = cs_insn_name(Int64_val(_handle), Int_val(_insn));
if(!name) {
if (!name) {
caml_invalid_argument("invalid insn_id");
name = "invalid";
}
return caml_copy_string(name);
}
CAMLprim value ocaml_group_name(value _handle, value _insn)
{
const char *name = cs_group_name(Int64_val(_handle), Int_val(_insn));
if(!name) {
if (!name) {
caml_invalid_argument("invalid insn_id");
name = "invalid";
}
return caml_copy_string(name);
}
@ -870,3 +905,13 @@ CAMLprim value ocaml_version(void)
int version = cs_version(NULL, NULL);
return Val_int(version);
}
CAMLprim value ocaml_close(value _handle)
{
CAMLparam1(_handle);
csh h;
h = Int64_val(_handle);
CAMLreturn(Val_int(cs_close(&h)));
}

@ -22,23 +22,23 @@ let _SYSZ_CODE = "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x
let _XCORE_CODE = "\xfe\x0f\xfe\x17\x13\x17\xc6\xfe\xec\x17\x97\xf8\xec\x4f\x1f\xfd\xec\x37\x07\xf2\x45\x5b\xf9\xfa\x02\x06\x1b\x10";;
let all_tests = [
(CS_ARCH_X86, [CS_MODE_16], _X86_CODE16, "X86 16bit (Intel syntax)", 0);
(CS_ARCH_X86, [CS_MODE_32], _X86_CODE32, "X86 32bit (ATT syntax)", 0);
(CS_ARCH_X86, [CS_MODE_32], _X86_CODE32, "X86 32 (Intel syntax)", 0);
(CS_ARCH_X86, [CS_MODE_64], _X86_CODE64, "X86 64 (Intel syntax)", 0);
(CS_ARCH_ARM, [CS_MODE_ARM], _ARM_CODE, "ARM", 0);
(CS_ARCH_ARM, [CS_MODE_ARM], _ARM_CODE2, "ARM: Cortex-A15 + NEON", 0);
(CS_ARCH_ARM, [CS_MODE_THUMB], _THUMB_CODE, "THUMB", 0);
(CS_ARCH_ARM, [CS_MODE_THUMB], _THUMB_CODE2, "THUMB-2", 0);
(CS_ARCH_ARM64, [CS_MODE_ARM], _ARM64_CODE, "ARM-64", 0);
(CS_ARCH_MIPS, [CS_MODE_32; CS_MODE_BIG_ENDIAN], _MIPS_CODE, "MIPS-32 (Big-endian)", 0);
(CS_ARCH_MIPS, [CS_MODE_64; CS_MODE_LITTLE_ENDIAN], _MIPS_CODE2, "MIPS-64-EL (Little-endian)", 0);
(CS_ARCH_PPC, [CS_MODE_BIG_ENDIAN], _PPC_CODE, "PPC-64", 0);
(CS_ARCH_PPC, [CS_MODE_BIG_ENDIAN], _PPC_CODE, "PPC-64, print register with number only", 0);
(CS_ARCH_SPARC, [CS_MODE_BIG_ENDIAN], _SPARC_CODE, "Sparc", 0);
(CS_ARCH_SPARC, [CS_MODE_BIG_ENDIAN; CS_MODE_V9], _SPARCV9_CODE, "SparcV9", 0);
(CS_ARCH_SYSZ, [CS_MODE_LITTLE_ENDIAN], _SYSZ_CODE, "SystemZ", 0);
(CS_ARCH_XCORE, [CS_MODE_LITTLE_ENDIAN], _XCORE_CODE, "XCore", 0);
(CS_ARCH_X86, [CS_MODE_16], _X86_CODE16, "X86 16bit (Intel syntax)", 0L);
(CS_ARCH_X86, [CS_MODE_32], _X86_CODE32, "X86 32bit (ATT syntax)", _CS_OPT_SYNTAX_ATT);
(CS_ARCH_X86, [CS_MODE_32], _X86_CODE32, "X86 32 (Intel syntax)", 0L);
(CS_ARCH_X86, [CS_MODE_64], _X86_CODE64, "X86 64 (Intel syntax)", 0L);
(CS_ARCH_ARM, [CS_MODE_ARM], _ARM_CODE, "ARM", 0L);
(CS_ARCH_ARM, [CS_MODE_ARM], _ARM_CODE2, "ARM: Cortex-A15 + NEON", 0L);
(CS_ARCH_ARM, [CS_MODE_THUMB], _THUMB_CODE, "THUMB", 0L);
(CS_ARCH_ARM, [CS_MODE_THUMB], _THUMB_CODE2, "THUMB-2", 0L);
(CS_ARCH_ARM64, [CS_MODE_ARM], _ARM64_CODE, "ARM-64", 0L);
(CS_ARCH_MIPS, [CS_MODE_32; CS_MODE_BIG_ENDIAN], _MIPS_CODE, "MIPS-32 (Big-endian)", 0L);
(CS_ARCH_MIPS, [CS_MODE_64; CS_MODE_LITTLE_ENDIAN], _MIPS_CODE2, "MIPS-64-EL (Little-endian)", 0L);
(CS_ARCH_PPC, [CS_MODE_BIG_ENDIAN], _PPC_CODE, "PPC-64", 0L);
(CS_ARCH_PPC, [CS_MODE_BIG_ENDIAN], _PPC_CODE, "PPC-64, print register with number only", 0L);
(CS_ARCH_SPARC, [CS_MODE_BIG_ENDIAN], _SPARC_CODE, "Sparc", 0L);
(CS_ARCH_SPARC, [CS_MODE_BIG_ENDIAN; CS_MODE_V9], _SPARCV9_CODE, "SparcV9", 0L);
(CS_ARCH_SYSZ, [CS_MODE_LITTLE_ENDIAN], _SYSZ_CODE, "SystemZ", 0L);
(CS_ARCH_XCORE, [CS_MODE_LITTLE_ENDIAN], _XCORE_CODE, "XCore", 0L);
];;
@ -47,26 +47,21 @@ let print_insn insn =
let print_arch x =
let (arch, mode, code, comment, syntax) = x in
let insns = cs_disasm_quick arch mode code 0x1000L 0L in
let handle = cs_open arch mode in (
if syntax != 0L then (
let err = cs_option handle CS_OPT_SYNTAX syntax in
match err with
| _ -> ();
);
let insns = cs_disasm handle code 0x1000L 0L in (
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter print_insn insns;;
List.iter print_arch all_tests;;
let print_insn_cls insn =
printf "0x%x\t%s\t%s\n" insn#address insn#mnemonic insn#op_str;;
let print_arch_cls x =
let (arch, mode, code, comment, syntax) = x in (
let d = new cs arch mode in
let insns = d#disasm code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter print_insn_cls insns;
List.iter print_insn insns;
);
match cs_close handle with
| 0 -> ();
| _ -> printf "Failed to close handle";
);;
List.iter print_arch_cls all_tests;;
List.iter print_arch all_tests;;

@ -29,19 +29,19 @@ let all_tests = [
];;
let print_op csh i op =
let print_op handle i op =
( match op.value with
| ARM_OP_INVALID _ -> (); (* this would never happens *)
| ARM_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name csh reg);
| ARM_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name handle reg);
| ARM_OP_CIMM imm -> printf "\t\top[%d]: C-IMM = %u\n" i imm;
| ARM_OP_PIMM imm -> printf "\t\top[%d]: P-IMM = %u\n" i imm;
| ARM_OP_IMM imm -> printf "\t\top[%d]: IMM = 0x%x\n" i imm;
| ARM_OP_FP fp -> printf "\t\top[%d]: FP = %f\n" i fp;
| ARM_OP_MEM mem -> ( printf "\t\top[%d]: MEM\n" i;
if mem.base != 0 then
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name csh mem.base);
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name handle mem.base);
if mem.index != 0 then
printf "\t\t\toperands[%u].mem.index: REG = %s\n" i (cs_reg_name csh mem.index);
printf "\t\t\toperands[%u].mem.index: REG = %s\n" i (cs_reg_name handle mem.index);
if mem.scale != 1 then
printf "\t\t\toperands[%u].mem.scale: %d\n" i mem.scale;
if mem.disp != 0 then
@ -56,68 +56,48 @@ let print_op csh i op =
();;
let print_detail csh arch =
match arch with
| CS_INFO_ARM64 _ -> ();
| CS_INFO_X86 _ -> ();
| CS_INFO_MIPS _ -> ();
| CS_INFO_PPC _ -> ();
| CS_INFO_SPARC _ -> ();
| CS_INFO_SYSZ _ -> ();
| CS_INFO_XCORE _ -> ();
| CS_INFO_ARM arm ->
if arm.cc != _ARM_CC_AL && arm.cc != _ARM_CC_INVALID then
printf "\tCode condition: %u\n" arm.cc;
if arm.update_flags then
printf "\tUpdate-flags: True\n";
if arm.writeback then
printf "\tWriteback: True\n";
(* print all operands info (type & value) *)
if (Array.length arm.operands) > 0 then (
printf "\top_count: %d\n" (Array.length arm.operands);
Array.iteri (print_op csh) arm.operands;
);
printf "\n";;
let print_detail handle insn =
match insn.arch with
| CS_INFO_ARM arm -> (
if arm.cc != _ARM_CC_AL && arm.cc != _ARM_CC_INVALID then
printf "\tCode condition: %u\n" arm.cc;
if arm.update_flags then
printf "\tUpdate-flags: True\n";
if arm.writeback then
printf "\tWriteback: True\n";
(* print all operands info (type & value) *)
if (Array.length arm.operands) > 0 then (
printf "\top_count: %d\n" (Array.length arm.operands);
Array.iteri (print_op handle) arm.operands;
);
printf "\n";
);
| _ -> ();
;;
let print_insn mode insn =
let print_insn handle insn =
printf "0x%x\t%s\t%s\n" insn.address insn.mnemonic insn.op_str;
let csh = cs_open CS_ARCH_ARM mode in
match csh with
| None -> ()
| Some v -> print_detail v insn.arch
print_detail handle insn
let print_arch x =
let (arch, mode, code, comment) = x in
let insns = cs_disasm_quick arch mode code 0x1000L 0L in
let handle = cs_open arch mode in
let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in
match err with
| _ -> ();
let insns = cs_disasm handle code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn mode) insns;;
List.iter (print_insn handle) insns;
match cs_close handle with
| 0 -> ();
| _ -> printf "Failed to close handle";
;;
List.iter print_arch all_tests;;
(* all below code use OO class of Capstone *)
let print_insn_cls csh insn =
printf "0x%x\t%s\t%s\n" insn#address insn#mnemonic insn#op_str;
print_detail csh insn#arch;;
let print_arch_cls x =
let (arch, mode, code, comment) = x in (
let d = new cs arch mode in
let insns = d#disasm code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn_cls d#get_csh) insns;
);;
List.iter print_arch_cls all_tests;;

@ -21,18 +21,18 @@ let all_tests = [
(CS_ARCH_ARM64, [CS_MODE_ARM], _ARM64_CODE, "ARM-64");
];;
let print_op csh i op =
let print_op handle i op =
( match op.value with
| ARM64_OP_INVALID _ -> (); (* this would never happens *)
| ARM64_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name csh reg);
| ARM64_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name handle reg);
| ARM64_OP_CIMM imm -> printf "\t\top[%d]: C-IMM = %u\n" i imm;
| ARM64_OP_IMM imm -> printf "\t\top[%d]: IMM = 0x%x\n" i imm;
| ARM64_OP_FP fp -> printf "\t\top[%d]: FP = %f\n" i fp;
| ARM64_OP_MEM mem -> ( printf "\t\top[%d]: MEM\n" i;
if mem.base != 0 then
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name csh mem.base);
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name handle mem.base);
if mem.index != 0 then
printf "\t\t\toperands[%u].mem.index: REG = %s\n" i (cs_reg_name csh mem.index);
printf "\t\t\toperands[%u].mem.index: REG = %s\n" i (cs_reg_name handle mem.index);
if mem.disp != 0 then
printf "\t\t\toperands[%u].mem.disp: 0x%x\n" i mem.disp;
);
@ -53,67 +53,49 @@ let print_op csh i op =
();;
let print_detail csh arch =
match arch with
| CS_INFO_ARM _ -> ();
| CS_INFO_MIPS _ -> ();
| CS_INFO_PPC _ -> ();
| CS_INFO_X86 _ -> ();
| CS_INFO_SPARC _ -> ();
| CS_INFO_SYSZ _ -> ();
| CS_INFO_XCORE _ -> ();
| CS_INFO_ARM64 arm64 ->
if arm64.cc != _ARM64_CC_AL && arm64.cc != _ARM64_CC_INVALID then
printf "\tCode condition: %u\n" arm64.cc;
if arm64.update_flags then
printf "\tUpdate-flags: True\n";
if arm64.writeback then
printf "\tWriteback: True\n";
(* print all operands info (type & value) *)
if (Array.length arm64.operands) > 0 then (
printf "\top_count: %d\n" (Array.length arm64.operands);
Array.iteri (print_op csh) arm64.operands;
);
printf "\n";;
let print_detail handle insn =
match insn.arch with
| CS_INFO_ARM64 arm64 -> (
if arm64.cc != _ARM64_CC_AL && arm64.cc != _ARM64_CC_INVALID then
printf "\tCode condition: %u\n" arm64.cc;
if arm64.update_flags then
printf "\tUpdate-flags: True\n";
if arm64.writeback then
printf "\tWriteback: True\n";
(* print all operands info (type & value) *)
if (Array.length arm64.operands) > 0 then (
printf "\top_count: %d\n" (Array.length arm64.operands);
Array.iteri (print_op handle) arm64.operands;
);
printf "\n";
)
| _ -> ();
;;
let print_insn mode insn =
let print_insn handle insn =
printf "0x%x\t%s\t%s\n" insn.address insn.mnemonic insn.op_str;
let csh = cs_open CS_ARCH_ARM64 mode in
match csh with
| None -> ()
| Some v -> print_detail v insn.arch
print_detail handle insn
let print_arch x =
let (arch, mode, code, comment) = x in
let insns = cs_disasm_quick arch mode code 0x1000L 0L in
let handle = cs_open arch mode in
let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in
match err with
| _ -> ();
let insns = cs_disasm handle code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn mode) insns;;
List.iter (print_insn handle) insns;
match cs_close handle with
| 0 -> ();
| _ -> printf "Failed to close handle";
;;
List.iter print_arch all_tests;;
(* all below code use OO class of Capstone *)
let print_insn_cls csh insn =
printf "0x%x\t%s\t%s\n" insn#address insn#mnemonic insn#op_str;
print_detail csh insn#arch;;
let print_arch_cls x =
let (arch, mode, code, comment) = x in (
let d = new cs arch mode in
let insns = d#disasm code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn_cls d#get_csh) insns;
);;
List.iter print_arch_cls all_tests;;

@ -41,17 +41,17 @@ let all_tests = [
];;
let print_detail csh insn =
let print_detail handle insn =
(* print immediate operands *)
if (Array.length insn.regs_read) > 0 then begin
printf "\tImplicit registers read: ";
Array.iter (fun x -> printf "%s "(cs_reg_name csh x)) insn.regs_read;
Array.iter (fun x -> printf "%s "(cs_reg_name handle x)) insn.regs_read;
printf "\n";
end;
if (Array.length insn.regs_write) > 0 then begin
printf "\tImplicit registers written: ";
Array.iter (fun x -> printf "%s "(cs_reg_name csh x)) insn.regs_write;
Array.iter (fun x -> printf "%s "(cs_reg_name handle x)) insn.regs_write;
printf "\n";
end;
@ -63,61 +63,25 @@ let print_detail csh insn =
printf "\n";;
let print_insn mode arch insn =
let print_insn handle insn =
printf "0x%x\t%s\t%s\n" insn.address insn.mnemonic insn.op_str;
let csh = cs_open arch mode in
match csh with
| None -> ()
| Some v -> print_detail v insn
print_detail handle insn
let print_arch x =
let (arch, mode, code, comment, syntax) = x in
let insns = cs_disasm_quick arch mode code 0x1000L 0L in
let handle = cs_open arch mode in
let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in
match err with
| _ -> ();
let insns = cs_disasm handle code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn mode arch) insns;;
List.iter (print_insn handle) insns;
match cs_close handle with
| 0 -> ();
| _ -> printf "Failed to close handle";
;;
List.iter print_arch all_tests;;
(* all below code use OO class of Capstone *)
let print_detail_cls arch csh insn =
(* print immediate operands *)
if (Array.length insn#regs_read) > 0 then begin
printf "\tImplicit registers read: ";
Array.iter (fun x -> printf "%s "(cs_reg_name csh x)) insn#regs_read;
printf "\n";
end;
if (Array.length insn#regs_write) > 0 then begin
printf "\tImplicit registers written: ";
Array.iter (fun x -> printf "%s "(cs_reg_name csh x)) insn#regs_write;
printf "\n";
end;
if (Array.length insn#groups) > 0 then begin
printf "\tThis instruction belongs to groups: ";
Array.iter (printf "%u ") insn#groups;
printf "\n";
end;
printf "\n";;
let print_insn_cls arch csh insn =
printf "0x%x\t%s\t%s\n" insn#address insn#mnemonic insn#op_str;
print_detail_cls arch csh insn;;
let print_arch_cls x =
let (arch, mode, code, comment, syntax) = x in
let d = new cs arch mode in
let insns = d#disasm code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn_cls arch (d#get_csh)) insns;
();;
List.iter print_arch_cls all_tests;;

@ -22,75 +22,54 @@ let all_tests = [
(CS_ARCH_MIPS, [CS_MODE_64; CS_MODE_LITTLE_ENDIAN], _MIPS_CODE2, "MIPS-64-EL (Little-endian)");
];;
let print_op csh i op =
let print_op handle i op =
( match op.value with
| MIPS_OP_INVALID _ -> (); (* this would never happens *)
| MIPS_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name csh reg);
| MIPS_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name handle reg);
| MIPS_OP_IMM imm -> printf "\t\top[%d]: IMM = 0x%x\n" i imm;
| MIPS_OP_MEM mem -> ( printf "\t\top[%d]: MEM\n" i;
if mem.base != 0 then
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name csh mem.base);
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name handle mem.base);
if mem.disp != 0 then
printf "\t\t\toperands[%u].mem.disp: 0x%x\n" i mem.disp;
);
);
();;
let print_detail csh arch =
match arch with
| CS_INFO_ARM _ -> ();
| CS_INFO_ARM64 _ -> ();
| CS_INFO_PPC _ -> ();
| CS_INFO_X86 _ -> ();
| CS_INFO_SPARC _ -> ();
| CS_INFO_SYSZ _ -> ();
| CS_INFO_XCORE _ -> ();
| CS_INFO_MIPS mips ->
(* print all operands info (type & value) *)
if (Array.length mips.operands) > 0 then (
printf "\top_count: %d\n" (Array.length mips.operands);
Array.iteri (print_op csh) mips.operands;
);
printf "\n";;
let print_detail handle insn =
match insn.arch with
| CS_INFO_MIPS mips -> (
(* print all operands info (type & value) *)
if (Array.length mips.operands) > 0 then (
printf "\top_count: %d\n" (Array.length mips.operands);
Array.iteri (print_op handle) mips.operands;
);
printf "\n";
);
| _ -> ();
;;
let print_insn mode insn =
let print_insn handle insn =
printf "0x%x\t%s\t%s\n" insn.address insn.mnemonic insn.op_str;
let csh = cs_open CS_ARCH_MIPS mode in
match csh with
| None -> ()
| Some v -> print_detail v insn.arch
print_detail handle insn
let print_arch x =
let (arch, mode, code, comment) = x in
let insns = cs_disasm_quick arch mode code 0x1000L 0L in
let handle = cs_open arch mode in
let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in
match err with
| _ -> ();
let insns = cs_disasm handle code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn mode) insns;;
List.iter (print_insn handle) insns;
match cs_close handle with
| 0 -> ();
| _ -> printf "Failed to close handle";
;;
List.iter print_arch all_tests;;
(* all below code use OO class of Capstone *)
let print_insn_cls csh insn =
printf "0x%x\t%s\t%s\n" insn#address insn#mnemonic insn#op_str;
print_detail csh insn#arch;;
let print_arch_cls x =
let (arch, mode, code, comment) = x in (
let d = new cs arch mode in
let insns = d#disasm code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn_cls d#get_csh) insns;
);;
List.iter print_arch_cls all_tests;;

@ -20,14 +20,14 @@ let all_tests = [
(CS_ARCH_PPC, [CS_MODE_32; CS_MODE_BIG_ENDIAN], _PPC_CODE, "PPC-64");
];;
let print_op csh i op =
let print_op handle i op =
( match op.value with
| PPC_OP_INVALID _ -> (); (* this would never happens *)
| PPC_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name csh reg);
| PPC_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name handle reg);
| PPC_OP_IMM imm -> printf "\t\top[%d]: IMM = 0x%x\n" i imm;
| PPC_OP_MEM mem -> ( printf "\t\top[%d]: MEM\n" i;
if mem.base != 0 then
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name csh mem.base);
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name handle mem.base);
if mem.disp != 0 then
printf "\t\t\toperands[%u].mem.disp: 0x%x\n" i mem.disp;
);
@ -35,59 +35,39 @@ let print_op csh i op =
();;
let print_detail csh arch =
match arch with
| CS_INFO_ARM _ -> ();
| CS_INFO_ARM64 _ -> ();
| CS_INFO_MIPS _ -> ();
| CS_INFO_X86 _ -> ();
| CS_INFO_SPARC _ -> ();
| CS_INFO_SYSZ _ -> ();
| CS_INFO_XCORE _ -> ();
| CS_INFO_PPC ppc ->
(* print all operands info (type & value) *)
if (Array.length ppc.operands) > 0 then (
printf "\top_count: %d\n" (Array.length ppc.operands);
Array.iteri (print_op csh) ppc.operands;
);
printf "\n";;
let print_detail handle insn =
match insn.arch with
| CS_INFO_PPC ppc -> (
(* print all operands info (type & value) *)
if (Array.length ppc.operands) > 0 then (
printf "\top_count: %d\n" (Array.length ppc.operands);
Array.iteri (print_op handle) ppc.operands;
);
printf "\n";
);
| _ -> ();
;;
let print_insn mode insn =
let print_insn handle insn =
printf "0x%x\t%s\t%s\n" insn.address insn.mnemonic insn.op_str;
let csh = cs_open CS_ARCH_PPC mode in
match csh with
| None -> ()
| Some v -> print_detail v insn.arch
print_detail handle insn
let print_arch x =
let (arch, mode, code, comment) = x in
let insns = cs_disasm_quick arch mode code 0x1000L 0L in
let handle = cs_open arch mode in
let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in
match err with
| _ -> ();
let insns = cs_disasm handle code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn mode) insns;;
List.iter (print_insn handle) insns;
match cs_close handle with
| 0 -> ();
| _ -> printf "Failed to close handle";
;;
List.iter print_arch all_tests;;
(* all below code use OO class of Capstone *)
let print_insn_cls csh insn =
printf "0x%x\t%s\t%s\n" insn#address insn#mnemonic insn#op_str;
print_detail csh insn#arch;;
let print_arch_cls x =
let (arch, mode, code, comment) = x in (
let d = new cs arch mode in
let insns = d#disasm code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn_cls d#get_csh) insns;
);;
List.iter print_arch_cls all_tests;;

@ -23,14 +23,14 @@ let all_tests = [
(CS_ARCH_SPARC, [CS_MODE_BIG_ENDIAN; CS_MODE_V9], _SPARCV9_CODE, "SparcV9");
];;
let print_op csh i op =
let print_op handle i op =
( match op.value with
| SPARC_OP_INVALID _ -> (); (* this would never happens *)
| SPARC_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name csh reg);
| SPARC_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name handle reg);
| SPARC_OP_IMM imm -> printf "\t\top[%d]: IMM = 0x%x\n" i imm;
| SPARC_OP_MEM mem -> ( printf "\t\top[%d]: MEM\n" i;
if mem.base != 0 then
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name csh mem.base);
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name handle mem.base);
if mem.index != 0 then
printf "\t\t\toperands[%u].mem.index: 0x%x\n" i mem.index;
if mem.disp != 0 then
@ -41,59 +41,39 @@ let print_op csh i op =
();;
let print_detail csh arch =
match arch with
| CS_INFO_ARM _ -> ();
| CS_INFO_ARM64 _ -> ();
| CS_INFO_MIPS _ -> ();
| CS_INFO_X86 _ -> ();
| CS_INFO_PPC _ -> ();
| CS_INFO_SYSZ _ -> ();
| CS_INFO_XCORE _ -> ();
| CS_INFO_SPARC sparc ->
(* print all operands info (type & value) *)
if (Array.length sparc.operands) > 0 then (
printf "\top_count: %d\n" (Array.length sparc.operands);
Array.iteri (print_op csh) sparc.operands;
);
printf "\n";;
let print_detail handle insn =
match insn.arch with
| CS_INFO_SPARC sparc -> (
(* print all operands info (type & value) *)
if (Array.length sparc.operands) > 0 then (
printf "\top_count: %d\n" (Array.length sparc.operands);
Array.iteri (print_op handle) sparc.operands;
);
printf "\n";
);
| _ -> ();
;;
let print_insn mode insn =
let print_insn handle insn =
printf "0x%x\t%s\t%s\n" insn.address insn.mnemonic insn.op_str;
let csh = cs_open CS_ARCH_SPARC mode in
match csh with
| None -> ()
| Some v -> print_detail v insn.arch
print_detail handle insn
let print_arch x =
let (arch, mode, code, comment) = x in
let insns = cs_disasm_quick arch mode code 0x1000L 0L in
let handle = cs_open arch mode in
let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in
match err with
| _ -> ();
let insns = cs_disasm handle code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn mode) insns;;
List.iter (print_insn handle) insns;
match cs_close handle with
| 0 -> ();
| _ -> printf "Failed to close handle";
;;
List.iter print_arch all_tests;;
(* all below code use OO class of Capstone *)
let print_insn_cls csh insn =
printf "0x%x\t%s\t%s\n" insn#address insn#mnemonic insn#op_str;
print_detail csh insn#arch;;
let print_arch_cls x =
let (arch, mode, code, comment) = x in (
let d = new cs arch mode in
let insns = d#disasm code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn_cls d#get_csh) insns;
);;
List.iter print_arch_cls all_tests;;

@ -22,15 +22,15 @@ let all_tests = [
(CS_ARCH_SYSZ, [CS_MODE_LITTLE_ENDIAN], _SYSZ_CODE, "SystemZ");
];;
let print_op csh i op =
let print_op handle i op =
( match op.value with
| SYSZ_OP_INVALID _ -> (); (* this would never happens *)
| SYSZ_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name csh reg);
| SYSZ_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name handle reg);
| SYSZ_OP_ACREG reg -> printf "\t\top[%d]: ACREG = %u\n" i reg;
| SYSZ_OP_IMM imm -> printf "\t\top[%d]: IMM = 0x%x\n" i imm;
| SYSZ_OP_MEM mem -> ( printf "\t\top[%d]: MEM\n" i;
if mem.base != 0 then
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name csh mem.base);
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name handle mem.base);
if mem.index != 0 then
printf "\t\t\toperands[%u].mem.index: 0x%x\n" i mem.index;
if mem.length != 0L then
@ -39,63 +39,42 @@ let print_op csh i op =
printf "\t\t\toperands[%u].mem.disp: 0x%Lx\n" i mem.disp;
);
);
();;
let print_detail csh arch =
match arch with
| CS_INFO_ARM _ -> ();
| CS_INFO_ARM64 _ -> ();
| CS_INFO_MIPS _ -> ();
| CS_INFO_X86 _ -> ();
| CS_INFO_PPC _ -> ();
| CS_INFO_SPARC _ -> ();
| CS_INFO_XCORE _ -> ();
| CS_INFO_SYSZ sysz ->
(* print all operands info (type & value) *)
if (Array.length sysz.operands) > 0 then (
printf "\top_count: %d\n" (Array.length sysz.operands);
Array.iteri (print_op csh) sysz.operands;
);
printf "\n";;
let print_detail handle insn =
match insn.arch with
| CS_INFO_SYSZ sysz -> (
(* print all operands info (type & value) *)
if (Array.length sysz.operands) > 0 then (
printf "\top_count: %d\n" (Array.length sysz.operands);
Array.iteri (print_op handle) sysz.operands;
);
printf "\n";
);
| _ -> ();
;;
let print_insn mode insn =
let print_insn handle insn =
printf "0x%x\t%s\t%s\n" insn.address insn.mnemonic insn.op_str;
let csh = cs_open CS_ARCH_SYSZ mode in
match csh with
| None -> ()
| Some v -> print_detail v insn.arch
print_detail handle insn
let print_arch x =
let (arch, mode, code, comment) = x in
let insns = cs_disasm_quick arch mode code 0x1000L 0L in
let handle = cs_open arch mode in
let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in
match err with
| _ -> ();
let insns = cs_disasm handle code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn mode) insns;;
List.iter (print_insn handle) insns;
match cs_close handle with
| 0 -> ();
| _ -> printf "Failed to close handle";
;;
List.iter print_arch all_tests;;
(* all below code use OO class of Capstone *)
let print_insn_cls csh insn =
printf "0x%x\t%s\t%s\n" insn#address insn#mnemonic insn#op_str;
print_detail csh insn#arch;;
let print_arch_cls x =
let (arch, mode, code, comment) = x in (
let d = new cs arch mode in
let insns = d#disasm code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn_cls d#get_csh) insns;
);;
List.iter print_arch_cls all_tests;;

@ -21,23 +21,23 @@ let _X86_CODE64 = "\x55\x48\x8b\x05\xb8\x13\x00\x00";;
let all_tests = [
(CS_ARCH_X86, [CS_MODE_16], _X86_CODE16, "X86 16bit (Intel syntax)", 0);
(CS_ARCH_X86, [CS_MODE_32], _X86_CODE32, "X86 32bit (ATT syntax)", 0);
(CS_ARCH_X86, [CS_MODE_32], _X86_CODE32, "X86 32 (Intel syntax)", 0);
(CS_ARCH_X86, [CS_MODE_64], _X86_CODE64, "X86 64 (Intel syntax)", 0);
(CS_ARCH_X86, [CS_MODE_16], _X86_CODE16, "X86 16bit (Intel syntax)", 0L);
(CS_ARCH_X86, [CS_MODE_32], _X86_CODE32, "X86 32bit (ATT syntax)", _CS_OPT_SYNTAX_ATT);
(CS_ARCH_X86, [CS_MODE_32], _X86_CODE32, "X86 32 (Intel syntax)", 0L);
(CS_ARCH_X86, [CS_MODE_64], _X86_CODE64, "X86 64 (Intel syntax)", 0L);
];;
let print_op csh i op =
let print_op handle i op =
( match op.value with
| X86_OP_INVALID _ -> (); (* this would never happens *)
| X86_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name csh reg);
| X86_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name handle reg);
| X86_OP_IMM imm -> printf "\t\top[%d]: IMM = 0x%x\n" i imm;
| X86_OP_FP fp -> printf "\t\top[%d]: FP = %f\n" i fp;
| X86_OP_MEM mem -> ( printf "\t\top[%d]: MEM\n" i;
if mem.base != 0 then
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name csh mem.base);
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name handle mem.base);
if mem.index != 0 then
printf "\t\t\toperands[%u].mem.index: REG = %s\n" i (cs_reg_name csh mem.index);
printf "\t\t\toperands[%u].mem.index: REG = %s\n" i (cs_reg_name handle mem.index);
if mem.scale != 1 then
printf "\t\t\toperands[%u].mem.scale: %d\n" i mem.scale;
if mem.disp != 0 then
@ -47,88 +47,72 @@ let print_op csh i op =
();;
let print_detail mode csh arch =
match arch with
| CS_INFO_ARM64 _ -> ();
| CS_INFO_ARM _ -> ();
| CS_INFO_MIPS _ -> ();
| CS_INFO_PPC _ -> ();
| CS_INFO_SPARC _ -> ();
| CS_INFO_SYSZ _ -> ();
| CS_INFO_XCORE _ -> ();
| CS_INFO_X86 x86 ->
print_string_hex "\tPrefix: " x86.prefix;
(* print instruction's opcode *)
print_string_hex "\tOpcode: " x86.opcode;
(* print operand's size, address size, displacement size & immediate size *)
printf "\taddr_size: %u\n" x86.addr_size;
(* print modRM byte *)
printf "\tmodrm: 0x%x\n" x86.modrm;
(* print displacement value *)
if x86.disp != 0 then
printf "\tdisp: 0x%x\n" x86.disp;
(* SIB is invalid in 16-bit mode *)
if not (List.mem CS_MODE_16 mode) then (
(* print SIB byte *)
printf "\tsib: 0x%x\n" x86.sib;
(* print sib index/scale/base (if applicable) *)
if x86.sib_index != _X86_REG_INVALID then
printf "\tsib_index: %s, sib_scale: %u, sib_base: %s\n"
(cs_reg_name csh x86.sib_index)
x86.sib_scale
(cs_reg_name csh x86.sib_base);
);
let print_detail handle mode insn =
match insn.arch with
| CS_INFO_X86 x86 -> (
print_string_hex "\tPrefix: " x86.prefix;
(* print instruction's opcode *)
print_string_hex "\tOpcode: " x86.opcode;
(* print operand's size, address size, displacement size & immediate size *)
printf "\taddr_size: %u\n" x86.addr_size;
(* print modRM byte *)
printf "\tmodrm: 0x%x\n" x86.modrm;
(* print displacement value *)
if x86.disp != 0 then
printf "\tdisp: 0x%x\n" x86.disp;
(* print all operands info (type & value) *)
if (Array.length x86.operands) > 0 then (
printf "\top_count: %d\n" (Array.length x86.operands);
Array.iteri (print_op csh) x86.operands;
(* SIB is invalid in 16-bit mode *)
if not (List.mem CS_MODE_16 mode) then (
(* print SIB byte *)
printf "\tsib: 0x%x\n" x86.sib;
(* print sib index/scale/base (if applicable) *)
if x86.sib_index != _X86_REG_INVALID then
printf "\tsib_index: %s, sib_scale: %u, sib_base: %s\n"
(cs_reg_name handle x86.sib_index)
x86.sib_scale
(cs_reg_name handle x86.sib_base);
);
(* print all operands info (type & value) *)
if (Array.length x86.operands) > 0 then (
printf "\top_count: %d\n" (Array.length x86.operands);
Array.iteri (print_op handle) x86.operands;
);
printf "\n";
);
printf "\n";;
| _ -> ();
;;
let print_insn mode insn =
let print_insn handle mode insn =
printf "0x%x\t%s\t%s\n" insn.address insn.mnemonic insn.op_str;
let csh = cs_open CS_ARCH_X86 mode in
match csh with
| None -> ()
| Some v -> print_detail mode v insn.arch
print_detail handle mode insn
let print_arch x =
let (arch, mode, code, comment, syntax) = x in
let insns = cs_disasm_quick arch mode code 0x1000L 0L in
let handle = cs_open arch mode in (
if syntax != 0L then (
let err = cs_option handle CS_OPT_SYNTAX syntax in
match err with
| _ -> ();
);
let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in
match err with
| _ -> ();
let insns = cs_disasm handle code 0x1000L 0L in (
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn mode) insns;;
List.iter print_arch all_tests;;
(* all below code use OO class of Capstone *)
let print_insn_cls mode csh insn =
printf "0x%x\t%s\t%s\n" insn#address insn#mnemonic insn#op_str;
print_string_hex "\tbytes: " insn#bytes;
print_detail mode csh insn#arch;;
let print_arch_cls x =
let (arch, mode, code, comment, syntax) = x in (
let d = new cs arch mode in
let insns = d#disasm code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn_cls mode d#get_csh) insns;
List.iter (print_insn handle mode) insns;
);
match cs_close handle with
| 0 -> ();
| _ -> printf "Failed to close handle";
);;
List.iter print_arch_cls all_tests;;
List.iter print_arch all_tests;;

@ -20,14 +20,14 @@ let all_tests = [
(CS_ARCH_XCORE, [CS_MODE_LITTLE_ENDIAN], _XCORE_CODE, "XCore");
];;
let print_op csh i op =
let print_op handle i op =
( match op.value with
| XCORE_OP_INVALID _ -> (); (* this would never happens *)
| XCORE_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name csh reg);
| XCORE_OP_REG reg -> printf "\t\top[%d]: REG = %s\n" i (cs_reg_name handle reg);
| XCORE_OP_IMM imm -> printf "\t\top[%d]: IMM = 0x%x\n" i imm;
| XCORE_OP_MEM mem -> ( printf "\t\top[%d]: MEM\n" i;
if mem.base != 0 then
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name csh mem.base);
printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name handle mem.base);
if mem.index != 0 then
printf "\t\t\toperands[%u].mem.index: 0x%x\n" i mem.index;
if mem.disp != 0 then
@ -40,59 +40,39 @@ let print_op csh i op =
();;
let print_detail csh arch =
match arch with
| CS_INFO_ARM _ -> ();
| CS_INFO_ARM64 _ -> ();
| CS_INFO_MIPS _ -> ();
| CS_INFO_X86 _ -> ();
| CS_INFO_PPC _ -> ();
| CS_INFO_SPARC _ -> ();
| CS_INFO_SYSZ _ -> ();
let print_detail handle insn =
match insn.arch with
| CS_INFO_XCORE xcore -> (
(* print all operands info (type & value) *)
if (Array.length xcore.operands) > 0 then (
printf "\top_count: %d\n" (Array.length xcore.operands);
Array.iteri (print_op csh) xcore.operands;
);
printf "\n";
);;
(* print all operands info (type & value) *)
if (Array.length xcore.operands) > 0 then (
printf "\top_count: %d\n" (Array.length xcore.operands);
Array.iteri (print_op handle) xcore.operands;
);
printf "\n";
);
| _ -> ();
;;
let print_insn mode insn =
let print_insn handle insn =
printf "0x%x\t%s\t%s\n" insn.address insn.mnemonic insn.op_str;
let csh = cs_open CS_ARCH_XCORE mode in
match csh with
| None -> ()
| Some v -> print_detail v insn.arch
print_detail handle insn
let print_arch x =
let (arch, mode, code, comment) = x in
let insns = cs_disasm_quick arch mode code 0x1000L 0L in
let handle = cs_open arch mode in
let err = cs_option handle CS_OPT_DETAIL _CS_OPT_ON in
match err with
| _ -> ();
let insns = cs_disasm handle code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn mode) insns;;
List.iter (print_insn handle) insns;
match cs_close handle with
| 0 -> ();
| _ -> printf "Failed to close handle";
;;
List.iter print_arch all_tests;;
(* all below code use OO class of Capstone *)
let print_insn_cls csh insn =
printf "0x%x\t%s\t%s\n" insn#address insn#mnemonic insn#op_str;
print_detail csh insn#arch;;
let print_arch_cls x =
let (arch, mode, code, comment) = x in (
let d = new cs arch mode in
let insns = d#disasm code 0x1000L 0L in
printf "*************\n";
printf "Platform: %s\n" comment;
List.iter (print_insn_cls d#get_csh) insns;
);;
List.iter print_arch_cls all_tests;;

@ -38,7 +38,6 @@ __all__ = [
'CS_MODE_THUMB',
'CS_MODE_MCLASS',
'CS_MODE_MICRO',
'CS_MODE_N64',
'CS_MODE_MIPS3',
'CS_MODE_MIPS32R6',
'CS_MODE_MIPSGP64',
@ -104,10 +103,9 @@ CS_MODE_64 = (1 << 3) # 64-bit mode (for X86, Mips)
CS_MODE_THUMB = (1 << 4) # ARM's Thumb mode, including Thumb-2
CS_MODE_MCLASS = (1 << 5) # ARM's Cortex-M series
CS_MODE_MICRO = (1 << 4) # MicroMips mode (MIPS architecture)
CS_MODE_N64 = (1 << 5) # Nintendo-64 mode (MIPS architecture)
CS_MODE_MIPS3 = 1 << 6 # Mips III ISA
CS_MODE_MIPS32R6 = 1 << 7 # Mips32r6 ISA
CS_MODE_MIPSGP64 = 1 << 8 # General Purpose Registers are 64-bit wide (MIPS arch)
CS_MODE_MIPS3 = (1 << 5) # Mips III ISA
CS_MODE_MIPS32R6 = (1 << 6) # Mips32r6 ISA
CS_MODE_MIPSGP64 = (1 << 7) # General Purpose Registers are 64-bit wide (MIPS arch)
CS_MODE_V9 = (1 << 4) # Nintendo-64 mode (MIPS architecture)
CS_MODE_BIG_ENDIAN = (1 << 31) # big-endian mode

@ -33,6 +33,7 @@ class ArmOp(ctypes.Structure):
('shift', ArmOpShift),
('type', ctypes.c_uint),
('value', ArmOpValue),
('subtracted', ctypes.c_bool),
)
@property

@ -151,14 +151,13 @@ MIPS_REG_W30 = 126
MIPS_REG_W31 = 127
MIPS_REG_HI = 128
MIPS_REG_LO = 129
MIPS_REG_PC = 130
MIPS_REG_P0 = 131
MIPS_REG_P1 = 132
MIPS_REG_P2 = 133
MIPS_REG_MPL0 = 134
MIPS_REG_MPL1 = 135
MIPS_REG_MPL2 = 136
MIPS_REG_ENDING = 137
MIPS_REG_P0 = 130
MIPS_REG_P1 = 131
MIPS_REG_P2 = 132
MIPS_REG_MPL0 = 133
MIPS_REG_MPL1 = 134
MIPS_REG_MPL2 = 135
MIPS_REG_ENDING = 136
MIPS_REG_ZERO = MIPS_REG_0
MIPS_REG_AT = MIPS_REG_1
MIPS_REG_V0 = MIPS_REG_2

@ -8,7 +8,7 @@ from capstone.arm import *
from xprint import to_hex, to_x, to_x_32
ARM_CODE = b"\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3\x00\x02\x01\xf1\x05\x40\xd0\xe8"
ARM_CODE = b"\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3\x00\x02\x01\xf1\x05\x40\xd0\xe8\xf4\x80\x00\x00"
ARM_CODE2 = b"\xd1\xe8\x00\xf0\xf0\x24\x04\x07\x1f\x3c\xf2\xc0\x00\x00\x4f\xf0\x00\x01\x46\x6c"
THUMB_CODE = b"\x70\x47\xeb\x46\x83\xb0\xc9\x68\x1f\xb1\x30\xbf\xaf\xf3\x20\x84"
THUMB_CODE2 = b"\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0\x18\xbf\xad\xbf\xf3\xff\x0b\x0c\x86\xf3\x00\x89\x80\xf3\x00\x8c\x4f\xfa\x99\xf6\xd0\xff\xa2\x01"
@ -70,6 +70,8 @@ def print_insn_detail(insn):
% (i.shift.type, i.shift.value))
if i.vector_index != -1:
print("\t\t\toperands[%u].vector_index = %u" %(c, i.vector_index))
if i.subtracted:
print("\t\t\toperands[%u].subtracted = True")
c += 1

116
cs.c

@ -238,9 +238,8 @@ cs_err cs_close(csh *handle)
if (ud->printer_info)
cs_mem_free(ud->printer_info);
// arch_destroy[ud->arch](ud);
cs_mem_free(ud->insn_cache);
memset(ud, 0, sizeof(*ud));
cs_mem_free(ud);
@ -410,7 +409,7 @@ static void skipdata_opstr(char *opstr, const uint8_t *buffer, size_t size)
CAPSTONE_EXPORT
size_t cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn)
{
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
struct cs_struct *handle;
MCInst mci;
uint16_t insn_size;
size_t c = 0, i;
@ -427,6 +426,7 @@ size_t cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, si
unsigned int cache_size = INSN_CACHE_SIZE;
size_t next_offset;
handle = (struct cs_struct *)(uintptr_t)ud;
if (!handle) {
// FIXME: how to handle this case:
// handle->errnum = CS_ERR_HANDLE;
@ -511,7 +511,7 @@ size_t cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, si
// we have to skip some amount of data, depending on arch & mode
insn_cache->id = 0; // invalid ID for this "data" instruction
insn_cache->address = offset;
insn_cache->size = (uint16_t) skipdata_bytes;
insn_cache->size = (uint16_t)skipdata_bytes;
memcpy(insn_cache->bytes, buffer, skipdata_bytes);
strncpy(insn_cache->mnemonic, handle->skipdata_setup.mnemonic,
sizeof(insn_cache->mnemonic) - 1);
@ -612,6 +612,114 @@ void cs_free(cs_insn *insn, size_t count)
cs_mem_free(insn);
}
CAPSTONE_EXPORT
cs_insn *cs_malloc(csh ud)
{
cs_insn *insn;
struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
insn = cs_mem_malloc(sizeof(cs_insn));
if (!insn) {
// insufficient memory
handle->errnum = CS_ERR_MEM;
return NULL;
} else {
if (handle->detail) {
// allocate memory for @detail pointer
insn->detail = cs_mem_malloc(sizeof(cs_detail));
if (insn->detail == NULL) { // insufficient memory
cs_mem_free(insn);
handle->errnum = CS_ERR_MEM;
return NULL;
}
} else
insn->detail = NULL;
}
return insn;
}
// iterator for instruction "single-stepping"
CAPSTONE_EXPORT
bool cs_disasm_iter(csh ud, const uint8_t **code, size_t *size,
uint64_t *address, cs_insn *insn)
{
struct cs_struct *handle;
uint16_t insn_size;
MCInst mci;
bool r;
handle = (struct cs_struct *)(uintptr_t)ud;
if (!handle) {
return false;
}
handle->errnum = CS_ERR_OK;
MCInst_Init(&mci);
mci.csh = handle;
// relative branches need to know the address & size of current insn
mci.address = *address;
// save all the information for non-detailed mode
mci.flat_insn = insn;
mci.flat_insn->address = *address;
#ifdef CAPSTONE_DIET
// zero out mnemonic & op_str
mci.flat_insn->mnemonic[0] = '\0';
mci.flat_insn->op_str[0] = '\0';
#endif
r = handle->disasm(ud, *code, *size, &mci, &insn_size, *address, handle->getinsn_info);
if (r) {
SStream ss;
SStream_Init(&ss);
mci.flat_insn->size = insn_size;
handle->printer(&mci, &ss, handle->printer_info);
fill_insn(handle, insn, ss.buffer, &mci, handle->post_printer, *code);
*code += insn_size;
*size -= insn_size;
*address += insn_size;
} else { // encounter a broken instruction
size_t skipdata_bytes;
// if there is no request to skip data, or remaining data is too small,
// then bail out
if (!handle->skipdata || handle->skipdata_size > *size)
return false;
if (handle->skipdata_setup.callback) {
skipdata_bytes = handle->skipdata_setup.callback(*code, *size,
0, handle->skipdata_setup.user_data);
if (skipdata_bytes > *size)
// remaining data is not enough
return false;
if (!skipdata_bytes)
// user requested not to skip data, so bail out
return false;
} else
skipdata_bytes = handle->skipdata_size;
// we have to skip some amount of data, depending on arch & mode
insn->id = 0; // invalid ID for this "data" instruction
insn->address = *address;
insn->size = (uint16_t)skipdata_bytes;
memcpy(insn->bytes, *code, skipdata_bytes);
strncpy(insn->mnemonic, handle->skipdata_setup.mnemonic,
sizeof(insn->mnemonic) - 1);
skipdata_opstr(insn->op_str, *code, skipdata_bytes);
*code += skipdata_bytes;
*size -= skipdata_bytes;
*address += skipdata_bytes;
}
return true;
}
// return friendly name of regiser in a string
CAPSTONE_EXPORT
const char *cs_reg_name(csh ud, unsigned int reg)

@ -36,6 +36,10 @@ Documention of Capstone disassembly framework.
http://capstone-engine.org/skipdata.html
* Quickly iterate instructions with cs_disasm_iter().
http://capstone-engine.org/iteration.html
* Build X86-reduce engine for firmware/OS kernel.
http://capstone-engine.org/x86reduce.html

@ -212,6 +212,9 @@ typedef struct cs_arm_op {
arm_op_mem mem; // base/index/scale/disp value for MEM operand
arm_setend_type setend; // SETEND instruction's operand type
};
// in some instructions, an operand can be subtracted or added to
// the base register,
bool subtracted; // if TRUE, this operand is subtracted. otherwise, it is added.
} cs_arm_op;
// Instruction structure

@ -16,15 +16,15 @@ extern "C" {
#include "platform.h"
#ifdef _MSC_VER
#pragma warning(disable:4201)
#pragma warning(disable:4100)
#ifdef CAPSTONE_SHARED
#define CAPSTONE_EXPORT __declspec(dllexport)
#else // defined(CAPSTONE_STATIC)
#define CAPSTONE_EXPORT
#endif
#pragma warning(disable:4201)
#pragma warning(disable:4100)
#ifdef CAPSTONE_SHARED
#define CAPSTONE_EXPORT __declspec(dllexport)
#else // defined(CAPSTONE_STATIC)
#define CAPSTONE_EXPORT
#endif
#else
#define CAPSTONE_EXPORT
#define CAPSTONE_EXPORT
#endif
#ifdef __GNUC__
@ -81,10 +81,9 @@ typedef enum cs_mode {
CS_MODE_THUMB = 1 << 4, // ARM's Thumb mode, including Thumb-2
CS_MODE_MCLASS = 1 << 5, // ARM's Cortex-M series
CS_MODE_MICRO = 1 << 4, // MicroMips mode (MIPS architecture)
CS_MODE_N64 = 1 << 5, // Nintendo-64 mode (MIPS architecture)
CS_MODE_MIPS3 = 1 << 6, // Mips III ISA
CS_MODE_MIPS32R6 = 1 << 7, // Mips32r6 ISA
CS_MODE_MIPSGP64 = 1 << 8, // General Purpose Registers are 64-bit wide (MIPS arch)
CS_MODE_MIPS3 = 1 << 5, // Mips III ISA
CS_MODE_MIPS32R6 = 1 << 6, // Mips32r6 ISA
CS_MODE_MIPSGP64 = 1 << 7, // General Purpose Registers are 64-bit wide (MIPS arch)
CS_MODE_V9 = 1 << 4, // SparcV9 mode (Sparc architecture)
CS_MODE_BIG_ENDIAN = 1 << 31 // big endian mode
} cs_mode;
@ -126,16 +125,21 @@ typedef enum cs_opt_value {
CS_OPT_SYNTAX_NOREGNAME, // Prints register name with only number (CS_OPT_SYNTAX)
} cs_opt_value;
// User-defined callback function for SKIPDATA option
// @code: the input buffer containing code to be disassembled. This is the
// same buffer passed to cs_disasm().
// @code_size: size (in bytes) of the above @code buffer.
// @offset: the position of the currently-examining byte in the input
// buffer @code mentioned above.
// @user_data: user-data passed to cs_option() via @user_data field in
// cs_opt_skipdata struct below.
// @return: return number of bytes to skip, or 0 to immediately stop disassembling.
typedef size_t (*cs_skipdata_cb_t)(const uint8_t *code, size_t code_size, size_t offset, void* user_data);
/*
User-defined callback function for SKIPDATA option.
See tests/test_skipdata.c for sample code demonstrating this API.
@code: the input buffer containing code to be disassembled.
This is the same buffer passed to cs_disasm().
@code_size: size (in bytes) of the above @code buffer.
@offset: the position of the currently-examining byte in the input
buffer @code mentioned above.
@user_data: user-data passed to cs_option() via @user_data field in
cs_opt_skipdata struct below.
@return: return number of bytes to skip, or 0 to immediately stop disassembling.
*/
typedef size_t (*cs_skipdata_cb_t)(const uint8_t *code, size_t code_size, size_t offset, void *user_data);
// User-customized setup for SKIPDATA option
typedef struct cs_opt_skipdata {
@ -205,6 +209,7 @@ typedef struct cs_insn {
// Find the instruction id from header file of corresponding architecture,
// such as arm.h for ARM, x86.h for X86, etc...
// This information is available even when CS_OPT_DETAIL = CS_OPT_OFF
// NOTE: in Skipdata mode, "data" instruction has 0 for this id field.
unsigned int id;
// Address (EIP) of this instruction
@ -227,10 +232,12 @@ typedef struct cs_insn {
char op_str[160];
// Pointer to cs_detail.
// NOTE: detail pointer is only valid (not NULL) when both requirements below are met:
// NOTE: detail pointer is only valid when both requirements below are met:
// (1) CS_OP_DETAIL = CS_OPT_ON
// (2) If engine is in Skipdata mode (CS_OP_SKIPDATA option set to CS_OPT_ON), then
// the current instruction is not the "data" instruction (which clearly has no detail).
// (2) Engine is not in Skipdata mode (CS_OP_SKIPDATA option set to CS_OPT_ON)
//
// NOTE 2: when in Skipdata mode, or when detail mode is OFF, even if this pointer
// is not NULL, its content is still irrelevant.
cs_detail *detail;
} cs_insn;
@ -267,8 +274,8 @@ typedef enum cs_err {
@minor: minor number of API version
@return hexical number as (major << 8 | minor), which encodes both
major & minor versions.
NOTE: This returned value can be compared with version number made
major & minor versions.
NOTE: This returned value can be compared with version number made
with macro CS_MAKE_VERSION
For example, second API version would return 1 in @major, and 1 in @minor
@ -334,7 +341,7 @@ cs_err cs_close(csh *handle);
@type: type of option to be set
@value: option value corresponding with @type
@return CS_ERR_OK on success, or other value on failure.
@return: CS_ERR_OK on success, or other value on failure.
Refer to cs_err enum for detailed error.
NOTE: in the case of CS_OPT_MEM, handle's value can be anything,
@ -362,27 +369,30 @@ cs_err cs_errno(csh handle);
@code: error code (see CS_ERR_* above)
@return: returns a pointer to a string that describes the error code
passed in the argument @code
passed in the argument @code
*/
CAPSTONE_EXPORT
const char *cs_strerror(cs_err code);
/*
Dynamicly allocate memory to contain disasm insn
Disassembled instructions will be put into @*insn
Disassemble binary code, given the code buffer, size, address and number
of instructions to be decoded.
This API dynamicly allocate memory to contain disassembled instruction.
Resulted instructions will be put into @*insn
NOTE 1: this API will automatically determine memory needed to contain
output disassembled instructions in @insn.
NOTE 2: caller must free() the allocated memory itself to avoid memory leaking
NOTE 2: caller must free the allocated memory itself to avoid memory leaking.
@handle: handle returned by cs_open()
@code: buffer containing raw binary code to be disassembled
@code_size: size of above code
@address: address of the first insn in given raw code buffer
@insn: array of insn filled in by this function
NOTE: @insn will be allocated by this function, and should be freed
@code: buffer containing raw binary code to be disassembled.
@code_size: size of the above code buffer.
@address: address of the first instruction in given raw code buffer.
@insn: array of instructions filled in by this API.
NOTE: @insn will be allocated by this function, and should be freed
with cs_free() API.
@count: number of instrutions to be disassembled, or 0 to get all of them
@return: the number of succesfully disassembled instructions,
or 0 if this function failed to disassemble the given code
@ -408,14 +418,58 @@ size_t cs_disasm_ex(csh handle,
cs_insn **insn);
/*
Free memory allocated in @insn by cs_disasm()
Free memory allocated by cs_malloc() or cs_disasm() (argument @insn)
@insn: pointer returned by @insn argument in cs_disasm()
@count: number of cs_insn structures returned by cs_disasm()
@insn: pointer returned by @insn argument in cs_disasm() or cs_malloc()
@count: number of cs_insn structures returned by cs_disasm(), or 1
to free memory allocated by cs_malloc().
*/
CAPSTONE_EXPORT
void cs_free(cs_insn *insn, size_t count);
/*
Allocate memory for 1 instruction to be used by cs_disasm_iter().
@handle: handle returned by cs_open()
NOTE: when no longer in use, you can reclaim the memory allocated for
this instruction with cs_free(insn, 1)
*/
CAPSTONE_EXPORT
cs_insn *cs_malloc(csh handle);
/*
Fast API to disassemble binary code, given the code buffer, size, address
and number of instructions to be decoded.
This API put the resulted instruction into a given cache in @insn.
See tests/test_iter.c for sample code demonstrating this API.
NOTE 1: this API will update @code, @size & @address to point to the next
instruction in the input buffer. Therefore, it is covenient to use
cs_disasm_iter() inside a loop to quickly iterate all the instructions.
While decoding one instruction at a time can also be achieved with
cs_disasm(count=1), some benchmarks shown that cs_disasm_iter() can be 30%
faster on random input.
NOTE 2: the cache in @insn can be created with cs_malloc() API.
@handle: handle returned by cs_open()
@code: buffer containing raw binary code to be disassembled
@code_size: size of above code
@address: address of the first insn in given raw code buffer
@insn: pointer to instruction to be filled in by this API.
@return: true if this API successfully decode 1 instruction,
or false otherwise.
On failure, call cs_errno() for error code.
*/
CAPSTONE_EXPORT
bool cs_disasm_iter(csh handle,
const uint8_t **code, size_t *size,
uint64_t *address, cs_insn *insn);
/*
Return friendly name of regiser in a string.
Find the instruction id from header file of corresponding architecture (arm.h for ARM,
@ -426,6 +480,7 @@ void cs_free(cs_insn *insn, size_t count);
@handle: handle returned by cs_open()
@reg_id: register id
@return: string name of the register, or NULL if @reg_id is invalid.
*/
CAPSTONE_EXPORT

@ -197,7 +197,6 @@ typedef enum mips_reg {
MIPS_REG_HI,
MIPS_REG_LO,
MIPS_REG_PC,
MIPS_REG_P0,
MIPS_REG_P1,

@ -1,4 +1,4 @@
# CS_ARCH_MIPS, CS_MODE_64+CS_MODE_BIG_ENDIAN+CS_MODE_N64, None
# CS_ARCH_MIPS, CS_MODE_64+CS_MODE_BIG_ENDIAN, None
0x02,0x04,0x80,0x20 = add $16, $16, $4
0x02,0x06,0x80,0x20 = add $16, $16, $6
0x02,0x07,0x80,0x20 = add $16, $16, $7

@ -64,7 +64,7 @@ endif
.PHONY: all clean
SOURCES = test.c test_detail.c test_skipdata.c
SOURCES = test.c test_detail.c test_skipdata.c test_iter.c
ifneq (,$(findstring arm,$(CAPSTONE_ARCHS)))
SOURCES += test_arm.c
endif

@ -10,6 +10,15 @@ This directory contains some test code to show how to use Capstone API.
instructions, such as implicit registers read/written, or groups of instructions
that this instruction belong to.
- test_skipdata.c:
This code shows how to use SKIPDATA option to skip broken instructions (most likely
some data mixed with instructions) and continue to decode at the next legitimate
instructions.
- test_iter.c:
This code shows how to use the API cs_disasm_iter() to decode one instruction at
a time inside a loop.
- test_<arch>.c
These code show how to access architecture-specific information for each
architecture.

@ -99,6 +99,9 @@ static void print_insn_detail(cs_insn *ins)
if (op->vector_index != -1) {
printf("\t\toperands[%u].vector_index = %u\n", i, op->vector_index);
}
if (op->subtracted)
printf("\t\tSubtracted: True\n");
}
if (arm->cc != ARM_CC_AL && arm->cc != ARM_CC_INVALID)
@ -176,7 +179,7 @@ static void test()
//#define ARM_CODE "\x90\x04\x0E\x00" // muleq lr, r0, r4
//#define ARM_CODE "\x90\x24\x0E\x00" // muleq lr, r0, r4
//#define ARM_CODE "\xb6\x10\x5f\xe1" // ldrh r1, [pc, #-6]
#define ARM_CODE "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3\x00\x02\x01\xf1\x05\x40\xd0\xe8"
#define ARM_CODE "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3\x00\x02\x01\xf1\x05\x40\xd0\xe8\xf4\x80\x00\x00"
//#define ARM_CODE2 "\xf0\x24"
//#define ARM_CODE2 "\x83\xb0"
#define ARM_CODE2 "\xd1\xe8\x00\xf0\xf0\x24\x04\x07\x1f\x3c\xf2\xc0\x00\x00\x4f\xf0\x00\x01\x46\x6c"

@ -215,9 +215,6 @@ static void test()
// print implicit registers used by this instruction
detail = i->detail;
// detail can be NULL on "data" instruction since we turned on SKIPDATA option above.
if (!detail)
continue;
if (detail->regs_read_count > 0) {
printf("\tImplicit registers read: ");

@ -0,0 +1,264 @@
/* Capstone Disassembler Engine */
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
// This sample code demonstrates the APIs cs_malloc() & cs_disasm_iter().
#include <stdio.h>
#include <stdlib.h>
#include "../inttypes.h"
#include <capstone.h>
struct platform {
cs_arch arch;
cs_mode mode;
unsigned char *code;
size_t size;
char *comment;
cs_opt_type opt_type;
cs_opt_value opt_value;
};
static void print_string_hex(unsigned char *str, size_t len)
{
unsigned char *c;
printf("Code: ");
for (c = str; c < str + len; c++) {
printf("0x%02x ", *c & 0xff);
}
printf("\n");
}
static void test()
{
#define X86_CODE16 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
#define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
//#define X86_CODE32 "\x0f\xa7\xc0" // xstorerng
#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00"
//#define ARM_CODE "\x04\xe0\x2d\xe5"
#define ARM_CODE "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3"
#define ARM_CODE2 "\x10\xf1\x10\xe7\x11\xf2\x31\xe7\xdc\xa1\x2e\xf3\xe8\x4e\x62\xf3"
#define THUMB_CODE "\x70\x47\xeb\x46\x83\xb0\xc9\x68"
#define THUMB_CODE2 "\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0"
#define MIPS_CODE "\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56\x00\x80\x04\x08"
//#define MIPS_CODE "\x21\x38\x00\x01"
//#define MIPS_CODE "\x21\x30\xe6\x70"
//#define MIPS_CODE "\x1c\x00\x40\x14"
#define MIPS_CODE2 "\x56\x34\x21\x34\xc2\x17\x01\x00"
//#define ARM64_CODE "\xe1\x0b\x40\xb9" // ldr w1, [sp, #0x8]
//#define ARM64_CODE "\x00\x40\x21\x4b" // sub w0, w0, w1, uxtw
//#define ARM64_CODE "\x21\x7c\x02\x9b" // mul x1, x1, x2
//#define ARM64_CODE "\x20\x74\x0b\xd5" // dc zva, x0
//#define ARM64_CODE "\x20\xfc\x02\x9b" // mneg x0, x1, x2
//#define ARM64_CODE "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x10\x20\x21\x1e"
//#define ARM64_CODE "\x21\x7c\x00\x53"
#define ARM64_CODE "\x09\x00\x38\xd5\xbf\x40\x00\xd5\x0c\x05\x13\xd5\x20\x50\x02\x0e\x20\xe4\x3d\x0f\x00\x18\xa0\x5f\xa2\x00\xae\x9e\x9f\x37\x03\xd5\xbf\x33\x03\xd5\xdf\x3f\x03\xd5\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b\x10\x5b\xe8\x3c"
//#define THUMB_CODE "\x0a\xbf" // itet eq
//#define X86_CODE32 "\x77\x04" // ja +6
#define PPC_CODE "\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21\x40\x82\x00\x14"
#define SPARC_CODE "\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03"
#define SPARCV9_CODE "\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0"
#define SYSZ_CODE "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78"
#define XCORE_CODE "\xfe\x0f\xfe\x17\x13\x17\xc6\xfe\xec\x17\x97\xf8\xec\x4f\x1f\xfd\xec\x37\x07\xf2\x45\x5b\xf9\xfa\x02\x06\x1b\x10"
struct platform platforms[] = {
{
CS_ARCH_X86,
CS_MODE_16,
(unsigned char *)X86_CODE16,
sizeof(X86_CODE32) - 1,
"X86 16bit (Intel syntax)"
},
{
CS_ARCH_X86,
CS_MODE_32,
(unsigned char *)X86_CODE32,
sizeof(X86_CODE32) - 1,
"X86 32bit (ATT syntax)",
CS_OPT_SYNTAX,
CS_OPT_SYNTAX_ATT,
},
{
CS_ARCH_X86,
CS_MODE_32,
(unsigned char *)X86_CODE32,
sizeof(X86_CODE32) - 1,
"X86 32 (Intel syntax)"
},
{
CS_ARCH_X86,
CS_MODE_64,
(unsigned char *)X86_CODE64,
sizeof(X86_CODE64) - 1,
"X86 64 (Intel syntax)"
},
{
CS_ARCH_ARM,
CS_MODE_ARM,
(unsigned char *)ARM_CODE,
sizeof(ARM_CODE) - 1,
"ARM"
},
{
CS_ARCH_ARM,
CS_MODE_THUMB,
(unsigned char *)THUMB_CODE2,
sizeof(THUMB_CODE2) - 1,
"THUMB-2"
},
{
CS_ARCH_ARM,
CS_MODE_ARM,
(unsigned char *)ARM_CODE2,
sizeof(ARM_CODE2) - 1,
"ARM: Cortex-A15 + NEON"
},
{
CS_ARCH_ARM,
CS_MODE_THUMB,
(unsigned char *)THUMB_CODE,
sizeof(THUMB_CODE) - 1,
"THUMB"
},
{
CS_ARCH_MIPS,
(cs_mode)(CS_MODE_32 + CS_MODE_BIG_ENDIAN),
(unsigned char *)MIPS_CODE,
sizeof(MIPS_CODE) - 1,
"MIPS-32 (Big-endian)"
},
{
CS_ARCH_MIPS,
(cs_mode)(CS_MODE_64 + CS_MODE_LITTLE_ENDIAN),
(unsigned char *)MIPS_CODE2,
sizeof(MIPS_CODE2) - 1,
"MIPS-64-EL (Little-endian)"
},
{
CS_ARCH_ARM64,
CS_MODE_ARM,
(unsigned char *)ARM64_CODE,
sizeof(ARM64_CODE) - 1,
"ARM-64"
},
{
CS_ARCH_PPC,
CS_MODE_BIG_ENDIAN,
(unsigned char*)PPC_CODE,
sizeof(PPC_CODE) - 1,
"PPC-64"
},
{
CS_ARCH_SPARC,
CS_MODE_BIG_ENDIAN,
(unsigned char*)SPARC_CODE,
sizeof(SPARC_CODE) - 1,
"Sparc"
},
{
CS_ARCH_SPARC,
(cs_mode)(CS_MODE_BIG_ENDIAN + CS_MODE_V9),
(unsigned char*)SPARCV9_CODE,
sizeof(SPARCV9_CODE) - 1,
"SparcV9"
},
{
CS_ARCH_SYSZ,
(cs_mode)0,
(unsigned char*)SYSZ_CODE,
sizeof(SYSZ_CODE) - 1,
"SystemZ"
},
{
CS_ARCH_XCORE,
(cs_mode)0,
(unsigned char*)XCORE_CODE,
sizeof(XCORE_CODE) - 1,
"XCore"
},
};
csh handle;
uint64_t address;
cs_insn *insn;
cs_detail *detail;
int i;
cs_err err;
const uint8_t *code;
size_t size;
for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
printf("****************\n");
printf("Platform: %s\n", platforms[i].comment);
err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
if (err) {
printf("Failed on cs_open() with error returned: %u\n", err);
continue;
}
if (platforms[i].opt_type)
cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
// allocate memory for the cache to be used by cs_disasm_iter()
insn = cs_malloc(handle);
print_string_hex(platforms[i].code, platforms[i].size);
printf("Disasm:\n");
address = 0x1000;
code = platforms[i].code;
size = platforms[i].size;
while(cs_disasm_iter(handle, &code, &size, &address, insn)) {
int n;
printf("0x%"PRIx64":\t%s\t\t%s // insn-ID: %u, insn-mnem: %s\n",
insn->address, insn->mnemonic, insn->op_str,
insn->id, cs_insn_name(handle, insn->id));
// print implicit registers used by this instruction
detail = insn->detail;
if (detail->regs_read_count > 0) {
printf("\tImplicit registers read: ");
for (n = 0; n < detail->regs_read_count; n++) {
printf("%s ", cs_reg_name(handle, detail->regs_read[n]));
}
printf("\n");
}
// print implicit registers modified by this instruction
if (detail->regs_write_count > 0) {
printf("\tImplicit registers modified: ");
for (n = 0; n < detail->regs_write_count; n++) {
printf("%s ", cs_reg_name(handle, detail->regs_write[n]));
}
printf("\n");
}
// print the groups this instruction belong to
if (detail->groups_count > 0) {
printf("\tThis instruction belongs to groups: ");
for (n = 0; n < detail->groups_count; n++) {
printf("%s ", cs_group_name(handle, detail->groups[n]));
}
printf("\n");
}
}
printf("\n");
// free memory allocated by cs_malloc()
cs_free(insn, 1);
cs_close(&handle);
}
}
int main()
{
test();
return 0;
}
Loading…
Cancel
Save