From 839c5e2c1939e22400f51971687cacd8280d5062 Mon Sep 17 00:00:00 2001 From: Catena cyber <35799796+catenacyber@users.noreply.github.com> Date: Mon, 1 Jul 2019 04:35:02 +0200 Subject: [PATCH 01/13] Updates files from LLVM for PPC64 (#1510) * Updates files from LLVM for PPC64 * Only fix tbegin, tabort and such --- suite/synctools/tablegen/PPC/PPCInstrHTM.td | 38 +++++++++---------- suite/synctools/tablegen/PPC/PPCInstrInfo.td | 4 -- .../synctools/tablegen/PPC/PPCRegisterInfo.td | 2 - 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/suite/synctools/tablegen/PPC/PPCInstrHTM.td b/suite/synctools/tablegen/PPC/PPCInstrHTM.td index 6c4e212908..f9c4f42bdf 100644 --- a/suite/synctools/tablegen/PPC/PPCInstrHTM.td +++ b/suite/synctools/tablegen/PPC/PPCInstrHTM.td @@ -21,55 +21,53 @@ def HTM_get_imm : SDNodeXForm; let hasSideEffects = 1, usesCustomInserter = 1 in { -def TCHECK_RET : Pseudo<(outs crrc:$out), (ins), "#TCHECK_RET", []>; +def TCHECK_RET : Pseudo<(outs gprc:$out), (ins), "#TCHECK_RET", []>; +def TBEGIN_RET : PPCCustomInserterPseudo<(outs gprc:$out), (ins u1imm:$R), "#TBEGIN_RET", []>; } let Predicates = [HasHTM] in { +let Defs = [CR0] in { def TBEGIN : XForm_htm0 <31, 654, - (outs crrc0:$ret), (ins u1imm:$R), "tbegin. $R", IIC_SprMTSPR, []>; + (outs), (ins u1imm:$R), "tbegin. $R", IIC_SprMTSPR, []>; def TEND : XForm_htm1 <31, 686, - (outs crrc0:$ret), (ins u1imm:$A), "tend. $A", IIC_SprMTSPR, []>; + (outs), (ins u1imm:$A), "tend. $A", IIC_SprMTSPR, []>; def TABORT : XForm_base_r3xo <31, 910, - (outs crrc0:$ret), (ins gprc:$A), "tabort. $A", IIC_SprMTSPR, + (outs), (ins gprc:$A), "tabort. $A", IIC_SprMTSPR, []>, isDOT { let RST = 0; let B = 0; } def TABORTWC : XForm_base_r3xo <31, 782, - (outs crrc0:$ret), (ins u5imm:$RTS, gprc:$A, gprc:$B), + (outs), (ins u5imm:$RTS, gprc:$A, gprc:$B), "tabortwc. $RTS, $A, $B", IIC_SprMTSPR, []>, isDOT; def TABORTWCI : XForm_base_r3xo <31, 846, - (outs crrc0:$ret), (ins u5imm:$RTS, gprc:$A, u5imm:$B), + (outs), (ins u5imm:$RTS, gprc:$A, u5imm:$B), "tabortwci. $RTS, $A, $B", IIC_SprMTSPR, []>, isDOT; def TABORTDC : XForm_base_r3xo <31, 814, - (outs crrc0:$ret), (ins u5imm:$RTS, gprc:$A, gprc:$B), + (outs), (ins u5imm:$RTS, gprc:$A, gprc:$B), "tabortdc. $RTS, $A, $B", IIC_SprMTSPR, []>, isDOT; def TABORTDCI : XForm_base_r3xo <31, 878, - (outs crrc0:$ret), (ins u5imm:$RTS, gprc:$A, u5imm:$B), + (outs), (ins u5imm:$RTS, gprc:$A, u5imm:$B), "tabortdci. $RTS, $A, $B", IIC_SprMTSPR, []>, isDOT; def TSR : XForm_htm2 <31, 750, - (outs crrc0:$ret), (ins u1imm:$L), "tsr. $L", IIC_SprMTSPR, []>, + (outs), (ins u1imm:$L), "tsr. $L", IIC_SprMTSPR, []>, isDOT; -def TCHECK : XForm_htm3 <31, 718, - (outs), (ins crrc:$BF), "tcheck $BF", IIC_SprMTSPR, []>; - - def TRECLAIM : XForm_base_r3xo <31, 942, - (outs crrc:$ret), (ins gprc:$A), "treclaim. $A", + (outs), (ins gprc:$A), "treclaim. $A", IIC_SprMTSPR, []>, isDOT { let RST = 0; @@ -77,13 +75,17 @@ def TRECLAIM : XForm_base_r3xo <31, 942, } def TRECHKPT : XForm_base_r3xo <31, 1006, - (outs crrc:$ret), (ins), "trechkpt.", IIC_SprMTSPR, []>, + (outs), (ins), "trechkpt.", IIC_SprMTSPR, []>, isDOT { let RST = 0; let A = 0; let B = 0; } +}//Defs = [CR0] + +def TCHECK : XForm_htm3 <31, 718, + (outs crrc:$BF), (ins), "tcheck $BF", IIC_SprMTSPR, []>; // Builtins // All HTM instructions, with the exception of tcheck, set CR0 with the @@ -94,15 +96,11 @@ def TRECHKPT : XForm_base_r3xo <31, 1006, // tbegin builtin API which defines a return value of 1 as success. def : Pat<(int_ppc_tbegin i32:$R), - (XORI - (EXTRACT_SUBREG ( - TBEGIN (HTM_get_imm imm:$R)), sub_eq), - 1)>; + (XORI (TBEGIN_RET(HTM_get_imm imm:$R)), 1)>; def : Pat<(int_ppc_tend i32:$R), (TEND (HTM_get_imm imm:$R))>; - def : Pat<(int_ppc_tabort i32:$R), (TABORT $R)>; diff --git a/suite/synctools/tablegen/PPC/PPCInstrInfo.td b/suite/synctools/tablegen/PPC/PPCInstrInfo.td index 1a43037e4a..863e13ed9a 100644 --- a/suite/synctools/tablegen/PPC/PPCInstrInfo.td +++ b/suite/synctools/tablegen/PPC/PPCInstrInfo.td @@ -540,10 +540,6 @@ def PPCRegCRRCAsmOperand : AsmOperandClass { def crrc : RegisterOperand { let ParserMatchClass = PPCRegCRRCAsmOperand; } -def crrc0 : RegisterOperand { - let ParserMatchClass = PPCRegCRRCAsmOperand; -} - def PPCRegSPERCAsmOperand : AsmOperandClass { let Name = "RegSPERC"; let PredicateMethod = "isRegNumber"; } diff --git a/suite/synctools/tablegen/PPC/PPCRegisterInfo.td b/suite/synctools/tablegen/PPC/PPCRegisterInfo.td index 825e9eb8db..e88590f6b9 100644 --- a/suite/synctools/tablegen/PPC/PPCRegisterInfo.td +++ b/suite/synctools/tablegen/PPC/PPCRegisterInfo.td @@ -369,8 +369,6 @@ def CRBITRC : RegisterClass<"PPC", [i1], 32, def CRRC : RegisterClass<"PPC", [i32], 32, (add CR0, CR1, CR5, CR6, CR7, CR2, CR3, CR4)>; -def CRRC0 : RegisterClass<"PPC", [i32], 32, (add CR0)>; - // The CTR registers are not allocatable because they're used by the // decrement-and-branch instructions, and thus need to stay live across // multiple basic blocks. From 626bd6ab8e1e18143f3ba51597005aca74a353f8 Mon Sep 17 00:00:00 2001 From: keenk <34660397+keenk@users.noreply.github.com> Date: Sun, 30 Jun 2019 21:36:51 -0500 Subject: [PATCH 02/13] Undo rollback of 3 movbe instruction's operand access fixes (#1512) * Fix a few registry access mode mappings * Fix rollback of operand access changes Re-fix operand access of three mov instructions --- arch/X86/X86MappingInsnOp.inc | 6 +++--- arch/X86/X86MappingInsnOp_reduce.inc | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/X86/X86MappingInsnOp.inc b/arch/X86/X86MappingInsnOp.inc index 1681e0717c..909a98dd61 100644 --- a/arch/X86/X86MappingInsnOp.inc +++ b/arch/X86/X86MappingInsnOp.inc @@ -7415,7 +7415,7 @@ { /* X86_MOVBE16mr, X86_INS_MOVBE: movbe */ 0, - { CS_AC_READ, CS_AC_READ, 0 } + { CS_AC_WRITE, CS_AC_READ, 0 } }, { /* X86_MOVBE16rm, X86_INS_MOVBE: movbe */ @@ -7425,7 +7425,7 @@ { /* X86_MOVBE32mr, X86_INS_MOVBE: movbe */ 0, - { CS_AC_READ, CS_AC_READ, 0 } + { CS_AC_WRITE, CS_AC_READ, 0 } }, { /* X86_MOVBE32rm, X86_INS_MOVBE: movbe */ @@ -7435,7 +7435,7 @@ { /* X86_MOVBE64mr, X86_INS_MOVBE: movbe */ 0, - { CS_AC_READ, CS_AC_READ, 0 } + { CS_AC_WRITE, CS_AC_READ, 0 } }, { /* X86_MOVBE64rm, X86_INS_MOVBE: movbe */ diff --git a/arch/X86/X86MappingInsnOp_reduce.inc b/arch/X86/X86MappingInsnOp_reduce.inc index 5fb4a3d6b7..c7e158e375 100644 --- a/arch/X86/X86MappingInsnOp_reduce.inc +++ b/arch/X86/X86MappingInsnOp_reduce.inc @@ -3720,7 +3720,7 @@ { /* X86_MOVBE16mr, X86_INS_MOVBE: movbe */ 0, - { CS_AC_READ, CS_AC_READ, 0 } + { CS_AC_WRITE, CS_AC_READ, 0 } }, { /* X86_MOVBE16rm, X86_INS_MOVBE: movbe */ @@ -3730,7 +3730,7 @@ { /* X86_MOVBE32mr, X86_INS_MOVBE: movbe */ 0, - { CS_AC_READ, CS_AC_READ, 0 } + { CS_AC_WRITE, CS_AC_READ, 0 } }, { /* X86_MOVBE32rm, X86_INS_MOVBE: movbe */ @@ -3740,7 +3740,7 @@ { /* X86_MOVBE64mr, X86_INS_MOVBE: movbe */ 0, - { CS_AC_READ, CS_AC_READ, 0 } + { CS_AC_WRITE, CS_AC_READ, 0 } }, { /* X86_MOVBE64rm, X86_INS_MOVBE: movbe */ From bb838aa7d871684ea8f9cd2435b7a33d5d25583b Mon Sep 17 00:00:00 2001 From: naq Date: Wed, 10 Jul 2019 17:32:46 +0800 Subject: [PATCH 03/13] systemz: fix truncated 64bit imm operand in issue #1515 --- arch/SystemZ/SystemZGenAsmWriter.inc | 10 ++++++++++ arch/SystemZ/SystemZInstPrinter.c | 7 +++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/SystemZ/SystemZGenAsmWriter.inc b/arch/SystemZ/SystemZGenAsmWriter.inc index bdc3a5aa68..149d07f363 100644 --- a/arch/SystemZ/SystemZGenAsmWriter.inc +++ b/arch/SystemZ/SystemZGenAsmWriter.inc @@ -10645,6 +10645,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) // Fragment 0 encoded into 5 bits for 18 unique commands. + // printf("Fragment 0 = %" PRIu64 "\n", (Bits >> 14) & 31); switch ((Bits >> 14) & 31) { default: // llvm_unreachable("Invalid command number."); case 0: @@ -10752,6 +10753,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) // Fragment 1 encoded into 5 bits for 17 unique commands. + // printf("Fragment 1 = %" PRIu64 "\n", (Bits >> 19) & 31); switch ((Bits >> 19) & 31) { default: // llvm_unreachable("Invalid command number."); case 0: @@ -10845,6 +10847,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) // Fragment 2 encoded into 6 bits for 34 unique commands. + // printf("Fragment 2 = %" PRIu64 "\n", (Bits >> 24) & 63); switch ((Bits >> 24) & 63) { default: // llvm_unreachable("Invalid command number."); case 0: @@ -11011,6 +11014,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) // Fragment 3 encoded into 5 bits for 20 unique commands. + // printf("Fragment 3 = %" PRIu64 "\n", (Bits >> 30) & 31); switch ((Bits >> 30) & 31) { default: // llvm_unreachable("Invalid command number."); case 0: @@ -11116,6 +11120,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) // Fragment 4 encoded into 6 bits for 33 unique commands. + // printf("Fragment 4 = %" PRIu64 "\n", (Bits >> 35) & 63); switch ((Bits >> 35) & 63) { default: // llvm_unreachable("Invalid command number."); case 0: @@ -11277,6 +11282,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) // Fragment 5 encoded into 4 bits for 9 unique commands. + // printf("Fragment 5 = %" PRIu64 "\n", (Bits >> 41) & 15); switch ((Bits >> 41) & 15) { default: // llvm_unreachable("Invalid command number."); case 0: @@ -11329,6 +11335,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) // Fragment 6 encoded into 4 bits for 11 unique commands. + // printf("Fragment 6 = %" PRIu64 "\n", (Bits >> 45) & 15); switch ((Bits >> 45) & 15) { default: // llvm_unreachable("Invalid command number."); case 0: @@ -11386,6 +11393,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) // Fragment 7 encoded into 1 bits for 2 unique commands. + // printf("Fragment 7 = %" PRIu64 "\n", (Bits >> 49) & 1); if ((Bits >> 49) & 1) { // RISBG, RISBG32, RISBGN, RISBHG, RISBLG, RNSBG, ROSBG, RXSBG, VAC, VACC... SStream_concat0(O, ", "); @@ -11396,6 +11404,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) // Fragment 8 encoded into 2 bits for 3 unique commands. + // printf("Fragment 8 = %" PRIu64 "\n", (Bits >> 50) & 3); switch ((Bits >> 50) & 3) { default: // llvm_unreachable("Invalid command number."); case 0: @@ -11416,6 +11425,7 @@ static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI) // Fragment 9 encoded into 1 bits for 2 unique commands. + // printf("Fragment 9 = %" PRIu64 "\n", (Bits >> 52) & 1); if ((Bits >> 52) & 1) { // VFCE, VFCH, VFCHE, VFMA, VFMAX, VFMIN, VFMS, VFNMA, VFNMS, VMSL, VSTRC SStream_concat0(O, ", "); diff --git a/arch/SystemZ/SystemZInstPrinter.c b/arch/SystemZ/SystemZInstPrinter.c index ee6061614e..b1f1c3360b 100644 --- a/arch/SystemZ/SystemZInstPrinter.c +++ b/arch/SystemZ/SystemZInstPrinter.c @@ -297,16 +297,15 @@ static void printU48ImmOperand(MCInst *MI, int OpNum, SStream *O) static void printPCRelOperand(MCInst *MI, int OpNum, SStream *O) { MCOperand *MO = MCInst_getOperand(MI, OpNum); - int32_t imm; if (MCOperand_isImm(MO)) { - imm = (int32_t)MCOperand_getImm(MO); + int64_t imm = (int64_t)MCOperand_getImm(MO); - printInt32(O, imm); + printInt64(O, imm); if (MI->csh->detail) { MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].type = SYSZ_OP_IMM; - MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = (int64_t)imm; + MI->flat_insn->detail->sysz.operands[MI->flat_insn->detail->sysz.op_count].imm = imm; MI->flat_insn->detail->sysz.op_count++; } } From 02ba83fadc2db702652364c2ec9ecf2410de7f63 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Wed, 10 Jul 2019 23:54:15 +0800 Subject: [PATCH 04/13] handle mnemonic customization better. issue #1514 --- cs.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/cs.c b/cs.c index a4672ba985..6c540bdfb7 100644 --- a/cs.c +++ b/cs.c @@ -514,6 +514,23 @@ cs_err CAPSTONE_API cs_close(csh *handle) return CS_ERR_OK; } +// replace str1 in target with str2; target starts with str1 +// output is put into result (which is array of char with size CS_MNEMONIC_SIZE) +// return 0 on success, -1 on failure +static int str_replace(char *result, char *target, const char *str1, char *str2) +{ + // only perform replacement if the output fits into result + if (strlen(target) - strlen(str1) + strlen(str2) < CS_MNEMONIC_SIZE - 1) { + // copy str2 to begining of result + strcpy(result, str2); + // skip str1 - already replaced by str2 + strcat(result, target + strlen(str1)); + + return 0; + } else + return -1; +} + // fill insn with mnemonic & operands info static void fill_insn(struct cs_struct *handle, cs_insn *insn, char *buffer, MCInst *mci, PostPrinter_t postprinter, const uint8_t *code) @@ -557,9 +574,14 @@ static void fill_insn(struct cs_struct *handle, cs_insn *insn, char *buffer, MCI struct insn_mnem *tmp = handle->mnem_list; while(tmp) { if (tmp->insn.id == insn->id) { - // found this instruction, so copy its mnemonic - (void)strncpy(insn->mnemonic, tmp->insn.mnemonic, sizeof(insn->mnemonic) - 1); - insn->mnemonic[sizeof(insn->mnemonic) - 1] = '\0'; + char str[CS_MNEMONIC_SIZE]; + + if (!str_replace(str, insn->mnemonic, cs_insn_name((csh)handle, insn->id), tmp->insn.mnemonic)) { + // copy result to mnemonic + (void)strncpy(insn->mnemonic, str, sizeof(insn->mnemonic) - 1); + insn->mnemonic[sizeof(insn->mnemonic) - 1] = '\0'; + } + break; } tmp = tmp->next; From ec6390f9404bd7725bf8169d59861994a148100c Mon Sep 17 00:00:00 2001 From: mquigley Date: Thu, 11 Jul 2019 02:34:06 -0700 Subject: [PATCH 05/13] #1246 - Fix Java bindings to use pointers instead of longs (#1516) Previously, a long was used instead of a pointer in the JNA binding library. This would work until the allocated pointers exceeded 32-bits. On modern JVMs, allocations may produce pointers in excess of 32-bits which would result in invalid memory access errors. This also updates the binding version to 5.0. --- bindings/java/capstone/Capstone.java | 52 +++++++++++++++------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/bindings/java/capstone/Capstone.java b/bindings/java/capstone/Capstone.java index 2d59997ff4..040c79e2b4 100644 --- a/bindings/java/capstone/Capstone.java +++ b/bindings/java/capstone/Capstone.java @@ -96,7 +96,7 @@ public List getFieldOrder() { } public static class CsInsn { - private NativeLong csh; + private Pointer csh; private CS cs; private _cs_insn raw; private int arch; @@ -121,7 +121,7 @@ public static class CsInsn { public byte[] groups; public OpInfo operands; - public CsInsn (_cs_insn insn, int _arch, NativeLong _csh, CS _cs, boolean diet) { + public CsInsn (_cs_insn insn, int _arch, Pointer _csh, CS _cs, boolean diet) { id = insn.id; address = insn.address; size = insn.size; @@ -294,31 +294,31 @@ private CsInsn[] fromArrayRaw(_cs_insn[] arr_raw) { } private interface CS extends Library { - public int cs_open(int arch, int mode, NativeLongByReference handle); - public NativeLong cs_disasm(NativeLong handle, byte[] code, NativeLong code_len, + public int cs_open(int arch, int mode, PointerByReference handle); + public NativeLong cs_disasm(Pointer handle, byte[] code, NativeLong code_len, long addr, NativeLong count, PointerByReference insn); public void cs_free(Pointer p, NativeLong count); - public int cs_close(NativeLongByReference handle); - public int cs_option(NativeLong handle, int option, NativeLong optionValue); - - public String cs_reg_name(NativeLong csh, int id); - public int cs_op_count(NativeLong csh, Pointer insn, int type); - public int cs_op_index(NativeLong csh, Pointer insn, int type, int index); - - public String cs_insn_name(NativeLong csh, int id); - public String cs_group_name(NativeLong csh, int id); - public byte cs_insn_group(NativeLong csh, Pointer insn, int id); - public byte cs_reg_read(NativeLong csh, Pointer insn, int id); - public byte cs_reg_write(NativeLong csh, Pointer insn, int id); - public int cs_errno(NativeLong csh); + public int cs_close(PointerByReference handle); + public int cs_option(Pointer handle, int option, NativeLong optionValue); + + public String cs_reg_name(Pointer csh, int id); + public int cs_op_count(Pointer csh, Pointer insn, int type); + public int cs_op_index(Pointer csh, Pointer insn, int type, int index); + + public String cs_insn_name(Pointer csh, int id); + public String cs_group_name(Pointer csh, int id); + public byte cs_insn_group(Pointer csh, Pointer insn, int id); + public byte cs_reg_read(Pointer csh, Pointer insn, int id); + public byte cs_reg_write(Pointer csh, Pointer insn, int id); + public int cs_errno(Pointer csh); public int cs_version(IntByReference major, IntByReference minor); public boolean cs_support(int query); public String cs_strerror(int code); - public int cs_regs_access(NativeLong handle, Pointer insn, Pointer regs_read, ByteByReference regs_read_count, Pointer regs_write, ByteByReference regs_write_count); + public int cs_regs_access(Pointer handle, Pointer insn, Pointer regs_read, ByteByReference regs_read_count, Pointer regs_write, ByteByReference regs_write_count); } // Capstone API version - public static final int CS_API_MAJOR = 4; + public static final int CS_API_MAJOR = 5; public static final int CS_API_MINOR = 0; // architectures @@ -420,8 +420,8 @@ public NativeLong cs_disasm(NativeLong handle, byte[] code, NativeLong code_len, public static final int CS_SUPPORT_X86_REDUCE = CS_ARCH_ALL+2; // X86 reduce mode protected class NativeStruct { - private NativeLong csh; - private NativeLongByReference handleRef; + private Pointer csh; + private PointerByReference handleRef; } private static final CsInsn[] EMPTY_INSN = new CsInsn[0]; @@ -436,15 +436,17 @@ protected class NativeStruct { public Capstone(int arch, int mode) { cs = (CS)Native.loadLibrary("capstone", CS.class); - int version = cs.cs_version(null, null); - if (version != (CS_API_MAJOR << 8) + CS_API_MINOR) { - throw new RuntimeException("Different API version between core & binding (CS_ERR_VERSION)"); + int coreVersion = cs.cs_version(null, null); + int bindingVersion = (CS_API_MAJOR << 8) + CS_API_MINOR; + if (coreVersion != bindingVersion) { + throw new RuntimeException("Different API version between core " + coreVersion + + " & binding " + bindingVersion + " (CS_ERR_VERSION)"); } this.arch = arch; this.mode = mode; ns = new NativeStruct(); - ns.handleRef = new NativeLongByReference(); + ns.handleRef = new PointerByReference(); if (cs.cs_open(arch, mode, ns.handleRef) != CS_ERR_OK) { throw new RuntimeException("ERROR: Wrong arch or mode"); } From 1065ce78c37df2c33588db63dfaa72c5d225337e Mon Sep 17 00:00:00 2001 From: Catena cyber <35799796+catenacyber@users.noreply.github.com> Date: Thu, 25 Jul 2019 03:06:52 +0200 Subject: [PATCH 06/13] Fuzzit integration (#1520) --- .travis.yml | 16 +++++++++++++--- README.md | 7 +++++++ suite/fuzz/Makefile | 30 +++++++++++++++++++++++------- suite/fuzz/README.md | 34 ++++++++++++++++++++++++++++++++++ suite/fuzz/fuzzit.sh | 27 +++++++++++++++++++++++++++ suite/fuzz/fuzzitid.txt | 3 +++ 6 files changed, 107 insertions(+), 10 deletions(-) create mode 100644 suite/fuzz/README.md create mode 100755 suite/fuzz/fuzzit.sh create mode 100644 suite/fuzz/fuzzitid.txt diff --git a/.travis.yml b/.travis.yml index a3e0733a7a..65a32951a9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ before_script: # TODO remove built in cmocka compile and use system cmocka (including brewfile) once xenial is default - git clone https://git.cryptomilk.org/projects/cmocka.git suite/cstest/cmocka - chmod +x suite/cstest/build_cstest.sh + - if [[ ${TRAVIS_OS_NAME} = linux ]]; then export PATH="/usr/lib/llvm-9/bin:${PATH}"; fi script: - ./make.sh - make check @@ -18,6 +19,7 @@ script: - if [[ "$NOPYTEST" != "true" ]]; then cd suite/cstest && ./build_cstest.sh; fi - if [[ "$NOPYTEST" != "true" ]]; then python cstest_report.py -D -t build/cstest -d ../MC; fi - if [[ "$NOPYTEST" != "true" ]]; then python cstest_report.py -D -t build/cstest -f issues.cs; fi + - if [ -n "$QA_FUZZIT" ]; then suite/fuzz/fuzzit.sh; fi compiler: - clang - gcc @@ -43,14 +45,22 @@ matrix: packages: - libcmocka-dev - name: fuzza - env: ASAN_OPTIONS=detect_leaks=0 CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address" CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address" LDFLAGS="-fsanitize=address" NOPYTEST=true + env: ASAN_OPTIONS=detect_leaks=0 CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link" CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link" LDFLAGS="-fsanitize=address" NOPYTEST=true QA_FUZZIT=asan compiler: clang os: linux - name: fuzzm - env: CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory" CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory" LDFLAGS="-fsanitize=memory" NOPYTEST=true + env: CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory -fsanitize=fuzzer-no-link" CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=memory -fsanitize=fuzzer-no-link" LDFLAGS="-fsanitize=memory" NOPYTEST=true QA_FUZZIT=msan compiler: clang os: linux - name: fuzzu - env: CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=undefined" CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=undefined -fno-sanitize-recover=undefined,integer" LDFLAGS="-fsanitize=undefined" NOPYTEST=true + env: CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=undefined -fsanitize=fuzzer-no-link" CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=undefined -fno-sanitize-recover=undefined,integer -fsanitize=fuzzer-no-link" LDFLAGS="-fsanitize=undefined" NOPYTEST=true QA_FUZZIT=ubsan compiler: clang os: linux + +addons: + apt: + sources: + - llvm-toolchain-trusty + - ubuntu-toolchain-r-test + packages: + - clang-9 diff --git a/README.md b/README.md index b7fa58cd35..8125789774 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Capstone Engine [![Build status](https://ci.appveyor.com/api/projects/status/a4wvbn89wu3pinas/branch/next?svg=true)](https://ci.appveyor.com/project/aquynh/capstone/branch/next) [![pypi package](https://badge.fury.io/py/capstone.svg)](https://pypi.python.org/pypi/capstone) [![pypi downloads](https://pepy.tech/badge/capstone)](https://pepy.tech/project/capstone) +[![Fuzzit Status](https://app.fuzzit.dev/badge?org_id=ANOh0D48gSLBxNZcDQMI&branch=master)](https://app.fuzzit.dev/admin/ANOh0D48gSLBxNZcDQMI/dashboard)
Capstone is a disassembly framework with the target of becoming the ultimate disasm engine for binary analysis and reversing in the security community. @@ -61,6 +62,12 @@ Hack See HACK.TXT file for the structure of the source code. +Fuzz +---- + +See suite/fuzz/README.md for more information. + + License ------- diff --git a/suite/fuzz/Makefile b/suite/fuzz/Makefile index dc45644d23..4cd958690c 100644 --- a/suite/fuzz/Makefile +++ b/suite/fuzz/Makefile @@ -27,6 +27,7 @@ LDFLAGS += -L$(LIBDIR) CFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch)) LDFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch)) +FUZZLDFLAGS = LIBNAME = capstone @@ -40,16 +41,20 @@ ARCHIVE = $(LIBDIR)/lib$(LIBNAME).$(AR_EXT) SOURCES = fuzz_disasm.c drivermc.c fuzz_harness.c driverbin.c platform.c OBJS = $(addprefix $(OBJDIR)/,$(SOURCES:.c=.o)) -BINARY = $(addprefix $(TESTDIR)/,fuzz_disasm$(BIN_EXT)) -BINARYBIN = $(addprefix $(TESTDIR)/,fuzz_bindisasm$(BIN_EXT)) +# reproducer using MC file as input +REPRODUCERMC = $(addprefix $(TESTDIR)/,fuzz_disasm$(BIN_EXT)) +# reproducer using raw binary file as input (as produced by fuzzer) +REPRODUCERBIN = $(addprefix $(TESTDIR)/,fuzz_bindisasm$(BIN_EXT)) +# fuzzer +FUZZERBIN = $(addprefix $(TESTDIR)/,fuzz_bindisasm2$(BIN_EXT)) PLATFORMDECODE = $(addprefix $(TESTDIR)/,fuzz_decode_platform$(BIN_EXT)) -all: $(BINARY) $(BINARYBIN) $(PLATFORMDECODE) +all: $(REPRODUCERMC) $(REPRODUCERBIN) $(FUZZERBIN) $(PLATFORMDECODE) clean: - rm -rf fuzz_harness $(OBJS) $(PLATFORMDECODE) $(BINARY) $(BINARYBIN) $(OBJDIR)/lib$(LIBNAME).* $(OBJDIR)/$(LIBNAME).* + rm -rf fuzz_harness $(OBJS) $(PLATFORMDECODE) $(REPRODUCERMC) $(REPRODUCERBIN) $(FUZZERBIN) $(OBJDIR)/lib$(LIBNAME).* $(OBJDIR)/$(LIBNAME).* -$(BINARY): fuzz_disasm.o drivermc.o platform.o +$(REPRODUCERMC): fuzz_disasm.o drivermc.o platform.o @mkdir -p $(@D) ifeq ($(V),0) $(call log,LINK,$(notdir $@)) @@ -58,7 +63,7 @@ else $(link-static) endif -$(BINARYBIN): fuzz_disasm.o driverbin.o platform.o +$(REPRODUCERBIN): fuzz_disasm.o driverbin.o platform.o @mkdir -p $(@D) ifeq ($(V),0) $(call log,LINK,$(notdir $@)) @@ -67,6 +72,17 @@ else $(link-static) endif +$(FUZZERBIN): FUZZLDFLAGS="-fsanitize=fuzzer" + +$(FUZZERBIN): fuzz_disasm.o platform.o + @mkdir -p $(@D) +ifeq ($(V),0) + $(call log,LINK,$(notdir $@)) + @$(link-static) || touch $(FUZZERBIN) +else + $(link-static) || touch $(FUZZERBIN) +endif + $(PLATFORMDECODE): fuzz_decode_platform.o platform.o @mkdir -p $(@D) ifeq ($(V),0) @@ -88,7 +104,7 @@ endif define link-static - $(CC) $(LDFLAGS) $^ $(ARCHIVE) -o $@ + $(CC) $(LDFLAGS) $(FUZZLDFLAGS) $^ $(ARCHIVE) -o $@ endef fuzz_harness: fuzz_harness.o diff --git a/suite/fuzz/README.md b/suite/fuzz/README.md new file mode 100644 index 0000000000..27c1c0c36c --- /dev/null +++ b/suite/fuzz/README.md @@ -0,0 +1,34 @@ +Fuzzing +=============== + + +Build the fuzz target +------- + +To build the fuzz target, you can simply run `make` with appropriate flags set : +``` +ASAN_OPTIONS=detect_leaks=0 CXXFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link" CFLAGS="-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -fsanitize=address -fsanitize=fuzzer-no-link" LDFLAGS="-fsanitize=address" make +``` +You can replace `address` with another sanitizer : `memory` or `undefined` +The fuzz target is then `suite/fuzz/fuzz_bindisasm2` + +You can find this in travis configuration `.travis.yml` + +Another way is to use oss-fuzz, see https://github.com/google/oss-fuzz/blob/master/projects/capstone/build.sh + +Fuzz drivers +------ + +There are custom drivers : +- driverbin.c : prints cstool command before running one input +- drivermc.c : converts MC test data to raw binary data before running as many inputs as there are lines in a file +- onefile.c : simple one file driver + +For libfuzzer, the preferred main function is now to use linker option `-fsanitize=fuzzer` + +Fuzzit integration +------ + +Travis will build the fuzz target with the different sanitizers. +Then, Travis will launch sanity fuzzit jobs as part of continuous integration (for each of the sanitizers) +The fuzzit target ids are stored in a configuration file fuzzitid.txt and used by fuzzit.sh diff --git a/suite/fuzz/fuzzit.sh b/suite/fuzz/fuzzit.sh new file mode 100755 index 0000000000..b962b773e5 --- /dev/null +++ b/suite/fuzz/fuzzit.sh @@ -0,0 +1,27 @@ +FUZZIT_API_KEY=f10b19a56d96b29dfdfe459d41b3d82e475e49c737095c74c99d65a032d5c2ab84d44dad510886bc824f101a860b1754 + +[ -s ./suite/fuzz/fuzz_bindisasm2 ] || exit 0 + +if [ ${TRAVIS_EVENT_TYPE} -eq 'cron' ]; then + FUZZING_TYPE=fuzzing +else + FUZZING_TYPE=sanity +fi +if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then + FUZZIT_BRANCH="${TRAVIS_BRANCH}" +else + FUZZIT_BRANCH="PR-${TRAVIS_PULL_REQUEST}" +fi + +FUZZIT_ARGS="--type ${FUZZING_TYPE} --branch ${FUZZIT_BRANCH} --revision ${TRAVIS_COMMIT}" +if [ -n "$UBSAN_OPTIONS" ]; then + FUZZIT_ARGS+=" --ubsan_options ${UBSAN_OPTIONS}" +fi +wget -O fuzzit https://github.com/fuzzitdev/fuzzit/releases/download/v1.2.5/fuzzit_1.2.5_Linux_x86_64 +chmod +x fuzzit +./fuzzit auth ${FUZZIT_API_KEY} +set -x +grep "$QA_FUZZIT" suite/fuzz/fuzzitid.txt | cut -d" " -f2 | while read i; do + ./fuzzit c job ${FUZZIT_ARGS} ${i} ./suite/fuzz/fuzz_bindisasm2 +done +set +x diff --git a/suite/fuzz/fuzzitid.txt b/suite/fuzz/fuzzitid.txt new file mode 100644 index 0000000000..57bbe73ca5 --- /dev/null +++ b/suite/fuzz/fuzzitid.txt @@ -0,0 +1,3 @@ +asan A1NqPndmOVrguCNj95LZ +msan JchjH3j58fOnB8ZXGyWl +ubsan JqHqVabfDEqitOusrPFx \ No newline at end of file From b8c7a9fb8b048ef73a1362aef93bbe355d2d6738 Mon Sep 17 00:00:00 2001 From: Cen Zhang Date: Sat, 27 Jul 2019 00:16:01 +0800 Subject: [PATCH 07/13] fix for make.sh for android (#1523) * fix for make.sh for android * remove commented line --- .gitignore | 3 +++ Makefile | 6 ++++++ make.sh | 19 ++++++++++++------- 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/.gitignore b/.gitignore index 1d328b0922..e9f057cbd0 100644 --- a/.gitignore +++ b/.gitignore @@ -124,3 +124,6 @@ capstone_get_setup *.s cstool/cstool + +# android +android-ndk-* diff --git a/Makefile b/Makefile index ff240cf78d..db477d7184 100644 --- a/Makefile +++ b/Makefile @@ -22,6 +22,11 @@ endif ifeq ($(CROSS),) RANLIB ?= ranlib +else ifeq ($(ANDROID), 1) +CC = $(CROSS)/../../bin/clang +AR = $(CROSS)/ar +RANLIB = $(CROSS)/ranlib +STRIP = $(CROSS)/strip else CC = $(CROSS)gcc AR = $(CROSS)ar @@ -467,6 +472,7 @@ clean: rm -f $(LIBOBJ) rm -f $(BLDIR)/lib$(LIBNAME).* $(BLDIR)/$(LIBNAME).pc rm -f $(PKGCFGF) + [ ${ANDROID} -eq 1 ] && rm -rf android-ndk-* $(MAKE) -C cstool clean ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY))) diff --git a/make.sh b/make.sh index ddc1791cff..6c29abb033 100755 --- a/make.sh +++ b/make.sh @@ -13,6 +13,7 @@ build_android() { echo "ERROR! Please set \$NDK to point at your Android NDK directory." exit 1 fi + HOSTOS=$(uname -s | tr 'LD' 'ld') HOSTARCH=$(uname -m) @@ -22,13 +23,11 @@ build_android() { case "$TARGARCH" in arm) [ -n "$APILEVEL" ] || APILEVEL="android-14" # default to ICS - [ -n "$GCCVER" ] || GCCVER="4.8" - CROSS=arm-linux-androideabi- + CROSS=arm-linux-androideabi ;; arm64) [ -n "$APILEVEL" ] || APILEVEL="android-21" # first with arm64 - [ -n "$GCCVER" ] || GCCVER="4.9" - CROSS=aarch64-linux-android- + CROSS=aarch64-linux-android ;; *) @@ -37,10 +36,16 @@ build_android() { ;; esac - TOOLCHAIN="$NDK/toolchains/$CROSS$GCCVER/prebuilt/$HOSTOS-$HOSTARCH" - PLATFORM="$NDK/platforms/$APILEVEL/arch-$TARGARCH" + STANDALONE=`realpath android-ndk-${TARGARCH}-${APILEVEL}` + + [ -d $STANDALONE ] || { + python ${NDK}/build/tools/make_standalone_toolchain.py \ + --arch ${TARGARCH} \ + --api ${APILEVEL##*-} \ + --install-dir ${STANDALONE} + } - CROSS="$TOOLCHAIN/bin/$CROSS" CFLAGS="--sysroot=$PLATFORM" LDFLAGS="--sysroot=$PLATFORM" ${MAKE} $* + ANDROID=1 CROSS="${STANDALONE}/${CROSS}/bin" CFLAGS="--sysroot=${STANDALONE}/sysroot" ${MAKE} $* } # build iOS lib for all iDevices, or only specific device From eb357143a223e53e09310c6e5908a205cc2d9069 Mon Sep 17 00:00:00 2001 From: Vemake Date: Mon, 29 Jul 2019 14:15:05 +0800 Subject: [PATCH 08/13] Fixed 47 missing dependencies and 51 excessive dependencies in Makefile (#1522) * Fix Excessive and Missing Dependencies found by Vemake * Remove extra spaces at the end of Makefile * Remove used macro df * Change "-rf" to "-f" in tests/Makefile * Change "-rf" to "-f" in suite/fuzz/Makefile * Remove 'r' from the removal command. * Remove an extra blank line. --- Makefile | 9 ++++++++- cstool/Makefile | 1 + functions.mk | 1 + suite/fuzz/Makefile | 1 + tests/Makefile | 1 + 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index db477d7184..9b2ddf5ae0 100644 --- a/Makefile +++ b/Makefile @@ -411,7 +411,7 @@ else endif endif -$(LIBOBJ): config.mk *.h include/capstone/*.h +$(LIBOBJ): config.mk $(LIBOBJ_ARM): $(DEP_ARM) $(LIBOBJ_ARM64): $(DEP_ARM64) @@ -449,6 +449,12 @@ else $(generate-pkgcfg) endif +# create a list of auto dependencies +AUTODEPS:= $(patsubst %.o,%.d, $(LIBOBJ)) + +# include by auto dependencies +-include $(AUTODEPS) + install: $(PKGCFGF) $(ARCHIVE) $(LIBRARY) mkdir -p $(LIBDIR) $(call install-library,$(LIBDIR)) @@ -472,6 +478,7 @@ clean: rm -f $(LIBOBJ) rm -f $(BLDIR)/lib$(LIBNAME).* $(BLDIR)/$(LIBNAME).pc rm -f $(PKGCFGF) + rm -f $(AUTODEPS) [ ${ANDROID} -eq 1 ] && rm -rf android-ndk-* $(MAKE) -C cstool clean diff --git a/cstool/Makefile b/cstool/Makefile index 9b28e43232..f709d3a79c 100644 --- a/cstool/Makefile +++ b/cstool/Makefile @@ -37,6 +37,7 @@ endif clean: ${RM} -rf *.o $(TARGET) + ${RM} -f *.d %.o: %.c ifeq ($(V), 0) diff --git a/functions.mk b/functions.mk index d946cd34e6..d734ce5d51 100644 --- a/functions.mk +++ b/functions.mk @@ -2,6 +2,7 @@ # Common functions used by Makefile & tests/Makefile define compile + @$(CC) -MM -MP -MT $@ -MT $(@:.o=.d) $(CFLAGS) $< > $(@:.o=.d) ${CC} ${CFLAGS} -c $< -o $@ endef diff --git a/suite/fuzz/Makefile b/suite/fuzz/Makefile index 4cd958690c..e0c0ef2b8a 100644 --- a/suite/fuzz/Makefile +++ b/suite/fuzz/Makefile @@ -53,6 +53,7 @@ all: $(REPRODUCERMC) $(REPRODUCERBIN) $(FUZZERBIN) $(PLATFORMDECODE) clean: rm -rf fuzz_harness $(OBJS) $(PLATFORMDECODE) $(REPRODUCERMC) $(REPRODUCERBIN) $(FUZZERBIN) $(OBJDIR)/lib$(LIBNAME).* $(OBJDIR)/$(LIBNAME).* + rm -f *.d $(OBJDIR)/*.d $(REPRODUCERMC): fuzz_disasm.o drivermc.o platform.o @mkdir -p $(@D) diff --git a/tests/Makefile b/tests/Makefile index e514c273ea..86a08e604f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -137,6 +137,7 @@ all: $(BINARY) clean: rm -rf $(OBJS) $(BINARY) $(TESTDIR)/*.exe $(TESTDIR)/*.static $(OBJDIR)/lib$(LIBNAME).* $(OBJDIR)/$(LIBNAME).* + rm -f *.d $(TESTDIR)/*.d $(OBJDIR)/*.d # remove orphan files due to renaming from test.c to test_basic.c rm -rf $(TESTDIR)/test.o $(TESTDIR)/test.exe $(TESTDIR)/test.static $(TESTDIR)/test From 68ebda0af8ca5706195b72a3e6507846f33b6bf1 Mon Sep 17 00:00:00 2001 From: Cen Zhang Date: Mon, 29 Jul 2019 17:37:41 +0800 Subject: [PATCH 09/13] resolve merge conflicts --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9b2ddf5ae0..7a51140aea 100644 --- a/Makefile +++ b/Makefile @@ -479,7 +479,7 @@ clean: rm -f $(BLDIR)/lib$(LIBNAME).* $(BLDIR)/$(LIBNAME).pc rm -f $(PKGCFGF) rm -f $(AUTODEPS) - [ ${ANDROID} -eq 1 ] && rm -rf android-ndk-* + [ "${ANDROID}" = "1" ] && rm -rf android-ndk-* || true $(MAKE) -C cstool clean ifeq (,$(findstring yes,$(CAPSTONE_BUILD_CORE_ONLY))) From 5f200f7bae883467883dc7ef611c25a6c5ac8b10 Mon Sep 17 00:00:00 2001 From: naq Date: Thu, 15 Aug 2019 15:28:15 +0800 Subject: [PATCH 10/13] tests: fix typo in test_detail.c --- tests/test_detail.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_detail.c b/tests/test_detail.c index ed81e0c40b..ea7d1fdd18 100644 --- a/tests/test_detail.c +++ b/tests/test_detail.c @@ -83,7 +83,7 @@ static void test() CS_ARCH_X86, CS_MODE_16, (unsigned char *)X86_CODE16, - sizeof(X86_CODE32) - 1, + sizeof(X86_CODE16) - 1, "X86 16bit (Intel syntax)" }, { From 23e98a39f61e38d555de2d7f2b69599b9a466439 Mon Sep 17 00:00:00 2001 From: Scott Knight <4534275+knightsc@users.noreply.github.com> Date: Wed, 28 Aug 2019 02:20:32 -0400 Subject: [PATCH 11/13] Update Go binding information (#1532) --- bindings/README | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/README b/bindings/README index c0ee8f5d61..8605806259 100644 --- a/bindings/README +++ b/bindings/README @@ -3,9 +3,9 @@ See /README for how to compile & install each binding. More bindings created & maintained by the community are available as followings. -- Gapstone: Go binding (by Ben Nagy). +- Gapstone: Go binding (by Scott Knight). - https://github.com/bnagy/gapstone + https://github.com/knightsc/gapstone - Crabstone: Ruby binding (by Ben Nagy). From 8f92ff325eb44b7a23069369a9fa6b2945246f40 Mon Sep 17 00:00:00 2001 From: Wu ChenXu <34511237+kabeor@users.noreply.github.com> Date: Fri, 30 Aug 2019 23:00:00 +0800 Subject: [PATCH 12/13] Update README (#1534) --- docs/README | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/README b/docs/README index 15bbeb3cbe..ec7c3aaa91 100644 --- a/docs/README +++ b/docs/README @@ -60,3 +60,7 @@ Documentation of Capstone disassembly framework. * Sample application on how to embed Capstone into Mac OSX Kext (kernel). https://github.com/aquynh/CapstoneTest + +* A Micro Capstone-Engine API Documentation in Chinese + + https://github.com/kabeor/Micro-Capstone-Engine-API-Documentation/blob/master/Micro%20Capstone-Engine%20API%20Documentation.md From ebc89f4f913755a00ee9f9305b64dd053a580474 Mon Sep 17 00:00:00 2001 From: Tom Kelly Date: Thu, 26 Sep 2019 09:45:11 +0100 Subject: [PATCH 13/13] Fix for x86_op record for ocaml bindings (#1539) --- bindings/ocaml/ocaml.c | 18 ++++++++++-------- bindings/ocaml/test_x86.ml | 6 +++--- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/bindings/ocaml/ocaml.c b/bindings/ocaml/ocaml.c index c74d5e60d9..8043d231d4 100644 --- a/bindings/ocaml/ocaml.c +++ b/bindings/ocaml/ocaml.c @@ -368,15 +368,15 @@ CAMLprim value _cs_disasm(cs_arch arch, csh handle, const uint8_t * code, size_t for (i = 0; i < lcount; i++) { switch(insn[j-1].detail->x86.operands[i].type) { case X86_OP_REG: - tmp = caml_alloc(5, 1); + tmp = caml_alloc(1, 1); Store_field(tmp, 0, Val_int(insn[j-1].detail->x86.operands[i].reg)); break; case X86_OP_IMM: - tmp = caml_alloc(5, 2); + tmp = caml_alloc(1, 2); Store_field(tmp, 0, Val_int(insn[j-1].detail->x86.operands[i].imm)); break; case X86_OP_MEM: - tmp = caml_alloc(5, 3); + tmp = caml_alloc(1, 3); tmp2 = caml_alloc(5, 0); Store_field(tmp2, 0, Val_int(insn[j-1].detail->x86.operands[i].mem.segment)); Store_field(tmp2, 1, Val_int(insn[j-1].detail->x86.operands[i].mem.base)); @@ -387,14 +387,16 @@ CAMLprim value _cs_disasm(cs_arch arch, csh handle, const uint8_t * code, size_t Store_field(tmp, 0, tmp2); break; default: + tmp = caml_alloc(1, 0); // X86_OP_INVALID break; } - Store_field(tmp, 1, Val_int(insn[j-1].detail->x86.operands[i].size)); - Store_field(tmp, 2, Val_int(insn[j-1].detail->x86.operands[i].access)); - Store_field(tmp, 3, Val_int(insn[j-1].detail->x86.operands[i].avx_bcast)); - Store_field(tmp, 4, Val_int(insn[j-1].detail->x86.operands[i].avx_zero_opmask)); - tmp2 = caml_alloc(1, 0); + + tmp2 = caml_alloc(5, 0); Store_field(tmp2, 0, tmp); + Store_field(tmp2, 1, Val_int(insn[j-1].detail->x86.operands[i].size)); + Store_field(tmp2, 2, Val_int(insn[j-1].detail->x86.operands[i].access)); + Store_field(tmp2, 3, Val_int(insn[j-1].detail->x86.operands[i].avx_bcast)); + Store_field(tmp2, 4, Val_int(insn[j-1].detail->x86.operands[i].avx_zero_opmask)); Store_field(array, i, tmp2); } } else // empty array diff --git a/bindings/ocaml/test_x86.ml b/bindings/ocaml/test_x86.ml index ce343e49ee..d35bf0f01b 100644 --- a/bindings/ocaml/test_x86.ml +++ b/bindings/ocaml/test_x86.ml @@ -30,9 +30,9 @@ let all_tests = [ 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 handle reg); - | X86_OP_IMM imm -> printf "\t\top[%d]: IMM = 0x%x\n" i imm; - | X86_OP_MEM mem -> ( printf "\t\top[%d]: MEM\n" i; + | X86_OP_REG reg -> printf "\t\top[%d]: REG = %s [sz=%d]\n" i (cs_reg_name handle reg) op.size; + | X86_OP_IMM imm -> printf "\t\top[%d]: IMM = 0x%x [sz=%d]\n" i imm op.size; + | X86_OP_MEM mem -> ( printf "\t\top[%d]: MEM [sz=%d]\n" i op.size; if mem.base != 0 then printf "\t\t\toperands[%u].mem.base: REG = %s\n" i (cs_reg_name handle mem.base); if mem.index != 0 then