diff --git a/cstool/Makefile b/cstool/Makefile index adde1656..be2c05ca 100644 --- a/cstool/Makefile +++ b/cstool/Makefile @@ -2,19 +2,25 @@ include ../functions.mk -.PHONY: clean +.PHONY: clean all LIBNAME = capstone CFLAGS = -I../include LDFLAGS = -O3 -Wall -L.. -l$(LIBNAME) -cstool: cstool.o +TARGET = cstool +SOURCES := $(wildcard *.c) +OBJECTS := $(SOURCES:.c=.o) + +all: $(TARGET) + +$(TARGET): $(OBJECTS) ifeq ($(V),0) $(call log,LINK,$@) - @${CC} $< $(LDFLAGS) -o $@ + @${CC} $(OBJECTS) $(LDFLAGS) -o $@ else - ${CC} $< $(LDFLAGS) -o $@ + ${CC} $(OBJECTS) $(LDFLAGS) -o $@ endif clean: diff --git a/cstool/cstool.c b/cstool/cstool.c index e9bef7d4..9c396b00 100644 --- a/cstool/cstool.c +++ b/cstool/cstool.c @@ -1,4 +1,4 @@ -/* Tang Yuhang <1648200150@qq.com> 2016 */ +/* Tang Yuhang 2016 */ #include #include #include @@ -7,7 +7,16 @@ #include -#define VERSION "1.0" +#define VERSION "2.0" + +void print_insn_detail_x86(csh ud, cs_mode mode, cs_insn *ins); +void print_insn_detail_arm(csh handle, cs_insn *ins); +void print_insn_detail_arm64(csh handle, cs_insn *ins); +void print_insn_detail_mips(csh handle, cs_insn *ins); +void print_insn_detail_ppc(csh handle, cs_insn *ins); +void print_insn_detail_sparc(csh handle, cs_insn *ins); +void print_insn_detail_sysz(csh handle, cs_insn *ins); +void print_insn_detail_xcore(csh handle, cs_insn *ins); // convert hexchar to hexnum static uint8_t char_to_hexnum(char c) @@ -53,7 +62,7 @@ static uint8_t *preprocess(char *code, size_t *size) static void usage(char *prog) { printf("Cstool v%s for Capstone Disassembler Engine (www.capstone-engine.org)\n\n", VERSION); - printf("Syntax: %s [start-address-in-hex-format]\n", prog); + printf("Syntax: %s [-d:print all debug information] [start-address-in-hex-format]\n", prog); printf("\nThe following options are supported:\n"); if (cs_support(CS_ARCH_X86)) { @@ -114,91 +123,131 @@ int main(int argc, char **argv) uint64_t address = 0; cs_insn *insn; cs_err err; - bool x86_arch = false; + cs_mode md; + char *arch; + bool debug_flag = false; - if (argc != 3 && argc != 4) { + if (argc != 3 && argc != 4 && argc != 5) { usage(argv[0]); return -1; } - mode = argv[1]; - assembly = preprocess(argv[2], &size); - if (assembly == NULL) { - printf("ERROR: invalid assembler-string argument, quit!\n"); - return -3; + if (!strcmp(argv[1], "-d")) { + if (argc == 3) { + usage(argv[0]); + return -1; } + debug_flag = true; + mode = argv[2]; + assembly = preprocess(argv[3], &size); + if (argc == 5) { + char *temp; + address = strtoull(argv[4], &temp, 16); + if (temp == argv[4] || *temp != '\0' || errno == ERANGE) { + printf("ERROR: invalid address argument, quit!\n"); + return -2; + } + } + } else { + if (argc == 5) { + usage(argv[0]); + return -1; + } - if (argc == 4) { - // cstool
- char *temp; - address = strtoull(argv[3], &temp, 16); - if (temp == argv[3] || *temp != '\0' || errno == ERANGE) { - printf("ERROR: invalid address argument, quit!\n"); - return -2; + mode = argv[1]; + assembly = preprocess(argv[2], &size); + if (assembly == NULL) { + printf("ERROR: invalid assembler-string argument, quit!\n"); + return -3; + } + + if (argc == 4) { + // cstool
+ char *temp; + address = strtoull(argv[3], &temp, 16); + if (temp == argv[3] || *temp != '\0' || errno == ERANGE) { + printf("ERROR: invalid address argument, quit!\n"); + return -2; + } } } - + if (!strcmp(mode, "arm")) { + arch = "arm"; err = cs_open(CS_ARCH_ARM, CS_MODE_ARM, &handle); } if (!strcmp(mode, "armb")) { + arch = "arm"; err = cs_open(CS_ARCH_ARM, CS_MODE_ARM + CS_MODE_BIG_ENDIAN, &handle); } if (!strcmp(mode, "arml")) { + arch = "arm"; err = cs_open(CS_ARCH_ARM, CS_MODE_ARM + CS_MODE_LITTLE_ENDIAN, &handle); } if (!strcmp(mode, "thumb")) { + arch = "arm"; err = cs_open(CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_LITTLE_ENDIAN, &handle); } if (!strcmp(mode, "thumbbe")) { + arch = "arm"; err = cs_open(CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_BIG_ENDIAN, &handle); } if (!strcmp(mode, "thumble")) { + arch = "arm"; err = cs_open(CS_ARCH_ARM, CS_MODE_ARM + CS_MODE_LITTLE_ENDIAN, &handle); } if (!strcmp(mode, "arm64")) { + arch = "arm64"; err = cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &handle); } if (!strcmp(mode, "mips")) { + arch = "mips"; err = cs_open(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_LITTLE_ENDIAN, &handle); } if (!strcmp(mode, "mipsbe")) { + arch = "mips"; err = cs_open(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN, &handle); } if (!strcmp(mode, "mips64")) { + arch = "mips"; err = cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64 + CS_MODE_BIG_ENDIAN, &handle); } if (!strcmp(mode, "mips64be")) { + arch = "mips"; err = cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64 + CS_MODE_BIG_ENDIAN, &handle); } if (!strcmp(mode, "x16")) { - x86_arch = true; + md = CS_MODE_16; + arch = "x86"; err = cs_open(CS_ARCH_X86, CS_MODE_16, &handle); } if (!strcmp(mode, "x32")) { - x86_arch = true; + md = CS_MODE_32; + arch = "x86"; err = cs_open(CS_ARCH_X86, CS_MODE_32, &handle); } if (!strcmp(mode, "x64")) { - x86_arch = true; + md = CS_MODE_64; + arch = "x86"; err = cs_open(CS_ARCH_X86, CS_MODE_64, &handle); } if (!strcmp(mode, "x16att")) { - x86_arch = true; + md = CS_MODE_16; + arch = "x86"; err = cs_open(CS_ARCH_X86, CS_MODE_16, &handle); if (!err) { cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); @@ -206,7 +255,8 @@ int main(int argc, char **argv) } if (!strcmp(mode,"x32att")) { - x86_arch = true; + md = CS_MODE_32; + arch = "x86"; err = cs_open(CS_ARCH_X86, CS_MODE_32, &handle); if (!err) { cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); @@ -214,7 +264,8 @@ int main(int argc, char **argv) } if (!strcmp(mode,"x64att")) { - x86_arch = true; + md = CS_MODE_64; + arch = "x86"; err = cs_open(CS_ARCH_X86, CS_MODE_64, &handle); if (!err) { cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); @@ -222,22 +273,27 @@ int main(int argc, char **argv) } if (!strcmp(mode,"ppc64")) { + arch = "ppc"; err = cs_open(CS_ARCH_PPC, CS_MODE_64+CS_MODE_LITTLE_ENDIAN, &handle); } if (!strcmp(mode,"ppc64be")) { + arch = "ppc"; err = cs_open(CS_ARCH_PPC,CS_MODE_64+CS_MODE_BIG_ENDIAN, &handle); } if (!strcmp(mode,"sparc")) { + arch = "sparc"; err = cs_open(CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, &handle); } if (!strcmp(mode, "systemz") || !strcmp(mode, "sysz") || !strcmp(mode, "s390x")) { + arch = "sysz"; err = cs_open(CS_ARCH_SYSZ, CS_MODE_BIG_ENDIAN, &handle); } if (!strcmp(mode,"xcore")) { + arch = "xcore"; err = cs_open(CS_ARCH_XCORE, CS_MODE_BIG_ENDIAN, &handle); } @@ -247,6 +303,10 @@ int main(int argc, char **argv) return -1; } + if (debug_flag) { + cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); + } + count = cs_disasm(handle, assembly, size, address, 0, &insn); if (count > 0) { size_t i; @@ -259,12 +319,45 @@ int main(int argc, char **argv) } // X86 instruction size is variable. // align assembly instruction after the opcode - if (x86_arch) { + if (!strcmp(arch, "x86")) { for (; j < 16; j++) { printf(" "); } } printf(" %s\t%s\n", insn[i].mnemonic, insn[i].op_str); + if (debug_flag) { + if (!strcmp(arch, "x86")) { + print_insn_detail_x86(handle, md, &insn[i]); + } + + if (!strcmp(arch, "arm")) { + print_insn_detail_arm(handle, &insn[i]); + } + + if (!strcmp(arch,"arm64")) { + print_insn_detail_arm64(handle,&insn[i]); + } + + if (!strcmp(arch, "mips")) { + print_insn_detail_mips(handle, &insn[i]); + } + + if (!strcmp(arch, "ppc")) { + print_insn_detail_ppc(handle, &insn[i]); + } + + if (!strcmp(arch, "sparc")) { + print_insn_detail_sparc(handle, &insn[i]); + } + + if (!strcmp(arch, "sysz")) { + print_insn_detail_sysz(handle, &insn[i]); + } + + if (!strcmp(arch, "xcore")) { + print_insn_detail_xcore(handle, &insn[i]); + } + } } cs_free(insn, count); } else { diff --git a/cstool/cstool_arm.c b/cstool/cstool_arm.c new file mode 100644 index 00000000..7dd926ba --- /dev/null +++ b/cstool/cstool_arm.c @@ -0,0 +1,125 @@ +#include +#include + +#include + +static void print_string_hex(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"); +} + +void print_insn_detail_arm(csh handle, cs_insn *ins) +{ + cs_arm *arm; + int i; + + // detail can be NULL on "data" instruction if SKIPDATA option is turned ON + if (ins->detail == NULL) + return; + + arm = &(ins->detail->arm); + + if (arm->op_count) + printf("\top_count: %u\n", arm->op_count); + + for (i = 0; i < arm->op_count; i++) { + cs_arm_op *op = &(arm->operands[i]); + switch((int)op->type) { + default: + break; + case ARM_OP_REG: + printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg)); + break; + case ARM_OP_IMM: + printf("\t\toperands[%u].type: IMM = 0x%x\n", i, op->imm); + break; + case ARM_OP_FP: +#if defined(_KERNEL_MODE) + // Issue #681: Windows kernel does not support formatting float point + printf("\t\toperands[%u].type: FP = \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 != X86_REG_INVALID) + printf("\t\t\toperands[%u].mem.base: REG = %s\n", + i, cs_reg_name(handle, op->mem.base)); + if (op->mem.index != X86_REG_INVALID) + printf("\t\t\toperands[%u].mem.index: REG = %s\n", + i, cs_reg_name(handle, op->mem.index)); + if (op->mem.scale != 1) + printf("\t\t\toperands[%u].mem.scale: %u\n", i, op->mem.scale); + if (op->mem.disp != 0) + printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp); + + break; + case ARM_OP_PIMM: + printf("\t\toperands[%u].type: P-IMM = %u\n", i, op->imm); + break; + case ARM_OP_CIMM: + printf("\t\toperands[%u].type: C-IMM = %u\n", i, op->imm); + break; + case ARM_OP_SETEND: + printf("\t\toperands[%u].type: SETEND = %s\n", i, op->setend == ARM_SETEND_BE? "be" : "le"); + break; + case ARM_OP_SYSREG: + printf("\t\toperands[%u].type: SYSREG = %u\n", i, op->reg); + break; + } + + if (op->shift.type != ARM_SFT_INVALID && op->shift.value) { + if (op->shift.type < ARM_SFT_ASR_REG) + // shift with constant value + printf("\t\t\tShift: %u = %u\n", op->shift.type, op->shift.value); + else + // shift with register + printf("\t\t\tShift: %u = %s\n", op->shift.type, + cs_reg_name(handle, op->shift.value)); + } + + if (op->vector_index != -1) { + printf("\t\toperands[%u].vector_index = %u\n", i, op->vector_index); + } + + if (op->subtracted) + printf("\t\tSubtracted: True\n"); + } + + if (arm->cc != ARM_CC_AL && arm->cc != ARM_CC_INVALID) + printf("\tCode condition: %u\n", arm->cc); + + if (arm->update_flags) + printf("\tUpdate-flags: True\n"); + + if (arm->writeback) + printf("\tWrite-back: True\n"); + + if (arm->cps_mode) + printf("\tCPSI-mode: %u\n", arm->cps_mode); + + if (arm->cps_flag) + printf("\tCPSI-flag: %u\n", arm->cps_flag); + + if (arm->vector_data) + printf("\tVector-data: %u\n", arm->vector_data); + + if (arm->vector_size) + printf("\tVector-size: %u\n", arm->vector_size); + + if (arm->usermode) + printf("\tUser-mode: True\n"); + + if (arm->mem_barrier) + printf("\tMemory-barrier: %u\n", arm->mem_barrier); + + printf("\n"); +} diff --git a/cstool/cstool_arm64.c b/cstool/cstool_arm64.c new file mode 100644 index 00000000..cce0244d --- /dev/null +++ b/cstool/cstool_arm64.c @@ -0,0 +1,114 @@ +/* Capstone Disassembler Engine */ +/* By Nguyen Anh Quynh , 2013> */ + +#include +#include + +#include + +static void print_string_hex(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"); +} + +void print_insn_detail_arm64(csh handle, cs_insn *ins) +{ + cs_arm64 *arm64; + int i; + + // detail can be NULL if SKIPDATA option is turned ON + if (ins->detail == NULL) + return; + + arm64 = &(ins->detail->arm64); + if (arm64->op_count) + printf("\top_count: %u\n", arm64->op_count); + + for (i = 0; i < arm64->op_count; i++) { + cs_arm64_op *op = &(arm64->operands[i]); + switch(op->type) { + default: + break; + case ARM64_OP_REG: + printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg)); + break; + case ARM64_OP_IMM: + printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm); + break; + case ARM64_OP_FP: +#if defined(_KERNEL_MODE) + // Issue #681: Windows kernel does not support formatting float point + printf("\t\toperands[%u].type: FP = \n", i); +#else + printf("\t\toperands[%u].type: FP = %f\n", i, op->fp); +#endif + break; + case ARM64_OP_MEM: + printf("\t\toperands[%u].type: MEM\n", i); + if (op->mem.base != ARM64_REG_INVALID) + printf("\t\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(handle, op->mem.base)); + if (op->mem.index != ARM64_REG_INVALID) + printf("\t\t\toperands[%u].mem.index: REG = %s\n", i, cs_reg_name(handle, op->mem.index)); + if (op->mem.disp != 0) + printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp); + + break; + case ARM64_OP_CIMM: + printf("\t\toperands[%u].type: C-IMM = %u\n", i, (int)op->imm); + break; + case ARM64_OP_REG_MRS: + printf("\t\toperands[%u].type: REG_MRS = 0x%x\n", i, op->reg); + break; + case ARM64_OP_REG_MSR: + printf("\t\toperands[%u].type: REG_MSR = 0x%x\n", i, op->reg); + break; + case ARM64_OP_PSTATE: + printf("\t\toperands[%u].type: PSTATE = 0x%x\n", i, op->pstate); + break; + case ARM64_OP_SYS: + printf("\t\toperands[%u].type: SYS = 0x%x\n", i, op->sys); + break; + case ARM64_OP_PREFETCH: + printf("\t\toperands[%u].type: PREFETCH = 0x%x\n", i, op->prefetch); + break; + case ARM64_OP_BARRIER: + printf("\t\toperands[%u].type: BARRIER = 0x%x\n", i, op->barrier); + break; + } + + if (op->shift.type != ARM64_SFT_INVALID && + op->shift.value) + printf("\t\t\tShift: type = %u, value = %u\n", + op->shift.type, op->shift.value); + + if (op->ext != ARM64_EXT_INVALID) + printf("\t\t\tExt: %u\n", op->ext); + + if (op->vas != ARM64_VAS_INVALID) + printf("\t\t\tVector Arrangement Specifier: 0x%x\n", op->vas); + + if (op->vess != ARM64_VESS_INVALID) + printf("\t\t\tVector Element Size Specifier: %u\n", op->vess); + + if (op->vector_index != -1) + printf("\t\t\tVector Index: %u\n", op->vector_index); + } + + if (arm64->update_flags) + printf("\tUpdate-flags: True\n"); + + if (arm64->writeback) + printf("\tWrite-back: True\n"); + + if (arm64->cc) + printf("\tCode-condition: %u\n", arm64->cc); + + printf("\n"); +} diff --git a/cstool/cstool_mips.c b/cstool/cstool_mips.c new file mode 100644 index 00000000..16796291 --- /dev/null +++ b/cstool/cstool_mips.c @@ -0,0 +1,59 @@ +/* Capstone Disassembler Engine */ +/* By Nguyen Anh Quynh , 2013> */ + +#include +#include + +#include + +static void print_string_hex(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"); +} + +void print_insn_detail_mips(csh handle, cs_insn *ins) +{ + int i; + cs_mips *mips; + + // detail can be NULL on "data" instruction if SKIPDATA option is turned ON + if (ins->detail == NULL) + return; + + mips = &(ins->detail->mips); + if (mips->op_count) + printf("\top_count: %u\n", mips->op_count); + + for (i = 0; i < mips->op_count; i++) { + cs_mips_op *op = &(mips->operands[i]); + switch((int)op->type) { + default: + break; + case MIPS_OP_REG: + printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg)); + break; + case MIPS_OP_IMM: + printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm); + break; + case MIPS_OP_MEM: + printf("\t\toperands[%u].type: MEM\n", i); + if (op->mem.base != X86_REG_INVALID) + printf("\t\t\toperands[%u].mem.base: REG = %s\n", + i, cs_reg_name(handle, op->mem.base)); + if (op->mem.disp != 0) + printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp); + + break; + } + + } + + printf("\n"); +} diff --git a/cstool/cstool_ppc.c b/cstool/cstool_ppc.c new file mode 100644 index 00000000..cc802ac6 --- /dev/null +++ b/cstool/cstool_ppc.c @@ -0,0 +1,103 @@ +/* Capstone Disassembler Engine */ +/* By Nguyen Anh Quynh , 2013> */ + +#include + +#include + +static csh handle; + +static void print_string_hex(char *comment, unsigned char *str, size_t len) +{ + unsigned char *c; + + printf("%s", comment); + for (c = str; c < str + len; c++) { + printf("0x%02x ", *c & 0xff); + } + + printf("\n"); +} + +static const char* get_bc_name(int bc) +{ + switch(bc) { + default: + case PPC_BC_INVALID: + return ("invalid"); + case PPC_BC_LT: + return ("lt"); + case PPC_BC_LE: + return ("le"); + case PPC_BC_EQ: + return ("eq"); + case PPC_BC_GE: + return ("ge"); + case PPC_BC_GT: + return ("gt"); + case PPC_BC_NE: + return ("ne"); + case PPC_BC_UN: + return ("un"); + case PPC_BC_NU: + return ("nu"); + case PPC_BC_SO: + return ("so"); + case PPC_BC_NS: + return ("ns"); + } +} + +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%x\n", i, op->imm); + break; + case PPC_OP_MEM: + printf("\t\toperands[%u].type: MEM\n", i); + if (op->mem.base != PPC_REG_INVALID) + printf("\t\t\toperands[%u].mem.base: REG = %s\n", + i, cs_reg_name(handle, op->mem.base)); + if (op->mem.disp != 0) + printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp); + + break; + case PPC_OP_CRX: + printf("\t\toperands[%u].type: CRX\n", i); + printf("\t\t\toperands[%u].crx.scale: %d\n", i, op->crx.scale); + printf("\t\t\toperands[%u].crx.reg: %s\n", i, cs_reg_name(handle, op->crx.reg)); + printf("\t\t\toperands[%u].crx.cond: %s\n", i, get_bc_name(op->crx.cond)); + break; + } + } + + if (ppc->bc != 0) + printf("\tBranch code: %u\n", ppc->bc); + + if (ppc->bh != 0) + printf("\tBranch hint: %u\n", ppc->bh); + + if (ppc->update_cr0) + printf("\tUpdate-CR0: True\n"); + + printf("\n"); +} diff --git a/cstool/cstool_sparc.c b/cstool/cstool_sparc.c new file mode 100644 index 00000000..f53defe2 --- /dev/null +++ b/cstool/cstool_sparc.c @@ -0,0 +1,66 @@ +/* Capstone Disassembler Engine */ +/* By Nguyen Anh Quynh , 2013-2014 */ + +#include + +#include + +static void print_string_hex(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"); +} + +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%x\n", i, op->imm); + break; + case SPARC_OP_MEM: + printf("\t\toperands[%u].type: MEM\n", i); + if (op->mem.base != X86_REG_INVALID) + printf("\t\t\toperands[%u].mem.base: REG = %s\n", + i, cs_reg_name(handle, op->mem.base)); + if (op->mem.index != X86_REG_INVALID) + printf("\t\t\toperands[%u].mem.index: REG = %s\n", + i, cs_reg_name(handle, op->mem.index)); + if (op->mem.disp != 0) + printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp); + + break; + } + } + + if (sparc->cc != 0) + printf("\tCode condition: %u\n", sparc->cc); + + if (sparc->hint != 0) + printf("\tHint code: %u\n", sparc->hint); + + printf("\n"); +} diff --git a/cstool/cstool_systemz.c b/cstool/cstool_systemz.c new file mode 100644 index 00000000..4256ff1a --- /dev/null +++ b/cstool/cstool_systemz.c @@ -0,0 +1,68 @@ +/* Capstone Disassembler Engine */ +/* By Nguyen Anh Quynh , 2013-2014 */ + +#include + +#include + +static void print_string_hex(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"); +} + +void print_insn_detail_sysz(csh handle, cs_insn *ins) +{ + cs_sysz *sysz; + int i; + + // detail can be NULL on "data" instruction if SKIPDATA option is turned ON + if (ins->detail == NULL) + return; + + sysz = &(ins->detail->sysz); + if (sysz->op_count) + printf("\top_count: %u\n", sysz->op_count); + + for (i = 0; i < sysz->op_count; i++) { + cs_sysz_op *op = &(sysz->operands[i]); + switch((int)op->type) { + default: + break; + case SYSZ_OP_REG: + printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg)); + break; + case SYSZ_OP_ACREG: + printf("\t\toperands[%u].type: ACREG = %u\n", i, op->reg); + break; + case SYSZ_OP_IMM: + printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm); + break; + case SYSZ_OP_MEM: + printf("\t\toperands[%u].type: MEM\n", i); + if (op->mem.base != SYSZ_REG_INVALID) + printf("\t\t\toperands[%u].mem.base: REG = %s\n", + i, cs_reg_name(handle, op->mem.base)); + if (op->mem.index != SYSZ_REG_INVALID) + printf("\t\t\toperands[%u].mem.index: REG = %s\n", + i, cs_reg_name(handle, op->mem.index)); + if (op->mem.length != 0) + printf("\t\t\toperands[%u].mem.length: 0x%" PRIx64 "\n", i, op->mem.length); + if (op->mem.disp != 0) + printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp); + + break; + } + } + + if (sysz->cc != 0) + printf("\tCode condition: %u\n", sysz->cc); + + printf("\n"); +} diff --git a/cstool/cstool_x86.c b/cstool/cstool_x86.c new file mode 100644 index 00000000..20a9e11c --- /dev/null +++ b/cstool/cstool_x86.c @@ -0,0 +1,123 @@ +/* Second-Best Disassembler Engine */ +/* By Nguyen Anh Quynh , 2013> */ + +#include +#include + +#include + +static void print_string_hex(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"); +} + +void print_insn_detail_x86(csh ud, cs_mode mode, cs_insn *ins) +{ + int count, i; + cs_x86 *x86; + + // 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%x\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); + } + + // 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); + } + + count = cs_op_count(ud, ins, X86_OP_IMM); + if (count) { + printf("\timm_count: %u\n", count); + for (i = 1; i < count + 1; i++) { + int index = cs_op_index(ud, ins, X86_OP_IMM, i); + printf("\t\timms[%u]: 0x%" PRIx64 "\n", i, x86->operands[index].imm); + } + } + + if (x86->op_count) + printf("\top_count: %u\n", x86->op_count); + 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); + } + + printf("\n"); +} diff --git a/cstool/cstool_xcore.c b/cstool/cstool_xcore.c new file mode 100644 index 00000000..4b451373 --- /dev/null +++ b/cstool/cstool_xcore.c @@ -0,0 +1,62 @@ +/* Capstone Disassembler Engine */ +/* By Nguyen Anh Quynh , 2013-2014 */ + +#include +#include + +static void print_string_hex(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"); +} + +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"); +}