aboutsummaryrefslogtreecommitdiffstats
path: root/capstone/tests
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /capstone/tests
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'capstone/tests')
-rw-r--r--capstone/tests/Makefile186
-rw-r--r--capstone/tests/README31
-rw-r--r--capstone/tests/test_arm.c293
-rw-r--r--capstone/tests/test_arm64.c228
-rw-r--r--capstone/tests/test_basic.c423
-rw-r--r--capstone/tests/test_bpf.c187
-rw-r--r--capstone/tests/test_customized_mnem.c86
-rw-r--r--capstone/tests/test_detail.c374
-rw-r--r--capstone/tests/test_evm.c126
-rw-r--r--capstone/tests/test_iter.c337
-rw-r--r--capstone/tests/test_m680x.c396
-rw-r--r--capstone/tests/test_m68k.c217
-rw-r--r--capstone/tests/test_mips.c175
-rw-r--r--capstone/tests/test_mos65xx.c230
-rw-r--r--capstone/tests/test_ppc.c186
-rw-r--r--capstone/tests/test_riscv.c154
-rw-r--r--capstone/tests/test_skipdata.c184
-rw-r--r--capstone/tests/test_sparc.c152
-rw-r--r--capstone/tests/test_systemz.c145
-rw-r--r--capstone/tests/test_tms320c64x.c193
-rw-r--r--capstone/tests/test_wasm.c149
-rw-r--r--capstone/tests/test_winkernel.cpp172
-rw-r--r--capstone/tests/test_x86.c464
-rw-r--r--capstone/tests/test_xcore.c140
24 files changed, 5228 insertions, 0 deletions
diff --git a/capstone/tests/Makefile b/capstone/tests/Makefile
new file mode 100644
index 000000000..86a08e604
--- /dev/null
+++ b/capstone/tests/Makefile
@@ -0,0 +1,186 @@
+# Capstone Disassembler Engine
+# By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014
+
+include ../config.mk
+include ../functions.mk
+
+# Verbose output?
+V ?= 0
+
+INCDIR = ../include
+ifndef BUILDDIR
+TESTDIR = .
+OBJDIR = .
+LIBDIR = ..
+else
+TESTDIR = $(BUILDDIR)/tests
+OBJDIR = $(BUILDDIR)/obj/tests
+LIBDIR = $(BUILDDIR)
+endif
+
+ifeq ($(CROSS),)
+CC ?= cc
+else
+CC = $(CROSS)gcc
+endif
+
+
+CFLAGS += -Wall -I$(INCDIR)
+LDFLAGS += -L$(LIBDIR)
+
+CFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
+LDFLAGS += $(foreach arch,$(LIBARCHS),-arch $(arch))
+
+LIBNAME = capstone
+
+BIN_EXT =
+AR_EXT = a
+
+# Cygwin?
+IS_CYGWIN := $(shell $(CC) -dumpmachine | grep -i cygwin | wc -l)
+ifeq ($(IS_CYGWIN),1)
+CFLAGS := $(CFLAGS:-fPIC=)
+BIN_EXT = .exe
+AR_EXT = lib
+else
+# mingw?
+IS_MINGW := $(shell $(CC) --version 2>/dev/null | grep -i "\(mingw\|MSYS\)" | wc -l)
+ifeq ($(IS_MINGW),1)
+CFLAGS := $(CFLAGS:-fPIC=)
+BIN_EXT = .exe
+AR_EXT = lib
+endif
+endif
+
+ifeq ($(CAPSTONE_STATIC),yes)
+ifeq ($(IS_MINGW),1)
+ARCHIVE = $(LIBDIR)/$(LIBNAME).$(AR_EXT)
+else ifeq ($(IS_CYGWIN),1)
+ARCHIVE = $(LIBDIR)/$(LIBNAME).$(AR_EXT)
+else
+ARCHIVE = $(LIBDIR)/lib$(LIBNAME).$(AR_EXT)
+endif
+endif
+
+.PHONY: all clean
+
+SOURCES = test_basic.c test_detail.c test_skipdata.c test_iter.c test_customized_mnem.c
+ifneq (,$(findstring arm,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_ARM
+SOURCES += test_arm.c
+endif
+ifneq (,$(findstring aarch64,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_ARM64
+SOURCES += test_arm64.c
+endif
+ifneq (,$(findstring m68k,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_M68K
+SOURCES += test_m68k.c
+endif
+ifneq (,$(findstring mips,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_MIPS
+SOURCES += test_mips.c
+endif
+ifneq (,$(findstring powerpc,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_POWERPC
+SOURCES += test_ppc.c
+endif
+ifneq (,$(findstring sparc,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_SPARC
+SOURCES += test_sparc.c
+endif
+ifneq (,$(findstring systemz,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_SYSZ
+SOURCES += test_systemz.c
+endif
+ifneq (,$(findstring x86,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_X86
+SOURCES += test_x86.c
+endif
+ifneq (,$(findstring xcore,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_XCORE
+SOURCES += test_xcore.c
+endif
+ifneq (,$(findstring tms320c64x,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_TMS320C64X
+SOURCES += test_tms320c64x.c
+endif
+ifneq (,$(findstring m680x,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_M680X
+SOURCES += test_m680x.c
+endif
+ifneq (,$(findstring evm,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_EVM
+SOURCES += test_evm.c
+endif
+ifneq (,$(findstring riscv,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_RISCV
+SOURCES += test_riscv.c
+endif
+ifneq (,$(findstring wasm,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_WASM
+SOURCES += test_wasm.c
+endif
+ifneq (,$(findstring evm,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_MOS65XX
+SOURCES += test_mos65xx.c
+endif
+ifneq (,$(findstring bpf,$(CAPSTONE_ARCHS)))
+CFLAGS += -DCAPSTONE_HAS_BPF
+SOURCES += test_bpf.c
+endif
+
+OBJS = $(addprefix $(OBJDIR)/,$(SOURCES:.c=.o))
+BINARY = $(addprefix $(TESTDIR)/,$(SOURCES:.c=$(BIN_EXT)))
+
+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
+
+$(BINARY): $(OBJS)
+
+$(TESTDIR)/%$(BIN_EXT): $(OBJDIR)/%.o
+ @mkdir -p $(@D)
+ifeq ($(V),0)
+ifeq ($(CAPSTONE_SHARED),yes)
+ $(call log,LINK,$(notdir $@))
+ @$(link-dynamic)
+endif
+ifeq ($(CAPSTONE_STATIC),yes)
+ $(call log,LINK,$(notdir $(call staticname,$@)))
+ @$(link-static)
+endif
+else
+ifeq ($(CAPSTONE_SHARED),yes)
+ $(link-dynamic)
+endif
+ifeq ($(CAPSTONE_STATIC),yes)
+ $(link-static)
+endif
+endif
+
+$(OBJDIR)/%.o: %.c
+ @mkdir -p $(@D)
+ifeq ($(V),0)
+ $(call log,CC,$(@:$(OBJDIR)/%=%))
+ @$(compile)
+else
+ $(compile)
+endif
+
+
+define link-dynamic
+ $(CC) $(LDFLAGS) $< -l$(LIBNAME) -o $@
+endef
+
+
+define link-static
+ $(CC) $(LDFLAGS) $< $(ARCHIVE) -o $(call staticname,$@)
+endef
+
+
+staticname = $(subst $(BIN_EXT),,$(1)).static$(BIN_EXT)
diff --git a/capstone/tests/README b/capstone/tests/README
new file mode 100644
index 000000000..e5d3efb48
--- /dev/null
+++ b/capstone/tests/README
@@ -0,0 +1,31 @@
+This directory contains some test code to show how to use Capstone API.
+
+- test_basic.c
+ This code shows the most simple form of API where we only want to get basic
+ information out of disassembled instruction, such as address, mnemonic and
+ operand string.
+
+- test_detail.c:
+ This code shows how to access to architecture-neutral information in disassembled
+ 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_customized_mnem.c:
+ This code shows how to use MNEMONIC option to customize instruction mnemonic
+ at run-time, and then how to reset the engine to use the default mnemonic.
+
+- test_<arch>.c
+ These code show how to access architecture-specific information for each
+ architecture.
+
+- test_winkernel.cpp
+ This code shows how to use Capstone from a Windows driver.
diff --git a/capstone/tests/test_arm.c b/capstone/tests/test_arm.c
new file mode 100644
index 000000000..a5016fafb
--- /dev/null
+++ b/capstone/tests/test_arm.c
@@ -0,0 +1,293 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+static csh handle;
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+ int syntax;
+};
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static void print_insn_detail(csh cs_handle, cs_insn *ins)
+{
+ cs_arm *arm;
+ int i;
+ cs_regs regs_read, regs_write;
+ uint8_t regs_read_count, regs_write_count;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ arm = &(ins->detail->arm);
+
+ if (arm->op_count)
+ printf("\top_count: %u\n", arm->op_count);
+
+ for (i = 0; i < arm->op_count; i++) {
+ cs_arm_op *op = &(arm->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case ARM_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(cs_handle, op->reg));
+ break;
+ case ARM_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%x\n", i, op->imm);
+ break;
+ case ARM_OP_FP:
+#if defined(_KERNEL_MODE)
+ // Issue #681: Windows kernel does not support formatting float point
+ printf("\t\toperands[%u].type: FP = <float_point_unsupported>\n", i);
+#else
+ printf("\t\toperands[%u].type: FP = %f\n", i, op->fp);
+#endif
+ break;
+ case ARM_OP_MEM:
+ printf("\t\toperands[%u].type: MEM\n", i);
+ if (op->mem.base != ARM_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n",
+ i, cs_reg_name(cs_handle, op->mem.base));
+ if (op->mem.index != ARM_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.index: REG = %s\n",
+ i, cs_reg_name(cs_handle, op->mem.index));
+ if (op->mem.scale != 1)
+ printf("\t\t\toperands[%u].mem.scale: %u\n", i, op->mem.scale);
+ if (op->mem.disp != 0)
+ printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
+ if (op->mem.lshift != 0)
+ printf("\t\t\toperands[%u].mem.lshift: 0x%x\n", i, op->mem.lshift);
+
+ break;
+ case ARM_OP_PIMM:
+ printf("\t\toperands[%u].type: P-IMM = %u\n", i, op->imm);
+ break;
+ case ARM_OP_CIMM:
+ printf("\t\toperands[%u].type: C-IMM = %u\n", i, op->imm);
+ break;
+ case ARM_OP_SETEND:
+ printf("\t\toperands[%u].type: SETEND = %s\n", i, op->setend == ARM_SETEND_BE? "be" : "le");
+ break;
+ case ARM_OP_SYSREG:
+ printf("\t\toperands[%u].type: SYSREG = %u\n", i, op->reg);
+ break;
+ }
+
+ if (op->neon_lane != -1) {
+ printf("\t\toperands[%u].neon_lane = %u\n", i, op->neon_lane);
+ }
+
+ switch(op->access) {
+ default:
+ break;
+ case CS_AC_READ:
+ printf("\t\toperands[%u].access: READ\n", i);
+ break;
+ case CS_AC_WRITE:
+ printf("\t\toperands[%u].access: WRITE\n", i);
+ break;
+ case CS_AC_READ | CS_AC_WRITE:
+ printf("\t\toperands[%u].access: READ | WRITE\n", i);
+ break;
+ }
+
+ if (op->shift.type != ARM_SFT_INVALID && op->shift.value) {
+ if (op->shift.type < ARM_SFT_ASR_REG)
+ // shift with constant value
+ printf("\t\t\tShift: %u = %u\n", op->shift.type, op->shift.value);
+ else
+ // shift with register
+ printf("\t\t\tShift: %u = %s\n", op->shift.type,
+ cs_reg_name(cs_handle, op->shift.value));
+ }
+
+ 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)
+ printf("\tCode condition: %u\n", arm->cc);
+
+ if (arm->update_flags)
+ printf("\tUpdate-flags: True\n");
+
+ if (arm->writeback)
+ printf("\tWrite-back: True\n");
+
+ if (arm->cps_mode)
+ printf("\tCPSI-mode: %u\n", arm->cps_mode);
+
+ if (arm->cps_flag)
+ printf("\tCPSI-flag: %u\n", arm->cps_flag);
+
+ if (arm->vector_data)
+ printf("\tVector-data: %u\n", arm->vector_data);
+
+ if (arm->vector_size)
+ printf("\tVector-size: %u\n", arm->vector_size);
+
+ if (arm->usermode)
+ printf("\tUser-mode: True\n");
+
+ if (arm->mem_barrier)
+ printf("\tMemory-barrier: %u\n", arm->mem_barrier);
+
+ // Print out all registers accessed by this instruction (either implicit or explicit)
+ if (!cs_regs_access(cs_handle, ins,
+ regs_read, &regs_read_count,
+ regs_write, &regs_write_count)) {
+ if (regs_read_count) {
+ printf("\tRegisters read:");
+ for(i = 0; i < regs_read_count; i++) {
+ printf(" %s", cs_reg_name(cs_handle, regs_read[i]));
+ }
+ printf("\n");
+ }
+
+ if (regs_write_count) {
+ printf("\tRegisters modified:");
+ for(i = 0; i < regs_write_count; i++) {
+ printf(" %s", cs_reg_name(cs_handle, regs_write[i]));
+ }
+ printf("\n");
+ }
+ }
+
+ printf("\n");
+}
+
+static void test()
+{
+#define ARM_CODE "\x86\x48\x60\xf4\x4d\x0f\xe2\xf4\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 "\xd1\xe8\x00\xf0\xf0\x24\x04\x07\x1f\x3c\xf2\xc0\x00\x00\x4f\xf0\x00\x01\x46\x6c"
+#define THUMB_CODE "\x60\xf9\x1f\x04\xe0\xf9\x4f\x07\x70\x47\x00\xf0\x10\xe8\xeb\x46\x83\xb0\xc9\x68\x1f\xb1\x30\xbf\xaf\xf3\x20\x84\x52\xf8\x23\xf0"
+#define THUMB_CODE2 "\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"
+#define THUMB_MCLASS "\xef\xf3\x02\x80"
+#define ARMV8 "\xe0\x3b\xb2\xee\x42\x00\x01\xe1\x51\xf0\x7f\xf5"
+
+ struct platform platforms[] = {
+ {
+ CS_ARCH_ARM,
+ CS_MODE_ARM,
+ (unsigned char *)ARM_CODE,
+ sizeof(ARM_CODE) - 1,
+ "ARM"
+ },
+ {
+ CS_ARCH_ARM,
+ CS_MODE_THUMB,
+ (unsigned char *)THUMB_CODE,
+ sizeof(THUMB_CODE) - 1,
+ "Thumb"
+ },
+ {
+ CS_ARCH_ARM,
+ CS_MODE_THUMB,
+ (unsigned char *)ARM_CODE2,
+ sizeof(ARM_CODE2) - 1,
+ "Thumb-mixed"
+ },
+ {
+ CS_ARCH_ARM,
+ CS_MODE_THUMB,
+ (unsigned char *)THUMB_CODE2,
+ sizeof(THUMB_CODE2) - 1,
+ "Thumb-2 & register named with numbers",
+ CS_OPT_SYNTAX_NOREGNAME
+ },
+ {
+ CS_ARCH_ARM,
+ (cs_mode)(CS_MODE_THUMB + CS_MODE_MCLASS),
+ (unsigned char*)THUMB_MCLASS,
+ sizeof(THUMB_MCLASS) - 1,
+ "Thumb-MClass"
+ },
+ {
+ CS_ARCH_ARM,
+ (cs_mode)(CS_MODE_ARM + CS_MODE_V8),
+ (unsigned char*)ARMV8,
+ sizeof(ARMV8) - 1,
+ "Arm-V8"
+ },
+ };
+
+ uint64_t address = 0x80001000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ if (platforms[i].syntax)
+ cs_option(handle, CS_OPT_SYNTAX, platforms[i].syntax);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(handle, &insn[j]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
+
diff --git a/capstone/tests/test_arm64.c b/capstone/tests/test_arm64.c
new file mode 100644
index 000000000..bafb9da21
--- /dev/null
+++ b/capstone/tests/test_arm64.c
@@ -0,0 +1,228 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+static csh handle;
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static void print_insn_detail(cs_insn *ins)
+{
+ cs_arm64 *arm64;
+ int i;
+ cs_regs regs_read, regs_write;
+ unsigned char regs_read_count, regs_write_count;
+ unsigned char access;
+
+ // detail can be NULL if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ arm64 = &(ins->detail->arm64);
+ if (arm64->op_count)
+ printf("\top_count: %u\n", arm64->op_count);
+
+ for (i = 0; i < arm64->op_count; i++) {
+ cs_arm64_op *op = &(arm64->operands[i]);
+ switch(op->type) {
+ default:
+ break;
+ case ARM64_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ break;
+ case ARM64_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
+ break;
+ case ARM64_OP_FP:
+#if defined(_KERNEL_MODE)
+ // Issue #681: Windows kernel does not support formatting float point
+ printf("\t\toperands[%u].type: FP = <float_point_unsupported>\n", i);
+#else
+ printf("\t\toperands[%u].type: FP = %f\n", i, op->fp);
+#endif
+ break;
+ case ARM64_OP_MEM:
+ printf("\t\toperands[%u].type: MEM\n", i);
+ if (op->mem.base != ARM64_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(handle, op->mem.base));
+ if (op->mem.index != ARM64_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.index: REG = %s\n", i, cs_reg_name(handle, op->mem.index));
+ if (op->mem.disp != 0)
+ printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
+
+ break;
+ case ARM64_OP_CIMM:
+ printf("\t\toperands[%u].type: C-IMM = %u\n", i, (int)op->imm);
+ break;
+ case ARM64_OP_REG_MRS:
+ printf("\t\toperands[%u].type: REG_MRS = 0x%x\n", i, op->reg);
+ break;
+ case ARM64_OP_REG_MSR:
+ printf("\t\toperands[%u].type: REG_MSR = 0x%x\n", i, op->reg);
+ break;
+ case ARM64_OP_PSTATE:
+ printf("\t\toperands[%u].type: PSTATE = 0x%x\n", i, op->pstate);
+ break;
+ case ARM64_OP_SYS:
+ printf("\t\toperands[%u].type: SYS = 0x%x\n", i, op->sys);
+ break;
+ case ARM64_OP_PREFETCH:
+ printf("\t\toperands[%u].type: PREFETCH = 0x%x\n", i, op->prefetch);
+ break;
+ case ARM64_OP_BARRIER:
+ printf("\t\toperands[%u].type: BARRIER = 0x%x\n", i, op->barrier);
+ break;
+ }
+
+ access = op->access;
+ switch(access) {
+ default:
+ break;
+ case CS_AC_READ:
+ printf("\t\toperands[%u].access: READ\n", i);
+ break;
+ case CS_AC_WRITE:
+ printf("\t\toperands[%u].access: WRITE\n", i);
+ break;
+ case CS_AC_READ | CS_AC_WRITE:
+ printf("\t\toperands[%u].access: READ | WRITE\n", i);
+ break;
+ }
+
+ if (op->shift.type != ARM64_SFT_INVALID &&
+ op->shift.value)
+ printf("\t\t\tShift: type = %u, value = %u\n",
+ op->shift.type, op->shift.value);
+
+ if (op->ext != ARM64_EXT_INVALID)
+ printf("\t\t\tExt: %u\n", op->ext);
+
+ if (op->vas != ARM64_VAS_INVALID)
+ printf("\t\t\tVector Arrangement Specifier: 0x%x\n", op->vas);
+
+ if (op->vector_index != -1)
+ printf("\t\t\tVector Index: %u\n", op->vector_index);
+ }
+
+ if (arm64->update_flags)
+ printf("\tUpdate-flags: True\n");
+
+ if (arm64->writeback)
+ printf("\tWrite-back: True\n");
+
+ if (arm64->cc)
+ printf("\tCode-condition: %u\n", arm64->cc);
+
+ // Print out all registers accessed by this instruction (either implicit or explicit)
+ if (!cs_regs_access(handle, ins,
+ regs_read, &regs_read_count,
+ regs_write, &regs_write_count)) {
+ if (regs_read_count) {
+ printf("\tRegisters read:");
+ for(i = 0; i < regs_read_count; i++) {
+ printf(" %s", cs_reg_name(handle, regs_read[i]));
+ }
+ printf("\n");
+ }
+
+ if (regs_write_count) {
+ printf("\tRegisters modified:");
+ for(i = 0; i < regs_write_count; i++) {
+ printf(" %s", cs_reg_name(handle, regs_write[i]));
+ }
+ printf("\n");
+ }
+ }
+
+ printf("\n");
+}
+
+static void test()
+{
+#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"
+
+ struct platform platforms[] = {
+ {
+ CS_ARCH_ARM64,
+ CS_MODE_ARM,
+ (unsigned char *)ARM64_CODE,
+ sizeof(ARM64_CODE) - 1,
+ "ARM-64"
+ },
+ };
+
+ uint64_t address = 0x2c;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code: ", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(&insn[j]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code: ", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
+
diff --git a/capstone/tests/test_basic.c b/capstone/tests/test_basic.c
new file mode 100644
index 000000000..3a8e1e0b9
--- /dev/null
+++ b/capstone/tests/test_basic.c
@@ -0,0 +1,423 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const 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()
+{
+#ifdef CAPSTONE_HAS_X86
+#define X86_CODE16 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
+#define X86_CODE32 "\xba\xcd\xab\x00\x00\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00"
+#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00"
+#endif
+#ifdef CAPSTONE_HAS_ARM
+#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 ARMV8 "\xe0\x3b\xb2\xee\x42\x00\x01\xe1\x51\xf0\x7f\xf5"
+#define THUMB_MCLASS "\xef\xf3\x02\x80"
+#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"
+#endif
+#ifdef CAPSTONE_HAS_MIPS
+#define MIPS_CODE "\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
+#define MIPS_CODE2 "\x56\x34\x21\x34\xc2\x17\x01\x00"
+#define MIPS_32R6M "\x00\x07\x00\x07\x00\x11\x93\x7c\x01\x8c\x8b\x7c\x00\xc7\x48\xd0"
+#define MIPS_32R6 "\xec\x80\x00\x19\x7c\x43\x22\xa0"
+#endif
+#ifdef CAPSTONE_HAS_ARM64
+#define ARM64_CODE "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9"
+#endif
+#ifdef CAPSTONE_HAS_POWERPC
+#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"
+#define PPC_CODE2 "\x10\x60\x2a\x10\x10\x64\x28\x88\x7c\x4a\x5d\x0f"
+#endif
+#ifdef CAPSTONE_HAS_SPARC
+#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"
+#endif
+#ifdef CAPSTONE_HAS_SYSZ
+#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"
+#endif
+#ifdef CAPSTONE_HAS_XCORE
+#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"
+#endif
+#ifdef CAPSTONE_HAS_M68K
+#define M68K_CODE "\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"
+#endif
+#ifdef CAPSTONE_HAS_TMS320C64X
+#define TMS320C64X_CODE "\x01\xac\x88\x40\x81\xac\x88\x43\x00\x00\x00\x00\x02\x90\x32\x96\x02\x80\x46\x9e\x05\x3c\x83\xe6\x0b\x0c\x8b\x24"
+#endif
+#ifdef CAPSTONE_HAS_M680X
+#define M680X_CODE "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39"
+#endif
+#ifdef CAPSTONE_HAS_EVM
+#define EVM_CODE "\x60\x61"
+#endif
+#ifdef CAPSTONE_HAS_WASM
+#define WASM_CODE "\x20\x00\x20\x01\x41\x20\x10\xc9\x01\x45\x0b"
+#endif
+#ifdef CAPSTONE_HAS_MOS65XX
+#define MOS65XX_CODE "\x0d\x34\x12\x00\x81\x65\x6c\x01\x00\x85\xFF\x10\x00\x19\x42\x42\x00\x49\x42"
+#endif
+#define EBPF_CODE "\x97\x09\x00\x00\x37\x13\x03\x00\xdc\x02\x00\x00\x20\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\xdb\x3a\x00\x01\x00\x00\x00\x00\x84\x02\x00\x00\x00\x00\x00\x00\x6d\x33\x17\x02\x00\x00\x00\x00"
+
+#ifdef CAPSTONE_HAS_RISCV
+#define RISCV_CODE32 "\x37\x34\x00\x00\x97\x82\x00\x00\xef\x00\x80\x00\xef\xf0\x1f\xff\xe7\x00\x45\x00\xe7\x00\xc0\xff\x63\x05\x41\x00\xe3\x9d\x61\xfe\x63\xca\x93\x00\x63\x53\xb5\x00\x63\x65\xd6\x00\x63\x76\xf7\x00\x03\x88\x18\x00\x03\x99\x49\x00\x03\xaa\x6a\x00\x03\xcb\x2b\x01\x03\xdc\x8c\x01\x23\x86\xad\x03\x23\x9a\xce\x03\x23\x8f\xef\x01\x93\x00\xe0\x00\x13\xa1\x01\x01\x13\xb2\x02\x7d\x13\xc3\x03\xdd\x13\xe4\xc4\x12\x13\xf5\x85\x0c\x13\x96\xe6\x01\x13\xd7\x97\x01\x13\xd8\xf8\x40\x33\x89\x49\x01\xb3\x0a\x7b\x41\x33\xac\xac\x01\xb3\x3d\xde\x01\x33\xd2\x62\x40\xb3\x43\x94\x00\x33\xe5\xc5\x00\xb3\x76\xf7\x00\xb3\x54\x39\x01\xb3\x50\x31\x00\x33\x9f\x0f\x00"
+#define RISCV_CODE64 "\x13\x04\xa8\x7a" // aaa80413
+#endif
+
+ struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+ cs_opt_type opt_type;
+ cs_opt_value opt_value;
+ };
+ struct platform platforms[] = {
+#ifdef CAPSTONE_HAS_X86
+ {
+ CS_ARCH_X86,
+ CS_MODE_16,
+ (unsigned char*)X86_CODE16,
+ sizeof(X86_CODE16) - 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_32,
+ (unsigned char*)X86_CODE32,
+ sizeof(X86_CODE32) - 1,
+ "X86 32 (MASM syntax)",
+ CS_OPT_SYNTAX,
+ CS_OPT_SYNTAX_MASM,
+ },
+ {
+ CS_ARCH_X86,
+ CS_MODE_64,
+ (unsigned char*)X86_CODE64,
+ sizeof(X86_CODE64) - 1,
+ "X86 64 (Intel syntax)"
+ },
+#endif
+#ifdef CAPSTONE_HAS_ARM
+ {
+ 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_ARM,
+ (cs_mode)(CS_MODE_THUMB + CS_MODE_MCLASS),
+ (unsigned char*)THUMB_MCLASS,
+ sizeof(THUMB_MCLASS) - 1,
+ "Thumb-MClass"
+ },
+ {
+ CS_ARCH_ARM,
+ (cs_mode)(CS_MODE_ARM + CS_MODE_V8),
+ (unsigned char*)ARMV8,
+ sizeof(ARMV8) - 1,
+ "Arm-V8"
+ },
+#endif
+#ifdef CAPSTONE_HAS_MIPS
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN),
+ (unsigned char*)MIPS_CODE,
+ sizeof(MIPS_CODE) - 1,
+ "MIPS-32 (Big-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS64 + CS_MODE_LITTLE_ENDIAN),
+ (unsigned char*)MIPS_CODE2,
+ sizeof(MIPS_CODE2) - 1,
+ "MIPS-64-EL (Little-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN),
+ (unsigned char*)MIPS_32R6M,
+ sizeof(MIPS_32R6M) - 1,
+ "MIPS-32R6 | Micro (Big-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN),
+ (unsigned char*)MIPS_32R6,
+ sizeof(MIPS_32R6) - 1,
+ "MIPS-32R6 (Big-endian)"
+ },
+#endif
+#ifdef CAPSTONE_HAS_ARM64
+ {
+ CS_ARCH_ARM64,
+ CS_MODE_ARM,
+ (unsigned char*)ARM64_CODE,
+ sizeof(ARM64_CODE) - 1,
+ "ARM-64"
+ },
+#endif
+#ifdef CAPSTONE_HAS_POWERPC
+ {
+ CS_ARCH_PPC,
+ CS_MODE_BIG_ENDIAN,
+ (unsigned char*)PPC_CODE,
+ sizeof(PPC_CODE) - 1,
+ "PPC-64"
+ },
+ {
+ CS_ARCH_PPC,
+ CS_MODE_BIG_ENDIAN,
+ (unsigned char*)PPC_CODE,
+ sizeof(PPC_CODE) - 1,
+ "PPC-64, print register with number only",
+ CS_OPT_SYNTAX,
+ CS_OPT_SYNTAX_NOREGNAME
+ },
+ {
+ CS_ARCH_PPC,
+ CS_MODE_BIG_ENDIAN + CS_MODE_QPX,
+ (unsigned char*)PPC_CODE2,
+ sizeof(PPC_CODE2) - 1,
+ "PPC-64 + QPX",
+ },
+#endif
+#ifdef CAPSTONE_HAS_SPARC
+ {
+ 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"
+ },
+#endif
+#ifdef CAPSTONE_HAS_SYSZ
+ {
+ CS_ARCH_SYSZ,
+ (cs_mode)0,
+ (unsigned char*)SYSZ_CODE,
+ sizeof(SYSZ_CODE) - 1,
+ "SystemZ"
+ },
+#endif
+#ifdef CAPSTONE_HAS_XCORE
+ {
+ CS_ARCH_XCORE,
+ (cs_mode)0,
+ (unsigned char*)XCORE_CODE,
+ sizeof(XCORE_CODE) - 1,
+ "XCore"
+ },
+#endif
+#ifdef CAPSTONE_HAS_M68K
+ {
+ CS_ARCH_M68K,
+ (cs_mode)(CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040),
+ (unsigned char*)M68K_CODE,
+ sizeof(M68K_CODE) - 1,
+ "M68K",
+ },
+#endif
+#ifdef CAPSTONE_HAS_TMS320C64X
+ {
+ CS_ARCH_TMS320C64X,
+ 0,
+ (unsigned char*)TMS320C64X_CODE,
+ sizeof(TMS320C64X_CODE) - 1,
+ "TMS320C64x",
+ },
+#endif
+#ifdef CAPSTONE_HAS_M680X
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_6809),
+ (unsigned char*)M680X_CODE,
+ sizeof(M680X_CODE) - 1,
+ "M680X_M6809",
+ },
+#endif
+#ifdef CAPSTONE_HAS_EVM
+ {
+ CS_ARCH_EVM,
+ 0,
+ (unsigned char*)EVM_CODE,
+ sizeof(EVM_CODE) - 1,
+ "EVM",
+ },
+#endif
+#ifdef CAPSTONE_HAS_WASM
+ {
+ CS_ARCH_WASM,
+ 0,
+ (unsigned char*)WASM_CODE,
+ sizeof(WASM_CODE) - 1,
+ "WASM",
+ },
+#endif
+#ifdef CAPSTONE_HAS_MOS65XX
+ {
+ CS_ARCH_MOS65XX,
+ 0,
+ (unsigned char *)MOS65XX_CODE,
+ sizeof(MOS65XX_CODE) - 1,
+ "MOS65XX"
+ },
+#endif
+#ifdef CAPSTONE_HAS_BPF
+ {
+ CS_ARCH_BPF,
+ CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED,
+ (unsigned char*) EBPF_CODE,
+ sizeof(EBPF_CODE) - 1,
+ "eBPF"
+ },
+#endif
+#ifdef CAPSTONE_HAS_RISCV
+ {
+ CS_ARCH_RISCV,
+ CS_MODE_RISCV32,
+ (unsigned char *)RISCV_CODE32,
+ sizeof(RISCV_CODE32) - 1,
+ "RISCV32"
+ },
+ {
+ CS_ARCH_RISCV,
+ CS_MODE_RISCV64,
+ (unsigned char *)RISCV_CODE64,
+ sizeof(RISCV_CODE64) - 1,
+ "RISCV64"
+ },
+#endif
+ };
+
+ csh handle;
+ uint64_t address = 0x1000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+ cs_err err;
+
+ 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);
+ abort();
+ }
+
+ if (platforms[i].opt_type)
+ cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ print_string_hex(platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t\t%s\n",
+ insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ }
+
+ // print out the next offset, after the last insn
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex(platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_bpf.c b/capstone/tests/test_bpf.c
new file mode 100644
index 000000000..b97e330cb
--- /dev/null
+++ b/capstone/tests/test_bpf.c
@@ -0,0 +1,187 @@
+/* Capstone Disassembly Engine */
+/* By david942j <david942j@gmail.com>, 2019 */
+
+#include <capstone/capstone.h>
+#include <capstone/platform.h>
+
+static csh handle;
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ const unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static void print_string_hex(const char *comment, const unsigned char *str, size_t len)
+{
+ const unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf(" 0x%02x", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static const char * ext_name[] = {
+ [BPF_EXT_LEN] = "#len",
+};
+
+static void print_insn_detail(csh cs_handle, cs_insn *ins)
+{
+ cs_bpf *bpf;
+ cs_regs regs_read, regs_write;
+ uint8_t regs_read_count, regs_write_count;
+ unsigned i;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ if (ins->detail->groups_count) {
+ int j;
+
+ printf("\tGroups:");
+ for(j = 0; j < ins->detail->groups_count; j++)
+ printf(" %s", cs_group_name(handle, ins->detail->groups[j]));
+ printf("\n");
+ }
+
+ bpf = &(ins->detail->bpf);
+
+ printf("\tOperand count: %u\n", bpf->op_count);
+ for (i = 0; i < bpf->op_count; i++) {
+ cs_bpf_op *op = &(bpf->operands[i]);
+ printf("\t\toperands[%u].type: ", i);
+ switch (op->type) {
+ case BPF_OP_INVALID:
+ printf("INVALID\n");
+ break;
+ case BPF_OP_REG:
+ printf("REG = %s\n", cs_reg_name(handle, op->reg));
+ break;
+ case BPF_OP_IMM:
+ printf("IMM = 0x%" PRIx64 "\n", op->imm);
+ break;
+ case BPF_OP_OFF:
+ printf("OFF = +0x%x\n", op->off);
+ break;
+ case BPF_OP_MEM:
+ printf("MEM\n");
+ if (op->mem.base != BPF_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.base));
+ printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
+ break;
+ case BPF_OP_MMEM:
+ printf("MMEM = M[0x%x]\n", op->mmem);
+ break;
+ case BPF_OP_MSH:
+ printf("MSH = 4*([0x%x]&0xf)\n", op->msh);
+ break;
+ case BPF_OP_EXT:
+ printf("EXT = %s\n", ext_name[op->ext]);
+ break;
+ }
+ }
+
+ /* print all registers that are involved in this instruction */
+ if (!cs_regs_access(cs_handle, ins,
+ regs_read, &regs_read_count,
+ regs_write, &regs_write_count)) {
+ if (regs_read_count) {
+ printf("\tRegisters read:");
+ for(i = 0; i < regs_read_count; i++)
+ printf(" %s", cs_reg_name(cs_handle, regs_read[i]));
+ printf("\n");
+ }
+
+ if (regs_write_count) {
+ printf("\tRegisters modified:");
+ for(i = 0; i < regs_write_count; i++)
+ printf(" %s", cs_reg_name(cs_handle, regs_write[i]));
+ printf("\n");
+ }
+ }
+ puts("");
+}
+
+static void test()
+{
+#define CBPF_CODE "\x94\x09\x00\x00\x37\x13\x03\x00" \
+ "\x87\x00\x00\x00\x00\x00\x00\x00" \
+ "\x07\x00\x00\x00\x00\x00\x00\x00" \
+ "\x16\x00\x00\x00\x00\x00\x00\x00" \
+ "\x80\x00\x00\x00\x00\x00\x00\x00"
+
+#define EBPF_CODE "\x97\x09\x00\x00\x37\x13\x03\x00" \
+ "\xdc\x02\x00\x00\x20\x00\x00\x00" \
+ "\x30\x00\x00\x00\x00\x00\x00\x00" \
+ "\xdb\x3a\x00\x01\x00\x00\x00\x00" \
+ "\x84\x02\x00\x00\x00\x00\x00\x00" \
+ "\x6d\x33\x17\x02\x00\x00\x00\x00"
+ struct platform platforms[] = {
+ {
+ CS_ARCH_BPF,
+ CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_CLASSIC,
+ (unsigned char *)CBPF_CODE,
+ sizeof(CBPF_CODE) - 1,
+ "cBPF Le"
+ },
+ {
+ CS_ARCH_BPF,
+ CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED,
+ (unsigned char *)EBPF_CODE,
+ sizeof(EBPF_CODE) - 1,
+ "eBPF Le"
+ },
+ };
+ uint64_t address = 0x0;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(handle, &insn[j]);
+ }
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+ return 0;
+}
diff --git a/capstone/tests/test_customized_mnem.c b/capstone/tests/test_customized_mnem.c
new file mode 100644
index 000000000..664cdb1cf
--- /dev/null
+++ b/capstone/tests/test_customized_mnem.c
@@ -0,0 +1,86 @@
+/* Capstone Disassembly Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2015-2019 */
+
+// This sample code demonstrates the option CS_OPT_MNEMONIC
+// to customize instruction mnemonic.
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+#define X86_CODE32 "\x75\x01"
+
+// Print out the input code in hexadecimal format
+static void print_string_hex(unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ for (c = str; c < str + len; c++) {
+ printf("%02x ", *c & 0xff);
+ }
+ printf("\t");
+}
+
+// Print one instruction
+static void print_insn(csh handle)
+{
+ cs_insn *insn;
+ size_t count;
+
+ count = cs_disasm(handle, (const uint8_t *)X86_CODE32, sizeof(X86_CODE32) - 1, 0x1000, 1, &insn);
+ if (count) {
+ print_string_hex((unsigned char *)X86_CODE32, sizeof(X86_CODE32) - 1);
+ printf("\t%s\t%s\n", insn[0].mnemonic, insn[0].op_str);
+ // Free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+}
+
+static void test()
+{
+ csh handle;
+ cs_err err;
+ // Customize mnemonic JNE to "jnz"
+ cs_opt_mnem my_mnem = { X86_INS_JNE, "jnz" };
+ // Set .mnemonic to NULL to reset to default mnemonic
+ cs_opt_mnem default_mnem = { X86_INS_JNE, NULL };
+
+ err = cs_open(CS_ARCH_X86, CS_MODE_32, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ // 1. Print out the instruction in default setup.
+ printf("Disassemble X86 code with default instruction mnemonic\n");
+ print_insn(handle);
+
+ // Customized mnemonic JNE to JNZ using CS_OPT_MNEMONIC option
+ printf("\nNow customize engine to change mnemonic from 'JNE' to 'JNZ'\n");
+ cs_option(handle, CS_OPT_MNEMONIC, (size_t)&my_mnem);
+
+ // 2. Now print out the instruction in newly customized setup.
+ print_insn(handle);
+
+ // Reset engine to use the default mnemonic of JNE
+ printf("\nReset engine to use the default mnemonic\n");
+ cs_option(handle, CS_OPT_MNEMONIC, (size_t)&default_mnem);
+
+ // 3. Now print out the instruction in default setup.
+ print_insn(handle);
+
+ // Done
+ cs_close(&handle);
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_detail.c b/capstone/tests/test_detail.c
new file mode 100644
index 000000000..ea7d1fdd1
--- /dev/null
+++ b/capstone/tests/test_detail.c
@@ -0,0 +1,374 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const 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()
+{
+#ifdef CAPSTONE_HAS_X86
+#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_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00"
+#endif
+#ifdef CAPSTONE_HAS_ARM
+#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 THUMB_MCLASS "\xef\xf3\x02\x80"
+#define ARMV8 "\xe0\x3b\xb2\xee\x42\x00\x01\xe1\x51\xf0\x7f\xf5"
+#endif
+#ifdef CAPSTONE_HAS_MIPS
+#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_CODE2 "\x56\x34\x21\x34\xc2\x17\x01\x00"
+#define MIPS_32R6M "\x00\x07\x00\x07\x00\x11\x93\x7c\x01\x8c\x8b\x7c\x00\xc7\x48\xd0"
+#define MIPS_32R6 "\xec\x80\x00\x19\x7c\x43\x22\xa0"
+#endif
+#ifdef CAPSTONE_HAS_ARM64
+#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"
+#endif
+#ifdef CAPSTONE_HAS_POWERPC
+#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 PPC_CODE2 "\x10\x60\x2a\x10\x10\x64\x28\x88\x7c\x4a\x5d\x0f"
+#endif
+#ifdef CAPSTONE_HAS_SPARC
+#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"
+#endif
+#ifdef CAPSTONE_HAS_SYSZ
+#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"
+#endif
+#ifdef CAPSTONE_HAS_XCORE
+#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"
+#endif
+#ifdef CAPSTONE_HAS_M68K
+#define M68K_CODE "\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"
+#endif
+#ifdef CAPSTONE_HAS_M680X
+#define M680X_CODE "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39"
+#endif
+#ifdef CAPSTONE_HAS_MOS65XX
+#define MOS65XX_CODE "\x0A\x00\xFE\x34\x12\xD0\xFF\xEA\x19\x56\x34\x46\x80"
+#endif
+#define EBPF_CODE "\x97\x09\x00\x00\x37\x13\x03\x00\xdc\x02\x00\x00\x20\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\xdb\x3a\x00\x01\x00\x00\x00\x00\x84\x02\x00\x00\x00\x00\x00\x00\x6d\x33\x17\x02\x00\x00\x00\x00"
+
+ struct platform platforms[] = {
+#ifdef CAPSTONE_HAS_X86
+ {
+ CS_ARCH_X86,
+ CS_MODE_16,
+ (unsigned char *)X86_CODE16,
+ sizeof(X86_CODE16) - 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)"
+ },
+#endif
+#ifdef CAPSTONE_HAS_ARM
+ {
+ 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_ARM,
+ (cs_mode)(CS_MODE_THUMB + CS_MODE_MCLASS),
+ (unsigned char*)THUMB_MCLASS,
+ sizeof(THUMB_MCLASS) - 1,
+ "Thumb-MClass"
+ },
+ {
+ CS_ARCH_ARM,
+ (cs_mode)(CS_MODE_ARM + CS_MODE_V8),
+ (unsigned char*)ARMV8,
+ sizeof(ARMV8) - 1,
+ "Arm-V8"
+ },
+#endif
+#ifdef CAPSTONE_HAS_MIPS
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN),
+ (unsigned char *)MIPS_CODE,
+ sizeof(MIPS_CODE) - 1,
+ "MIPS-32 (Big-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS64 + CS_MODE_LITTLE_ENDIAN),
+ (unsigned char *)MIPS_CODE2,
+ sizeof(MIPS_CODE2) - 1,
+ "MIPS-64-EL (Little-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN),
+ (unsigned char*)MIPS_32R6M,
+ sizeof(MIPS_32R6M) - 1,
+ "MIPS-32R6 | Micro (Big-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN),
+ (unsigned char*)MIPS_32R6,
+ sizeof(MIPS_32R6) - 1,
+ "MIPS-32R6 (Big-endian)"
+ },
+#endif
+#ifdef CAPSTONE_HAS_ARM64
+ {
+ CS_ARCH_ARM64,
+ CS_MODE_ARM,
+ (unsigned char *)ARM64_CODE,
+ sizeof(ARM64_CODE) - 1,
+ "ARM-64"
+ },
+#endif
+#ifdef CAPSTONE_HAS_POWERPC
+ {
+ CS_ARCH_PPC,
+ CS_MODE_BIG_ENDIAN,
+ (unsigned char*)PPC_CODE,
+ sizeof(PPC_CODE) - 1,
+ "PPC-64"
+ },
+ {
+ CS_ARCH_PPC,
+ CS_MODE_BIG_ENDIAN + CS_MODE_QPX,
+ (unsigned char*)PPC_CODE2,
+ sizeof(PPC_CODE2) - 1,
+ "PPC-64 + QPX",
+ },
+#endif
+#ifdef CAPSTONE_HAS_SPARC
+ {
+ 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"
+ },
+#endif
+#ifdef CAPSTONE_HAS_SYSZ
+ {
+ CS_ARCH_SYSZ,
+ (cs_mode)0,
+ (unsigned char*)SYSZ_CODE,
+ sizeof(SYSZ_CODE) - 1,
+ "SystemZ"
+ },
+#endif
+#ifdef CAPSTONE_HAS_XCORE
+ {
+ CS_ARCH_XCORE,
+ (cs_mode)0,
+ (unsigned char*)XCORE_CODE,
+ sizeof(XCORE_CODE) - 1,
+ "XCore"
+ },
+#endif
+#ifdef CAPSTONE_HAS_M68K
+ {
+ CS_ARCH_M68K,
+ (cs_mode)(CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040),
+ (unsigned char*)M68K_CODE,
+ sizeof(M68K_CODE) - 1,
+ "M68K",
+ },
+#endif
+#ifdef CAPSTONE_HAS_M680X
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_6809),
+ (unsigned char*)M680X_CODE,
+ sizeof(M680X_CODE) - 1,
+ "M680X_M6809",
+ },
+#endif
+#ifdef CAPSTONE_HAS_MOS65XX
+ {
+ CS_ARCH_MOS65XX,
+ (cs_mode)0,
+ (unsigned char*)MOS65XX_CODE,
+ sizeof(MOS65XX_CODE) - 1,
+ "MOS65XX",
+ },
+#endif
+#ifdef CAPSTONE_HAS_BPF
+ {
+ CS_ARCH_BPF,
+ CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED,
+ (unsigned char*) EBPF_CODE,
+ sizeof(EBPF_CODE) - 1,
+ "eBPF"
+ },
+#endif
+ };
+
+ csh handle;
+ uint64_t address = 0x1000;
+ cs_insn *all_insn;
+ cs_detail *detail;
+ int i;
+ size_t count;
+ cs_err err;
+
+ 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);
+ abort();
+ }
+
+ 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);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &all_insn);
+ if (count) {
+ size_t j;
+ int n;
+
+ print_string_hex(platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ cs_insn *in = &(all_insn[j]);
+ printf("0x%" PRIx64 ":\t%s\t\t%s // insn-ID: %u, insn-mnem: %s\n",
+ in->address, in->mnemonic, in->op_str,
+ in->id, cs_insn_name(handle, in->id));
+
+ // print implicit registers used by this instruction
+ detail = in->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");
+ }
+ }
+
+ // print out the next offset, after the last insn
+ printf("0x%" PRIx64 ":\n", all_insn[j-1].address + all_insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(all_insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex(platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_evm.c b/capstone/tests/test_evm.c
new file mode 100644
index 000000000..7fd0aa30f
--- /dev/null
+++ b/capstone/tests/test_evm.c
@@ -0,0 +1,126 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2018-2019 */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+static csh handle;
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static void print_insn_detail(csh cs_handle, cs_insn *ins)
+{
+ cs_evm *evm;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ evm = &(ins->detail->evm);
+
+ if (evm->pop)
+ printf("\tPop: %u\n", evm->pop);
+
+ if (evm->push)
+ printf("\tPush: %u\n", evm->push);
+
+ if (evm->fee)
+ printf("\tGas fee: %u\n", evm->fee);
+
+ if (ins->detail->groups_count) {
+ int j;
+
+ printf("\tGroups: ");
+ for(j = 0; j < ins->detail->groups_count; j++) {
+ printf("%s ", cs_group_name(handle, ins->detail->groups[j]));
+ }
+ printf("\n");
+ }
+}
+
+static void test()
+{
+#define EVM_CODE "\x60\x61\x50"
+
+ struct platform platforms[] = {
+ {
+ CS_ARCH_EVM,
+ 0,
+ (unsigned char *)EVM_CODE,
+ sizeof(EVM_CODE) - 1,
+ "EVM"
+ },
+ };
+
+ uint64_t address = 0x80001000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(handle, &insn[j]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
+
diff --git a/capstone/tests/test_iter.c b/capstone/tests/test_iter.c
new file mode 100644
index 000000000..e3edfb0c8
--- /dev/null
+++ b/capstone/tests/test_iter.c
@@ -0,0 +1,337 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
+
+// This sample code demonstrates the APIs cs_malloc() & cs_disasm_iter().
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const 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()
+{
+#ifdef CAPSTONE_HAS_X86
+#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_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00"
+#endif
+#ifdef CAPSTONE_HAS_ARM
+#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"
+#endif
+#ifdef CAPSTONE_HAS_MIPS
+#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_CODE2 "\x56\x34\x21\x34\xc2\x17\x01\x00"
+#endif
+#ifdef CAPSTONE_HAS_ARM64
+#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"
+#endif
+#ifdef CAPSTONE_HAS_POWERPC
+#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"
+#endif
+#ifdef CAPSTONE_HAS_SPARC
+#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"
+#endif
+#ifdef CAPSTONE_HAS_SYSZ
+#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"
+#endif
+#ifdef CAPSTONE_HAS_XCORE
+#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"
+#endif
+#ifdef CAPSTONE_HAS_M680X
+#define M680X_CODE "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39"
+#endif
+#ifdef CAPSTONE_HAS_MOS65XX
+#define MOS65XX_CODE "\x0d\x34\x12\x08\x09\xFF\x10\x80\x20\x00\x00\x98"
+#endif
+#define EBPF_CODE "\x97\x09\x00\x00\x37\x13\x03\x00\xdc\x02\x00\x00\x20\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\xdb\x3a\x00\x01\x00\x00\x00\x00\x84\x02\x00\x00\x00\x00\x00\x00\x6d\x33\x17\x02\x00\x00\x00\x00"
+
+#ifdef CAPSTONE_HAS_RISCV
+#define RISCV_CODE32 "\x37\x34\x00\x00\x97\x82\x00\x00\xef\x00\x80\x00\xef\xf0\x1f\xff\xe7\x00\x45\x00\xe7\x00\xc0\xff\x63\x05\x41\x00\xe3\x9d\x61\xfe\x63\xca\x93\x00\x63\x53\xb5\x00\x63\x65\xd6\x00\x63\x76\xf7\x00\x03\x88\x18\x00\x03\x99\x49\x00\x03\xaa\x6a\x00\x03\xcb\x2b\x01\x03\xdc\x8c\x01\x23\x86\xad\x03\x23\x9a\xce\x03\x23\x8f\xef\x01\x93\x00\xe0\x00\x13\xa1\x01\x01\x13\xb2\x02\x7d\x13\xc3\x03\xdd\x13\xe4\xc4\x12\x13\xf5\x85\x0c\x13\x96\xe6\x01\x13\xd7\x97\x01\x13\xd8\xf8\x40\x33\x89\x49\x01\xb3\x0a\x7b\x41\x33\xac\xac\x01\xb3\x3d\xde\x01\x33\xd2\x62\x40\xb3\x43\x94\x00\x33\xe5\xc5\x00\xb3\x76\xf7\x00\xb3\x54\x39\x01\xb3\x50\x31\x00\x33\x9f\x0f\x00"
+#define RISCV_CODE64 "\x13\x04\xa8\x7a" // aaa80413
+#endif
+
+struct platform platforms[] = {
+#ifdef CAPSTONE_HAS_X86
+ {
+ 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)"
+ },
+#endif
+#ifdef CAPSTONE_HAS_ARM
+ {
+ 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"
+ },
+#endif
+#ifdef CAPSTONE_HAS_MIPS
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN),
+ (unsigned char *)MIPS_CODE,
+ sizeof(MIPS_CODE) - 1,
+ "MIPS-32 (Big-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS64 + CS_MODE_LITTLE_ENDIAN),
+ (unsigned char *)MIPS_CODE2,
+ sizeof(MIPS_CODE2) - 1,
+ "MIPS-64-EL (Little-endian)"
+ },
+#endif
+#ifdef CAPSTONE_HAS_ARM64
+ {
+ CS_ARCH_ARM64,
+ CS_MODE_ARM,
+ (unsigned char *)ARM64_CODE,
+ sizeof(ARM64_CODE) - 1,
+ "ARM-64"
+ },
+#endif
+#ifdef CAPSTONE_HAS_POWERPC
+ {
+ CS_ARCH_PPC,
+ CS_MODE_BIG_ENDIAN,
+ (unsigned char*)PPC_CODE,
+ sizeof(PPC_CODE) - 1,
+ "PPC-64"
+ },
+#endif
+#ifdef CAPSTONE_HAS_SPARC
+ {
+ 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"
+ },
+#endif
+#ifdef CAPSTONE_HAS_SYSZ
+ {
+ CS_ARCH_SYSZ,
+ (cs_mode)0,
+ (unsigned char*)SYSZ_CODE,
+ sizeof(SYSZ_CODE) - 1,
+ "SystemZ"
+ },
+#endif
+#ifdef CAPSTONE_HAS_XCORE
+ {
+ CS_ARCH_XCORE,
+ (cs_mode)0,
+ (unsigned char*)XCORE_CODE,
+ sizeof(XCORE_CODE) - 1,
+ "XCore"
+ },
+#endif
+#ifdef CAPSTONE_HAS_M680X
+ {
+ CS_ARCH_M680X,
+ (cs_mode)CS_MODE_M680X_6809,
+ (unsigned char*)M680X_CODE,
+ sizeof(M680X_CODE) - 1,
+ "M680X_6809"
+ },
+#endif
+#ifdef CAPSTONE_HAS_MOS65XX
+ {
+ CS_ARCH_MOS65XX,
+ (cs_mode)CS_MODE_LITTLE_ENDIAN,
+ (unsigned char*)MOS65XX_CODE,
+ sizeof(MOS65XX_CODE) - 1,
+ "MOS65XX"
+ },
+#endif
+#ifdef CAPSTONE_HAS_BPF
+ {
+ CS_ARCH_BPF,
+ CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED,
+ (unsigned char*) EBPF_CODE,
+ sizeof(EBPF_CODE) - 1,
+ "eBPF"
+ },
+#endif
+#ifdef CAPSTONE_HAS_RISCV
+ {
+ CS_ARCH_RISCV,
+ CS_MODE_RISCV32,
+ (unsigned char *)RISCV_CODE32,
+ sizeof(RISCV_CODE32) - 1,
+ "RISCV32"
+ },
+ {
+ CS_ARCH_RISCV,
+ CS_MODE_RISCV64,
+ (unsigned char *)RISCV_CODE64,
+ sizeof(RISCV_CODE64) - 1,
+ "RISCV64"
+ },
+#endif
+ };
+
+ 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);
+ abort();
+ }
+
+ 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;
+}
diff --git a/capstone/tests/test_m680x.c b/capstone/tests/test_m680x.c
new file mode 100644
index 000000000..aa1f57272
--- /dev/null
+++ b/capstone/tests/test_m680x.c
@@ -0,0 +1,396 @@
+/* Capstone Disassembler Engine */
+/* M680X Backend by Wolfgang Schwotzer <wolfgang.schwotzer@gmx.net> 2017 */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+#define WITH_DETAILS
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+
+ for (c = str; c < str + len; c++)
+ printf("0x%02x ", *c & 0xff);
+
+ printf("\n");
+}
+
+static void print_string_hex_short(unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ for (c = str; c < str + len; c++)
+ printf("%02x", *c & 0xff);
+}
+
+static const char *s_access[] = {
+ "UNCHANGED", "READ", "WRITE", "READ | WRITE",
+};
+
+static void print_read_write_regs(csh handle, cs_detail *detail)
+{
+ int i;
+
+ if (detail->regs_read_count > 0) {
+ printf("\tRegisters read:");
+
+ for (i = 0; i < detail->regs_read_count; ++i)
+ printf(" %s",
+ cs_reg_name(handle, detail->regs_read[i]));
+
+ printf("\n");
+ }
+
+ if (detail->regs_write_count > 0) {
+ printf("\tRegisters modified:");
+
+ for (i = 0; i < detail->regs_write_count; ++i)
+ printf(" %s",
+ cs_reg_name(handle, detail->regs_write[i]));
+
+ printf("\n");
+ }
+}
+
+static void print_insn_detail(csh handle, cs_insn *insn)
+{
+ cs_detail *detail = insn->detail;
+ cs_m680x *m680x = NULL;
+ int i;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (detail == NULL)
+ return;
+
+ m680x = &detail->m680x;
+
+ if (m680x->op_count)
+ printf("\top_count: %u\n", m680x->op_count);
+
+ for (i = 0; i < m680x->op_count; i++) {
+ cs_m680x_op *op = &(m680x->operands[i]);
+ const char *comment;
+
+ switch ((int)op->type) {
+ default:
+ break;
+
+ case M680X_OP_REGISTER:
+ comment = "";
+
+ if ((i == 0 && (m680x->flags &
+ M680X_FIRST_OP_IN_MNEM)) ||
+ ((i == 1 && (m680x->flags &
+ M680X_SECOND_OP_IN_MNEM))))
+ comment = " (in mnemonic)";
+
+ printf("\t\toperands[%u].type: REGISTER = %s%s\n", i,
+ cs_reg_name(handle, op->reg), comment);
+ break;
+
+ case M680X_OP_CONSTANT:
+ printf("\t\toperands[%u].type: CONSTANT = %u\n", i,
+ op->const_val);
+ break;
+
+ case M680X_OP_IMMEDIATE:
+ printf("\t\toperands[%u].type: IMMEDIATE = #%d\n", i,
+ op->imm);
+ break;
+
+ case M680X_OP_DIRECT:
+ printf("\t\toperands[%u].type: DIRECT = 0x%02x\n", i,
+ op->direct_addr);
+ break;
+
+ case M680X_OP_EXTENDED:
+ printf("\t\toperands[%u].type: EXTENDED %s = 0x%04x\n",
+ i, op->ext.indirect ? "INDIRECT" : "",
+ op->ext.address);
+ break;
+
+ case M680X_OP_RELATIVE:
+ printf("\t\toperands[%u].type: RELATIVE = 0x%04x\n", i,
+ op->rel.address);
+ break;
+
+ case M680X_OP_INDEXED:
+ printf("\t\toperands[%u].type: INDEXED%s\n", i,
+ (op->idx.flags & M680X_IDX_INDIRECT) ?
+ " INDIRECT" : "");
+
+ if (op->idx.base_reg != M680X_REG_INVALID)
+ printf("\t\t\tbase register: %s\n",
+ cs_reg_name(handle, op->idx.base_reg));
+
+ if (op->idx.offset_reg != M680X_REG_INVALID)
+ printf("\t\t\toffset register: %s\n",
+ cs_reg_name(handle, op->idx.offset_reg));
+
+ if ((op->idx.offset_bits != 0) &&
+ (op->idx.offset_reg == M680X_REG_INVALID) &&
+ !op->idx.inc_dec) {
+ printf("\t\t\toffset: %d\n", op->idx.offset);
+
+ if (op->idx.base_reg == M680X_REG_PC)
+ printf("\t\t\toffset address: 0x%x\n",
+ op->idx.offset_addr);
+
+ printf("\t\t\toffset bits: %u\n",
+ op->idx.offset_bits);
+ }
+
+ if (op->idx.inc_dec) {
+ const char *post_pre = op->idx.flags &
+ M680X_IDX_POST_INC_DEC ? "post" : "pre";
+ const char *inc_dec = (op->idx.inc_dec > 0) ?
+ "increment" : "decrement";
+
+ printf("\t\t\t%s %s: %d\n", post_pre, inc_dec,
+ abs(op->idx.inc_dec));
+ }
+
+ break;
+ }
+
+ if (op->size != 0)
+ printf("\t\t\tsize: %u\n", op->size);
+
+ if (op->access != CS_AC_INVALID)
+ printf("\t\t\taccess: %s\n", s_access[op->access]);
+
+ }
+
+ print_read_write_regs(handle, detail);
+
+ if (detail->groups_count) {
+ printf("\tgroups_count: %u\n", detail->groups_count);
+ }
+
+ printf("\n");
+}
+
+static bool consistency_checks()
+{
+ return true;
+}
+
+static void test()
+{
+#define M6800_CODE \
+ "\x01\x09\x36\x64\x7f\x74\x10\x00\x90\x10\xA4\x10\xb6\x10\x00\x39"
+
+#define M6801_CODE \
+ "\x04\x05\x3c\x3d\x38\x93\x10\xec\x10\xed\x10\x39"
+
+#define M6805_CODE \
+ "\x04\x7f\x00\x17\x22\x28\x00\x2e\x00\x40\x42\x5a\x70\x8e\x97\x9c" \
+ "\xa0\x15\xad\x00\xc3\x10\x00\xda\x12\x34\xe5\x7f\xfe"
+
+#define M6808_CODE \
+ "\x31\x22\x00\x35\x22\x45\x10\x00\x4b\x00\x51\x10\x52\x5e\x22\x62" \
+ "\x65\x12\x34\x72\x84\x85\x86\x87\x8a\x8b\x8c\x94\x95\xa7\x10\xaf\x10" \
+ "\x9e\x60\x7f\x9e\x6b\x7f\x00\x9e\xd6\x10\x00\x9e\xe6\x7f"
+
+#define HCS08_CODE \
+ "\x32\x10\x00\x9e\xae\x9e\xce\x7f\x9e\xbe\x10\x00\x9e\xfe\x7f" \
+ "\x3e\x10\x00\x9e\xf3\x7f\x96\x10\x00\x9e\xff\x7f\x82"
+
+#define M6811_CODE \
+ "\x02\x03\x12\x7f\x10\x00\x13\x99\x08\x00\x14\x7f\x02\x15\x7f\x01" \
+ "\x1e\x7f\x20\x00\x8f\xcf" \
+ "\x18\x08\x18\x30\x18\x3c\x18\x67\x18\x8c\x10\x00\x18\x8f" \
+ "\x18\xce\x10\x00\x18\xff\x10\x00" \
+ "\x1a\xa3\x7f\x1a\xac\x1a\xee\x7f\x1a\xef\x7f\xcd\xac\x7f"
+
+#define CPU12_CODE \
+ "\x00\x04\x01\x00\x0c\x00\x80\x0e\x00\x80\x00\x11\x1e\x10\x00\x80\x00" \
+ "\x3b\x4a\x10\x00\x04\x4b\x01\x04\x4f\x7f\x80\x00\x8f\x10\x00\xb7\x52" \
+ "\xb7\xb1\xa6\x67\xa6\xfe\xa6\xf7\x18\x02\xe2\x30\x39\xe2\x10\x00" \
+ "\x18\x0c\x30\x39\x10\x00\x18\x11\x18\x12\x10\x00\x18\x19\x00\x18\x1e\x00" \
+ "\x18\x3e\x18\x3f\x00"
+
+#define HD6301_CODE \
+ "\x6b\x10\x00\x71\x10\x00\x72\x10\x10\x39"
+
+#define M6809_CODE \
+ "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81" \
+ "\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00" \
+ "\x11\xac\x99\x10\x00\x39" \
+ \
+ "\xA6\x07\xA6\x27\xA6\x47\xA6\x67\xA6\x0F\xA6\x10" \
+ "\xA6\x80\xA6\x81\xA6\x82\xA6\x83\xA6\x84\xA6\x85\xA6\x86" \
+ "\xA6\x88\x7F\xA6\x88\x80\xA6\x89\x7F\xFF\xA6\x89\x80\x00" \
+ "\xA6\x8B\xA6\x8C\x10\xA6\x8D\x10\x00" \
+ \
+ "\xA6\x91\xA6\x93\xA6\x94\xA6\x95\xA6\x96" \
+ "\xA6\x98\x7F\xA6\x98\x80\xA6\x99\x7F\xFF\xA6\x99\x80\x00" \
+ "\xA6\x9B\xA6\x9C\x10\xA6\x9D\x10\x00\xA6\x9F\x10\x00"
+
+#define HD6309_CODE \
+ "\x01\x10\x10\x62\x10\x10\x7b\x10\x10\x00\xcd\x49\x96\x02\xd2" \
+ "\x10\x30\x23\x10\x38\x10\x3b\x10\x53\x10\x5d" \
+ "\x11\x30\x43\x10\x11\x37\x25\x10\x11\x38\x12\x11\x39\x23\x11\x3b\x34" \
+ "\x11\x8e\x10\x00\x11\xaf\x10\x11\xab\x10\x11\xf6\x80\x00"
+
+ struct platform platforms[] = {
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_6301),
+ (unsigned char *)HD6301_CODE,
+ sizeof(HD6301_CODE) - 1,
+ "M680X_HD6301",
+ },
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_6309),
+ (unsigned char *)HD6309_CODE,
+ sizeof(HD6309_CODE) - 1,
+ "M680X_HD6309",
+ },
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_6800),
+ (unsigned char *)M6800_CODE,
+ sizeof(M6800_CODE) - 1,
+ "M680X_M6800",
+ },
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_6801),
+ (unsigned char *)M6801_CODE,
+ sizeof(M6801_CODE) - 1,
+ "M680X_M6801",
+ },
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_6805),
+ (unsigned char *)M6805_CODE,
+ sizeof(M6805_CODE) - 1,
+ "M680X_M68HC05",
+ },
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_6808),
+ (unsigned char *)M6808_CODE,
+ sizeof(M6808_CODE) - 1,
+ "M680X_M68HC08",
+ },
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_6809),
+ (unsigned char *)M6809_CODE,
+ sizeof(M6809_CODE) - 1,
+ "M680X_M6809",
+ },
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_6811),
+ (unsigned char *)M6811_CODE,
+ sizeof(M6811_CODE) - 1,
+ "M680X_M68HC11",
+ },
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_CPU12),
+ (unsigned char *)CPU12_CODE,
+ sizeof(CPU12_CODE) - 1,
+ "M680X_CPU12",
+ },
+ {
+ CS_ARCH_M680X,
+ (cs_mode)(CS_MODE_M680X_HCS08),
+ (unsigned char *)HCS08_CODE,
+ sizeof(HCS08_CODE) - 1,
+ "M680X_HCS08",
+ },
+ };
+
+ uint64_t address = 0x1000;
+ csh handle;
+ cs_insn *insn;
+ int i;
+ size_t count;
+ const char *nine_spaces = " ";
+
+ if (!consistency_checks())
+ abort();
+
+ for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode,
+ &handle);
+
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n",
+ err);
+ abort();
+ }
+
+#ifdef WITH_DETAILS
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+#endif
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size,
+ address, 0, &insn);
+
+ if (count) {
+ size_t j;
+
+ printf("********************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code: ", platforms[i].code,
+ platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ int slen;
+ printf("0x%04x: ", (uint16_t)insn[j].address);
+ print_string_hex_short(insn[j].bytes,
+ insn[j].size);
+ printf("%.*s", 1 + ((5 - insn[j].size) * 2),
+ nine_spaces);
+ printf("%s", insn[j].mnemonic);
+ slen = (int)strlen(insn[j].mnemonic);
+ printf("%.*s", 1 + (5 - slen), nine_spaces);
+ printf("%s\n", insn[j].op_str);
+#ifdef WITH_DETAILS
+ print_insn_detail(handle, &insn[j]);
+#endif
+ }
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ }
+ else {
+ printf("********************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code,
+ platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_m68k.c b/capstone/tests/test_m68k.c
new file mode 100644
index 000000000..aff11dfac
--- /dev/null
+++ b/capstone/tests/test_m68k.c
@@ -0,0 +1,217 @@
+/* Capstone Disassembler Engine */
+/* By Daniel Collin, 2013-2019 */
+
+#include <stdio.h>
+#include <assert.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char* code;
+ size_t size;
+ const char* comment;
+};
+
+static csh handle;
+
+static void print_string_hex(const char* comment, unsigned char* str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+const char* s_addressing_modes[] = {
+ "<invalid mode>",
+
+ "Register Direct - Data",
+ "Register Direct - Address",
+
+ "Register Indirect - Address",
+ "Register Indirect - Address with Postincrement",
+ "Register Indirect - Address with Predecrement",
+ "Register Indirect - Address with Displacement",
+
+ "Address Register Indirect With Index - 8-bit displacement",
+ "Address Register Indirect With Index - Base displacement",
+
+ "Memory indirect - Postindex",
+ "Memory indirect - Preindex",
+
+ "Program Counter Indirect - with Displacement",
+
+ "Program Counter Indirect with Index - with 8-Bit Displacement",
+ "Program Counter Indirect with Index - with Base Displacement",
+
+ "Program Counter Memory Indirect - Postindexed",
+ "Program Counter Memory Indirect - Preindexed",
+
+ "Absolute Data Addressing - Short",
+ "Absolute Data Addressing - Long",
+ "Immediate value",
+};
+
+static void print_read_write_regs(cs_detail* detail)
+{
+ int i;
+
+ for (i = 0; i < detail->regs_read_count; ++i)
+ {
+ uint16_t reg_id = detail->regs_read[i];
+ const char* reg_name = cs_reg_name(handle, reg_id);
+ printf("\treading from reg: %s\n", reg_name);
+ }
+
+ for (i = 0; i < detail->regs_write_count; ++i)
+ {
+ uint16_t reg_id = detail->regs_write[i];
+ const char* reg_name = cs_reg_name(handle, reg_id);
+ printf("\twriting to reg: %s\n", reg_name);
+ }
+}
+
+static void print_insn_detail(cs_insn *ins)
+{
+ cs_m68k* m68k;
+ cs_detail* detail;
+ int i;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ detail = ins->detail;
+ m68k = &detail->m68k;
+ if (m68k->op_count)
+ printf("\top_count: %u\n", m68k->op_count);
+
+ print_read_write_regs(detail);
+
+ printf("\tgroups_count: %u\n", detail->groups_count);
+
+ for (i = 0; i < m68k->op_count; i++) {
+ cs_m68k_op* op = &(m68k->operands[i]);
+
+ switch((int)op->type) {
+ default:
+ break;
+ case M68K_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ break;
+ case M68K_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%x\n", i, (int)op->imm);
+ break;
+ case M68K_OP_MEM:
+ printf("\t\toperands[%u].type: MEM\n", i);
+ if (op->mem.base_reg != M68K_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.base_reg));
+ if (op->mem.index_reg != M68K_REG_INVALID) {
+ printf("\t\t\toperands[%u].mem.index: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.index_reg));
+ printf("\t\t\toperands[%u].mem.index: size = %c\n",
+ i, op->mem.index_size ? 'l' : 'w');
+ }
+ if (op->mem.disp != 0)
+ printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
+ if (op->mem.scale != 0)
+ printf("\t\t\toperands[%u].mem.scale: %d\n", i, op->mem.scale);
+
+ printf("\t\taddress mode: %s\n", s_addressing_modes[op->address_mode]);
+ break;
+ case M68K_OP_FP_SINGLE:
+ printf("\t\toperands[%u].type: FP_SINGLE\n", i);
+ printf("\t\t\toperands[%u].simm: %f\n", i, op->simm);
+ break;
+ case M68K_OP_FP_DOUBLE:
+ 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);
+ break;
+ case M68K_OP_REG_PAIR:
+ printf("\t\toperands[%u].type: REG_PAIR = (%s, %s)\n", i,
+ cs_reg_name(handle, op->reg_pair.reg_0),
+ cs_reg_name(handle, op->reg_pair.reg_1));
+ break;
+ }
+ }
+
+ printf("\n");
+}
+
+static void test()
+{
+#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,
+ (cs_mode)(CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040),
+ (unsigned char*)M68K_CODE,
+ sizeof(M68K_CODE) - 1,
+ "M68K",
+ },
+ };
+
+ uint64_t address = 0x01000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code: ", platforms[i].code, platforms[i].size);
+ 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]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_mips.c b/capstone/tests/test_mips.c
new file mode 100644
index 000000000..e5c5a400c
--- /dev/null
+++ b/capstone/tests/test_mips.c
@@ -0,0 +1,175 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static csh handle;
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static void print_insn_detail(cs_insn *ins)
+{
+ int i;
+ cs_mips *mips;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ mips = &(ins->detail->mips);
+ if (mips->op_count)
+ printf("\top_count: %u\n", mips->op_count);
+
+ for (i = 0; i < mips->op_count; i++) {
+ cs_mips_op *op = &(mips->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case MIPS_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ break;
+ case MIPS_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
+ break;
+ case MIPS_OP_MEM:
+ printf("\t\toperands[%u].type: MEM\n", i);
+ if (op->mem.base != MIPS_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.base));
+ if (op->mem.disp != 0)
+ printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp);
+
+ break;
+ }
+
+ }
+
+ printf("\n");
+}
+
+static void test()
+{
+#define MIPS_CODE "\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56"
+#define MIPS_CODE2 "\x56\x34\x21\x34\xc2\x17\x01\x00"
+#define MIPS_32R6M "\x00\x07\x00\x07\x00\x11\x93\x7c\x01\x8c\x8b\x7c\x00\xc7\x48\xd0"
+#define MIPS_32R6 "\xec\x80\x00\x19\x7c\x43\x22\xa0"
+#define MIPS_64SD "\x70\x00\xb2\xff"
+
+ struct platform platforms[] = {
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS32 | CS_MODE_BIG_ENDIAN),
+ (unsigned char *)MIPS_CODE,
+ sizeof(MIPS_CODE) - 1,
+ "MIPS-32 (Big-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS64 | CS_MODE_LITTLE_ENDIAN),
+ (unsigned char *)MIPS_CODE2,
+ sizeof(MIPS_CODE2) - 1,
+ "MIPS-64-EL (Little-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS32R6 | CS_MODE_MICRO | CS_MODE_BIG_ENDIAN),
+ (unsigned char*)MIPS_32R6M,
+ sizeof(MIPS_32R6M) - 1,
+ "MIPS-32R6 | Micro (Big-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS32R6 | CS_MODE_BIG_ENDIAN),
+ (unsigned char*)MIPS_32R6,
+ sizeof(MIPS_32R6) - 1,
+ "MIPS-32R6 (Big-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS64 | CS_MODE_MIPS2 | CS_MODE_LITTLE_ENDIAN),
+ (unsigned char *)MIPS_64SD,
+ sizeof(MIPS_64SD) - 1,
+ "MIPS-64-EL + Mips II (Little-endian)"
+ },
+ {
+ CS_ARCH_MIPS,
+ (cs_mode)(CS_MODE_MIPS64 | CS_MODE_LITTLE_ENDIAN),
+ (unsigned char *)MIPS_64SD,
+ sizeof(MIPS_64SD) - 1,
+ "MIPS-64-EL (Little-endian)"
+ },
+ };
+
+ uint64_t address = 0x1000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(&insn[j]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_mos65xx.c b/capstone/tests/test_mos65xx.c
new file mode 100644
index 000000000..cc31de803
--- /dev/null
+++ b/capstone/tests/test_mos65xx.c
@@ -0,0 +1,230 @@
+/* Capstone Disassembler Engine */
+/* By Sebastian Macke <sebastian@macke.de>, 2018 */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static csh handle;
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf(" 0x%02x", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static const char *get_am_name(mos65xx_address_mode mode)
+{
+ switch(mode) {
+ default:
+ case MOS65XX_AM_NONE:
+ return "No address mode";
+ case MOS65XX_AM_IMP:
+ return "implied";
+ case MOS65XX_AM_ACC:
+ return "accumulator";
+ case MOS65XX_AM_IMM:
+ return "immediate value";
+ case MOS65XX_AM_REL:
+ return "relative";
+ case MOS65XX_AM_INT:
+ return "interrupt signature";
+ case MOS65XX_AM_BLOCK:
+ return "block move";
+ case MOS65XX_AM_ZP:
+ return "zero page";
+ case MOS65XX_AM_ZP_X:
+ return "zero page indexed with x";
+ case MOS65XX_AM_ZP_Y:
+ return "zero page indexed with y";
+ case MOS65XX_AM_ZP_REL:
+ return "relative bit branch";
+ case MOS65XX_AM_ZP_IND:
+ return "zero page indirect";
+ case MOS65XX_AM_ZP_X_IND:
+ return "zero page indexed with x indirect";
+ case MOS65XX_AM_ZP_IND_Y:
+ return "zero page indirect indexed with y";
+ case MOS65XX_AM_ZP_IND_LONG:
+ return "zero page indirect long";
+ case MOS65XX_AM_ZP_IND_LONG_Y:
+ return "zero page indirect long indexed with y";
+ case MOS65XX_AM_ABS:
+ return "absolute";
+ case MOS65XX_AM_ABS_X:
+ return "absolute indexed with x";
+ case MOS65XX_AM_ABS_Y:
+ return "absolute indexed with y";
+ case MOS65XX_AM_ABS_IND:
+ return "absolute indirect";
+ case MOS65XX_AM_ABS_X_IND:
+ return "absolute indexed with x indirect";
+ case MOS65XX_AM_ABS_IND_LONG:
+ return "absolute indirect long";
+ case MOS65XX_AM_ABS_LONG:
+ return "absolute long";
+ case MOS65XX_AM_ABS_LONG_X:
+ return "absolute long indexed with x";
+ case MOS65XX_AM_SR:
+ return "stack relative";
+ case MOS65XX_AM_SR_IND_Y:
+ return "stack relative indirect indexed with y";
+ }
+}
+
+
+static void print_insn_detail(cs_insn *ins)
+{
+ cs_mos65xx *mos65xx;
+ int i;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ mos65xx = &(ins->detail->mos65xx);
+
+ // printf("insn_detail\n");
+ printf("\taddress mode: %s\n", get_am_name(mos65xx->am));
+ printf("\tmodifies flags: %s\n", mos65xx->modifies_flags ? "true": "false");
+
+ if (mos65xx->op_count)
+ printf("\top_count: %u\n", mos65xx->op_count);
+
+ for (i = 0; i < mos65xx->op_count; i++) {
+ cs_mos65xx_op *op = &(mos65xx->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case MOS65XX_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ break;
+ case MOS65XX_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%x\n", i, op->imm);
+ break;
+ case MOS65XX_OP_MEM:
+ printf("\t\toperands[%u].type: MEM = 0x%x\n", i, op->mem);
+ break;
+ }
+ }
+}
+
+static void test()
+{
+#define M6502_CODE "\xa1\x12\xa5\x12\xa9\x12\xad\x34\x12\xb1\x12\xb5\x12\xb9\x34\x12\xbd\x34\x12" \
+ "\x0d\x34\x12\x00\x81\x87\x6c\x01\x00\x85\xFF\x10\x00\x19\x42\x42\x00\x49\x42"
+
+#define M65C02_CODE "\x1a\x3a" \
+ "\x02\x12\x03\x5c\x34\x12"
+
+#define MW65C02_CODE \
+ "\x07\x12\x27\x12\x47\x12\x67\x12\x87\x12\xa7\x12\xc7\x12\xe7\x12" \
+ "\x0f\x12\xfd\x4f\x12\xfd\x8f\x12\xfd\xcf\x12\xfd"
+
+#define M65816_CODE \
+ "\xa9\x34\x12" "\xad\x34\x12" "\xbd\x34\x12" "\xb9\x34\x12" \
+ "\xaf\x56\x34\x12" "\xbf\x56\x34\x12" \
+ "\xa5\x12" "\xb5\x12" "\xb2\x12" "\xa1\x12" "\xb1\x12" "\xa7\x12" "\xb7\x12" \
+ "\xa3\x12" "\xb3\x12" \
+ "\xc2\x00" "\xe2\x00" "\x54\x34\x12" "\x44\x34\x12" "\x02\x12"
+
+ struct platform platforms[] = {
+ {
+ CS_ARCH_MOS65XX,
+ (cs_mode)(CS_MODE_MOS65XX_6502),
+ (unsigned char *)M6502_CODE,
+ sizeof(M6502_CODE) - 1,
+ "MOS65XX_6502"
+ },
+ {
+ CS_ARCH_MOS65XX,
+ (cs_mode)(CS_MODE_MOS65XX_65C02),
+ (unsigned char *)M65C02_CODE,
+ sizeof(M65C02_CODE) - 1,
+ "MOS65XX_65C02"
+ },
+ {
+ CS_ARCH_MOS65XX,
+ (cs_mode)(CS_MODE_MOS65XX_W65C02),
+ (unsigned char *)MW65C02_CODE,
+ sizeof(MW65C02_CODE) - 1,
+ "MOS65XX_W65C02"
+ },
+ {
+ CS_ARCH_MOS65XX,
+ (cs_mode)(CS_MODE_MOS65XX_65816_LONG_MX),
+ (unsigned char *)M65816_CODE,
+ sizeof(M65816_CODE) - 1,
+ "MOS65XX_65816 (long m/x)"
+ },
+ };
+
+ uint64_t address = 0x1000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u (%s)\n", err, cs_strerror(err));
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+ cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_MOTOROLA);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+
+ if (count) {
+ size_t j;
+
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(&insn[j]);
+ puts("");
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+ return 0;
+}
diff --git a/capstone/tests/test_ppc.c b/capstone/tests/test_ppc.c
new file mode 100644
index 000000000..43da000e2
--- /dev/null
+++ b/capstone/tests/test_ppc.c
@@ -0,0 +1,186 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
+
+#include <stdio.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static csh handle;
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static const char* get_bc_name(int bc)
+{
+ switch(bc) {
+ default:
+ case PPC_BC_INVALID:
+ return ("invalid");
+ case PPC_BC_LT:
+ return ("lt");
+ case PPC_BC_LE:
+ return ("le");
+ case PPC_BC_EQ:
+ return ("eq");
+ case PPC_BC_GE:
+ return ("ge");
+ case PPC_BC_GT:
+ return ("gt");
+ case PPC_BC_NE:
+ return ("ne");
+ case PPC_BC_UN:
+ return ("un");
+ case PPC_BC_NU:
+ return ("nu");
+ case PPC_BC_SO:
+ return ("so");
+ case PPC_BC_NS:
+ return ("ns");
+ }
+}
+
+static void print_insn_detail(cs_insn *ins)
+{
+ cs_ppc *ppc;
+ int i;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ ppc = &(ins->detail->ppc);
+ if (ppc->op_count)
+ printf("\top_count: %u\n", ppc->op_count);
+
+ for (i = 0; i < ppc->op_count; i++) {
+ cs_ppc_op *op = &(ppc->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case PPC_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ break;
+ case PPC_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
+ break;
+ case PPC_OP_MEM:
+ printf("\t\toperands[%u].type: MEM\n", i);
+ if (op->mem.base != PPC_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.base));
+ if (op->mem.disp != 0)
+ printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
+
+ break;
+ case PPC_OP_CRX:
+ printf("\t\toperands[%u].type: CRX\n", i);
+ printf("\t\t\toperands[%u].crx.scale: %d\n", i, op->crx.scale);
+ printf("\t\t\toperands[%u].crx.reg: %s\n", i, cs_reg_name(handle, op->crx.reg));
+ printf("\t\t\toperands[%u].crx.cond: %s\n", i, get_bc_name(op->crx.cond));
+ break;
+ }
+ }
+
+ if (ppc->bc != 0)
+ printf("\tBranch code: %u\n", ppc->bc);
+
+ if (ppc->bh != 0)
+ printf("\tBranch hint: %u\n", ppc->bh);
+
+ if (ppc->update_cr0)
+ printf("\tUpdate-CR0: True\n");
+
+ printf("\n");
+}
+
+static void test()
+{
+#define PPC_CODE "\x43\x20\x0c\x07\x41\x56\xff\x17\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 PPC_CODE2 "\x10\x60\x2a\x10\x10\x64\x28\x88\x7c\x4a\x5d\x0f"
+
+ struct platform platforms[] = {
+ {
+ CS_ARCH_PPC,
+ CS_MODE_BIG_ENDIAN,
+ (unsigned char*)PPC_CODE,
+ sizeof(PPC_CODE) - 1,
+ "PPC-64",
+ },
+ {
+ CS_ARCH_PPC,
+ (cs_mode)(CS_MODE_BIG_ENDIAN + CS_MODE_QPX),
+ (unsigned char*)PPC_CODE2,
+ sizeof(PPC_CODE2) - 1,
+ "PPC-64 + QPX",
+ },
+ };
+
+ uint64_t address = 0x1000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(&insn[j]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_riscv.c b/capstone/tests/test_riscv.c
new file mode 100644
index 000000000..a9b8b10c8
--- /dev/null
+++ b/capstone/tests/test_riscv.c
@@ -0,0 +1,154 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static csh handle;
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static void print_insn_detail(cs_insn *ins)
+{
+ int i;
+ int n;
+ cs_riscv *riscv;
+ cs_detail *detail;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ riscv = &(ins->detail->riscv);
+ detail = ins->detail;
+ if (riscv->op_count)
+ printf("\top_count: %u\n", riscv->op_count);
+
+ for (i = 0; i < riscv->op_count; i++) {
+ cs_riscv_op *op = &(riscv->operands[i]);
+ switch((int)op->type) {
+ default:
+ printf("\terror in opt_type: %u\n", (int)op->type);
+ break;
+ case RISCV_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ break;
+ case RISCV_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
+ break;
+ case RISCV_OP_MEM:
+ printf("\t\toperands[%u].type: MEM\n", i);
+ if (op->mem.base != RISCV_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.base));
+ if (op->mem.disp != 0)
+ printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp);
+
+ break;
+ }
+
+ }
+
+ //print the groups this instruction belongs 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");
+}
+
+static void test()
+{
+#define RISCV_CODE32 "\x37\x34\x00\x00\x97\x82\x00\x00\xef\x00\x80\x00\xef\xf0\x1f\xff\xe7\x00\x45\x00\xe7\x00\xc0\xff\x63\x05\x41\x00\xe3\x9d\x61\xfe\x63\xca\x93\x00\x63\x53\xb5\x00\x63\x65\xd6\x00\x63\x76\xf7\x00\x03\x88\x18\x00\x03\x99\x49\x00\x03\xaa\x6a\x00\x03\xcb\x2b\x01\x03\xdc\x8c\x01\x23\x86\xad\x03\x23\x9a\xce\x03\x23\x8f\xef\x01\x93\x00\xe0\x00\x13\xa1\x01\x01\x13\xb2\x02\x7d\x13\xc3\x03\xdd\x13\xe4\xc4\x12\x13\xf5\x85\x0c\x13\x96\xe6\x01\x13\xd7\x97\x01\x13\xd8\xf8\x40\x33\x89\x49\x01\xb3\x0a\x7b\x41\x33\xac\xac\x01\xb3\x3d\xde\x01\x33\xd2\x62\x40\xb3\x43\x94\x00\x33\xe5\xc5\x00\xb3\x76\xf7\x00\xb3\x54\x39\x01\xb3\x50\x31\x00\x33\x9f\x0f\x00"
+#define RISCV_CODE64 "\x13\x04\xa8\x7a" // aaa80413
+ struct platform platforms[] = {
+ {
+ CS_ARCH_RISCV,
+ CS_MODE_RISCV32,
+ (unsigned char *)RISCV_CODE32,
+ sizeof(RISCV_CODE32) - 1,
+ "riscv32"
+ },
+ {
+ CS_ARCH_RISCV,
+ CS_MODE_RISCV64,
+ (unsigned char *)RISCV_CODE64,
+ sizeof(RISCV_CODE64) - 1,
+ "riscv64"
+ }
+ };
+
+ uint64_t address = 0x1000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ continue;
+ }
+
+ //To turn on or off the Print Details option
+ //cs_option(handle, CS_OPT_DETAIL, CS_OPT_OFF);
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(&insn[j]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_skipdata.c b/capstone/tests/test_skipdata.c
new file mode 100644
index 000000000..8ab046f10
--- /dev/null
+++ b/capstone/tests/test_skipdata.c
@@ -0,0 +1,184 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+ cs_opt_type opt_type;
+ cs_opt_value opt_value;
+ cs_opt_type opt_skipdata;
+ size_t skipdata;
+};
+
+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");
+}
+
+#ifdef CAPSTONE_HAS_ARM
+static size_t CAPSTONE_API mycallback(const uint8_t *buffer, size_t buffer_size, size_t offset, void *p)
+{
+ // always skip 2 bytes when encountering data
+ return 2;
+}
+#endif
+
+static void test()
+{
+#ifdef CAPSTONE_HAS_X86
+#define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x00\x91\x92"
+#endif
+#define RANDOM_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"
+
+#if defined(CAPSTONE_HAS_X86)
+ cs_opt_skipdata skipdata = {
+ // rename default "data" instruction from ".byte" to "db"
+ "db",
+ };
+#endif
+
+#ifdef CAPSTONE_HAS_ARM
+ cs_opt_skipdata skipdata_callback = {
+ "db",
+ &mycallback,
+ };
+#endif
+
+ struct platform platforms[] = {
+#ifdef CAPSTONE_HAS_X86
+ {
+ CS_ARCH_X86,
+ CS_MODE_32,
+ (unsigned char*)X86_CODE32,
+ sizeof(X86_CODE32) - 1,
+ "X86 32 (Intel syntax) - Skip data",
+ },
+ {
+ CS_ARCH_X86,
+ CS_MODE_32,
+ (unsigned char*)X86_CODE32,
+ sizeof(X86_CODE32) - 1,
+ "X86 32 (Intel syntax) - Skip data with custom mnemonic",
+ CS_OPT_INVALID,
+ CS_OPT_OFF,
+ CS_OPT_SKIPDATA_SETUP,
+ (size_t) &skipdata,
+ },
+#endif
+#ifdef CAPSTONE_HAS_ARM
+ {
+ CS_ARCH_ARM,
+ CS_MODE_ARM,
+ (unsigned char*)RANDOM_CODE,
+ sizeof(RANDOM_CODE) - 1,
+ "Arm - Skip data",
+ },
+ {
+ CS_ARCH_ARM,
+ CS_MODE_ARM,
+ (unsigned char*)RANDOM_CODE,
+ sizeof(RANDOM_CODE) - 1,
+ "Arm - Skip data with callback",
+ CS_OPT_INVALID,
+ CS_OPT_OFF,
+ CS_OPT_SKIPDATA_SETUP,
+ (size_t) &skipdata_callback,
+ },
+#endif
+ };
+
+ csh handle;
+ uint64_t address = 0x1000;
+ cs_insn *insn;
+ cs_err err;
+ int i;
+ size_t count;
+
+ 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);
+ abort();
+ }
+
+ if (platforms[i].opt_type)
+ cs_option(handle, platforms[i].opt_type, platforms[i].opt_value);
+
+ // turn on SKIPDATA mode
+ cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
+ cs_option(handle, platforms[i].opt_skipdata, platforms[i].skipdata);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ print_string_hex(platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t\t%s\n",
+ insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ }
+
+ // print out the next offset, after the last insn
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex(platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+#if 0
+ #define offsetof(st, m) __builtin_offsetof(st, m)
+
+ cs_insn insn;
+ printf("size: %lu\n", sizeof(insn));
+ printf("@id: %lu\n", offsetof(cs_insn, id));
+ printf("@address: %lu\n", offsetof(cs_insn, address));
+ printf("@size: %lu\n", offsetof(cs_insn, size));
+ printf("@bytes: %lu\n", offsetof(cs_insn, bytes));
+ printf("@mnemonic: %lu\n", offsetof(cs_insn, mnemonic));
+ printf("@op_str: %lu\n", offsetof(cs_insn, op_str));
+ printf("@regs_read: %lu\n", offsetof(cs_insn, regs_read));
+ printf("@regs_read_count: %lu\n", offsetof(cs_insn, regs_read_count));
+ printf("@regs_write: %lu\n", offsetof(cs_insn, regs_write));
+ printf("@regs_write_count: %lu\n", offsetof(cs_insn, regs_write_count));
+ printf("@groups: %lu\n", offsetof(cs_insn, groups));
+ printf("@groups_count: %lu\n", offsetof(cs_insn, groups_count));
+ printf("@arch: %lu\n", offsetof(cs_insn, x86));
+#endif
+
+ return 0;
+}
diff --git a/capstone/tests/test_sparc.c b/capstone/tests/test_sparc.c
new file mode 100644
index 000000000..98c39494e
--- /dev/null
+++ b/capstone/tests/test_sparc.c
@@ -0,0 +1,152 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
+
+#include <stdio.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static csh handle;
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static void print_insn_detail(cs_insn *ins)
+{
+ cs_sparc *sparc;
+ int i;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ sparc = &(ins->detail->sparc);
+ if (sparc->op_count)
+ printf("\top_count: %u\n", sparc->op_count);
+
+ for (i = 0; i < sparc->op_count; i++) {
+ cs_sparc_op *op = &(sparc->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case SPARC_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ break;
+ case SPARC_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
+ break;
+ case SPARC_OP_MEM:
+ printf("\t\toperands[%u].type: MEM\n", i);
+ if (op->mem.base != X86_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.base));
+ if (op->mem.index != X86_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.index: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.index));
+ if (op->mem.disp != 0)
+ printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
+
+ break;
+ }
+ }
+
+ if (sparc->cc != 0)
+ printf("\tCode condition: %u\n", sparc->cc);
+
+ if (sparc->hint != 0)
+ printf("\tHint code: %u\n", sparc->hint);
+
+ printf("\n");
+}
+
+static void test()
+{
+#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"
+
+ struct platform platforms[] = {
+ {
+ 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"
+ },
+ };
+
+ uint64_t address = 0x1000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(&insn[j]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_systemz.c b/capstone/tests/test_systemz.c
new file mode 100644
index 000000000..f662247b8
--- /dev/null
+++ b/capstone/tests/test_systemz.c
@@ -0,0 +1,145 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
+
+#include <stdio.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static csh handle;
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static void print_insn_detail(cs_insn *ins)
+{
+ cs_sysz *sysz;
+ int i;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ sysz = &(ins->detail->sysz);
+ if (sysz->op_count)
+ printf("\top_count: %u\n", sysz->op_count);
+
+ for (i = 0; i < sysz->op_count; i++) {
+ cs_sysz_op *op = &(sysz->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case SYSZ_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ break;
+ case SYSZ_OP_ACREG:
+ printf("\t\toperands[%u].type: ACREG = %u\n", i, op->reg);
+ break;
+ case SYSZ_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
+ break;
+ case SYSZ_OP_MEM:
+ printf("\t\toperands[%u].type: MEM\n", i);
+ if (op->mem.base != SYSZ_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.base));
+ if (op->mem.index != SYSZ_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.index: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.index));
+ if (op->mem.length != 0)
+ printf("\t\t\toperands[%u].mem.length: 0x%" PRIx64 "\n", i, op->mem.length);
+ if (op->mem.disp != 0)
+ printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp);
+
+ break;
+ }
+ }
+
+ if (sysz->cc != 0)
+ printf("\tCode condition: %u\n", sysz->cc);
+
+ printf("\n");
+}
+
+static void test()
+{
+#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\xec\x18\x00\x00\xc1\x7f"
+
+ struct platform platforms[] = {
+ {
+ CS_ARCH_SYSZ,
+ CS_MODE_BIG_ENDIAN,
+ (unsigned char*)SYSZ_CODE,
+ sizeof(SYSZ_CODE) - 1,
+ "SystemZ",
+ },
+ };
+
+ uint64_t address = 0x1000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(&insn[j]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_tms320c64x.c b/capstone/tests/test_tms320c64x.c
new file mode 100644
index 000000000..86a6d76d7
--- /dev/null
+++ b/capstone/tests/test_tms320c64x.c
@@ -0,0 +1,193 @@
+/* Capstone Disassembly Engine */
+/* TMS320C64x Backend by Fotis Loukos <me@fotisl.com> 2016 */
+
+#include <stdio.h>
+
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static csh handle;
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static void print_insn_detail(cs_insn *ins)
+{
+ cs_tms320c64x *tms320c64x;
+ int i;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ tms320c64x = &(ins->detail->tms320c64x);
+ if (tms320c64x->op_count)
+ printf("\top_count: %u\n", tms320c64x->op_count);
+
+ for (i = 0; i < tms320c64x->op_count; i++) {
+ cs_tms320c64x_op *op = &(tms320c64x->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case TMS320C64X_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ break;
+ case TMS320C64X_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%x\n", i, op->imm);
+ break;
+ case TMS320C64X_OP_MEM:
+ printf("\t\toperands[%u].type: MEM\n", i);
+ if (op->mem.base != TMS320C64X_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.base));
+ printf("\t\t\toperands[%u].mem.disptype: ", i);
+ if(op->mem.disptype == TMS320C64X_MEM_DISP_INVALID) {
+ printf("Invalid\n");
+ printf("\t\t\toperands[%u].mem.disp: %u\n", i, op->mem.disp);
+ }
+ if(op->mem.disptype == TMS320C64X_MEM_DISP_CONSTANT) {
+ printf("Constant\n");
+ printf("\t\t\toperands[%u].mem.disp: %u\n", i, op->mem.disp);
+ }
+ if(op->mem.disptype == TMS320C64X_MEM_DISP_REGISTER) {
+ printf("Register\n");
+ printf("\t\t\toperands[%u].mem.disp: %s\n", i, cs_reg_name(handle, op->mem.disp));
+ }
+ printf("\t\t\toperands[%u].mem.unit: %u\n", i, op->mem.unit);
+ printf("\t\t\toperands[%u].mem.direction: ", i);
+ if(op->mem.direction == TMS320C64X_MEM_DIR_INVALID)
+ printf("Invalid\n");
+ if(op->mem.direction == TMS320C64X_MEM_DIR_FW)
+ printf("Forward\n");
+ if(op->mem.direction == TMS320C64X_MEM_DIR_BW)
+ printf("Backward\n");
+ printf("\t\t\toperands[%u].mem.modify: ", i);
+ if(op->mem.modify == TMS320C64X_MEM_MOD_INVALID)
+ printf("Invalid\n");
+ if(op->mem.modify == TMS320C64X_MEM_MOD_NO)
+ printf("No\n");
+ if(op->mem.modify == TMS320C64X_MEM_MOD_PRE)
+ printf("Pre\n");
+ if(op->mem.modify == TMS320C64X_MEM_MOD_POST)
+ printf("Post\n");
+ printf("\t\t\toperands[%u].mem.scaled: %u\n", i, op->mem.scaled);
+
+
+ break;
+ case TMS320C64X_OP_REGPAIR:
+ printf("\t\toperands[%u].type: REGPAIR = %s:%s\n", i, cs_reg_name(handle, op->reg + 1), cs_reg_name(handle, op->reg));
+ break;
+ }
+ }
+
+ printf("\tFunctional unit: ");
+ switch(tms320c64x->funit.unit) {
+ case TMS320C64X_FUNIT_D:
+ printf("D%u\n", tms320c64x->funit.side);
+ break;
+ case TMS320C64X_FUNIT_L:
+ printf("L%u\n", tms320c64x->funit.side);
+ break;
+ case TMS320C64X_FUNIT_M:
+ printf("M%u\n", tms320c64x->funit.side);
+ break;
+ case TMS320C64X_FUNIT_S:
+ printf("S%u\n", tms320c64x->funit.side);
+ break;
+ case TMS320C64X_FUNIT_NO:
+ printf("No Functional Unit\n");
+ break;
+ default:
+ printf("Unknown (Unit %u, Side %u)\n", tms320c64x->funit.unit, tms320c64x->funit.side);
+ break;
+ }
+ if(tms320c64x->funit.crosspath == 1)
+ printf("\tCrosspath: 1\n");
+
+ if(tms320c64x->condition.reg != TMS320C64X_REG_INVALID)
+ printf("\tCondition: [%c%s]\n", (tms320c64x->condition.zero == 1) ? '!' : ' ', cs_reg_name(handle, tms320c64x->condition.reg));
+ printf("\tParallel: %s\n", (tms320c64x->parallel == 1) ? "true" : "false");
+
+ printf("\n");
+}
+
+static void test()
+{
+#define TMS320C64X_CODE "\x01\xac\x88\x40\x81\xac\x88\x43\x00\x00\x00\x00\x02\x90\x32\x96\x02\x80\x46\x9e\x05\x3c\x83\xe6\x0b\x0c\x8b\x24"
+
+ struct platform platforms[] = {
+ {
+ CS_ARCH_TMS320C64X,
+ CS_MODE_BIG_ENDIAN,
+ (unsigned char*)TMS320C64X_CODE,
+ sizeof(TMS320C64X_CODE) - 1,
+ "TMS320C64x",
+ },
+ };
+
+ uint64_t address = 0x1000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ continue;
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%"PRIx64":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(&insn[j]);
+ }
+ printf("0x%"PRIx64":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_wasm.c b/capstone/tests/test_wasm.c
new file mode 100644
index 000000000..0f98bdf60
--- /dev/null
+++ b/capstone/tests/test_wasm.c
@@ -0,0 +1,149 @@
+/* Capstone Disassembler Engine */
+/* By Spike <spikeinhouse@gmail.com>, 2018 */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+static csh handle;
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static void print_insn_detail(csh cs_handle, cs_insn *ins)
+{
+ cs_wasm *wasm;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ if (ins->detail->groups_count) {
+ int j;
+
+ printf("\tGroups: ");
+ for(j = 0; j < ins->detail->groups_count; j++) {
+ printf("%s ", cs_group_name(handle, ins->detail->groups[j]));
+ }
+ printf("\n");
+ }
+
+ wasm = &(ins->detail->wasm);
+
+ if (wasm->op_count > 0) {
+ unsigned int i;
+
+ printf("\tOperand count: %u\n", wasm->op_count);
+
+ for (i = 0; i < wasm->op_count; i++) {
+ switch (wasm->operands[i].type) {
+ default:
+ break;
+ case WASM_OP_INT7:
+ printf("\t\tOperand[%u] type: int7\n", i);
+ printf("\t\tOperand[%u] value: %d\n", i, wasm->operands[i].int7);
+ break;
+ case WASM_OP_UINT32:
+ printf("\t\tOperand[%u] type: uint32\n", i);
+ printf("\t\tOperand[%u] value: 0x%x\n", i, wasm->operands[i].uint32);
+ break;
+ case WASM_OP_UINT64:
+ printf("\t\tOperand[%u] type: uint64\n", i);
+ printf("\t\tOperand[%u] value: 0x%" PRIx64 "\n", i, wasm->operands[i].uint64);
+ break;
+ case WASM_OP_VARUINT32:
+ printf("\t\tOperand[%u] type: varuint32\n", i);
+ printf("\t\tOperand[%u] value: 0x%x\n", i, wasm->operands[i].varuint32);
+ break;
+ case WASM_OP_VARUINT64:
+ printf("\t\tOperand[%u] type: varuint64\n", i);
+ printf("\t\tOperand[%u] value: 0x%" PRIx64 "\n", i, wasm->operands[i].varuint64);
+ break;
+ }
+ printf("\t\tOperand[%u] size: %u\n", i, wasm->operands[i].size);
+ }
+ }
+}
+
+static void test()
+{
+#define WASM_CODE "\x20\x00\x20\x01\x41\x20\x10\xc9\x01\x45\x0b"
+ struct platform platforms[] = {
+ {
+ CS_ARCH_WASM,
+ 0,
+ (unsigned char *)WASM_CODE,
+ sizeof(WASM_CODE) - 1,
+ "WASM"
+ },
+ };
+
+ uint64_t address = 0xffff;
+ cs_insn *insn;
+ size_t count;
+ int i;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code: ", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(handle, &insn[j]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code: ", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+ return 0;
+}
+
diff --git a/capstone/tests/test_winkernel.cpp b/capstone/tests/test_winkernel.cpp
new file mode 100644
index 000000000..6413b1a2c
--- /dev/null
+++ b/capstone/tests/test_winkernel.cpp
@@ -0,0 +1,172 @@
+/* Capstone Disassembly Engine */
+/* By Satoshi Tanda <tanda.sat@gmail.com>, 2016 */
+
+#include <ntddk.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "../utils.h" // for cs_snprintf
+
+#ifdef __cplusplus
+}
+#endif
+
+EXTERN_C DRIVER_INITIALIZE DriverEntry;
+
+#pragma warning(push)
+#pragma warning(disable : 4005) // 'identifier' : macro redefinition
+#pragma warning(disable : 4007) // 'main': must be '__cdecl'
+
+// Drivers must protect floating point hardware state. See use of float.
+// Use KeSaveFloatingPointState/KeRestoreFloatingPointState around floating
+// point operations. Display Drivers should use the corresponding Eng... routines.
+#pragma warning(disable : 28110) // Suppress this, as it is false positive.
+
+// "Import" existing tests into this file. All code is encaptured into unique
+// namespace so that the same name does not conflict. Beware that those code
+// is going to be compiled as C++ source file and not C files because this file
+// is C++.
+
+namespace basic {
+#include "test_basic.c"
+} // namespace basic
+
+namespace detail {
+#include "test_detail.c"
+} // namespace detail
+
+namespace skipdata {
+#include "test_skipdata.c"
+} // namespace skipdata
+
+namespace iter {
+#include "test_iter.c"
+} // namespace iter
+
+namespace customized_mnem_ {
+#include "test_customized_mnem.c"
+} // namespace customized_mnem_
+
+namespace arm {
+#include "test_arm.c"
+} // namespace arm
+
+namespace arm64 {
+#include "test_arm64.c"
+} // namespace arm64
+
+namespace mips {
+#include "test_mips.c"
+} // namespace mips
+
+namespace m68k {
+#include "test_m68k.c"
+} // namespace m68k
+
+namespace ppc {
+#include "test_ppc.c"
+} // namespace ppc
+
+namespace sparc {
+#include "test_sparc.c"
+} // namespace sparc
+
+namespace systemz {
+#include "test_systemz.c"
+} // namespace systemz
+
+namespace x86 {
+#include "test_x86.c"
+} // namespace x86
+
+namespace xcore {
+#include "test_xcore.c"
+} // namespace xcore
+
+#pragma warning(pop)
+
+// Exercises all existing regression tests
+static void test()
+{
+ KFLOATING_SAVE float_save;
+ NTSTATUS status;
+
+ // Any of Capstone APIs cannot be called at IRQL higher than DISPATCH_LEVEL
+ // since our malloc implementation using ExAllocatePoolWithTag() is able to
+ // allocate memory only up to the DISPATCH_LEVEL level.
+ NT_ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
+
+ // On a 32bit driver, KeSaveFloatingPointState() is required before using any
+ // Capstone function because Capstone can access to the MMX/x87 registers and
+ // 32bit Windows requires drivers to use KeSaveFloatingPointState() before and
+ // KeRestoreFloatingPointState() after accessing them. See "Using Floating
+ // Point or MMX in a WDM Driver" on MSDN for more details.
+ status = KeSaveFloatingPointState(&float_save);
+ if (!NT_SUCCESS(status)) {
+ printf("ERROR: Failed to save floating point state!\n");
+ return;
+ }
+
+ basic::test();
+ detail::test();
+ skipdata::test();
+ iter::test();
+ customized_mnem_::test();
+ arm::test();
+ arm64::test();
+ mips::test();
+ m68k::test();
+ ppc::test();
+ sparc::test();
+ systemz::test();
+ x86::test();
+ xcore::test();
+
+ // Restores the nonvolatile floating-point context.
+ KeRestoreFloatingPointState(&float_save);
+}
+
+// Functional test for cs_winkernel_vsnprintf()
+static void cs_winkernel_vsnprintf_test()
+{
+ char buf[10];
+ bool ok = true;
+ ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "") == 0 && strcmp(buf, "") == 0);
+ ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0") == 1 && strcmp(buf, "0") == 0);
+ ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "012345678") == 9 && strcmp(buf, "012345678") == 0);
+ ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789") == 10 && strcmp(buf, "012345678") == 0);
+ ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "01234567890") == 11 && strcmp(buf, "012345678") == 0);
+ ok = (ok && cs_snprintf(buf, sizeof(buf), "%s", "0123456789001234567890") == 22 && strcmp(buf, "012345678") == 0);
+ if (!ok) {
+ printf("ERROR: cs_winkernel_vsnprintf_test() did not produce expected results!\n");
+ }
+}
+
+// Driver entry point
+EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
+{
+ UNREFERENCED_PARAMETER(DriverObject);
+ UNREFERENCED_PARAMETER(RegistryPath);
+ cs_winkernel_vsnprintf_test();
+ test();
+ return STATUS_CANCELLED;
+}
+
+// This functions mimics printf() but does not return the same value as printf()
+// would do. printf() is required to exercise regression tests.
+_Use_decl_annotations_
+int __cdecl printf(const char * format, ...)
+{
+ NTSTATUS status;
+ va_list args;
+
+ va_start(args, format);
+ status = vDbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, format, args);
+ va_end(args);
+ return NT_SUCCESS(status);
+}
diff --git a/capstone/tests/test_x86.c b/capstone/tests/test_x86.c
new file mode 100644
index 000000000..775c096d3
--- /dev/null
+++ b/capstone/tests/test_x86.c
@@ -0,0 +1,464 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013 */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+static csh handle;
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+ cs_opt_type opt_type;
+ cs_opt_value opt_value;
+};
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static const char *get_eflag_name(uint64_t flag)
+{
+ switch(flag) {
+ default:
+ return NULL;
+ case X86_EFLAGS_UNDEFINED_OF:
+ return "UNDEF_OF";
+ case X86_EFLAGS_UNDEFINED_SF:
+ return "UNDEF_SF";
+ case X86_EFLAGS_UNDEFINED_ZF:
+ return "UNDEF_ZF";
+ case X86_EFLAGS_MODIFY_AF:
+ return "MOD_AF";
+ case X86_EFLAGS_UNDEFINED_PF:
+ return "UNDEF_PF";
+ case X86_EFLAGS_MODIFY_CF:
+ return "MOD_CF";
+ case X86_EFLAGS_MODIFY_SF:
+ return "MOD_SF";
+ case X86_EFLAGS_MODIFY_ZF:
+ return "MOD_ZF";
+ case X86_EFLAGS_UNDEFINED_AF:
+ return "UNDEF_AF";
+ case X86_EFLAGS_MODIFY_PF:
+ return "MOD_PF";
+ case X86_EFLAGS_UNDEFINED_CF:
+ return "UNDEF_CF";
+ case X86_EFLAGS_MODIFY_OF:
+ return "MOD_OF";
+ case X86_EFLAGS_RESET_OF:
+ return "RESET_OF";
+ case X86_EFLAGS_RESET_CF:
+ return "RESET_CF";
+ case X86_EFLAGS_RESET_DF:
+ return "RESET_DF";
+ case X86_EFLAGS_RESET_IF:
+ return "RESET_IF";
+ case X86_EFLAGS_TEST_OF:
+ return "TEST_OF";
+ case X86_EFLAGS_TEST_SF:
+ return "TEST_SF";
+ case X86_EFLAGS_TEST_ZF:
+ return "TEST_ZF";
+ case X86_EFLAGS_TEST_PF:
+ return "TEST_PF";
+ case X86_EFLAGS_TEST_CF:
+ return "TEST_CF";
+ case X86_EFLAGS_RESET_SF:
+ return "RESET_SF";
+ case X86_EFLAGS_RESET_AF:
+ return "RESET_AF";
+ case X86_EFLAGS_RESET_TF:
+ return "RESET_TF";
+ case X86_EFLAGS_RESET_NT:
+ return "RESET_NT";
+ case X86_EFLAGS_PRIOR_OF:
+ return "PRIOR_OF";
+ case X86_EFLAGS_PRIOR_SF:
+ return "PRIOR_SF";
+ case X86_EFLAGS_PRIOR_ZF:
+ return "PRIOR_ZF";
+ case X86_EFLAGS_PRIOR_AF:
+ return "PRIOR_AF";
+ case X86_EFLAGS_PRIOR_PF:
+ return "PRIOR_PF";
+ case X86_EFLAGS_PRIOR_CF:
+ return "PRIOR_CF";
+ case X86_EFLAGS_PRIOR_TF:
+ return "PRIOR_TF";
+ case X86_EFLAGS_PRIOR_IF:
+ return "PRIOR_IF";
+ case X86_EFLAGS_PRIOR_DF:
+ return "PRIOR_DF";
+ case X86_EFLAGS_TEST_NT:
+ return "TEST_NT";
+ case X86_EFLAGS_TEST_DF:
+ return "TEST_DF";
+ case X86_EFLAGS_RESET_PF:
+ return "RESET_PF";
+ case X86_EFLAGS_PRIOR_NT:
+ return "PRIOR_NT";
+ case X86_EFLAGS_MODIFY_TF:
+ return "MOD_TF";
+ case X86_EFLAGS_MODIFY_IF:
+ return "MOD_IF";
+ case X86_EFLAGS_MODIFY_DF:
+ return "MOD_DF";
+ case X86_EFLAGS_MODIFY_NT:
+ return "MOD_NT";
+ case X86_EFLAGS_MODIFY_RF:
+ return "MOD_RF";
+ case X86_EFLAGS_SET_CF:
+ return "SET_CF";
+ case X86_EFLAGS_SET_DF:
+ return "SET_DF";
+ case X86_EFLAGS_SET_IF:
+ return "SET_IF";
+ }
+}
+
+static const char *get_fpu_flag_name(uint64_t flag)
+{
+ switch (flag) {
+ default:
+ return NULL;
+ case X86_FPU_FLAGS_MODIFY_C0:
+ return "MOD_C0";
+ case X86_FPU_FLAGS_MODIFY_C1:
+ return "MOD_C1";
+ case X86_FPU_FLAGS_MODIFY_C2:
+ return "MOD_C2";
+ case X86_FPU_FLAGS_MODIFY_C3:
+ return "MOD_C3";
+ case X86_FPU_FLAGS_RESET_C0:
+ return "RESET_C0";
+ case X86_FPU_FLAGS_RESET_C1:
+ return "RESET_C1";
+ case X86_FPU_FLAGS_RESET_C2:
+ return "RESET_C2";
+ case X86_FPU_FLAGS_RESET_C3:
+ return "RESET_C3";
+ case X86_FPU_FLAGS_SET_C0:
+ return "SET_C0";
+ case X86_FPU_FLAGS_SET_C1:
+ return "SET_C1";
+ case X86_FPU_FLAGS_SET_C2:
+ return "SET_C2";
+ case X86_FPU_FLAGS_SET_C3:
+ return "SET_C3";
+ case X86_FPU_FLAGS_UNDEFINED_C0:
+ return "UNDEF_C0";
+ case X86_FPU_FLAGS_UNDEFINED_C1:
+ return "UNDEF_C1";
+ case X86_FPU_FLAGS_UNDEFINED_C2:
+ return "UNDEF_C2";
+ case X86_FPU_FLAGS_UNDEFINED_C3:
+ return "UNDEF_C3";
+ case X86_FPU_FLAGS_TEST_C0:
+ return "TEST_C0";
+ case X86_FPU_FLAGS_TEST_C1:
+ return "TEST_C1";
+ case X86_FPU_FLAGS_TEST_C2:
+ return "TEST_C2";
+ case X86_FPU_FLAGS_TEST_C3:
+ return "TEST_C3";
+ }
+}
+
+static void print_insn_detail(csh ud, cs_mode mode, cs_insn *ins)
+{
+ int count, i;
+ cs_x86 *x86;
+ cs_regs regs_read, regs_write;
+ uint8_t regs_read_count, regs_write_count;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ x86 = &(ins->detail->x86);
+
+ print_string_hex("\tPrefix:", x86->prefix, 4);
+
+ print_string_hex("\tOpcode:", x86->opcode, 4);
+
+ printf("\trex: 0x%x\n", x86->rex);
+
+ printf("\taddr_size: %u\n", x86->addr_size);
+ printf("\tmodrm: 0x%x\n", x86->modrm);
+ if (x86->encoding.modrm_offset != 0) {
+ printf("\tmodrm_offset: 0x%x\n", x86->encoding.modrm_offset);
+ }
+
+ printf("\tdisp: 0x%" PRIx64 "\n", x86->disp);
+ if (x86->encoding.disp_offset != 0) {
+ printf("\tdisp_offset: 0x%x\n", x86->encoding.disp_offset);
+ }
+
+ if (x86->encoding.disp_size != 0) {
+ printf("\tdisp_size: 0x%x\n", x86->encoding.disp_size);
+ }
+
+ // SIB is not available in 16-bit mode
+ if ((mode & CS_MODE_16) == 0) {
+ printf("\tsib: 0x%x\n", x86->sib);
+ if (x86->sib_base != X86_REG_INVALID)
+ printf("\t\tsib_base: %s\n", cs_reg_name(handle, x86->sib_base));
+ if (x86->sib_index != X86_REG_INVALID)
+ printf("\t\tsib_index: %s\n", cs_reg_name(handle, x86->sib_index));
+ if (x86->sib_scale != 0)
+ printf("\t\tsib_scale: %d\n", x86->sib_scale);
+ }
+
+ // XOP code condition
+ if (x86->xop_cc != X86_XOP_CC_INVALID) {
+ printf("\txop_cc: %u\n", x86->xop_cc);
+ }
+
+ // SSE code condition
+ if (x86->sse_cc != X86_SSE_CC_INVALID) {
+ printf("\tsse_cc: %u\n", x86->sse_cc);
+ }
+
+ // AVX code condition
+ if (x86->avx_cc != X86_AVX_CC_INVALID) {
+ printf("\tavx_cc: %u\n", x86->avx_cc);
+ }
+
+ // AVX Suppress All Exception
+ if (x86->avx_sae) {
+ printf("\tavx_sae: %u\n", x86->avx_sae);
+ }
+
+ // AVX Rounding Mode
+ if (x86->avx_rm != X86_AVX_RM_INVALID) {
+ printf("\tavx_rm: %u\n", x86->avx_rm);
+ }
+
+ // Print out all immediate operands
+ count = cs_op_count(ud, ins, X86_OP_IMM);
+ if (count) {
+ printf("\timm_count: %u\n", count);
+ for (i = 1; i < count + 1; i++) {
+ int index = cs_op_index(ud, ins, X86_OP_IMM, i);
+ printf("\t\timms[%u]: 0x%" PRIx64 "\n", i, x86->operands[index].imm);
+ if (x86->encoding.imm_offset != 0) {
+ printf("\timm_offset: 0x%x\n", x86->encoding.imm_offset);
+ }
+
+ if (x86->encoding.imm_size != 0) {
+ printf("\timm_size: 0x%x\n", x86->encoding.imm_size);
+ }
+ }
+ }
+
+ if (x86->op_count)
+ printf("\top_count: %u\n", x86->op_count);
+
+ // Print out all operands
+ for (i = 0; i < x86->op_count; i++) {
+ cs_x86_op *op = &(x86->operands[i]);
+
+ switch((int)op->type) {
+ case X86_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ break;
+ case X86_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
+ break;
+ case X86_OP_MEM:
+ printf("\t\toperands[%u].type: MEM\n", i);
+ if (op->mem.segment != X86_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.segment: REG = %s\n", i, cs_reg_name(handle, op->mem.segment));
+ if (op->mem.base != X86_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(handle, op->mem.base));
+ if (op->mem.index != X86_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.index: REG = %s\n", i, cs_reg_name(handle, op->mem.index));
+ if (op->mem.scale != 1)
+ printf("\t\t\toperands[%u].mem.scale: %u\n", i, op->mem.scale);
+ if (op->mem.disp != 0)
+ printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp);
+ break;
+ default:
+ break;
+ }
+
+ // AVX broadcast type
+ if (op->avx_bcast != X86_AVX_BCAST_INVALID)
+ printf("\t\toperands[%u].avx_bcast: %u\n", i, op->avx_bcast);
+
+ // AVX zero opmask {z}
+ if (op->avx_zero_opmask != false)
+ printf("\t\toperands[%u].avx_zero_opmask: TRUE\n", i);
+
+ printf("\t\toperands[%u].size: %u\n", i, op->size);
+
+ switch(op->access) {
+ default:
+ break;
+ case CS_AC_READ:
+ printf("\t\toperands[%u].access: READ\n", i);
+ break;
+ case CS_AC_WRITE:
+ printf("\t\toperands[%u].access: WRITE\n", i);
+ break;
+ case CS_AC_READ | CS_AC_WRITE:
+ printf("\t\toperands[%u].access: READ | WRITE\n", i);
+ break;
+ }
+ }
+
+ // Print out all registers accessed by this instruction (either implicit or explicit)
+ if (!cs_regs_access(ud, ins,
+ regs_read, &regs_read_count,
+ regs_write, &regs_write_count)) {
+ if (regs_read_count) {
+ printf("\tRegisters read:");
+ for(i = 0; i < regs_read_count; i++) {
+ printf(" %s", cs_reg_name(handle, regs_read[i]));
+ }
+ printf("\n");
+ }
+
+ if (regs_write_count) {
+ printf("\tRegisters modified:");
+ for(i = 0; i < regs_write_count; i++) {
+ printf(" %s", cs_reg_name(handle, regs_write[i]));
+ }
+ printf("\n");
+ }
+ }
+
+ if (x86->eflags || x86->fpu_flags) {
+ for(i = 0; i < ins->detail->groups_count; i++) {
+ if (ins->detail->groups[i] == X86_GRP_FPU) {
+ printf("\tFPU_FLAGS:");
+ for(i = 0; i <= 63; i++)
+ if (x86->fpu_flags & ((uint64_t)1 << i)) {
+ printf(" %s", get_fpu_flag_name((uint64_t)1 << i));
+ }
+ printf("\n");
+ break;
+ }
+ }
+
+ if (i == ins->detail->groups_count) {
+ printf("\tEFLAGS:");
+ for(i = 0; i <= 63; i++)
+ if (x86->eflags & ((uint64_t)1 << i)) {
+ printf(" %s", get_eflag_name((uint64_t)1 << i));
+ }
+ printf("\n");
+ }
+ }
+
+ printf("\n");
+}
+
+static void test()
+{
+#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff"
+#define X86_CODE16 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6\x66\xe9\xb8\x00\x00\x00\x67\xff\xa0\x23\x01\x00\x00\x66\xe8\xcb\x00\x00\x00\x74\xfc"
+#define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6\xe9\xea\xbe\xad\xde\xff\xa0\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff"
+
+ struct platform platforms[] = {
+ {
+ CS_ARCH_X86,
+ CS_MODE_16,
+ (unsigned char *)X86_CODE16,
+ sizeof(X86_CODE16) - 1,
+ "X86 16bit (Intel syntax)"
+ },
+ {
+ CS_ARCH_X86,
+ CS_MODE_32,
+ (unsigned char *)X86_CODE32,
+ sizeof(X86_CODE32) - 1,
+ "X86 32 (AT&T 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)"
+ },
+ };
+
+ uint64_t address = 0x1000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ 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);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(handle, platforms[i].mode, &insn[j]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}
diff --git a/capstone/tests/test_xcore.c b/capstone/tests/test_xcore.c
new file mode 100644
index 000000000..12cc1f1bb
--- /dev/null
+++ b/capstone/tests/test_xcore.c
@@ -0,0 +1,140 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
+
+#include <stdio.h>
+
+#include <capstone/platform.h>
+#include <capstone/capstone.h>
+
+struct platform {
+ cs_arch arch;
+ cs_mode mode;
+ unsigned char *code;
+ size_t size;
+ const char *comment;
+};
+
+static csh handle;
+
+static void print_string_hex(const char *comment, unsigned char *str, size_t len)
+{
+ unsigned char *c;
+
+ printf("%s", comment);
+ for (c = str; c < str + len; c++) {
+ printf("0x%02x ", *c & 0xff);
+ }
+
+ printf("\n");
+}
+
+static void print_insn_detail(cs_insn *ins)
+{
+ cs_xcore *xcore;
+ int i;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ xcore = &(ins->detail->xcore);
+ if (xcore->op_count)
+ printf("\top_count: %u\n", xcore->op_count);
+
+ for (i = 0; i < xcore->op_count; i++) {
+ cs_xcore_op *op = &(xcore->operands[i]);
+ switch((int)op->type) {
+ default:
+ break;
+ case XCORE_OP_REG:
+ printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
+ break;
+ case XCORE_OP_IMM:
+ printf("\t\toperands[%u].type: IMM = 0x%x\n", i, op->imm);
+ break;
+ case XCORE_OP_MEM:
+ printf("\t\toperands[%u].type: MEM\n", i);
+ if (op->mem.base != XCORE_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.base));
+ if (op->mem.index != XCORE_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.index: REG = %s\n",
+ i, cs_reg_name(handle, op->mem.index));
+ if (op->mem.disp != 0)
+ printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
+ if (op->mem.direct != 1)
+ printf("\t\t\toperands[%u].mem.direct: -1\n", i);
+
+
+ break;
+ }
+ }
+
+ printf("\n");
+}
+
+static void test()
+{
+#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\x09\xfd\xec\xa7"
+
+ struct platform platforms[] = {
+ {
+ CS_ARCH_XCORE,
+ CS_MODE_BIG_ENDIAN,
+ (unsigned char*)XCORE_CODE,
+ sizeof(XCORE_CODE) - 1,
+ "XCore",
+ },
+ };
+
+ uint64_t address = 0x1000;
+ cs_insn *insn;
+ int i;
+ size_t count;
+
+ for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
+ cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
+ if (err) {
+ printf("Failed on cs_open() with error returned: %u\n", err);
+ abort();
+ }
+
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
+ if (count) {
+ size_t j;
+
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("Disasm:\n");
+
+ for (j = 0; j < count; j++) {
+ printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
+ print_insn_detail(&insn[j]);
+ }
+ printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
+
+ // free memory allocated by cs_disasm()
+ cs_free(insn, count);
+ } else {
+ printf("****************\n");
+ printf("Platform: %s\n", platforms[i].comment);
+ print_string_hex("Code:", platforms[i].code, platforms[i].size);
+ printf("ERROR: Failed to disasm given code!\n");
+ abort();
+ }
+
+ printf("\n");
+
+ cs_close(&handle);
+ }
+}
+
+int main()
+{
+ test();
+
+ return 0;
+}