Squashed 'external/capstone/' content from commit 5430745e962
git-subtree-dir: external/capstone git-subtree-split: 5430745e9623786f65c0d773a417f389ebb43395
This commit is contained in:
49
cstool/Makefile
Normal file
49
cstool/Makefile
Normal file
@@ -0,0 +1,49 @@
|
||||
# Makefile for Cstool of Capstone Disassembly Engine
|
||||
|
||||
include ../functions.mk
|
||||
|
||||
.PHONY: clean all
|
||||
|
||||
LIBNAME = capstone
|
||||
|
||||
CFLAGS += -I../include -I.
|
||||
CFLAGS += -std=gnu99
|
||||
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
|
||||
47
cstool/README
Normal file
47
cstool/README
Normal file
@@ -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
|
||||
745
cstool/cstool.c
Normal file
745
cstool/cstool.c
Normal file
@@ -0,0 +1,745 @@
|
||||
/* 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>
|
||||
#include "cstool.h"
|
||||
|
||||
#ifdef CAPSTONE_AARCH64_COMPAT_HEADER
|
||||
#define CS_ARCH_AARCH64 CS_ARCH_ARM
|
||||
#endif
|
||||
|
||||
void print_string_hex(const char *comment, unsigned char *str, size_t len);
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
const char *desc;
|
||||
cs_arch archs[CS_ARCH_MAX];
|
||||
cs_opt_value opt;
|
||||
cs_mode mode;
|
||||
} all_opts[] = {
|
||||
// cs_opt_value only
|
||||
{ "+att", "ATT syntax", {
|
||||
CS_ARCH_X86, CS_ARCH_MAX }, CS_OPT_SYNTAX_ATT, 0 },
|
||||
{ "+intel", "Intel syntax", {
|
||||
CS_ARCH_X86, CS_ARCH_MAX }, CS_OPT_SYNTAX_INTEL, 0 },
|
||||
{ "+masm", "Intel MASM syntax", {
|
||||
CS_ARCH_X86, CS_ARCH_MAX }, CS_OPT_SYNTAX_MASM, 0 },
|
||||
{ "+noregname", "Number only registers", {
|
||||
CS_ARCH_AARCH64, CS_ARCH_ARM, CS_ARCH_LOONGARCH,
|
||||
CS_ARCH_MIPS, CS_ARCH_PPC, CS_ARCH_MAX },
|
||||
CS_OPT_SYNTAX_NOREGNAME, 0 },
|
||||
{ "+moto", "Use $ as hex prefix", {
|
||||
CS_ARCH_MOS65XX, CS_ARCH_MAX }, CS_OPT_SYNTAX_MOTOROLA, 0 },
|
||||
{ "+regalias", "Use register aliases, like r9 > sb", {
|
||||
CS_ARCH_ARM, CS_ARCH_AARCH64, CS_ARCH_MAX },
|
||||
CS_OPT_SYNTAX_CS_REG_ALIAS, 0 },
|
||||
{ "+percentage", "Adds % in front of the registers", {
|
||||
CS_ARCH_PPC, CS_ARCH_MAX }, CS_OPT_SYNTAX_PERCENT, 0 },
|
||||
{ "+nodollar", "Removes $ in front of the registers", {
|
||||
CS_ARCH_MIPS, CS_ARCH_MAX }, CS_OPT_SYNTAX_NO_DOLLAR, 0 },
|
||||
// cs_mode only
|
||||
{ "+nofloat", "Disables floating point support", {
|
||||
CS_ARCH_MIPS, CS_ARCH_MAX }, 0, CS_MODE_MIPS_NOFLOAT },
|
||||
{ "+ptr64", "Enables 64-bit pointers support", {
|
||||
CS_ARCH_MIPS, CS_ARCH_MAX }, 0, CS_MODE_MIPS_PTR64 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
const char *desc;
|
||||
cs_arch arch;
|
||||
cs_mode mode;
|
||||
} all_archs[] = {
|
||||
{ "arm", "ARM, little endian", CS_ARCH_ARM, CS_MODE_ARM },
|
||||
{ "armle", "ARM, little endian", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_LITTLE_ENDIAN },
|
||||
{ "armbe", "ARM, big endian", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_BIG_ENDIAN },
|
||||
{ "armv8", "ARM v8", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_V8 },
|
||||
{ "armv8be", "ARM v8, big endian", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_V8 | CS_MODE_BIG_ENDIAN },
|
||||
{ "cortexm", "ARM Cortex-M Thumb", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_MCLASS },
|
||||
{ "cortexmv8", "ARM Cortex-M Thumb, v8", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_MCLASS | CS_MODE_V8 },
|
||||
{ "thumb", "ARM Thumb mode, little endian", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB },
|
||||
{ "thumble", "ARM Thumb mode, little endian", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_LITTLE_ENDIAN },
|
||||
{ "thumbbe", "ARM Thumb mode, big endian", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_BIG_ENDIAN },
|
||||
{ "thumbv8", "ARM Thumb v8", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_V8 },
|
||||
{ "thumbv8be", "ARM Thumb v8, big endian", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_V8 | CS_MODE_BIG_ENDIAN },
|
||||
|
||||
{ "aarch64", "AArch64", CS_ARCH_AARCH64, CS_MODE_LITTLE_ENDIAN },
|
||||
{ "aarch64be", "AArch64, big endian", CS_ARCH_AARCH64, CS_MODE_BIG_ENDIAN },
|
||||
|
||||
{ "alpha", "Alpha, little endian", CS_ARCH_ALPHA, CS_MODE_LITTLE_ENDIAN },
|
||||
{ "alphabe", "Alpha, big endian", CS_ARCH_ALPHA, CS_MODE_BIG_ENDIAN },
|
||||
|
||||
{ "hppa11", "HPPA V1.1, little endian", CS_ARCH_HPPA, CS_MODE_HPPA_11 | CS_MODE_LITTLE_ENDIAN },
|
||||
{ "hppa11be", "HPPA V1.1, big endian", CS_ARCH_HPPA, CS_MODE_HPPA_11 | CS_MODE_BIG_ENDIAN },
|
||||
{ "hppa20", "HPPA V2.0, little endian", CS_ARCH_HPPA, CS_MODE_HPPA_20 | CS_MODE_LITTLE_ENDIAN },
|
||||
{ "hppa20be", "HPPA V2.0, big endian", CS_ARCH_HPPA, CS_MODE_HPPA_20 | CS_MODE_BIG_ENDIAN },
|
||||
{ "hppa20w", "HPPA V2.0 wide, little endian", CS_ARCH_HPPA, CS_MODE_HPPA_20W | CS_MODE_LITTLE_ENDIAN },
|
||||
{ "hppa20wbe", "HPPA V2.0 wide, big endian", CS_ARCH_HPPA, CS_MODE_HPPA_20W | CS_MODE_BIG_ENDIAN },
|
||||
|
||||
{ "mipsel16", "Mips 16-bit (generic), little endian", CS_ARCH_MIPS, CS_MODE_MIPS16 },
|
||||
{ "mips16", "Mips 16-bit (generic)", CS_ARCH_MIPS, CS_MODE_MIPS16 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel", "Mips 32-bit (generic), little endian", CS_ARCH_MIPS, CS_MODE_MIPS32 },
|
||||
{ "mips", "Mips 32-bit (generic)", CS_ARCH_MIPS, CS_MODE_MIPS32 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel64", "Mips 64-bit (generic), little endian", CS_ARCH_MIPS, CS_MODE_MIPS64 },
|
||||
{ "mips64", "Mips 64-bit (generic)", CS_ARCH_MIPS, CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN },
|
||||
{ "micromipsel", "MicroMips, little endian", CS_ARCH_MIPS, CS_MODE_MICRO },
|
||||
{ "micromips", "MicroMips", CS_ARCH_MIPS, CS_MODE_MICRO | CS_MODE_BIG_ENDIAN },
|
||||
{ "micromipselr3", "MicroMips32r3, little endian", CS_ARCH_MIPS, CS_MODE_MICRO32R3 },
|
||||
{ "micromipsr3", "MicroMips32r3", CS_ARCH_MIPS, CS_MODE_MICRO32R3 | CS_MODE_BIG_ENDIAN },
|
||||
{ "micromipselr6", "MicroMips32r6, little endian", CS_ARCH_MIPS, CS_MODE_MICRO32R6 },
|
||||
{ "micromipsr6", "MicroMips32r6", CS_ARCH_MIPS, CS_MODE_MICRO32R6 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel1", "Mips I ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS1 },
|
||||
{ "mips1", "Mips I ISA", CS_ARCH_MIPS, CS_MODE_MIPS1 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel2", "Mips II ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS2 },
|
||||
{ "mips2", "Mips II ISA", CS_ARCH_MIPS, CS_MODE_MIPS2 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel32r2", "Mips32 r2 ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS32R2 },
|
||||
{ "mips32r2", "Mips32 r2 ISA", CS_ARCH_MIPS, CS_MODE_MIPS32R2 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel32r3", "Mips32 r3 ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS32R3 },
|
||||
{ "mips32r3", "Mips32 r3 ISA", CS_ARCH_MIPS, CS_MODE_MIPS32R3 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel32r5", "Mips32 r5 ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS32R5 },
|
||||
{ "mips32r5", "Mips32 r5 ISA", CS_ARCH_MIPS, CS_MODE_MIPS32R5 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel32r6", "Mips32 r6 ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS32R6 },
|
||||
{ "mips32r6", "Mips32 r6 ISA", CS_ARCH_MIPS, CS_MODE_MIPS32R6 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel3", "Mips III ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS3 },
|
||||
{ "mips3", "Mips III ISA", CS_ARCH_MIPS, CS_MODE_MIPS3 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel4", "Mips IV ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS4 },
|
||||
{ "mips4", "Mips IV ISA", CS_ARCH_MIPS, CS_MODE_MIPS4 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel5", "Mips V ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS5 },
|
||||
{ "mips5", "Mips V ISA", CS_ARCH_MIPS, CS_MODE_MIPS5 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel64r2", "Mips64 r2 ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS64R2 },
|
||||
{ "mips64r2", "Mips64 r2 ISA", CS_ARCH_MIPS, CS_MODE_MIPS64R2 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel64r3", "Mips64 r3 ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS64R3 },
|
||||
{ "mips64r3", "Mips64 r3 ISA", CS_ARCH_MIPS, CS_MODE_MIPS64R3 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel64r5", "Mips64 r5 ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS64R5 },
|
||||
{ "mips64r5", "Mips64 r5 ISA", CS_ARCH_MIPS, CS_MODE_MIPS64R5 | CS_MODE_BIG_ENDIAN },
|
||||
{ "mipsel64r6", "Mips64 r6 ISA, little endian", CS_ARCH_MIPS, CS_MODE_MIPS64R6 },
|
||||
{ "mips64r6", "Mips64 r6 ISA", CS_ARCH_MIPS, CS_MODE_MIPS64R6 | CS_MODE_BIG_ENDIAN },
|
||||
{ "octeonle", "Octeon cnMIPS, little endian", CS_ARCH_MIPS, CS_MODE_OCTEON },
|
||||
{ "octeon", "Octeon cnMIPS", CS_ARCH_MIPS, CS_MODE_OCTEON | CS_MODE_BIG_ENDIAN },
|
||||
{ "octeonple", "Octeon+ cnMIPS, little endian", CS_ARCH_MIPS, CS_MODE_OCTEONP },
|
||||
{ "octeonp", "Octeon+ cnMIPS", CS_ARCH_MIPS, CS_MODE_OCTEONP | CS_MODE_BIG_ENDIAN },
|
||||
{ "nanomips", "nanoMIPS", CS_ARCH_MIPS, CS_MODE_NANOMIPS },
|
||||
{ "nms1", "nanoMIPS Subset", CS_ARCH_MIPS, CS_MODE_NMS1 },
|
||||
{ "i7200", "nanoMIPS i7200", CS_ARCH_MIPS, CS_MODE_I7200 },
|
||||
|
||||
{ "x16", "x86 16-bit mode", CS_ARCH_X86, CS_MODE_16 }, // CS_MODE_16
|
||||
{ "x32", "x86 32-bit mode", CS_ARCH_X86, CS_MODE_32 }, // CS_MODE_32
|
||||
{ "x64", "x86 64-bit mode", CS_ARCH_X86, CS_MODE_64 }, // CS_MODE_64
|
||||
|
||||
{ "ppc32", "PowerPC 32-bit, little endian", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_LITTLE_ENDIAN },
|
||||
{ "ppc32be", "PowerPC 32-bit, big endian", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_BIG_ENDIAN },
|
||||
{ "ppc32qpx", "PowerPC 32-bit, qpx, little endian", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_QPX | CS_MODE_LITTLE_ENDIAN },
|
||||
{ "ppc32beqpx", "PowerPC 32-bit, qpx, big endian", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_QPX | CS_MODE_BIG_ENDIAN },
|
||||
{ "ppc32ps", "PowerPC 32-bit, ps, little endian", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_PS | CS_MODE_LITTLE_ENDIAN },
|
||||
{ "ppc32beps", "PowerPC 32-bit, ps, big endian", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_PS | CS_MODE_BIG_ENDIAN },
|
||||
{ "ppc64", "PowerPC 64-bit, little endian", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_LITTLE_ENDIAN },
|
||||
{ "ppc64be", "PowerPC 64-bit, big endian", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN },
|
||||
{ "ppc64qpx", "PowerPC 64-bit, qpx, little endian", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_QPX | CS_MODE_LITTLE_ENDIAN },
|
||||
{ "ppc64beqpx", "PowerPC 64-bit, qpx, big endian", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_QPX | CS_MODE_BIG_ENDIAN },
|
||||
|
||||
{ "sparc", "Sparc, big endian", CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN },
|
||||
{ "sparcv9", "Sparc v9, big endian", CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN | CS_MODE_V9 },
|
||||
|
||||
{ "systemz", "systemz (s390x) - all features", CS_ARCH_SYSTEMZ, CS_MODE_BIG_ENDIAN },
|
||||
{ "systemz_arch8", "(arch8/z10/generic)\n", CS_ARCH_SYSTEMZ, CS_MODE_SYSTEMZ_ARCH8 | CS_MODE_BIG_ENDIAN },
|
||||
{ "systemz_arch9", "(arch9/z196)\n", CS_ARCH_SYSTEMZ, CS_MODE_SYSTEMZ_ARCH9 | CS_MODE_BIG_ENDIAN },
|
||||
{ "systemz_arch10", "(arch10/zec12)\n", CS_ARCH_SYSTEMZ, CS_MODE_SYSTEMZ_ARCH10 | CS_MODE_BIG_ENDIAN },
|
||||
{ "systemz_arch11", "(arch11/z13)\n", CS_ARCH_SYSTEMZ, CS_MODE_SYSTEMZ_ARCH11 | CS_MODE_BIG_ENDIAN },
|
||||
{ "systemz_arch12", "(arch12/z14)\n", CS_ARCH_SYSTEMZ, CS_MODE_SYSTEMZ_ARCH12 | CS_MODE_BIG_ENDIAN },
|
||||
{ "systemz_arch13", "(arch13/z15)\n", CS_ARCH_SYSTEMZ, CS_MODE_SYSTEMZ_ARCH13 | CS_MODE_BIG_ENDIAN },
|
||||
{ "systemz_arch14", "(arch14/z16)\n", CS_ARCH_SYSTEMZ, CS_MODE_SYSTEMZ_ARCH14 | CS_MODE_BIG_ENDIAN },
|
||||
|
||||
{ "s390x", "SystemZ s390x, big endian", CS_ARCH_SYSTEMZ, CS_MODE_BIG_ENDIAN },
|
||||
|
||||
{ "xcore", "xcore, big endian", CS_ARCH_XCORE, CS_MODE_BIG_ENDIAN },
|
||||
|
||||
{ "m68k", "m68k + big endian", CS_ARCH_M68K, CS_MODE_BIG_ENDIAN },
|
||||
{ "m68k40", "m68k40", CS_ARCH_M68K, CS_MODE_M68K_040 },
|
||||
|
||||
{ "tms320c64x", "tms320c64x, big endian", CS_ARCH_TMS320C64X, CS_MODE_BIG_ENDIAN },
|
||||
|
||||
{ "m6800", "m680x, M6800/2", CS_ARCH_M680X, CS_MODE_M680X_6800 },
|
||||
{ "m6801", "m680x, M6801/3", CS_ARCH_M680X, CS_MODE_M680X_6801 },
|
||||
{ "m6805", "m680x, M6805", CS_ARCH_M680X, CS_MODE_M680X_6805 },
|
||||
{ "m6808", "m680x, M68HC08", CS_ARCH_M680X, CS_MODE_M680X_6808 },
|
||||
{ "m6809", "m680x, M6809", CS_ARCH_M680X, CS_MODE_M680X_6809 },
|
||||
{ "m6811", "m680x, M68HC11", CS_ARCH_M680X, CS_MODE_M680X_6811 },
|
||||
{ "cpu12", "m680x, M68HC12/HCS12", CS_ARCH_M680X, CS_MODE_M680X_CPU12 },
|
||||
{ "hd6301", "m680x, HD6301/3", CS_ARCH_M680X, CS_MODE_M680X_6301 },
|
||||
{ "hd6309", "m680x, HD6309", CS_ARCH_M680X, CS_MODE_M680X_6309 },
|
||||
{ "hcs08", "m680x, HCS08", CS_ARCH_M680X, CS_MODE_M680X_HCS08 },
|
||||
|
||||
{ "evm", "ethereum virtual machine", CS_ARCH_EVM, 0 },
|
||||
|
||||
{ "wasm", "web assembly", CS_ARCH_WASM, 0 },
|
||||
|
||||
{ "bpf", "Classic BPF, little endian", CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_CLASSIC },
|
||||
{ "bpfbe", "Classic BPF, big endian", CS_ARCH_BPF, CS_MODE_BIG_ENDIAN | CS_MODE_BPF_CLASSIC },
|
||||
{ "ebpf", "Extended BPF, little endian", CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED },
|
||||
{ "ebpfbe", "Extended BPF, big endian", CS_ARCH_BPF, CS_MODE_BIG_ENDIAN | CS_MODE_BPF_EXTENDED },
|
||||
|
||||
{ "riscv32", "Risc-V 32-bit, little endian", CS_ARCH_RISCV, CS_MODE_RISCV32 | CS_MODE_RISCVC },
|
||||
{ "riscv64", "Risc-V 64-bit, little endian", CS_ARCH_RISCV, CS_MODE_RISCV64 | CS_MODE_RISCVC },
|
||||
|
||||
{ "6502", "MOS 6502", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_6502 },
|
||||
{ "65c02", "WDC 65c02", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_65C02 },
|
||||
{ "w65c02", "WDC w65c02", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_W65C02 },
|
||||
{ "65816", "WDC 65816 (long m/x)", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_65816_LONG_MX },
|
||||
|
||||
{ "sh", "SuperH SH1", CS_ARCH_SH, CS_MODE_BIG_ENDIAN },
|
||||
{ "sh2", "SuperH SH2", CS_ARCH_SH, CS_MODE_SH2 | CS_MODE_BIG_ENDIAN},
|
||||
{ "sh2e", "SuperH SH2E", CS_ARCH_SH, CS_MODE_SH2 | CS_MODE_SHFPU | CS_MODE_BIG_ENDIAN},
|
||||
{ "sh-dsp", "SuperH SH2-DSP", CS_ARCH_SH, CS_MODE_SH2 | CS_MODE_SHDSP | CS_MODE_BIG_ENDIAN},
|
||||
{ "sh2a", "SuperH SH2A", CS_ARCH_SH, CS_MODE_SH2A | CS_MODE_BIG_ENDIAN},
|
||||
{ "sh2a-fpu", "SuperH SH2A-FPU", CS_ARCH_SH, CS_MODE_SH2A | CS_MODE_SHFPU | CS_MODE_BIG_ENDIAN},
|
||||
{ "sh3", "SuperH SH3", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH3 },
|
||||
{ "sh3be", "SuperH SH3, big endian", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH3 },
|
||||
{ "sh3e", "SuperH SH3E", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH3 | CS_MODE_SHFPU},
|
||||
{ "sh3ebe", "SuperH SH3E, big endian", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH3 | CS_MODE_SHFPU},
|
||||
{ "sh3-dsp", "SuperH SH3-DSP", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH3 | CS_MODE_SHDSP },
|
||||
{ "sh3-dspbe", "SuperH SH3-DSP, big endian", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH3 | CS_MODE_SHDSP },
|
||||
{ "sh4", "SuperH SH4", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH4 | CS_MODE_SHFPU },
|
||||
{ "sh4be", "SuperH SH4, big endian", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH4 | CS_MODE_SHFPU },
|
||||
{ "sh4a", "SuperH SH4A", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH4A | CS_MODE_SHFPU },
|
||||
{ "sh4abe", "SuperH SH4A, big endian", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH4A | CS_MODE_SHFPU },
|
||||
{ "sh4al-dsp", "SuperH SH4AL-DSP", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH4A | CS_MODE_SHDSP | CS_MODE_SHFPU },
|
||||
{ "sh4al-dspbe", "SuperH SH4AL-DSP, big endian", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH4A | CS_MODE_SHDSP | CS_MODE_SHFPU },
|
||||
|
||||
{ "tc110", "Tricore V1.1", CS_ARCH_TRICORE, CS_MODE_TRICORE_110 },
|
||||
{ "tc120", "Tricore V1.2", CS_ARCH_TRICORE, CS_MODE_TRICORE_120 },
|
||||
{ "tc130", "Tricore V1.3", CS_ARCH_TRICORE, CS_MODE_TRICORE_130 },
|
||||
{ "tc131", "Tricore V1.3.1", CS_ARCH_TRICORE, CS_MODE_TRICORE_131 },
|
||||
{ "tc160", "Tricore V1.6", CS_ARCH_TRICORE, CS_MODE_TRICORE_160 },
|
||||
{ "tc161", "Tricore V1.6.1", CS_ARCH_TRICORE, CS_MODE_TRICORE_161 },
|
||||
{ "tc162", "Tricore V1.6.2", CS_ARCH_TRICORE, CS_MODE_TRICORE_162 },
|
||||
|
||||
{ "loongarch32", "LoongArch 32-bit", CS_ARCH_LOONGARCH, CS_MODE_LOONGARCH32 },
|
||||
{ "loongarch64", "LoongArch 64-bit", CS_ARCH_LOONGARCH, CS_MODE_LOONGARCH64 },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
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 const char *get_arch_name(cs_arch arch)
|
||||
{
|
||||
switch(arch) {
|
||||
case CS_ARCH_ARM: return "ARM";
|
||||
case CS_ARCH_AARCH64: return "Arm64";
|
||||
case CS_ARCH_MIPS: return "Mips";
|
||||
case CS_ARCH_X86: return "x86";
|
||||
case CS_ARCH_PPC: return "PowerPC";
|
||||
case CS_ARCH_SPARC: return "Sparc";
|
||||
case CS_ARCH_SYSTEMZ: return "SystemZ";
|
||||
case CS_ARCH_XCORE: return "Xcore";
|
||||
case CS_ARCH_M68K: return "M68K";
|
||||
case CS_ARCH_TMS320C64X: return "TMS320C64X";
|
||||
case CS_ARCH_M680X: return "M680X";
|
||||
case CS_ARCH_EVM: return "Evm";
|
||||
case CS_ARCH_MOS65XX: return "MOS65XX";
|
||||
case CS_ARCH_WASM: return "Wasm";
|
||||
case CS_ARCH_BPF: return "BPF";
|
||||
case CS_ARCH_RISCV: return "RiscV";
|
||||
case CS_ARCH_SH: return "SH";
|
||||
case CS_ARCH_TRICORE: return "TriCore";
|
||||
case CS_ARCH_ALPHA: return "Alpha";
|
||||
case CS_ARCH_HPPA: return "HPPA";
|
||||
case CS_ARCH_LOONGARCH: return "LoongArch";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void usage(char *prog)
|
||||
{
|
||||
int i, j;
|
||||
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|-a|-r|-s|-u|-v] <arch+opts> <assembly-hexstring> [start-address-in-hex-format]\n", prog);
|
||||
printf("\nThe following <arch+opts> options are supported:\n");
|
||||
|
||||
for (i = 0; all_archs[i].name; i++) {
|
||||
if (cs_support(all_archs[i].arch)) {
|
||||
printf(" %-16s %s\n", all_archs[i].name, all_archs[i].desc);
|
||||
}
|
||||
}
|
||||
|
||||
printf("\nArch specific options:\n");
|
||||
for (i = 0; all_opts[i].name; i++) {
|
||||
printf(" %-16s %s (only: ", all_opts[i].name, all_opts[i].desc);
|
||||
for (j = 0; j < CS_ARCH_MAX; j++) {
|
||||
cs_arch arch = all_opts[i].archs[j];
|
||||
const char *name = get_arch_name(arch);
|
||||
if (!name) {
|
||||
break;
|
||||
}
|
||||
if (j > 0) {
|
||||
printf(", %s", name);
|
||||
} else {
|
||||
printf("%s", name);
|
||||
}
|
||||
}
|
||||
printf(")\n");
|
||||
}
|
||||
|
||||
printf("\nExtra options:\n");
|
||||
printf(" -d show detailed information of the instructions\n");
|
||||
printf(" -r show detailed information of the real instructions (even for alias)\n");
|
||||
printf(" -a Print Capstone register alias (if any). Otherwise LLVM register names are emitted.\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));
|
||||
if (ins->is_alias) {
|
||||
printf("\tIs alias: %" PRIu64 " (%s) ", ins->alias_id, cs_insn_name(handle, ins->alias_id));
|
||||
printf("with %s operand set\n", ins->usesAliasDetails ? "ALIAS" : "REAL");
|
||||
}
|
||||
|
||||
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_AARCH64:
|
||||
print_insn_detail_aarch64(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_SYSTEMZ:
|
||||
print_insn_detail_systemz(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;
|
||||
case CS_ARCH_SH:
|
||||
print_insn_detail_sh(handle, ins);
|
||||
break;
|
||||
case CS_ARCH_TRICORE:
|
||||
print_insn_detail_tricore(handle, ins);
|
||||
break;
|
||||
case CS_ARCH_ALPHA:
|
||||
print_insn_detail_alpha(handle, ins);
|
||||
break;
|
||||
case CS_ARCH_HPPA:
|
||||
print_insn_detail_hppa(handle, ins);
|
||||
break;
|
||||
case CS_ARCH_LOONGARCH:
|
||||
print_insn_detail_loongarch(handle, ins);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if (ins->detail && 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");
|
||||
}
|
||||
|
||||
static cs_mode find_additional_modes(const char *input, cs_arch arch) {
|
||||
if (!input) {
|
||||
return 0;
|
||||
}
|
||||
cs_mode mode = 0;
|
||||
int i, j;
|
||||
for (i = 0; all_opts[i].name; i++) {
|
||||
if (all_opts[i].opt || !strstr(input, all_opts[i].name)) {
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < CS_ARCH_MAX; j++) {
|
||||
if (arch == all_opts[i].archs[j]) {
|
||||
mode |= all_opts[i].mode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
static void enable_additional_options(csh handle, const char *input, cs_arch arch) {
|
||||
if (!input) {
|
||||
return;
|
||||
}
|
||||
int i, j;
|
||||
for (i = 0; all_opts[i].name; i++) {
|
||||
if (all_opts[i].mode || !strstr(input, all_opts[i].name)) {
|
||||
continue;
|
||||
}
|
||||
for (j = 0; j < CS_ARCH_MAX; j++) {
|
||||
if (arch == all_opts[i].archs[j]) {
|
||||
cs_option(handle, CS_OPT_SYNTAX, all_opts[i].opt);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, c;
|
||||
csh handle;
|
||||
char *choosen_arch;
|
||||
uint8_t *assembly;
|
||||
size_t count, size;
|
||||
uint64_t address = 0LL;
|
||||
cs_insn *insn;
|
||||
cs_err err;
|
||||
cs_mode mode;
|
||||
cs_arch arch = CS_ARCH_ALL;
|
||||
bool detail_flag = false;
|
||||
bool unsigned_flag = false;
|
||||
bool skipdata = false;
|
||||
bool custom_reg_alias = false;
|
||||
bool set_real_detail = false;
|
||||
int args_left;
|
||||
|
||||
while ((c = getopt (argc, argv, "rasudhvf")) != -1) {
|
||||
switch (c) {
|
||||
case 'a':
|
||||
custom_reg_alias = true;
|
||||
break;
|
||||
case 'r':
|
||||
set_real_detail = true;
|
||||
break;
|
||||
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_AARCH64)) {
|
||||
printf("aarch64=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_SYSTEMZ)) {
|
||||
printf("systemz=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_ARCH_SH)) {
|
||||
printf("sh=1 ");
|
||||
}
|
||||
|
||||
if (cs_support(CS_SUPPORT_DIET)) {
|
||||
printf("diet=1 ");
|
||||
}
|
||||
|
||||
if (cs_support(CS_SUPPORT_X86_REDUCE)) {
|
||||
printf("x86_reduce=1 ");
|
||||
}
|
||||
|
||||
if (cs_support(CS_ARCH_TRICORE)) {
|
||||
printf("tricore=1 ");
|
||||
}
|
||||
|
||||
if (cs_support(CS_ARCH_ALPHA)) {
|
||||
printf("alpha=1 ");
|
||||
}
|
||||
|
||||
if (cs_support(CS_ARCH_HPPA)) {
|
||||
printf("hppa=1 ");
|
||||
}
|
||||
|
||||
if (cs_support(CS_ARCH_LOONGARCH)) {
|
||||
printf("loongarch=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;
|
||||
}
|
||||
|
||||
choosen_arch = 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) {
|
||||
fprintf(stderr, "ERROR: invalid address argument, quit!\n");
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
size_t arch_len = strlen(choosen_arch);
|
||||
const char *plus = strchr(choosen_arch, '+');
|
||||
if (plus) {
|
||||
arch_len = plus - choosen_arch;
|
||||
}
|
||||
|
||||
for (i = 0; all_archs[i].name; i++) {
|
||||
size_t len = strlen(all_archs[i].name);
|
||||
if (len == arch_len && !strncmp(all_archs[i].name, choosen_arch, arch_len)) {
|
||||
arch = all_archs[i].arch;
|
||||
mode = all_archs[i].mode;
|
||||
mode |= find_additional_modes(plus, arch);
|
||||
|
||||
err = cs_open(all_archs[i].arch, mode, &handle);
|
||||
if (!err) {
|
||||
enable_additional_options(handle, plus, arch);
|
||||
|
||||
// turn on SKIPDATA mode
|
||||
if (skipdata) {
|
||||
cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (arch == CS_ARCH_ALL) {
|
||||
fprintf(stderr, "ERROR: Invalid <arch+mode>: \"%s\", quit!\n", choosen_arch);
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
const char *error = cs_strerror(err);
|
||||
fprintf(stderr, "ERROR: Failed on cs_open(): %s\n", error);
|
||||
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);
|
||||
}
|
||||
|
||||
if (custom_reg_alias) {
|
||||
cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_CS_REG_ALIAS);
|
||||
}
|
||||
|
||||
if (set_real_detail) {
|
||||
cs_option(handle, CS_OPT_DETAIL, (CS_OPT_DETAIL_REAL | CS_OPT_ON));
|
||||
}
|
||||
|
||||
count = cs_disasm(handle, assembly, size, address, 0, &insn);
|
||||
if (count > 0) {
|
||||
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]);
|
||||
}
|
||||
// Align instruction when it varies in size.
|
||||
// ex: x86, s390x or compressed riscv
|
||||
if (arch == CS_ARCH_RISCV) {
|
||||
for (; j < 4; j++) {
|
||||
printf(" ");
|
||||
}
|
||||
} else if (arch == CS_ARCH_X86) {
|
||||
for (; j < 16; j++) {
|
||||
printf(" ");
|
||||
}
|
||||
} else if (arch == CS_ARCH_SYSTEMZ) {
|
||||
for (; j < 6; j++) {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
printf(" %s\t%s\n", insn[i].mnemonic, insn[i].op_str);
|
||||
|
||||
if (detail_flag) {
|
||||
print_details(handle, arch, mode, &insn[i]);
|
||||
}
|
||||
}
|
||||
|
||||
cs_free(insn, count);
|
||||
free(assembly);
|
||||
} else {
|
||||
fprintf(stderr, "ERROR: invalid assembly code\n");
|
||||
cs_close(&handle);
|
||||
free(assembly);
|
||||
return(-4);
|
||||
}
|
||||
|
||||
cs_close(&handle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
26
cstool/cstool.h
Normal file
26
cstool/cstool.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef CAPSTONE_CSTOOL_CSTOOL_H_
|
||||
#define CAPSTONE_CSTOOL_CSTOOL_H_
|
||||
|
||||
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_aarch64(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_systemz(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);
|
||||
void print_insn_detail_sh(csh handle, cs_insn *ins);
|
||||
void print_insn_detail_tricore(csh handle, cs_insn *ins);
|
||||
void print_insn_detail_alpha(csh handle, cs_insn *ins);
|
||||
void print_insn_detail_hppa(csh handle, cs_insn *ins);
|
||||
void print_insn_detail_loongarch(csh handle, cs_insn *ins);
|
||||
|
||||
#endif //CAPSTONE_CSTOOL_CSTOOL_H_
|
||||
245
cstool/cstool_aarch64.c
Normal file
245
cstool/cstool_aarch64.c
Normal file
@@ -0,0 +1,245 @@
|
||||
/* Capstone Disassembler Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
|
||||
|
||||
#include "capstone/aarch64.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
void print_insn_detail_aarch64(csh handle, cs_insn *ins)
|
||||
{
|
||||
cs_aarch64 *aarch64;
|
||||
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;
|
||||
|
||||
aarch64 = &(ins->detail->aarch64);
|
||||
if (aarch64->op_count)
|
||||
printf("\top_count: %u\n", aarch64->op_count);
|
||||
|
||||
for (i = 0; i < aarch64->op_count; i++) {
|
||||
cs_aarch64_op *op = &(aarch64->operands[i]);
|
||||
switch(op->type) {
|
||||
default:
|
||||
printf("\t\tOperand type %" PRId32 " not handled\n", op->type);
|
||||
break;
|
||||
case AARCH64_OP_REG:
|
||||
printf("\t\toperands[%u].type: REG = %s%s\n", i, cs_reg_name(handle, op->reg), op->is_vreg ? " (vreg)" : "");
|
||||
if (op->is_list_member) {
|
||||
printf("\t\toperands[%u].is_list_member: true\n", i);
|
||||
}
|
||||
break;
|
||||
case AARCH64_OP_IMM:
|
||||
printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
|
||||
break;
|
||||
case AARCH64_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 AARCH64_OP_MEM:
|
||||
printf("\t\toperands[%u].type: MEM\n", i);
|
||||
if (op->mem.base != AARCH64_REG_INVALID)
|
||||
printf("\t\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(handle, op->mem.base));
|
||||
if (op->mem.index != AARCH64_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 (ins->detail->aarch64.post_index)
|
||||
printf("\t\t\tpost-indexed: true\n");
|
||||
|
||||
break;
|
||||
case AARCH64_OP_SME:
|
||||
printf("\t\toperands[%u].type: SME_MATRIX\n", i);
|
||||
printf("\t\toperands[%u].sme.type: %d\n", i, op->sme.type);
|
||||
|
||||
if (op->sme.tile != AARCH64_REG_INVALID)
|
||||
printf("\t\toperands[%u].sme.tile: %s\n", i, cs_reg_name(handle, op->sme.tile));
|
||||
if (op->sme.slice_reg != AARCH64_REG_INVALID)
|
||||
printf("\t\toperands[%u].sme.slice_reg: %s\n", i, cs_reg_name(handle, op->sme.slice_reg));
|
||||
if (op->sme.slice_offset.imm != AARCH64_SLICE_IMM_INVALID || op->sme.slice_offset.imm_range.first != AARCH64_SLICE_IMM_RANGE_INVALID) {
|
||||
printf("\t\toperands[%u].sme.slice_offset: ", i);
|
||||
if (op->sme.has_range_offset)
|
||||
printf("%hhd:%hhd\n", op->sme.slice_offset.imm_range.first, op->sme.slice_offset.imm_range.offset);
|
||||
else
|
||||
printf("%d\n", op->sme.slice_offset.imm);
|
||||
}
|
||||
if (op->sme.slice_reg != AARCH64_REG_INVALID || op->sme.slice_offset.imm != AARCH64_SLICE_IMM_INVALID)
|
||||
printf("\t\toperands[%u].sme.is_vertical: %s\n", i, (op->sme.is_vertical ? "true" : "false"));
|
||||
break;
|
||||
case AARCH64_OP_PRED:
|
||||
printf("\t\toperands[%u].type: PREDICATE\n", i);
|
||||
if (op->pred.reg != AARCH64_REG_INVALID)
|
||||
printf("\t\toperands[%u].pred.reg: %s\n", i, cs_reg_name(handle, op->pred.reg));
|
||||
if (op->pred.vec_select != AARCH64_REG_INVALID)
|
||||
printf("\t\toperands[%u].pred.vec_select: %s\n", i, cs_reg_name(handle, op->pred.vec_select));
|
||||
if (op->pred.imm_index != -1)
|
||||
printf("\t\toperands[%u].pred.imm_index: %d\n", i, op->pred.imm_index);
|
||||
break;
|
||||
case AARCH64_OP_CIMM:
|
||||
printf("\t\toperands[%u].type: C-IMM = %u\n", i, (int)op->imm);
|
||||
break;
|
||||
case AARCH64_OP_SYSREG:
|
||||
printf("\t\toperands[%u].type: SYS REG:\n", i);
|
||||
switch (op->sysop.sub_type) {
|
||||
default:
|
||||
printf("Sub type %d not handled.\n", op->sysop.sub_type);
|
||||
break;
|
||||
case AARCH64_OP_REG_MRS:
|
||||
printf("\t\toperands[%u].subtype: REG_MRS = 0x%x\n", i, op->sysop.reg.sysreg);
|
||||
break;
|
||||
case AARCH64_OP_REG_MSR:
|
||||
printf("\t\toperands[%u].subtype: REG_MSR = 0x%x\n", i, op->sysop.reg.sysreg);
|
||||
break;
|
||||
case AARCH64_OP_TLBI:
|
||||
printf("\t\toperands[%u].subtype TLBI = 0x%x\n", i, op->sysop.reg.tlbi);
|
||||
break;
|
||||
case AARCH64_OP_IC:
|
||||
printf("\t\toperands[%u].subtype IC = 0x%x\n", i, op->sysop.reg.ic);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AARCH64_OP_SYSALIAS:
|
||||
printf("\t\toperands[%u].type: SYS ALIAS:\n", i);
|
||||
switch (op->sysop.sub_type) {
|
||||
default:
|
||||
printf("Sub type %d not handled.\n", op->sysop.sub_type);
|
||||
break;
|
||||
case AARCH64_OP_SVCR:
|
||||
if(op->sysop.alias.svcr == AARCH64_SVCR_SVCRSM)
|
||||
printf("\t\t\toperands[%u].svcr: BIT = SM\n", i);
|
||||
else if(op->sysop.alias.svcr == AARCH64_SVCR_SVCRZA)
|
||||
printf("\t\t\toperands[%u].svcr: BIT = ZA\n", i);
|
||||
else if(op->sysop.alias.svcr == AARCH64_SVCR_SVCRSMZA)
|
||||
printf("\t\t\toperands[%u].svcr: BIT = SM & ZA\n", i);
|
||||
break;
|
||||
case AARCH64_OP_AT:
|
||||
printf("\t\toperands[%u].subtype AT = 0x%x\n", i, op->sysop.alias.at);
|
||||
break;
|
||||
case AARCH64_OP_DB:
|
||||
printf("\t\toperands[%u].subtype DB = 0x%x\n", i, op->sysop.alias.db);
|
||||
break;
|
||||
case AARCH64_OP_DC:
|
||||
printf("\t\toperands[%u].subtype DC = 0x%x\n", i, op->sysop.alias.dc);
|
||||
break;
|
||||
case AARCH64_OP_ISB:
|
||||
printf("\t\toperands[%u].subtype ISB = 0x%x\n", i, op->sysop.alias.isb);
|
||||
break;
|
||||
case AARCH64_OP_TSB:
|
||||
printf("\t\toperands[%u].subtype TSB = 0x%x\n", i, op->sysop.alias.tsb);
|
||||
break;
|
||||
case AARCH64_OP_PRFM:
|
||||
printf("\t\toperands[%u].subtype PRFM = 0x%x\n", i, op->sysop.alias.prfm);
|
||||
break;
|
||||
case AARCH64_OP_SVEPRFM:
|
||||
printf("\t\toperands[%u].subtype SVEPRFM = 0x%x\n", i, op->sysop.alias.sveprfm);
|
||||
break;
|
||||
case AARCH64_OP_RPRFM:
|
||||
printf("\t\toperands[%u].subtype RPRFM = 0x%x\n", i, op->sysop.alias.rprfm);
|
||||
break;
|
||||
case AARCH64_OP_PSTATEIMM0_15:
|
||||
printf("\t\toperands[%u].subtype PSTATEIMM0_15 = 0x%x\n", i, op->sysop.alias.pstateimm0_15);
|
||||
break;
|
||||
case AARCH64_OP_PSTATEIMM0_1:
|
||||
printf("\t\toperands[%u].subtype PSTATEIMM0_1 = 0x%x\n", i, op->sysop.alias.pstateimm0_1);
|
||||
break;
|
||||
case AARCH64_OP_PSB:
|
||||
printf("\t\toperands[%u].subtype PSB = 0x%x\n", i, op->sysop.alias.psb);
|
||||
break;
|
||||
case AARCH64_OP_BTI:
|
||||
printf("\t\toperands[%u].subtype BTI = 0x%x\n", i, op->sysop.alias.bti);
|
||||
break;
|
||||
case AARCH64_OP_SVEPREDPAT:
|
||||
printf("\t\toperands[%u].subtype SVEPREDPAT = 0x%x\n", i, op->sysop.alias.svepredpat);
|
||||
break;
|
||||
case AARCH64_OP_SVEVECLENSPECIFIER:
|
||||
printf("\t\toperands[%u].subtype SVEVECLENSPECIFIER = 0x%x\n", i, op->sysop.alias.sveveclenspecifier);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case AARCH64_OP_SYSIMM:
|
||||
printf("\t\toperands[%u].type: SYS IMM:\n", i);
|
||||
switch(op->sysop.sub_type) {
|
||||
default:
|
||||
printf("Sub type %d not handled.\n", op->sysop.sub_type);
|
||||
break;
|
||||
case AARCH64_OP_EXACTFPIMM:
|
||||
printf("\t\toperands[%u].subtype EXACTFPIMM = %d\n", i, op->sysop.imm.exactfpimm);
|
||||
break;
|
||||
case AARCH64_OP_DBNXS:
|
||||
printf("\t\toperands[%u].subtype DBNXS = %d\n", i, op->sysop.imm.dbnxs);
|
||||
break;
|
||||
}
|
||||
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 != AARCH64_SFT_INVALID &&
|
||||
op->shift.value)
|
||||
printf("\t\t\tShift: type = %u, value = %u\n",
|
||||
op->shift.type, op->shift.value);
|
||||
|
||||
if (op->ext != AARCH64_EXT_INVALID)
|
||||
printf("\t\t\tExt: %u\n", op->ext);
|
||||
|
||||
if (op->vas != AARCH64LAYOUT_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 (aarch64->update_flags)
|
||||
printf("\tUpdate-flags: True\n");
|
||||
|
||||
if (ins->detail->writeback)
|
||||
printf("\tWrite-back: True\n");
|
||||
|
||||
if (aarch64->cc != AArch64CC_Invalid)
|
||||
printf("\tCode-condition: %u\n", aarch64->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");
|
||||
}
|
||||
}
|
||||
}
|
||||
63
cstool/cstool_alpha.c
Normal file
63
cstool/cstool_alpha.c
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
void print_insn_detail_alpha(csh handle, cs_insn *ins)
|
||||
{
|
||||
cs_alpha *alpha;
|
||||
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;
|
||||
|
||||
alpha = &(ins->detail->alpha);
|
||||
|
||||
if (alpha->op_count)
|
||||
printf("\top_count: %u\n", alpha->op_count);
|
||||
|
||||
for (i = 0; i < alpha->op_count; i++) {
|
||||
cs_alpha_op *op = &(alpha->operands[i]);
|
||||
switch ((int)op->type) {
|
||||
default:
|
||||
break;
|
||||
case ALPHA_OP_REG:
|
||||
printf("\t\toperands[%u].type: REG = %s\n", i,
|
||||
cs_reg_name(handle, op->reg));
|
||||
break;
|
||||
case ALPHA_OP_IMM:
|
||||
printf("\t\toperands[%u].type: IMM = 0x%x\n", i,
|
||||
op->imm);
|
||||
break;
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
200
cstool/cstool_arm.c
Normal file
200
cstool/cstool_arm.c
Normal file
@@ -0,0 +1,200 @@
|
||||
#include "capstone/arm.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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:
|
||||
if (op->imm < 0)
|
||||
printf("\t\toperands[%u].type: IMM = -0x%" PRIx64 "\n", i, -(op->imm));
|
||||
else
|
||||
printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
|
||||
break;
|
||||
case ARM_OP_PRED:
|
||||
printf("\t\toperands[%u].type: PRED = %d\n", i, op->pred);
|
||||
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 != 0)
|
||||
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.align != 0)
|
||||
printf("\t\t\toperands[%u].mem.align: 0x%x\n", i, op->mem.align);
|
||||
|
||||
break;
|
||||
case ARM_OP_PIMM:
|
||||
printf("\t\toperands[%u].type: P-IMM = %" PRIu64 "\n", i, op->imm);
|
||||
break;
|
||||
case ARM_OP_CIMM:
|
||||
printf("\t\toperands[%u].type: C-IMM = %" PRIu64 "\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_SYSM:
|
||||
printf("\t\toperands[%u].type: SYSM = 0x%" PRIx16 "\n", i, op->sysop.sysm);
|
||||
printf("\t\toperands[%u].type: MASK = %" PRIu8 "\n", i, op->sysop.msr_mask);
|
||||
break;
|
||||
case ARM_OP_SYSREG:
|
||||
printf("\t\toperands[%u].type: SYSREG = %s\n", i, cs_reg_name(handle, (uint32_t) op->sysop.reg.mclasssysreg));
|
||||
printf("\t\toperands[%u].type: MASK = %" PRIu8 "\n", i, op->sysop.msr_mask);
|
||||
break;
|
||||
case ARM_OP_BANKEDREG:
|
||||
// FIXME: Printing the name is currently not supported if the encodings overlap
|
||||
// with system registers.
|
||||
printf("\t\toperands[%u].type: BANKEDREG = %" PRIu32 "\n", i, (uint32_t) op->sysop.reg.bankedreg);
|
||||
if (op->sysop.msr_mask != UINT8_MAX)
|
||||
printf("\t\toperands[%u].type: MASK = %" PRIu8 "\n", i, op->sysop.msr_mask);
|
||||
break;
|
||||
case ARM_OP_SPSR:
|
||||
case ARM_OP_CPSR: {
|
||||
const char type = op->type == ARM_OP_SPSR ? 'S' : 'C';
|
||||
printf("\t\toperands[%u].type: %cPSR = ", i, type);
|
||||
uint16_t field = op->sysop.psr_bits;
|
||||
if ((field & ARM_FIELD_SPSR_F) || (field & ARM_FIELD_CPSR_F))
|
||||
printf("f");
|
||||
if ((field & ARM_FIELD_SPSR_S) || (field & ARM_FIELD_CPSR_S))
|
||||
printf("s");
|
||||
if ((field & ARM_FIELD_SPSR_X) || (field & ARM_FIELD_CPSR_X))
|
||||
printf("x");
|
||||
if ((field & ARM_FIELD_SPSR_C) || (field & ARM_FIELD_CPSR_C))
|
||||
printf("c");
|
||||
printf("\n");
|
||||
printf("\t\toperands[%u].type: MASK = %" PRIu8 "\n", i, op->sysop.msr_mask);
|
||||
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) {
|
||||
if (op->shift.type < ARM_SFT_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,
|
||||
op->shift.value > 0 ? 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 != ARMCC_AL && arm->cc != ARMCC_UNDEF)
|
||||
printf("\tCode condition: %u\n", arm->cc);
|
||||
|
||||
if (arm->vcc != ARMVCC_None)
|
||||
printf("\tVector code condition: %u\n", arm->vcc);
|
||||
|
||||
if (arm->update_flags)
|
||||
printf("\tUpdate-flags: True\n");
|
||||
|
||||
if (ins->detail->writeback) {
|
||||
printf("\tWrite-back: True\n");
|
||||
printf("\tPost index: %s\n", arm->post_index ? "True" : "False");
|
||||
}
|
||||
|
||||
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 != 0)
|
||||
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);
|
||||
|
||||
if (arm->pred_mask)
|
||||
printf("\tPredicate Mask: 0x%x\n", arm->pred_mask);
|
||||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
79
cstool/cstool_bpf.c
Normal file
79
cstool/cstool_bpf.c
Normal file
@@ -0,0 +1,79 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include <capstone/platform.h>
|
||||
#include "cstool.h"
|
||||
|
||||
static const char * ext_name[] = {
|
||||
[BPF_EXT_LEN] = "#len",
|
||||
};
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
25
cstool/cstool_evm.c
Normal file
25
cstool/cstool_evm.c
Normal file
@@ -0,0 +1,25 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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);
|
||||
}
|
||||
89
cstool/cstool_hppa.c
Normal file
89
cstool/cstool_hppa.c
Normal file
@@ -0,0 +1,89 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include <capstone/platform.h>
|
||||
#include "cstool.h"
|
||||
#include "limits.h"
|
||||
|
||||
void print_insn_detail_hppa(csh handle, cs_insn *ins)
|
||||
{
|
||||
cs_hppa *hppa;
|
||||
cs_regs regs_read, regs_write;
|
||||
uint8_t regs_read_count, regs_write_count;
|
||||
|
||||
if (ins->detail == NULL)
|
||||
return;
|
||||
|
||||
hppa = &ins->detail->hppa;
|
||||
|
||||
printf("\top_count: %u\n", hppa->op_count);
|
||||
for (unsigned i = 0; i < hppa->op_count; i++) {
|
||||
cs_hppa_op *op = &(hppa->operands[i]);
|
||||
uint64_t target_addr;
|
||||
switch (op->type) {
|
||||
default:
|
||||
break;
|
||||
case HPPA_OP_REG:
|
||||
printf("\t\toperands[%u].type: REG = %s\n", i,
|
||||
cs_reg_name(handle, op->reg));
|
||||
break;
|
||||
case HPPA_OP_IMM:
|
||||
if (op->imm < 0)
|
||||
printf("\t\toperands[%u].type: IMM = -0x%" PRIx64
|
||||
"\n",
|
||||
i, -(op->imm));
|
||||
else
|
||||
printf("\t\toperands[%u].type: IMM = 0x%" PRIx64
|
||||
"\n",
|
||||
i, op->imm);
|
||||
break;
|
||||
case HPPA_OP_IDX_REG:
|
||||
printf("\t\toperands[%u].type: IDX_REG = %s\n", i,
|
||||
cs_reg_name(handle, op->reg));
|
||||
break;
|
||||
case HPPA_OP_DISP:
|
||||
if (op->imm < 0)
|
||||
printf("\t\toperands[%u].type: DISP = -0x%" PRIx64
|
||||
"\n",
|
||||
i, -(op->imm));
|
||||
else
|
||||
printf("\t\toperands[%u].type: DISP = 0x%" PRIx64
|
||||
"\n",
|
||||
i, op->imm);
|
||||
break;
|
||||
case HPPA_OP_MEM:
|
||||
printf("\t\toperands[%u].type: MEM\n", i);
|
||||
if (op->mem.space != HPPA_REG_INVALID) {
|
||||
printf("\t\t\toperands[%u].mem.space: REG = %s\n",
|
||||
i, cs_reg_name(handle, op->mem.space));
|
||||
}
|
||||
printf("\t\t\toperands[%u].mem.base: REG = %s\n", i,
|
||||
cs_reg_name(handle, op->mem.base));
|
||||
break;
|
||||
case HPPA_OP_TARGET:
|
||||
printf("\t\toperands[%u].type: ", i);
|
||||
target_addr = ins->address + op->imm;
|
||||
printf("TARGET = 0x%" PRIx64 "\n", target_addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!cs_regs_access(handle, ins, regs_read, ®s_read_count,
|
||||
regs_write, ®s_write_count)) {
|
||||
if (regs_read_count) {
|
||||
printf("\tRegisters read:");
|
||||
for (unsigned 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 (unsigned i = 0; i < regs_write_count; i++)
|
||||
printf(" %s",
|
||||
cs_reg_name(handle, regs_write[i]));
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
91
cstool/cstool_loongarch.c
Normal file
91
cstool/cstool_loongarch.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/* Capstone Disassembler Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
|
||||
/* Jiajie Chen <c@jia.je>, 2013-2024 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
void print_insn_detail_loongarch(csh handle, cs_insn *ins)
|
||||
{
|
||||
cs_loongarch *loongarch;
|
||||
int i;
|
||||
cs_regs regs_read, regs_write;
|
||||
uint8_t regs_read_count, regs_write_count;
|
||||
uint8_t access;
|
||||
|
||||
// detail can be NULL on "data" instruction if SKIPDATA option is turned ON
|
||||
if (ins->detail == NULL)
|
||||
return;
|
||||
|
||||
loongarch = &(ins->detail->loongarch);
|
||||
if (loongarch->op_count)
|
||||
printf("\top_count: %u\n", loongarch->op_count);
|
||||
|
||||
for (i = 0; i < loongarch->op_count; i++) {
|
||||
cs_loongarch_op *op = &(loongarch->operands[i]);
|
||||
switch ((int)op->type) {
|
||||
default:
|
||||
break;
|
||||
case LOONGARCH_OP_REG:
|
||||
printf("\t\toperands[%u].type: REG = %s\n", i,
|
||||
cs_reg_name(handle, op->reg));
|
||||
break;
|
||||
case LOONGARCH_OP_IMM:
|
||||
printf("\t\toperands[%u].type: IMM = 0x%lx\n", i,
|
||||
(long)op->imm);
|
||||
break;
|
||||
case LOONGARCH_OP_MEM:
|
||||
printf("\t\toperands[%u].type: MEM\n", i);
|
||||
if (op->mem.base != LOONGARCH_REG_INVALID)
|
||||
printf("\t\t\toperands[%u].mem.base: REG = %s\n",
|
||||
i, cs_reg_name(handle, op->mem.base));
|
||||
if (op->mem.index != LOONGARCH_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%lx\n",
|
||||
i, (long)op->mem.disp);
|
||||
|
||||
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 (ins->detail->writeback)
|
||||
printf("\tWrite-back: True\n");
|
||||
|
||||
/* 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
154
cstool/cstool_m680x.c
Normal file
154
cstool/cstool_m680x.c
Normal file
@@ -0,0 +1,154 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* M680X Backend by Wolfgang Schwotzer <wolfgang.schwotzer@gmx.net> 2017 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
120
cstool/cstool_m68k.c
Normal file
120
cstool/cstool_m68k.c
Normal file
@@ -0,0 +1,120 @@
|
||||
//
|
||||
// cstool_m68k.c
|
||||
//
|
||||
//
|
||||
// Created by YUHANG TANG on 26/10/16.
|
||||
//
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
cstool/cstool_mips.c
Normal file
48
cstool/cstool_mips.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/* Capstone Disassembler Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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));
|
||||
printf("\t\toperands[%u].is_reglist: %s\n", i, op->is_reglist ? "true" : "false");
|
||||
break;
|
||||
case MIPS_OP_IMM:
|
||||
printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
|
||||
printf("\t\toperands[%u].is_unsigned: %s\n", i, op->is_unsigned ? "true" : "false");
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
98
cstool/cstool_mos65xx.c
Normal file
98
cstool/cstool_mos65xx.c
Normal file
@@ -0,0 +1,98 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
182
cstool/cstool_powerpc.c
Normal file
182
cstool/cstool_powerpc.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/* Capstone Disassembler Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "capstone/ppc.h"
|
||||
#include "cstool.h"
|
||||
|
||||
static const char* get_pred_name(ppc_pred pred)
|
||||
{
|
||||
switch(pred) {
|
||||
default:
|
||||
return ("invalid");
|
||||
case PPC_PRED_LT:
|
||||
case PPC_PRED_LT_MINUS:
|
||||
case PPC_PRED_LT_PLUS:
|
||||
case PPC_PRED_LT_RESERVED:
|
||||
return ("lt");
|
||||
case PPC_PRED_LE:
|
||||
case PPC_PRED_LE_MINUS:
|
||||
case PPC_PRED_LE_PLUS:
|
||||
case PPC_PRED_LE_RESERVED:
|
||||
return ("le");
|
||||
case PPC_PRED_EQ:
|
||||
case PPC_PRED_EQ_MINUS:
|
||||
case PPC_PRED_EQ_PLUS:
|
||||
case PPC_PRED_EQ_RESERVED:
|
||||
return ("eq");
|
||||
case PPC_PRED_GE:
|
||||
case PPC_PRED_GE_MINUS:
|
||||
case PPC_PRED_GE_PLUS:
|
||||
case PPC_PRED_GE_RESERVED:
|
||||
return ("ge");
|
||||
case PPC_PRED_GT:
|
||||
case PPC_PRED_GT_MINUS:
|
||||
case PPC_PRED_GT_PLUS:
|
||||
case PPC_PRED_GT_RESERVED:
|
||||
return ("gt");
|
||||
case PPC_PRED_NE:
|
||||
case PPC_PRED_NE_MINUS:
|
||||
case PPC_PRED_NE_PLUS:
|
||||
case PPC_PRED_NE_RESERVED:
|
||||
return ("ne");
|
||||
case PPC_PRED_UN: // PPC_PRED_SO
|
||||
case PPC_PRED_UN_MINUS:
|
||||
case PPC_PRED_UN_PLUS:
|
||||
case PPC_PRED_UN_RESERVED:
|
||||
return ("so/un");
|
||||
case PPC_PRED_NU: // PPC_PRED_NS
|
||||
case PPC_PRED_NU_MINUS:
|
||||
case PPC_PRED_NU_PLUS:
|
||||
case PPC_PRED_NU_RESERVED:
|
||||
return ("ns/nu");
|
||||
case PPC_PRED_NZ:
|
||||
case PPC_PRED_NZ_MINUS:
|
||||
case PPC_PRED_NZ_PLUS:
|
||||
case PPC_PRED_NZ_RESERVED:
|
||||
return ("nz");
|
||||
case PPC_PRED_Z:
|
||||
case PPC_PRED_Z_MINUS:
|
||||
case PPC_PRED_Z_PLUS:
|
||||
case PPC_PRED_Z_RESERVED:
|
||||
return ("z");
|
||||
case PPC_PRED_BIT_SET:
|
||||
return "bit-set";
|
||||
case PPC_PRED_BIT_UNSET:
|
||||
return "bit-unset";
|
||||
}
|
||||
}
|
||||
|
||||
static const char *get_pred_hint(ppc_br_hint at) {
|
||||
switch (at) {
|
||||
default:
|
||||
return "invalid";
|
||||
case PPC_BR_NOT_GIVEN:
|
||||
return "not-given";
|
||||
case PPC_BR_TAKEN:
|
||||
return "likely-taken";
|
||||
case PPC_BR_NOT_TAKEN:
|
||||
return "likely-not-taken";
|
||||
case PPC_BR_RESERVED:
|
||||
return "reserved";
|
||||
}
|
||||
}
|
||||
|
||||
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.offset != PPC_REG_INVALID)
|
||||
printf("\t\t\toperands[%u].mem.offset: REG = %s\n", i,
|
||||
cs_reg_name(handle, op->mem.offset));
|
||||
if (op->mem.disp != 0)
|
||||
printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
|
||||
|
||||
break;
|
||||
}
|
||||
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_WRITE:
|
||||
printf("\t\toperands[%u].access: READ | WRITE\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ppc->bc.pred_cr != PPC_PRED_INVALID ||
|
||||
ppc->bc.pred_ctr != PPC_PRED_INVALID) {
|
||||
printf("\tBranch:\n");
|
||||
printf("\t\tbi: %u\n", ppc->bc.bi);
|
||||
printf("\t\tbo: %u\n", ppc->bc.bo);
|
||||
if (ppc->bc.bh != PPC_BH_INVALID)
|
||||
printf("\t\tbh: %u\n", ppc->bc.bh);
|
||||
if (ppc->bc.pred_cr != PPC_PRED_INVALID) {
|
||||
printf("\t\tcrX: %s\n", cs_reg_name(handle, ppc->bc.crX));
|
||||
printf("\t\tpred CR-bit: %s\n", get_pred_name(ppc->bc.pred_cr));
|
||||
}
|
||||
if (ppc->bc.pred_ctr != PPC_PRED_INVALID)
|
||||
printf("\t\tpred CTR: %s\n", get_pred_name(ppc->bc.pred_ctr));
|
||||
if (ppc->bc.hint != PPC_BR_NOT_GIVEN)
|
||||
printf("\t\thint: %s\n", get_pred_hint(ppc->bc.hint));
|
||||
}
|
||||
|
||||
if (ppc->bc.hint != PPC_BR_NOT_GIVEN)
|
||||
printf("\tBranch hint: %u\n", ppc->bc.hint);
|
||||
|
||||
if (ppc->update_cr0)
|
||||
printf("\tUpdate-CR0: True\n");
|
||||
|
||||
uint16_t *regs_read = ins->detail->regs_read;
|
||||
uint16_t *regs_write = ins->detail->regs_write;
|
||||
uint8_t regs_read_count = ins->detail->regs_read_count;
|
||||
uint8_t regs_write_count = ins->detail->regs_write_count;
|
||||
// Print out all registers accessed by this instruction (either implicit or explicit)
|
||||
if (regs_read_count) {
|
||||
printf("\tImplicit registers 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("\tImplicit registers modified:");
|
||||
for(i = 0; i < regs_write_count; i++) {
|
||||
printf(" %s", cs_reg_name(handle, regs_write[i]));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
59
cstool/cstool_riscv.c
Normal file
59
cstool/cstool_riscv.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/* Capstone Disassembler Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
}
|
||||
87
cstool/cstool_sh.c
Normal file
87
cstool/cstool_sh.c
Normal file
@@ -0,0 +1,87 @@
|
||||
//
|
||||
// cstool_sh.c
|
||||
//
|
||||
// Yoshinori Sato 2022/09/07
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
static const char* s_addressing_modes[] = {
|
||||
"<invalid mode>",
|
||||
|
||||
"Register Direct", /// Rn
|
||||
|
||||
"Register Indirect", /// @Rn
|
||||
"Register Indirect with Postincrement", /// @Rn+
|
||||
"Register Indirect with Predecrement", /// @-Rn
|
||||
"Register Indirect with Displacement", /// @(disp,Rn)
|
||||
|
||||
"Indexed register indirect", /// @(R0, Rn)
|
||||
"GBR indirect with displacement", /// @(disp,GBR)
|
||||
"Indexed GBR indirect", /// @(R0, GBR)
|
||||
|
||||
"PC-relative with Displacement", /// @(disp, PC)
|
||||
|
||||
"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_sh(csh handle, cs_insn *ins)
|
||||
{
|
||||
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;
|
||||
|
||||
print_read_write_regs(detail, handle);
|
||||
|
||||
printf("\tgroups_count: %u\n", detail->groups_count);
|
||||
|
||||
for (i = 0; i < detail->sh.op_count; i++) {
|
||||
cs_sh_op* op = &(detail->sh.operands[i]);
|
||||
|
||||
switch((int)op->type) {
|
||||
default:
|
||||
break;
|
||||
case SH_OP_REG:
|
||||
printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
|
||||
break;
|
||||
case SH_OP_IMM:
|
||||
printf("\t\toperands[%u].type: IMM = 0x%x\n", i, (int)op->imm);
|
||||
break;
|
||||
case SH_OP_MEM:
|
||||
printf("\t\toperands[%u].type: MEM\n", i);
|
||||
if (op->mem.reg != SH_REG_INVALID)
|
||||
printf("\t\t\toperands[%u].mem.reg: REG = %s\n",
|
||||
i, cs_reg_name(handle, op->mem.reg));
|
||||
if (op->mem.disp != 0)
|
||||
printf("\t\t\toperands[%u].mem.disp: 0x%x\n",
|
||||
i, op->mem.disp);
|
||||
printf("\t\taddress mode: %s\n", s_addressing_modes[op->mem.address]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
53
cstool/cstool_sparc.c
Normal file
53
cstool/cstool_sparc.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/* Capstone Disassembler Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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);
|
||||
}
|
||||
85
cstool/cstool_systemz.c
Normal file
85
cstool/cstool_systemz.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/* Capstone Disassembler Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
void print_insn_detail_systemz(csh handle, cs_insn *ins)
|
||||
{
|
||||
cs_systemz *systemz;
|
||||
int i;
|
||||
|
||||
// detail can be NULL on "data" instruction if SKIPDATA option is turned ON
|
||||
if (ins->detail == NULL)
|
||||
return;
|
||||
|
||||
systemz = &(ins->detail->systemz);
|
||||
if (systemz->op_count)
|
||||
printf("\top_count: %u\n", systemz->op_count);
|
||||
|
||||
for (i = 0; i < systemz->op_count; i++) {
|
||||
cs_systemz_op *op = &(systemz->operands[i]);
|
||||
switch((int)op->type) {
|
||||
default:
|
||||
break;
|
||||
case SYSTEMZ_OP_REG:
|
||||
printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
|
||||
break;
|
||||
case SYSTEMZ_OP_IMM:
|
||||
printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
|
||||
break;
|
||||
case SYSTEMZ_OP_MEM:
|
||||
printf("\t\toperands[%u].type: MEM\n", i);
|
||||
if (op->mem.base != SYSTEMZ_REG_INVALID)
|
||||
printf("\t\t\toperands[%u].mem.base: REG = %s\n",
|
||||
i, cs_reg_name(handle, op->mem.base));
|
||||
if (op->mem.index != SYSTEMZ_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);
|
||||
}
|
||||
printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp);
|
||||
switch(op->mem.am) {
|
||||
default:
|
||||
printf("\t\t\toperands[%u].mem.am: UNHANDLED\n", i);
|
||||
break;
|
||||
case SYSTEMZ_AM_BD:
|
||||
printf("\t\t\toperands[%u].mem.am: SYSTEMZ_AM_BD\n", i);
|
||||
break;
|
||||
case SYSTEMZ_AM_BDX:
|
||||
printf("\t\t\toperands[%u].mem.am: SYSTEMZ_AM_BDX\n", i);
|
||||
break;
|
||||
case SYSTEMZ_AM_BDL:
|
||||
printf("\t\t\toperands[%u].mem.am: SYSTEMZ_AM_BDL\n", i);
|
||||
break;
|
||||
case SYSTEMZ_AM_BDR:
|
||||
printf("\t\t\toperands[%u].mem.am: SYSTEMZ_AM_BDR\n", i);
|
||||
break;
|
||||
case SYSTEMZ_AM_BDV:
|
||||
printf("\t\t\toperands[%u].mem.am: SYSTEMZ_AM_BDV\n", i);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
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 (systemz->cc != SYSTEMZ_CC_INVALID)
|
||||
printf("\tCode condition: %u\n", systemz->cc);
|
||||
}
|
||||
105
cstool/cstool_tms320c64x.c
Normal file
105
cstool/cstool_tms320c64x.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/* Capstone Disassembler Engine */
|
||||
/* By Fotis Loukos <me@fotisl.com>, 2017 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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");
|
||||
}
|
||||
83
cstool/cstool_tricore.c
Normal file
83
cstool/cstool_tricore.c
Normal file
@@ -0,0 +1,83 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
void print_insn_detail_tricore(csh handle, cs_insn *ins)
|
||||
{
|
||||
cs_tricore *tricore;
|
||||
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;
|
||||
|
||||
tricore = &(ins->detail->tricore);
|
||||
|
||||
if (tricore->op_count)
|
||||
printf("\top_count: %u\n", tricore->op_count);
|
||||
|
||||
for (i = 0; i < tricore->op_count; i++) {
|
||||
cs_tricore_op *op = &(tricore->operands[i]);
|
||||
switch ((int)op->type) {
|
||||
default:
|
||||
break;
|
||||
case TRICORE_OP_REG:
|
||||
printf("\t\toperands[%u].type: REG = %s\n", i,
|
||||
cs_reg_name(handle, op->reg));
|
||||
break;
|
||||
case TRICORE_OP_IMM:
|
||||
printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n",
|
||||
i, op->imm);
|
||||
break;
|
||||
case TRICORE_OP_MEM:
|
||||
printf("\t\toperands[%u].type: MEM\n"
|
||||
"\t\t\t.mem.base: REG = %s\n"
|
||||
"\t\t\t.mem.disp: 0x%" PRIx64 "\n",
|
||||
i, cs_reg_name(handle, op->mem.base),
|
||||
op->mem.disp);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (op->access) {
|
||||
default:
|
||||
break;
|
||||
case CS_AC_READ:
|
||||
printf("\t\t\t.access: READ\n");
|
||||
break;
|
||||
case CS_AC_WRITE:
|
||||
printf("\t\t\t.access: WRITE\n");
|
||||
break;
|
||||
case CS_AC_READ | CS_AC_WRITE:
|
||||
printf("\t\t\t.access: READ | WRITE\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
if (tricore->update_flags)
|
||||
printf("\tUpdate-flags: True\n");
|
||||
}
|
||||
50
cstool/cstool_wasm.c
Normal file
50
cstool/cstool_wasm.c
Normal file
@@ -0,0 +1,50 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
350
cstool/cstool_x86.c
Normal file
350
cstool/cstool_x86.c
Normal file
@@ -0,0 +1,350 @@
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013> */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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);
|
||||
if (index < 0) {
|
||||
printf("Operand was not found!\n");
|
||||
break;
|
||||
}
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
51
cstool/cstool_xcore.c
Normal file
51
cstool/cstool_xcore.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/* Capstone Disassembler Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
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");
|
||||
}
|
||||
76
cstool/getopt.c
Normal file
76
cstool/getopt.c
Normal file
@@ -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 */
|
||||
}
|
||||
|
||||
14
cstool/getopt.h
Normal file
14
cstool/getopt.h
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user