aboutsummaryrefslogtreecommitdiffstats
path: root/capstone/cstool
diff options
context:
space:
mode:
Diffstat (limited to 'capstone/cstool')
-rw-r--r--capstone/cstool/Makefile48
-rw-r--r--capstone/cstool/README47
-rw-r--r--capstone/cstool/cstool.c566
-rw-r--r--capstone/cstool/cstool_arm.c156
-rw-r--r--capstone/cstool/cstool_arm64.c138
-rw-r--r--capstone/cstool/cstool_bpf.c80
-rw-r--r--capstone/cstool/cstool_evm.c26
-rw-r--r--capstone/cstool/cstool_m680x.c156
-rw-r--r--capstone/cstool/cstool_m68k.c121
-rw-r--r--capstone/cstool/cstool_mips.c47
-rw-r--r--capstone/cstool/cstool_mos65xx.c101
-rw-r--r--capstone/cstool/cstool_ppc.c90
-rw-r--r--capstone/cstool/cstool_riscv.c46
-rw-r--r--capstone/cstool/cstool_sparc.c55
-rw-r--r--capstone/cstool/cstool_systemz.c56
-rw-r--r--capstone/cstool/cstool_tms320c64x.c106
-rw-r--r--capstone/cstool/cstool_wasm.c51
-rw-r--r--capstone/cstool/cstool_x86.c347
-rw-r--r--capstone/cstool/cstool_xcore.c52
-rw-r--r--capstone/cstool/getopt.c76
-rw-r--r--capstone/cstool/getopt.h14
21 files changed, 2379 insertions, 0 deletions
diff --git a/capstone/cstool/Makefile b/capstone/cstool/Makefile
new file mode 100644
index 000000000..f709d3a79
--- /dev/null
+++ b/capstone/cstool/Makefile
@@ -0,0 +1,48 @@
+# Makefile for Cstool of Capstone Disassembly Engine
+
+include ../functions.mk
+
+.PHONY: clean all
+
+LIBNAME = capstone
+
+CFLAGS += -I../include -I.
+LDFLAGS += -O3 -Wall -L.. -l$(LIBNAME)
+
+TARGET = cstool
+SOURCES := $(wildcard *.c)
+OBJECTS := $(SOURCES:.c=.o)
+
+LIBCAPSTONE = libcapstone.a
+
+IS_CYGWIN := $(shell $(CC) -dumpmachine 2>/dev/null | grep -i cygwin | wc -l)
+ifeq ($(IS_CYGWIN),1)
+LIBCAPSTONE = capstone.lib
+else
+IS_MINGW := $(shell $(CC) --version 2>/dev/null | grep -i "\(mingw\|MSYS\)" | wc -l)
+ifeq ($(IS_MINGW),1)
+LIBCAPSTONE = capstone.lib
+endif
+endif
+
+all: $(TARGET)
+
+$(TARGET): ../$(LIBCAPSTONE) $(OBJECTS)
+ifeq ($(V), 0)
+ $(call log,LINK,$@)
+ @${CC} $(OBJECTS) $(LDFLAGS) -o $@
+else
+ ${CC} $(OBJECTS) $(LDFLAGS) -o $@
+endif
+
+clean:
+ ${RM} -rf *.o $(TARGET)
+ ${RM} -f *.d
+
+%.o: %.c
+ifeq ($(V), 0)
+ $(call log,CC,$@)
+ @${CC} $(CFLAGS) -c $< -o $@
+else
+ ${CC} $(CFLAGS) -c $< -o $@
+endif
diff --git a/capstone/cstool/README b/capstone/cstool/README
new file mode 100644
index 000000000..a6b0208aa
--- /dev/null
+++ b/capstone/cstool/README
@@ -0,0 +1,47 @@
+This directory contains cstool of Capstone Engine.
+
+Cstool is a command-line tool to disassemble assembly hex-string.
+For example, to decode a hexcode string for Intel 32bit, run:
+
+ $ cstool x32 "90 91"
+
+ 0 90 nop
+ 1 91 xchg eax, ecx
+
+Cstool disassembles the input and prints out the assembly instructions.
+On each line, the first column is the instruction offset, the second
+column is opcodes, and the rest is the instruction itself.
+
+Cstool is flexible enough to accept all kind of hexcode format. The following
+inputs have the same output with the example above.
+
+ $ cstool x32 "0x90 0x91"
+ $ cstool x32 "\x90\x91"
+ $ cstool x32 "90,91"
+ $ cstool x32 "90;91"
+ $ cstool x32 "90+91"
+ $ cstool x32 "90:91"
+
+To print out instruction details, run Cstool with -d option, like below.
+
+ $ cstool -d x32 "01 d8"
+ 0 01d8 add eax, ebx
+ Prefix:0x00 0x00 0x00 0x00
+ Opcode:0x01 0x00 0x00 0x00
+ rex: 0x0
+ addr_size: 4
+ modrm: 0xd8
+ disp: 0x0
+ sib: 0x0
+ op_count: 2
+ operands[0].type: REG = eax
+ operands[0].size: 4
+ operands[0].access: READ | WRITE
+ operands[1].type: REG = ebx
+ operands[1].size: 4
+ operands[1].access: READ
+ Registers read: eax ebx
+ Registers modified: eflags eax
+ EFLAGS: MOD_AF MOD_CF MOD_SF MOD_ZF MOD_PF MOD_OF
+
+To see all the supported options, run ./cstool
diff --git a/capstone/cstool/cstool.c b/capstone/cstool/cstool.c
new file mode 100644
index 000000000..9bd5543d4
--- /dev/null
+++ b/capstone/cstool/cstool.c
@@ -0,0 +1,566 @@
+/* Tang Yuhang <tyh000011112222@gmail.com> 2016 */
+/* pancake <pancake@nopcode.org> 2017 */
+
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include "getopt.h"
+
+#include <capstone/capstone.h>
+
+void print_string_hex(const char *comment, unsigned char *str, size_t len);
+
+static struct {
+ const char *name;
+ cs_arch arch;
+ cs_mode mode;
+} all_archs[] = {
+ { "arm", CS_ARCH_ARM, CS_MODE_ARM },
+ { "armb", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_BIG_ENDIAN },
+ { "armbe", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_BIG_ENDIAN },
+ { "arml", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_LITTLE_ENDIAN },
+ { "armle", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_LITTLE_ENDIAN },
+ { "armv8", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_V8 },
+ { "thumbv8", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_V8 },
+ { "armv8be", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_V8 | CS_MODE_BIG_ENDIAN },
+ { "thumbv8be", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_V8 | CS_MODE_BIG_ENDIAN },
+ { "cortexm", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_MCLASS },
+ { "thumb", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB },
+ { "thumbbe", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_BIG_ENDIAN },
+ { "thumble", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_LITTLE_ENDIAN },
+ { "arm64", CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN },
+ { "arm64be", CS_ARCH_ARM64, CS_MODE_BIG_ENDIAN },
+ { "mips", CS_ARCH_MIPS, CS_MODE_MIPS32 | CS_MODE_LITTLE_ENDIAN },
+ { "mipsmicro", CS_ARCH_MIPS, CS_MODE_MIPS32 | CS_MODE_MICRO },
+ { "mipsbemicro", CS_ARCH_MIPS, CS_MODE_MIPS32 | CS_MODE_MICRO | CS_MODE_BIG_ENDIAN },
+ { "mipsbe32r6", CS_ARCH_MIPS, CS_MODE_MIPS32R6 | CS_MODE_BIG_ENDIAN},
+ { "mipsbe32r6micro", CS_ARCH_MIPS, CS_MODE_MIPS32R6 | CS_MODE_BIG_ENDIAN | CS_MODE_MICRO },
+ { "mips32r6", CS_ARCH_MIPS, CS_MODE_MIPS32R6 },
+ { "mips32r6micro", CS_ARCH_MIPS, CS_MODE_MIPS32R6 | CS_MODE_MICRO },
+ { "mipsbe", CS_ARCH_MIPS, CS_MODE_MIPS32 | CS_MODE_BIG_ENDIAN },
+ { "mips64", CS_ARCH_MIPS, CS_MODE_MIPS64 | CS_MODE_LITTLE_ENDIAN },
+ { "mips64be", CS_ARCH_MIPS, CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN },
+ { "x16", CS_ARCH_X86, CS_MODE_16 }, // CS_MODE_16
+ { "x16att", CS_ARCH_X86, CS_MODE_16 }, // CS_MODE_16 , CS_OPT_SYNTAX_ATT
+ { "x32", CS_ARCH_X86, CS_MODE_32 }, // CS_MODE_32
+ { "x32att", CS_ARCH_X86, CS_MODE_32 }, // CS_MODE_32, CS_OPT_SYNTAX_ATT
+ { "x64", CS_ARCH_X86, CS_MODE_64 }, // CS_MODE_64
+ { "x64att", CS_ARCH_X86, CS_MODE_64 }, // CS_MODE_64, CS_OPT_SYNTAX_ATT
+ { "ppc32", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_LITTLE_ENDIAN },
+ { "ppc32be", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_BIG_ENDIAN },
+ { "ppc32qpx", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_QPX | CS_MODE_LITTLE_ENDIAN },
+ { "ppc32beqpx", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_QPX | CS_MODE_BIG_ENDIAN },
+ { "ppc64", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_LITTLE_ENDIAN },
+ { "ppc64be", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN },
+ { "ppc64qpx", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_QPX | CS_MODE_LITTLE_ENDIAN },
+ { "ppc64beqpx", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_QPX | CS_MODE_BIG_ENDIAN },
+ { "sparc", CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN },
+ { "sparcv9", CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN | CS_MODE_V9 },
+ { "systemz", CS_ARCH_SYSZ, CS_MODE_BIG_ENDIAN },
+ { "sysz", CS_ARCH_SYSZ, CS_MODE_BIG_ENDIAN },
+ { "s390x", CS_ARCH_SYSZ, CS_MODE_BIG_ENDIAN },
+ { "xcore", CS_ARCH_XCORE, CS_MODE_BIG_ENDIAN },
+ { "m68k", CS_ARCH_M68K, CS_MODE_BIG_ENDIAN },
+ { "m68k40", CS_ARCH_M68K, CS_MODE_M68K_040 },
+ { "tms320c64x", CS_ARCH_TMS320C64X, CS_MODE_BIG_ENDIAN },
+ { "m6800", CS_ARCH_M680X, CS_MODE_M680X_6800 },
+ { "m6801", CS_ARCH_M680X, CS_MODE_M680X_6801 },
+ { "m6805", CS_ARCH_M680X, CS_MODE_M680X_6805 },
+ { "m6808", CS_ARCH_M680X, CS_MODE_M680X_6808 },
+ { "m6809", CS_ARCH_M680X, CS_MODE_M680X_6809 },
+ { "m6811", CS_ARCH_M680X, CS_MODE_M680X_6811 },
+ { "cpu12", CS_ARCH_M680X, CS_MODE_M680X_CPU12 },
+ { "hd6301", CS_ARCH_M680X, CS_MODE_M680X_6301 },
+ { "hd6309", CS_ARCH_M680X, CS_MODE_M680X_6309 },
+ { "hcs08", CS_ARCH_M680X, CS_MODE_M680X_HCS08 },
+ { "evm", CS_ARCH_EVM, 0 },
+ { "wasm", CS_ARCH_WASM, 0 },
+ { "bpf", CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_CLASSIC },
+ { "bpfbe", CS_ARCH_BPF, CS_MODE_BIG_ENDIAN | CS_MODE_BPF_CLASSIC },
+ { "ebpf", CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED },
+ { "ebpfbe", CS_ARCH_BPF, CS_MODE_BIG_ENDIAN | CS_MODE_BPF_EXTENDED },
+ { "riscv32", CS_ARCH_RISCV, CS_MODE_RISCV32 },
+ { "riscv64", CS_ARCH_RISCV, CS_MODE_RISCV64 },
+ { "6502", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_6502 },
+ { "65c02", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_65C02 },
+ { "w65c02", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_W65C02 },
+ { "65816", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_65816_LONG_MX },
+ { NULL }
+};
+
+void print_insn_detail_x86(csh ud, cs_mode mode, cs_insn *ins);
+void print_insn_detail_arm(csh handle, cs_insn *ins);
+void print_insn_detail_arm64(csh handle, cs_insn *ins);
+void print_insn_detail_mips(csh handle, cs_insn *ins);
+void print_insn_detail_ppc(csh handle, cs_insn *ins);
+void print_insn_detail_sparc(csh handle, cs_insn *ins);
+void print_insn_detail_sysz(csh handle, cs_insn *ins);
+void print_insn_detail_xcore(csh handle, cs_insn *ins);
+void print_insn_detail_m68k(csh handle, cs_insn *ins);
+void print_insn_detail_tms320c64x(csh handle, cs_insn *ins);
+void print_insn_detail_m680x(csh handle, cs_insn *ins);
+void print_insn_detail_evm(csh handle, cs_insn *ins);
+void print_insn_detail_riscv(csh handle, cs_insn *ins);
+void print_insn_detail_wasm(csh handle, cs_insn *ins);
+void print_insn_detail_mos65xx(csh handle, cs_insn *ins);
+void print_insn_detail_bpf(csh handle, cs_insn *ins);
+
+static void print_details(csh handle, cs_arch arch, cs_mode md, cs_insn *ins);
+
+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");
+}
+
+// convert hexchar to hexnum
+static uint8_t char_to_hexnum(char c)
+{
+ if (c >= '0' && c <= '9') {
+ return (uint8_t)(c - '0');
+ }
+
+ if (c >= 'a' && c <= 'f') {
+ return (uint8_t)(10 + c - 'a');
+ }
+
+ // c >= 'A' && c <= 'F'
+ return (uint8_t)(10 + c - 'A');
+}
+
+// convert user input (char[]) to uint8_t[], each element of which is
+// valid hexadecimal, and return actual length of uint8_t[] in @size.
+static uint8_t *preprocess(char *code, size_t *size)
+{
+ size_t i = 0, j = 0;
+ uint8_t high, low;
+ uint8_t *result;
+
+ if (strlen(code) == 0)
+ return NULL;
+
+ result = (uint8_t *)malloc(strlen(code));
+ if (result != NULL) {
+ while (code[i] != '\0') {
+ if (isxdigit(code[i]) && isxdigit(code[i+1])) {
+ high = 16 * char_to_hexnum(code[i]);
+ low = char_to_hexnum(code[i+1]);
+ result[j] = high + low;
+ i++;
+ j++;
+ }
+ i++;
+ }
+ *size = j;
+ }
+
+ return result;
+}
+
+static void usage(char *prog)
+{
+ printf("Cstool for Capstone Disassembler Engine v%u.%u.%u\n\n", CS_VERSION_MAJOR, CS_VERSION_MINOR, CS_VERSION_EXTRA);
+ printf("Syntax: %s [-d|-s|-u|-v] <arch+mode> <assembly-hexstring> [start-address-in-hex-format]\n", prog);
+ printf("\nThe following <arch+mode> options are supported:\n");
+
+ if (cs_support(CS_ARCH_X86)) {
+ printf(" x16 16-bit mode (X86)\n");
+ printf(" x32 32-bit mode (X86)\n");
+ printf(" x64 64-bit mode (X86)\n");
+ printf(" x16att 16-bit mode (X86), syntax AT&T\n");
+ printf(" x32att 32-bit mode (X86), syntax AT&T\n");
+ printf(" x64att 64-bit mode (X86), syntax AT&T\n");
+ }
+
+ if (cs_support(CS_ARCH_ARM)) {
+ printf(" arm arm\n");
+ printf(" armbe arm + big endian\n");
+ printf(" thumb thumb mode\n");
+ printf(" thumbbe thumb + big endian\n");
+ printf(" cortexm thumb + cortex-m extensions\n");
+ printf(" armv8 arm v8\n");
+ printf(" thumbv8 thumb v8\n");
+ printf(" armv8be arm v8 + big endian\n");
+ printf(" thumbv8be thumb v8 + big endian\n");
+ }
+
+ if (cs_support(CS_ARCH_ARM64)) {
+ printf(" arm64 aarch64 mode\n");
+ printf(" arm64be aarch64 + big endian\n");
+ }
+
+ if (cs_support(CS_ARCH_MIPS)) {
+ printf(" mips mips32 + little endian\n");
+ printf(" mipsbe mips32 + big endian\n");
+ printf(" mips64 mips64 + little endian\n");
+ printf(" mips64be mips64 + big endian\n");
+ }
+
+ if (cs_support(CS_ARCH_PPC)) {
+ printf(" ppc32 ppc32 + little endian\n");
+ printf(" ppc32be ppc32 + big endian\n");
+ printf(" ppc32qpx ppc32 + qpx + little endian\n");
+ printf(" ppc32beqpx ppc32 + qpx + big endian\n");
+ printf(" ppc64 ppc64 + little endian\n");
+ printf(" ppc64be ppc64 + big endian\n");
+ printf(" ppc64qpx ppc64 + qpx + little endian\n");
+ printf(" ppc64beqpx ppc64 + qpx + big endian\n");
+ }
+
+ if (cs_support(CS_ARCH_SPARC)) {
+ printf(" sparc sparc\n");
+ }
+
+ if (cs_support(CS_ARCH_SYSZ)) {
+ printf(" systemz systemz (s390x)\n");
+ }
+
+ if (cs_support(CS_ARCH_XCORE)) {
+ printf(" xcore xcore\n");
+ }
+
+ if (cs_support(CS_ARCH_M68K)) {
+ printf(" m68k m68k + big endian\n");
+ printf(" m68k40 m68k_040\n");
+ }
+
+ if (cs_support(CS_ARCH_TMS320C64X)) {
+ printf(" tms320c64x TMS320C64x\n");
+ }
+
+ if (cs_support(CS_ARCH_M680X)) {
+ printf(" m6800 M6800/2\n");
+ printf(" m6801 M6801/3\n");
+ printf(" m6805 M6805\n");
+ printf(" m6808 M68HC08\n");
+ printf(" m6809 M6809\n");
+ printf(" m6811 M68HC11\n");
+ printf(" cpu12 M68HC12/HCS12\n");
+ printf(" hd6301 HD6301/3\n");
+ printf(" hd6309 HD6309\n");
+ printf(" hcs08 HCS08\n");
+ }
+
+ if (cs_support(CS_ARCH_EVM)) {
+ printf(" evm Ethereum Virtual Machine\n");
+ }
+
+ if (cs_support(CS_ARCH_MOS65XX)) {
+ printf(" 6502 MOS 6502\n");
+ printf(" 65c02 WDC 65c02\n");
+ printf(" w65c02 WDC w65c02\n");
+ printf(" 65816 WDC 65816 (long m/x)\n");
+ }
+
+ if (cs_support(CS_ARCH_WASM)) {
+ printf(" wasm: Web Assembly\n");
+ }
+
+ if (cs_support(CS_ARCH_BPF)) {
+ printf(" bpf Classic BPF\n");
+ printf(" bpfbe Classic BPF + big endian\n");
+ printf(" ebpf Extended BPF\n");
+ printf(" ebpfbe Extended BPF + big endian\n");
+ }
+
+ if (cs_support(CS_ARCH_RISCV)) {
+ printf(" riscv32 riscv32\n");
+ printf(" riscv64 riscv64\n");
+ }
+
+ printf("\nExtra options:\n");
+ printf(" -d show detailed information of the instructions\n");
+ printf(" -s decode in SKIPDATA mode\n");
+ printf(" -u show immediates as unsigned\n");
+ printf(" -v show version & Capstone core build info\n\n");
+}
+
+static void print_details(csh handle, cs_arch arch, cs_mode md, cs_insn *ins)
+{
+ printf("\tID: %u (%s)\n", ins->id, cs_insn_name(handle, ins->id));
+
+ switch(arch) {
+ case CS_ARCH_X86:
+ print_insn_detail_x86(handle, md, ins);
+ break;
+ case CS_ARCH_ARM:
+ print_insn_detail_arm(handle, ins);
+ break;
+ case CS_ARCH_ARM64:
+ print_insn_detail_arm64(handle, ins);
+ break;
+ case CS_ARCH_MIPS:
+ print_insn_detail_mips(handle, ins);
+ break;
+ case CS_ARCH_PPC:
+ print_insn_detail_ppc(handle, ins);
+ break;
+ case CS_ARCH_SPARC:
+ print_insn_detail_sparc(handle, ins);
+ break;
+ case CS_ARCH_SYSZ:
+ print_insn_detail_sysz(handle, ins);
+ break;
+ case CS_ARCH_XCORE:
+ print_insn_detail_xcore(handle, ins);
+ break;
+ case CS_ARCH_M68K:
+ print_insn_detail_m68k(handle, ins);
+ break;
+ case CS_ARCH_TMS320C64X:
+ print_insn_detail_tms320c64x(handle, ins);
+ break;
+ case CS_ARCH_M680X:
+ print_insn_detail_m680x(handle, ins);
+ break;
+ case CS_ARCH_EVM:
+ print_insn_detail_evm(handle, ins);
+ break;
+ case CS_ARCH_WASM:
+ print_insn_detail_wasm(handle, ins);
+ break;
+ case CS_ARCH_MOS65XX:
+ print_insn_detail_mos65xx(handle, ins);
+ break;
+ case CS_ARCH_BPF:
+ print_insn_detail_bpf(handle, ins);
+ break;
+ case CS_ARCH_RISCV:
+ print_insn_detail_riscv(handle, ins);
+ break;
+ default: break;
+ }
+
+ 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");
+ }
+
+ printf("\n");
+}
+
+int main(int argc, char **argv)
+{
+ int i, c;
+ csh handle;
+ char *mode;
+ uint8_t *assembly;
+ size_t count, size;
+ uint64_t address = 0LL;
+ cs_insn *insn;
+ cs_err err;
+ cs_mode md;
+ cs_arch arch = CS_ARCH_ALL;
+ bool detail_flag = false;
+ bool unsigned_flag = false;
+ bool skipdata = false;
+ int args_left;
+
+ while ((c = getopt (argc, argv, "sudhv")) != -1) {
+ switch (c) {
+ case 's':
+ skipdata = true;
+ break;
+ case 'u':
+ unsigned_flag = true;
+ break;
+ case 'd':
+ detail_flag = true;
+ break;
+ case 'v':
+ printf("cstool for Capstone Disassembler, v%u.%u.%u\n", CS_VERSION_MAJOR, CS_VERSION_MINOR, CS_VERSION_EXTRA);
+
+ printf("Capstone build: ");
+ if (cs_support(CS_ARCH_X86)) {
+ printf("x86=1 ");
+ }
+
+ if (cs_support(CS_ARCH_ARM)) {
+ printf("arm=1 ");
+ }
+
+ if (cs_support(CS_ARCH_ARM64)) {
+ printf("arm64=1 ");
+ }
+
+ if (cs_support(CS_ARCH_MIPS)) {
+ printf("mips=1 ");
+ }
+
+ if (cs_support(CS_ARCH_PPC)) {
+ printf("ppc=1 ");
+ }
+
+ if (cs_support(CS_ARCH_SPARC)) {
+ printf("sparc=1 ");
+ }
+
+ if (cs_support(CS_ARCH_SYSZ)) {
+ printf("sysz=1 ");
+ }
+
+ if (cs_support(CS_ARCH_XCORE)) {
+ printf("xcore=1 ");
+ }
+
+ if (cs_support(CS_ARCH_M68K)) {
+ printf("m68k=1 ");
+ }
+
+ if (cs_support(CS_ARCH_TMS320C64X)) {
+ printf("tms320c64x=1 ");
+ }
+
+ if (cs_support(CS_ARCH_M680X)) {
+ printf("m680x=1 ");
+ }
+
+ if (cs_support(CS_ARCH_EVM)) {
+ printf("evm=1 ");
+ }
+
+ if (cs_support(CS_ARCH_WASM)) {
+ printf("wasm=1 ");
+ }
+
+ if (cs_support(CS_ARCH_MOS65XX)) {
+ printf("mos65xx=1 ");
+ }
+
+ if (cs_support(CS_ARCH_BPF)) {
+ printf("bpf=1 ");
+ }
+
+ if (cs_support(CS_ARCH_RISCV)) {
+ printf("riscv=1 ");
+ }
+
+ if (cs_support(CS_SUPPORT_DIET)) {
+ printf("diet=1 ");
+ }
+
+ if (cs_support(CS_SUPPORT_X86_REDUCE)) {
+ printf("x86_reduce=1 ");
+ }
+
+ printf("\n");
+ return 0;
+ case 'h':
+ usage(argv[0]);
+ return 0;
+ default:
+ usage(argv[0]);
+ return -1;
+ }
+ }
+
+ args_left = argc - optind;
+ if (args_left < 2 || args_left > 3) {
+ usage(argv[0]);
+ return -1;
+ }
+
+ mode = argv[optind];
+ assembly = preprocess(argv[optind + 1], &size);
+ if (!assembly) {
+ usage(argv[0]);
+ return -1;
+ }
+
+ if (args_left == 3) {
+ char *temp, *src = argv[optind + 2];
+ address = strtoull(src, &temp, 16);
+ if (temp == src || *temp != '\0' || errno == ERANGE) {
+ printf("ERROR: invalid address argument, quit!\n");
+ return -2;
+ }
+ }
+
+ for (i = 0; all_archs[i].name; i++) {
+ if (!strcmp(all_archs[i].name, mode)) {
+ arch = all_archs[i].arch;
+ err = cs_open(all_archs[i].arch, all_archs[i].mode, &handle);
+ if (!err) {
+ md = all_archs[i].mode;
+ if (strstr (mode, "att")) {
+ cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);
+ }
+
+ // turn on SKIPDATA mode
+ if (skipdata)
+ cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
+ }
+ break;
+ }
+ }
+
+ if (arch == CS_ARCH_ALL) {
+ printf("ERROR: Invalid <arch+mode>: \"%s\", quit!\n", mode);
+ usage(argv[0]);
+ return -1;
+ }
+
+ if (err) {
+ printf("ERROR: Failed on cs_open(), quit!\n");
+ usage(argv[0]);
+ return -1;
+ }
+
+ if (detail_flag) {
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+ }
+
+ if (unsigned_flag) {
+ cs_option(handle, CS_OPT_UNSIGNED, CS_OPT_ON);
+ }
+
+ count = cs_disasm(handle, assembly, size, address, 0, &insn);
+ if (count > 0) {
+ size_t i;
+
+ for (i = 0; i < count; i++) {
+ int j;
+
+ printf("%2"PRIx64" ", insn[i].address);
+ for (j = 0; j < insn[i].size; j++) {
+ if (j > 0)
+ putchar(' ');
+ printf("%02x", insn[i].bytes[j]);
+ }
+ // X86 instruction size is variable.
+ // align assembly instruction after the opcode
+ if (arch == CS_ARCH_X86) {
+ for (; j < 16; j++) {
+ printf(" ");
+ }
+ }
+
+ printf(" %s\t%s\n", insn[i].mnemonic, insn[i].op_str);
+
+ if (detail_flag) {
+ print_details(handle, arch, md, &insn[i]);
+ }
+ }
+
+ cs_free(insn, count);
+ } else {
+ printf("ERROR: invalid assembly code\n");
+ return(-4);
+ }
+
+ cs_close(&handle);
+ free(assembly);
+
+ return 0;
+}
diff --git a/capstone/cstool/cstool_arm.c b/capstone/cstool/cstool_arm.c
new file mode 100644
index 000000000..26cba3bd0
--- /dev/null
+++ b/capstone/cstool/cstool_arm.c
@@ -0,0 +1,156 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/capstone.h>
+
+void print_insn_detail_arm(csh handle, cs_insn *ins);
+
+void print_insn_detail_arm(csh 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(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(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(handle, op->mem.index));
+ if (op->mem.scale != 1)
+ printf("\t\t\toperands[%u].mem.scale: %d\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(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(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");
+ }
+ }
+}
diff --git a/capstone/cstool/cstool_arm64.c b/capstone/cstool/cstool_arm64.c
new file mode 100644
index 000000000..a01fcfbe6
--- /dev/null
+++ b/capstone/cstool/cstool_arm64.c
@@ -0,0 +1,138 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/capstone.h>
+
+void print_insn_detail_arm64(csh handle, cs_insn *ins);
+
+void print_insn_detail_arm64(csh handle, cs_insn *ins)
+{
+ cs_arm64 *arm64;
+ int i;
+ cs_regs regs_read, regs_write;
+ uint8_t regs_read_count, regs_write_count;
+ uint8_t 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");
+ }
+ }
+}
diff --git a/capstone/cstool/cstool_bpf.c b/capstone/cstool/cstool_bpf.c
new file mode 100644
index 000000000..879f45fef
--- /dev/null
+++ b/capstone/cstool/cstool_bpf.c
@@ -0,0 +1,80 @@
+#include <stdio.h>
+
+#include <capstone/capstone.h>
+#include <capstone/platform.h>
+
+static const char * ext_name[] = {
+ [BPF_EXT_LEN] = "#len",
+};
+
+void print_insn_detail_bpf(csh handle, cs_insn *ins);
+
+void print_insn_detail_bpf(csh handle, cs_insn *ins)
+{
+ unsigned i;
+ cs_bpf *bpf;
+ 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;
+
+ 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(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");
+ }
+ }
+}
diff --git a/capstone/cstool/cstool_evm.c b/capstone/cstool/cstool_evm.c
new file mode 100644
index 000000000..d3ecb5c34
--- /dev/null
+++ b/capstone/cstool/cstool_evm.c
@@ -0,0 +1,26 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/capstone.h>
+
+void print_insn_detail_evm(csh handle, cs_insn *ins);
+
+void print_insn_detail_evm(csh 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);
+}
diff --git a/capstone/cstool/cstool_m680x.c b/capstone/cstool/cstool_m680x.c
new file mode 100644
index 000000000..b1f931a76
--- /dev/null
+++ b/capstone/cstool/cstool_m680x.c
@@ -0,0 +1,156 @@
+/* Capstone Disassembly Engine */
+/* M680X Backend by Wolfgang Schwotzer <wolfgang.schwotzer@gmx.net> 2017 */
+
+#include <stdio.h>
+#include <capstone/capstone.h>
+
+void print_insn_detail_m680x(csh handle, cs_insn *insn);
+
+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("\treading from regs: ");
+
+ for (i = 0; i < detail->regs_read_count; ++i) {
+ if (i > 0)
+ printf(", ");
+
+ printf("%s", cs_reg_name(handle, detail->regs_read[i]));
+ }
+
+ printf("\n");
+ }
+
+ if (detail->regs_write_count > 0) {
+ printf("\twriting to regs: ");
+
+ for (i = 0; i < detail->regs_write_count; ++i) {
+ if (i > 0)
+ printf(", ");
+
+ printf("%s", cs_reg_name(handle,
+ detail->regs_write[i]));
+ }
+
+ printf("\n");
+ }
+}
+
+void print_insn_detail_m680x(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);
+}
+
diff --git a/capstone/cstool/cstool_m68k.c b/capstone/cstool/cstool_m68k.c
new file mode 100644
index 000000000..9d860ea99
--- /dev/null
+++ b/capstone/cstool/cstool_m68k.c
@@ -0,0 +1,121 @@
+//
+// cstool_m68k.c
+//
+//
+// Created by YUHANG TANG on 26/10/16.
+//
+//
+
+#include <stdio.h>
+#include <capstone/capstone.h>
+
+void print_insn_detail_m68k(csh handle, cs_insn *ins);
+
+static 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, csh handle)
+{
+ 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);
+ }
+}
+
+void print_insn_detail_m68k(csh handle, 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, handle);
+
+ 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;
+ }
+ }
+}
+
diff --git a/capstone/cstool/cstool_mips.c b/capstone/cstool/cstool_mips.c
new file mode 100644
index 000000000..df87aeae1
--- /dev/null
+++ b/capstone/cstool/cstool_mips.c
@@ -0,0 +1,47 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/capstone.h>
+
+void print_insn_detail_mips(csh handle, cs_insn *ins);
+
+void print_insn_detail_mips(csh handle, 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;
+ }
+
+ }
+}
diff --git a/capstone/cstool/cstool_mos65xx.c b/capstone/cstool/cstool_mos65xx.c
new file mode 100644
index 000000000..316253f6e
--- /dev/null
+++ b/capstone/cstool/cstool_mos65xx.c
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/capstone.h>
+
+void print_insn_detail_mos65xx(csh handle, cs_insn *ins);
+
+
+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";
+ }
+}
+
+
+void print_insn_detail_mos65xx(csh handle, cs_insn *ins)
+{
+ int i;
+ cs_mos65xx *mos65xx;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ mos65xx = &(ins->detail->mos65xx);
+ 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;
+ }
+ }
+}
diff --git a/capstone/cstool/cstool_ppc.c b/capstone/cstool/cstool_ppc.c
new file mode 100644
index 000000000..73de772fd
--- /dev/null
+++ b/capstone/cstool/cstool_ppc.c
@@ -0,0 +1,90 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
+
+#include <stdio.h>
+
+#include <capstone/capstone.h>
+
+void print_insn_detail_ppc(csh handle, cs_insn *ins);
+
+
+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");
+ }
+}
+
+void print_insn_detail_ppc(csh handle, 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");
+}
diff --git a/capstone/cstool/cstool_riscv.c b/capstone/cstool/cstool_riscv.c
new file mode 100644
index 000000000..2fd5b5be3
--- /dev/null
+++ b/capstone/cstool/cstool_riscv.c
@@ -0,0 +1,46 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
+
+#include <stdio.h>
+#include <capstone/capstone.h>
+
+void print_insn_detail_riscv(csh handle, cs_insn *ins);
+
+void print_insn_detail_riscv(csh handle, cs_insn *ins)
+{
+ cs_riscv *riscv;
+ int i;
+
+ // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
+ if (ins->detail == NULL)
+ return;
+
+ riscv = &(ins->detail->riscv);
+ 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:
+ 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%lx\n", i, (long)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%lx\n", i, (long)op->mem.disp);
+
+ break;
+ }
+ }
+
+ printf("\n");
+}
diff --git a/capstone/cstool/cstool_sparc.c b/capstone/cstool/cstool_sparc.c
new file mode 100644
index 000000000..f3594a596
--- /dev/null
+++ b/capstone/cstool/cstool_sparc.c
@@ -0,0 +1,55 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
+
+#include <stdio.h>
+
+#include <capstone/capstone.h>
+
+void print_insn_detail_sparc(csh handle, cs_insn *ins);
+
+
+void print_insn_detail_sparc(csh handle, 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);
+}
diff --git a/capstone/cstool/cstool_systemz.c b/capstone/cstool/cstool_systemz.c
new file mode 100644
index 000000000..002f9a80d
--- /dev/null
+++ b/capstone/cstool/cstool_systemz.c
@@ -0,0 +1,56 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
+
+#include <stdio.h>
+
+#include <capstone/capstone.h>
+
+void print_insn_detail_sysz(csh handle, cs_insn *ins);
+
+void print_insn_detail_sysz(csh handle, 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);
+}
diff --git a/capstone/cstool/cstool_tms320c64x.c b/capstone/cstool/cstool_tms320c64x.c
new file mode 100644
index 000000000..7eae894aa
--- /dev/null
+++ b/capstone/cstool/cstool_tms320c64x.c
@@ -0,0 +1,106 @@
+/* Capstone Disassembler Engine */
+/* By Fotis Loukos <me@fotisl.com>, 2017 */
+
+#include <stdio.h>
+#include <capstone/capstone.h>
+
+void print_insn_detail_tms320c64x(csh handle, cs_insn *ins);
+
+void print_insn_detail_tms320c64x(csh handle, 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");
+}
diff --git a/capstone/cstool/cstool_wasm.c b/capstone/cstool/cstool_wasm.c
new file mode 100644
index 000000000..80bb2b912
--- /dev/null
+++ b/capstone/cstool/cstool_wasm.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/capstone.h>
+
+void print_insn_detail_wasm(csh handle, cs_insn *ins);
+
+void print_insn_detail_wasm(csh 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;
+
+ wasm = &(ins->detail->wasm);
+ if (wasm->op_count > 0) {
+ unsigned int i;
+
+ printf("\tOperand count: %d\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);
+ }
+ }
+}
diff --git a/capstone/cstool/cstool_x86.c b/capstone/cstool/cstool_x86.c
new file mode 100644
index 000000000..e504e8a14
--- /dev/null
+++ b/capstone/cstool/cstool_x86.c
@@ -0,0 +1,347 @@
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <capstone/capstone.h>
+
+void print_insn_detail_x86(csh ud, cs_mode mode, cs_insn *ins);
+
+void print_string_hex(const char *comment, unsigned char *str, size_t len);
+
+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_RESET_ZF:
+ return "RESET_ZF";
+ 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";
+ case X86_EFLAGS_SET_OF:
+ return "SET_OF";
+ case X86_EFLAGS_SET_SF:
+ return "SET_SF";
+ case X86_EFLAGS_SET_ZF:
+ return "SET_ZF";
+ case X86_EFLAGS_SET_AF:
+ return "SET_AF";
+ case X86_EFLAGS_SET_PF:
+ return "SET_PF";
+ case X86_EFLAGS_TEST_AF:
+ return "TEST_AF";
+ case X86_EFLAGS_TEST_TF:
+ return "TEST_TF";
+ case X86_EFLAGS_TEST_RF:
+ return "TEST_RF";
+ case X86_EFLAGS_RESET_0F:
+ return "RESET_0F";
+ case X86_EFLAGS_RESET_AC:
+ return "RESET_AC";
+ }
+}
+
+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";
+ }
+}
+
+void print_insn_detail_x86(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);
+ printf("\tdisp: 0x%" PRIx64 "\n", x86->disp);
+
+ // 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(ud, x86->sib_base));
+ if (x86->sib_index != X86_REG_INVALID)
+ printf("\t\tsib_index: %s\n", cs_reg_name(ud, 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 > 0) {
+ 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->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(ud, 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(ud, op->mem.segment));
+ if (op->mem.base != X86_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(ud, op->mem.base));
+ if (op->mem.index != X86_REG_INVALID)
+ printf("\t\t\toperands[%u].mem.index: REG = %s\n", i, cs_reg_name(ud, 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(ud, 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(ud, 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");
+ }
+ }
+}
diff --git a/capstone/cstool/cstool_xcore.c b/capstone/cstool/cstool_xcore.c
new file mode 100644
index 000000000..2ab95507a
--- /dev/null
+++ b/capstone/cstool/cstool_xcore.c
@@ -0,0 +1,52 @@
+/* Capstone Disassembler Engine */
+/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
+
+#include <stdio.h>
+#include <capstone/capstone.h>
+
+void print_insn_detail_xcore(csh handle, cs_insn *ins);
+
+void print_insn_detail_xcore(csh handle, 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");
+}
diff --git a/capstone/cstool/getopt.c b/capstone/cstool/getopt.c
new file mode 100644
index 000000000..f4404c168
--- /dev/null
+++ b/capstone/cstool/getopt.c
@@ -0,0 +1,76 @@
+#include <string.h>
+#include <stdio.h>
+
+#include "getopt.h"
+
+int opterr = 1, /* if error message should be printed */
+optind = 1, /* index into parent argv vector */
+optopt, /* character checked for validity */
+optreset; /* reset getopt */
+const char *optarg; /* argument associated with option */
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int getopt (int nargc, char * const nargv[], const char *ostr)
+{
+ static const char *place = EMSG; /* option letter processing */
+ const char *oli; /* option letter list index */
+
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return (-1);
+ }
+
+ if (place[1] && *++place == '-') { /* found "--" */
+ ++optind;
+ place = EMSG;
+ return (-1);
+ }
+ } /* option letter okay? */
+
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr (ostr, optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means -1.
+ */
+ if (optopt == (int)'-')
+ return (-1);
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':')
+ (void)printf ("illegal option -- %c\n", optopt);
+ return (BADCH);
+ }
+
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ } else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return (BADARG);
+ if (opterr)
+ (void)printf ("option requires an argument -- %c\n", optopt);
+ return (BADCH);
+ } else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+
+ return optopt; /* dump back option letter */
+}
+
diff --git a/capstone/cstool/getopt.h b/capstone/cstool/getopt.h
new file mode 100644
index 000000000..bca36c172
--- /dev/null
+++ b/capstone/cstool/getopt.h
@@ -0,0 +1,14 @@
+#ifndef CSTOOL_GETOPT_H
+#define CSTOOL_GETOPT_H
+
+// global
+extern int opterr, /* if error message should be printed */
+optind, /* index into parent argv vector */
+optopt, /* character checked for validity */
+optreset; /* reset getopt */
+
+extern const char *optarg; /* argument associated with option */
+
+int getopt (int nargc, char *const nargv[], const char *ostr);
+
+#endif