From fcaf7d9a6f24a5795d3d0c2223e6528e071687c9 Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh Date: Sun, 7 May 2017 11:17:23 +0800 Subject: [PATCH] x86: add UD0 instruction --- MCInst.c | 1 + MCInst.h | 1 + arch/X86/X86ATTInstPrinter.c | 13 ++++++++++++- arch/X86/X86Disassembler.c | 19 +++++++++++++++++++ arch/X86/X86IntelInstPrinter.c | 13 ++++++++++++- arch/X86/X86Mapping.c | 2 ++ bindings/java/capstone/X86_const.java | 3 ++- bindings/ocaml/x86_const.ml | 3 ++- bindings/python/capstone/x86_const.py | 3 ++- include/capstone/x86.h | 2 ++ 10 files changed, 55 insertions(+), 5 deletions(-) diff --git a/MCInst.c b/MCInst.c index 0a4209170..d52184543 100644 --- a/MCInst.c +++ b/MCInst.c @@ -23,6 +23,7 @@ void MCInst_Init(MCInst *inst) inst->writeback = false; inst->ac_idx = 0; inst->popcode_adjust = 0; + inst->assembly[0] = '\0'; } void MCInst_clear(MCInst *inst) diff --git a/MCInst.h b/MCInst.h index 3d25bc8f9..befb5e9b0 100644 --- a/MCInst.h +++ b/MCInst.h @@ -108,6 +108,7 @@ struct MCInst { // operand access index for list of registers sharing the same access right (for ARM) uint8_t ac_idx; uint8_t popcode_adjust; // Pseudo X86 instruction adjust + char assembly[8]; // for special instruction, so that we dont need printer }; void MCInst_Init(MCInst *inst); diff --git a/arch/X86/X86ATTInstPrinter.c b/arch/X86/X86ATTInstPrinter.c index a28ddf878..539de5ac2 100644 --- a/arch/X86/X86ATTInstPrinter.c +++ b/arch/X86/X86ATTInstPrinter.c @@ -342,8 +342,13 @@ static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O) // convert Intel access info to AT&T access info static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access, uint64_t *eflags) { - uint8_t *arr = X86_get_op_access(h, id, eflags); uint8_t count, i; + uint8_t *arr = X86_get_op_access(h, id, eflags); + + if (!arr) { + access[0] = 0; + return; + } // find the non-zero last entry for(count = 0; arr[count]; count++); @@ -874,6 +879,12 @@ void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info) enum cs_ac_type access1, access2; int i; + // perhaps this instruction does not need printer + if (MI->assembly[0]) { + strncpy(OS->buffer, MI->assembly, sizeof(MI->assembly)); + return; + } + // Output CALLpcrel32 as "callq" in 64-bit mode. // In Intel annotation it's always emitted as "call". // diff --git a/arch/X86/X86Disassembler.c b/arch/X86/X86Disassembler.c index 008679eab..c331902f2 100644 --- a/arch/X86/X86Disassembler.c +++ b/arch/X86/X86Disassembler.c @@ -946,6 +946,25 @@ bool X86_getInstruction(csh ud, const uint8_t *code, size_t code_len, if (ret) { *size = (uint16_t)(insn.readerCursor - address); + // handle some special cases here. + // FIXME: fix this in the next major update. + if (*size == 2) { + unsigned char b1, b2; + + reader(&info, &b1, address); + reader(&info, &b2, address + 1); + if (b1 == 0x0f && b2 == 0xff) { + instr->OpcodePub = X86_INS_UD0; + strncpy(instr->assembly, "ud0", 4); + if (instr->flat_insn->detail) { + instr->flat_insn->detail->x86.opcode[0] = b1; + instr->flat_insn->detail->x86.opcode[1] = b2; + } + return true; + } + + return false; + } return false; } else { diff --git a/arch/X86/X86IntelInstPrinter.c b/arch/X86/X86IntelInstPrinter.c index 0eed4dd07..57778a7eb 100644 --- a/arch/X86/X86IntelInstPrinter.c +++ b/arch/X86/X86IntelInstPrinter.c @@ -453,8 +453,13 @@ static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O) static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access, uint64_t *eflags) { #ifndef CAPSTONE_DIET - uint8_t *arr = X86_get_op_access(h, id, eflags); uint8_t i; + uint8_t *arr = X86_get_op_access(h, id, eflags); + + if (!arr) { + access[0] = 0; + return; + } // copy to access but zero out CS_AC_IGNORE for(i = 0; arr[i]; i++) { @@ -723,6 +728,12 @@ void X86_Intel_printInst(MCInst *MI, SStream *O, void *Info) x86_reg reg, reg2; enum cs_ac_type access1, access2; + // perhaps this instruction does not need printer + if (MI->assembly[0]) { + strncpy(O->buffer, MI->assembly, sizeof(MI->assembly)); + return; + } + // Try to print any aliases first. mnem = printAliasInstr(MI, O, Info); if (mnem) diff --git a/arch/X86/X86Mapping.c b/arch/X86/X86Mapping.c index ee16406b9..032d70198 100644 --- a/arch/X86/X86Mapping.c +++ b/arch/X86/X86Mapping.c @@ -2346,6 +2346,8 @@ static name_map insn_name_maps[] = { { X86_INS_VCMPGE_OQPD, "vcmpge_oqpd" }, { X86_INS_VCMPGT_OQPD, "vcmpgt_oqpd" }, { X86_INS_VCMPTRUE_USPD, "vcmptrue_uspd" }, + + { X86_INS_UD0, "ud0" }, }; #endif diff --git a/bindings/java/capstone/X86_const.java b/bindings/java/capstone/X86_const.java index 71fb01e09..67129125c 100644 --- a/bindings/java/capstone/X86_const.java +++ b/bindings/java/capstone/X86_const.java @@ -1894,7 +1894,8 @@ public class X86_const { public static final int X86_INS_VCMPGE_OQPD = 1495; public static final int X86_INS_VCMPGT_OQPD = 1496; public static final int X86_INS_VCMPTRUE_USPD = 1497; - public static final int X86_INS_ENDING = 1498; + public static final int X86_INS_UD0 = 1498; + public static final int X86_INS_ENDING = 1499; // Group of X86 instructions diff --git a/bindings/ocaml/x86_const.ml b/bindings/ocaml/x86_const.ml index 1da2a8105..c42de3a5b 100644 --- a/bindings/ocaml/x86_const.ml +++ b/bindings/ocaml/x86_const.ml @@ -1891,7 +1891,8 @@ let _X86_INS_VCMPNEQ_OSPD = 1494;; let _X86_INS_VCMPGE_OQPD = 1495;; let _X86_INS_VCMPGT_OQPD = 1496;; let _X86_INS_VCMPTRUE_USPD = 1497;; -let _X86_INS_ENDING = 1498;; +let _X86_INS_UD0 = 1498;; +let _X86_INS_ENDING = 1499;; (* Group of X86 instructions *) diff --git a/bindings/python/capstone/x86_const.py b/bindings/python/capstone/x86_const.py index 37007112a..d4e2f2658 100644 --- a/bindings/python/capstone/x86_const.py +++ b/bindings/python/capstone/x86_const.py @@ -1891,7 +1891,8 @@ X86_INS_VCMPNEQ_OSPD = 1494 X86_INS_VCMPGE_OQPD = 1495 X86_INS_VCMPGT_OQPD = 1496 X86_INS_VCMPTRUE_USPD = 1497 -X86_INS_ENDING = 1498 +X86_INS_UD0 = 1498 +X86_INS_ENDING = 1499 # Group of X86 instructions diff --git a/include/capstone/x86.h b/include/capstone/x86.h index daf8ecf9e..098a0b03f 100644 --- a/include/capstone/x86.h +++ b/include/capstone/x86.h @@ -1836,6 +1836,8 @@ typedef enum x86_insn { X86_INS_VCMPGT_OQPD, X86_INS_VCMPTRUE_USPD, + X86_INS_UD0, + X86_INS_ENDING, // mark the end of the list of insn } x86_insn;