From cc2965bada279af9a8ac140e0aa4b4628e4dac5c Mon Sep 17 00:00:00 2001 From: Erik Hemming Date: Mon, 21 Jan 2019 09:55:05 +0100 Subject: [PATCH] Fix a couple of corner-cases with rarely used m68k instructions. (#1344) * Bump the "cs_insn.bytes[]" size to 24 (from 16) to support M680x0 instructions with full EA (maximum 11 words) Added a test for this in test_m68k.s * Bump the "cs_detail.regs_read[]" size to 16 (from 12) to support M680x0 instructions with full REG_BITS (Dn+An = 16) * m68k: use immediate mode syntax (#$0) for movem/fmovem instructions with empty register list * update bindings to match changes to cs_insn and cs_detail --- arch/M68K/M68KInstPrinter.c | 5 +++++ bindings/java/capstone/Capstone.java | 4 ++-- bindings/powershell/Capstone/Capstone.psm1 | 4 ++-- bindings/python/capstone/__init__.py | 4 ++-- bindings/python/pyx/ccapstone.pxd | 2 +- bindings/vb6/CInstDetails.cls | 2 +- bindings/vb6/CInstruction.cls | 2 +- bindings/vb6/Module1.bas | 6 +++--- include/capstone/capstone.h | 4 ++-- tests/test_m68k.c | 8 +++++++- 10 files changed, 26 insertions(+), 15 deletions(-) diff --git a/arch/M68K/M68KInstPrinter.c b/arch/M68K/M68KInstPrinter.c index 411e9842b..a7d1e7de0 100644 --- a/arch/M68K/M68KInstPrinter.c +++ b/arch/M68K/M68KInstPrinter.c @@ -108,6 +108,11 @@ static void registerBits(SStream* O, const cs_m68k_op* op) buffer[0] = 0; + if (!data) { + SStream_concat(O, "%s", "#$0"); + return; + } + printRegbitsRange(buffer, data & 0xff, "d"); printRegbitsRange(buffer, (data >> 8) & 0xff, "a"); printRegbitsRange(buffer, (data >> 16) & 0xff, "fp"); diff --git a/bindings/java/capstone/Capstone.java b/bindings/java/capstone/Capstone.java index 668d0dedf..2d59997ff 100644 --- a/bindings/java/capstone/Capstone.java +++ b/bindings/java/capstone/Capstone.java @@ -55,7 +55,7 @@ public class Capstone { public _cs_detail.ByReference cs_detail; public _cs_insn() { - bytes = new byte[16]; + bytes = new byte[24]; mnemonic = new byte[32]; op_str = new byte[160]; java.util.Arrays.fill(mnemonic, (byte) 0); @@ -78,7 +78,7 @@ public class Capstone { public static class ByReference extends _cs_detail implements Structure.ByReference {}; // list of all implicit registers being read. - public short[] regs_read = new short[12]; + public short[] regs_read = new short[16]; public byte regs_read_count; // list of all implicit registers being written. public short[] regs_write = new short[20]; diff --git a/bindings/powershell/Capstone/Capstone.psm1 b/bindings/powershell/Capstone/Capstone.psm1 index 023e9cabe..ba50143a8 100755 --- a/bindings/powershell/Capstone/Capstone.psm1 +++ b/bindings/powershell/Capstone/Capstone.psm1 @@ -55,7 +55,7 @@ function Initialize-Capstone { public uint id; public ulong address; public ushort size; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)] public byte[] bytes; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)] public string mnemonic; @@ -68,7 +68,7 @@ function Initialize-Capstone { [StructLayout(LayoutKind.Sequential)] public struct cs_detail { - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)] + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] regs_read; public byte regs_read_count; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)] diff --git a/bindings/python/capstone/__init__.py b/bindings/python/capstone/__init__.py index c74b7f2f9..8c5716b2f 100644 --- a/bindings/python/capstone/__init__.py +++ b/bindings/python/capstone/__init__.py @@ -350,7 +350,7 @@ class _cs_arch(ctypes.Union): class _cs_detail(ctypes.Structure): _fields_ = ( - ('regs_read', ctypes.c_uint16 * 12), + ('regs_read', ctypes.c_uint16 * 16), ('regs_read_count', ctypes.c_ubyte), ('regs_write', ctypes.c_uint16 * 20), ('regs_write_count', ctypes.c_ubyte), @@ -364,7 +364,7 @@ class _cs_insn(ctypes.Structure): ('id', ctypes.c_uint), ('address', ctypes.c_uint64), ('size', ctypes.c_uint16), - ('bytes', ctypes.c_ubyte * 16), + ('bytes', ctypes.c_ubyte * 24), ('mnemonic', ctypes.c_char * 32), ('op_str', ctypes.c_char * 160), ('detail', ctypes.POINTER(_cs_detail)), diff --git a/bindings/python/pyx/ccapstone.pxd b/bindings/python/pyx/ccapstone.pxd index 0943f81b1..8b163f2f6 100644 --- a/bindings/python/pyx/ccapstone.pxd +++ b/bindings/python/pyx/ccapstone.pxd @@ -20,7 +20,7 @@ cdef extern from "": unsigned int id uint64_t address uint16_t size - uint8_t bytes[16] + uint8_t bytes[24] char mnemonic[32] char op_str[160] cs_detail *detail diff --git a/bindings/vb6/CInstDetails.cls b/bindings/vb6/CInstDetails.cls index c6e0b2054..9495f7fc1 100644 --- a/bindings/vb6/CInstDetails.cls +++ b/bindings/vb6/CInstDetails.cls @@ -19,7 +19,7 @@ Option Explicit 'Copyright: FireEye 2017 'Public Type cs_detail -' regs_read(0 To 11) As Byte ' list of implicit registers read by this insn UNSIGNED +' regs_read(0 To 15) As Byte ' list of implicit registers read by this insn UNSIGNED ' regs_read_count As Byte ' number of implicit registers read by this insn UNSIGNED ' regs_write(0 To 19) As Byte ' list of implicit registers modified by this insn UNSIGNED ' regs_write_count As Byte ' number of implicit registers modified by this insn UNSIGNED diff --git a/bindings/vb6/CInstruction.cls b/bindings/vb6/CInstruction.cls index 646323773..6c9bcc4ff 100644 --- a/bindings/vb6/CInstruction.cls +++ b/bindings/vb6/CInstruction.cls @@ -31,7 +31,7 @@ Option Explicit ' align As Long 'not sure why it needs this..but it does.. ' address As Currency ' Address (EIP) of this instruction available even when CS_OPT_DETAIL = CS_OPT_OFF UNSIGNED ' size As Integer ' Size of this instruction available even when CS_OPT_DETAIL = CS_OPT_OFF UNSIGNED -' bytes(0 To 15) As Byte ' Machine bytes of this instruction, with number of bytes indicated by @size above available even when CS_OPT_DETAIL = CS_OPT_OFF +' bytes(0 To 23) As Byte ' Machine bytes of this instruction, with number of bytes indicated by @size above available even when CS_OPT_DETAIL = CS_OPT_OFF ' mnemonic(0 To 31) As Byte ' Ascii text of instruction mnemonic available even when CS_OPT_DETAIL = CS_OPT_OFF ' op_str(0 To 159) As Byte ' Ascii text of instruction operands available even when CS_OPT_DETAIL = CS_OPT_OFF ' diff --git a/bindings/vb6/Module1.bas b/bindings/vb6/Module1.bas index 2fc057704..fcb566348 100644 --- a/bindings/vb6/Module1.bas +++ b/bindings/vb6/Module1.bas @@ -88,7 +88,7 @@ End Enum 'NOTE: All information in cs_detail is only available when CS_OPT_DETAIL = CS_OPT_ON Public Type cs_detail - regs_read(0 To 11) As Byte ' list of implicit registers read by this insn UNSIGNED + regs_read(0 To 15) As Byte ' list of implicit registers read by this insn UNSIGNED regs_read_count As Byte ' number of implicit registers read by this insn UNSIGNED regs_write(0 To 19) As Byte ' list of implicit registers modified by this insn UNSIGNED regs_write_count As Byte ' number of implicit registers modified by this insn UNSIGNED @@ -97,7 +97,7 @@ Public Type cs_detail End Type 'typedef struct cs_detail { -' uint8_t regs_read[12]; // list of implicit registers read by this insn +' uint8_t regs_read[16]; // list of implicit registers read by this insn ' uint8_t regs_read_count; // number of implicit registers read by this insn ' ' uint8_t regs_write[20]; // list of implicit registers modified by this insn @@ -131,7 +131,7 @@ Public Type cs_insn align As Long 'not sure why it needs this..but it does.. address As Currency ' Address (EIP) of this instruction available even when CS_OPT_DETAIL = CS_OPT_OFF UNSIGNED size As Integer ' Size of this instruction available even when CS_OPT_DETAIL = CS_OPT_OFF UNSIGNED - bytes(0 To 15) As Byte ' Machine bytes of this instruction, with number of bytes indicated by @size above available even when CS_OPT_DETAIL = CS_OPT_OFF + bytes(0 To 23) As Byte ' Machine bytes of this instruction, with number of bytes indicated by @size above available even when CS_OPT_DETAIL = CS_OPT_OFF mnemonic(0 To 31) As Byte ' Ascii text of instruction mnemonic available even when CS_OPT_DETAIL = CS_OPT_OFF op_str(0 To 159) As Byte ' Ascii text of instruction operands available even when CS_OPT_DETAIL = CS_OPT_OFF diff --git a/include/capstone/capstone.h b/include/capstone/capstone.h index 635dc67e6..6e1ee1d0b 100644 --- a/include/capstone/capstone.h +++ b/include/capstone/capstone.h @@ -286,7 +286,7 @@ typedef struct cs_opt_skipdata { /// if cs_detail changes, in particular if a field is added after the union, /// then update arch/ARCH/ARCHDisassembler.c accordingly typedef struct cs_detail { - uint16_t regs_read[12]; ///< list of implicit registers read by this insn + uint16_t regs_read[16]; ///< list of implicit registers read by this insn uint8_t regs_read_count; ///< number of implicit registers read by this insn uint16_t regs_write[20]; ///< list of implicit registers modified by this insn @@ -333,7 +333,7 @@ typedef struct cs_insn { /// Machine bytes of this instruction, with number of bytes indicated by @size above /// This information is available even when CS_OPT_DETAIL = CS_OPT_OFF - uint8_t bytes[16]; + uint8_t bytes[24]; /// Ascii text of instruction mnemonic /// This information is available even when CS_OPT_DETAIL = CS_OPT_OFF diff --git a/tests/test_m68k.c b/tests/test_m68k.c index 62b05be0c..9eb371043 100644 --- a/tests/test_m68k.c +++ b/tests/test_m68k.c @@ -2,6 +2,7 @@ /* By Nguyen Anh Quynh , 2013-2014 */ #include +#include #include #include @@ -134,6 +135,9 @@ static void print_insn_detail(cs_insn *ins) printf("\t\toperands[%u].type: FP_DOUBLE\n", i); printf("\t\t\toperands[%u].dimm: %lf\n", i, op->dimm); break; + case M68K_OP_REG_BITS: + printf("\t\toperands[%u].type: REG_BITS = $%x\n", i, op->register_bits); + } } @@ -142,7 +146,7 @@ static void print_insn_detail(cs_insn *ins) static void test() { -#define M68K_CODE "\x4C\x00\x54\x04\x48\xe7\xe0\x30\x4C\xDF\x0C\x07\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75" +#define M68K_CODE "\xf0\x10\xf0\x00\x48\xaf\xff\xff\x7f\xff\x11\xb0\x01\x37\x7f\xff\xff\xff\x12\x34\x56\x78\x01\x33\x10\x10\x10\x10\x32\x32\x32\x32\x4C\x00\x54\x04\x48\xe7\xe0\x30\x4C\xDF\x0C\x07\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75" struct platform platforms[] = { { CS_ARCH_M68K, @@ -177,6 +181,8 @@ static void test() printf("Disasm:\n"); for (j = 0; j < count; j++) { + assert(address == insn[j].address && "this means the size of the previous instruction was incorrect"); + address += insn[j].size; printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); print_insn_detail(&insn[j]); }