diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /capstone/cstool | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'capstone/cstool')
-rw-r--r-- | capstone/cstool/Makefile | 48 | ||||
-rw-r--r-- | capstone/cstool/README | 47 | ||||
-rw-r--r-- | capstone/cstool/cstool.c | 566 | ||||
-rw-r--r-- | capstone/cstool/cstool_arm.c | 156 | ||||
-rw-r--r-- | capstone/cstool/cstool_arm64.c | 138 | ||||
-rw-r--r-- | capstone/cstool/cstool_bpf.c | 80 | ||||
-rw-r--r-- | capstone/cstool/cstool_evm.c | 26 | ||||
-rw-r--r-- | capstone/cstool/cstool_m680x.c | 156 | ||||
-rw-r--r-- | capstone/cstool/cstool_m68k.c | 121 | ||||
-rw-r--r-- | capstone/cstool/cstool_mips.c | 47 | ||||
-rw-r--r-- | capstone/cstool/cstool_mos65xx.c | 101 | ||||
-rw-r--r-- | capstone/cstool/cstool_ppc.c | 90 | ||||
-rw-r--r-- | capstone/cstool/cstool_riscv.c | 46 | ||||
-rw-r--r-- | capstone/cstool/cstool_sparc.c | 55 | ||||
-rw-r--r-- | capstone/cstool/cstool_systemz.c | 56 | ||||
-rw-r--r-- | capstone/cstool/cstool_tms320c64x.c | 106 | ||||
-rw-r--r-- | capstone/cstool/cstool_wasm.c | 51 | ||||
-rw-r--r-- | capstone/cstool/cstool_x86.c | 347 | ||||
-rw-r--r-- | capstone/cstool/cstool_xcore.c | 52 | ||||
-rw-r--r-- | capstone/cstool/getopt.c | 76 | ||||
-rw-r--r-- | capstone/cstool/getopt.h | 14 |
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, ®s_read_count, + regs_write, ®s_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, ®s_read_count, + regs_write, ®s_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, ®s_read_count, + regs_write, ®s_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, ®s_read_count, + regs_write, ®s_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 |