From 5e0a15521bf9947693661518ec687f1bd1866192 Mon Sep 17 00:00:00 2001 From: YUHANG TANG Date: Thu, 27 Oct 2016 12:12:59 +0800 Subject: [PATCH] cstool: add m68k and change cstool_x86 --- cstool/cstool.c | 22 +++++ cstool/cstool_arm.c | 89 +++++++++++++++----- cstool/cstool_arm64.c | 68 +++++++++++---- cstool/cstool_m68k.c | 125 +++++++++++++++++++++++++++ cstool/cstool_mips.c | 16 ++-- cstool/cstool_x86.c | 190 ++++++++++++++++++++++++++++++++++++++---- 6 files changed, 446 insertions(+), 64 deletions(-) create mode 100644 cstool/cstool_m68k.c diff --git a/cstool/cstool.c b/cstool/cstool.c index f174fe04c..aab0e80d8 100644 --- a/cstool/cstool.c +++ b/cstool/cstool.c @@ -17,6 +17,7 @@ void print_insn_detail_ppc(csh handle, cs_insn *ins); void print_insn_detail_sparc(csh handle, cs_insn *ins); void print_insn_detail_sysz(csh handle, cs_insn *ins); void print_insn_detail_xcore(csh handle, cs_insn *ins); +void print_insn_detail_x86(csh ud, cs_mode mode, cs_insn *ins); void print_string_hex(char *comment, unsigned char *str, size_t len) { @@ -122,6 +123,12 @@ static void usage(char *prog) if (cs_support(CS_ARCH_XCORE)) { printf(" xcore: xcore\n"); } + + if (cs_support(CS_ARCH_M68K)) { + printf(" m68kb: m68k+big endian\n"); + printf(" m68k40: m68k_040\n"); + + } printf("\n"); } @@ -308,6 +315,17 @@ int main(int argc, char **argv) arch = CS_ARCH_XCORE; err = cs_open(CS_ARCH_XCORE, CS_MODE_BIG_ENDIAN, &handle); } + + if (!strcmp(mode,"m68kb")) { + arch = CS_ARCH_M68K; + err = cs_open(CS_ARCH_M68K, CS_MODE_BIG_ENDIAN, &handle); + } + + if (!strcmp(mode,"m68k40")) { + arch = CS_ARCH_M68K; + err = cs_open(CS_ARCH_M68K, CS_MODE_M68K_040, &handle); + } + if (err) { printf("ERROR: Failed on cs_open(), quit!\n"); @@ -372,6 +390,10 @@ int main(int argc, char **argv) if (arch == CS_ARCH_XCORE) { print_insn_detail_xcore(handle, &insn[i]); } + + if (arch == CS_ARCH_M68K) { + print_insn_detail_m68k(handle, &insn[i]); + } } } cs_free(insn, count); diff --git a/cstool/cstool_arm.c b/cstool/cstool_arm.c index 65f281f7c..e62436541 100644 --- a/cstool/cstool_arm.c +++ b/cstool/cstool_arm.c @@ -9,16 +9,18 @@ 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) { @@ -40,17 +42,19 @@ void print_insn_detail_arm(csh handle, cs_insn *ins) break; case ARM_OP_MEM: printf("\t\toperands[%u].type: MEM\n", i); - if (op->mem.base != X86_REG_INVALID) + 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 != X86_REG_INVALID) + 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)); + 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); - + if (op->mem.lshift != 0) + printf("\t\t\toperands[%u].mem.lshift: 0x%x\n", i, op->mem.lshift); + break; case ARM_OP_PIMM: printf("\t\toperands[%u].type: P-IMM = %u\n", i, op->imm); @@ -65,7 +69,25 @@ void print_insn_detail_arm(csh handle, cs_insn *ins) printf("\t\toperands[%u].type: SYSREG = %u\n", i, op->reg); break; } - + + if (op->neon_lane != -1) { + printf("\t\toperands[%u].neon_lane = %u\n", i, op->neon_lane); + } + + switch(op->access) { + default: + break; + case CS_AC_READ: + printf("\t\toperands[%u].access: READ\n", i); + break; + case CS_AC_WRITE: + printf("\t\toperands[%u].access: WRITE\n", i); + break; + case CS_AC_READ | CS_AC_WRITE: + printf("\t\toperands[%u].access: READ | WRITE\n", i); + break; + } + if (op->shift.type != ARM_SFT_INVALID && op->shift.value) { if (op->shift.type < ARM_SFT_ASR_REG) // shift with constant value @@ -73,43 +95,64 @@ void print_insn_detail_arm(csh handle, cs_insn *ins) else // shift with register printf("\t\t\tShift: %u = %s\n", op->shift.type, - cs_reg_name(handle, op->shift.value)); + cs_reg_name(handle, op->shift.value)); } - + if (op->vector_index != -1) { printf("\t\toperands[%u].vector_index = %u\n", i, op->vector_index); } - + if (op->subtracted) printf("\t\tSubtracted: True\n"); } - + if (arm->cc != ARM_CC_AL && arm->cc != ARM_CC_INVALID) printf("\tCode condition: %u\n", arm->cc); - + if (arm->update_flags) printf("\tUpdate-flags: True\n"); - + if (arm->writeback) printf("\tWrite-back: True\n"); - + if (arm->cps_mode) printf("\tCPSI-mode: %u\n", arm->cps_mode); - + if (arm->cps_flag) printf("\tCPSI-flag: %u\n", arm->cps_flag); - + if (arm->vector_data) printf("\tVector-data: %u\n", arm->vector_data); - + if (arm->vector_size) printf("\tVector-size: %u\n", arm->vector_size); - + if (arm->usermode) printf("\tUser-mode: True\n"); - + if (arm->mem_barrier) printf("\tMemory-barrier: %u\n", arm->mem_barrier); - + + // Print out all registers accessed by this instruction (either implicit or explicit) + if (!cs_regs_access(handle, ins, + regs_read, ®s_read_count, + regs_write, ®s_write_count)) { + if (regs_read_count) { + printf("\tRegisters read:"); + for(i = 0; i < regs_read_count; i++) { + printf(" %s", cs_reg_name(handle, regs_read[i])); + } + printf("\n"); + } + + if (regs_write_count) { + printf("\tRegisters modified:"); + for(i = 0; i < regs_write_count; i++) { + printf(" %s", cs_reg_name(handle, regs_write[i])); + } + printf("\n"); + } + } + printf("\n"); } diff --git a/cstool/cstool_arm64.c b/cstool/cstool_arm64.c index e91b6a9e3..bdb01ba76 100644 --- a/cstool/cstool_arm64.c +++ b/cstool/cstool_arm64.c @@ -12,15 +12,17 @@ void print_insn_detail_arm64(csh handle, cs_insn *ins) { cs_arm64 *arm64; int i; - + cs_regs regs_read, regs_write; + uint8_t regs_read_count, regs_write_count; + // 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) { @@ -48,7 +50,7 @@ void print_insn_detail_arm64(csh handle, cs_insn *ins) 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); @@ -72,33 +74,69 @@ void print_insn_detail_arm64(csh handle, cs_insn *ins) printf("\t\toperands[%u].type: BARRIER = 0x%x\n", i, op->barrier); break; } - + + uint8_t access = op->access; + switch(access) { + default: + break; + case CS_AC_READ: + printf("\t\toperands[%u].access: READ\n", i); + break; + case CS_AC_WRITE: + printf("\t\toperands[%u].access: WRITE\n", i); + break; + case CS_AC_READ | CS_AC_WRITE: + printf("\t\toperands[%u].access: READ | WRITE\n", i); + break; + } + if (op->shift.type != ARM64_SFT_INVALID && - op->shift.value) + op->shift.value) printf("\t\t\tShift: type = %u, value = %u\n", - op->shift.type, op->shift.value); - + 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); - + + // 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"); + } + } + printf("\n"); } diff --git a/cstool/cstool_m68k.c b/cstool/cstool_m68k.c new file mode 100644 index 000000000..902bf9754 --- /dev/null +++ b/cstool/cstool_m68k.c @@ -0,0 +1,125 @@ +// +// cstool_m68k.c +// +// +// Created by YUHANG TANG on 26/10/16. +// +// + +#include +#include + +void print_string_hex(char *comment, unsigned char *str, size_t len); + +const char* s_addressing_modes[] = { + "", + + "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", +}; + +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; + } + } + + printf("\n"); +} + diff --git a/cstool/cstool_mips.c b/cstool/cstool_mips.c index 8e5d13973..01557f318 100644 --- a/cstool/cstool_mips.c +++ b/cstool/cstool_mips.c @@ -12,15 +12,15 @@ 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) { @@ -34,16 +34,16 @@ void print_insn_detail_mips(csh handle, cs_insn *ins) break; case MIPS_OP_MEM: printf("\t\toperands[%u].type: MEM\n", i); - if (op->mem.base != X86_REG_INVALID) + 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)); + 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_x86.c b/cstool/cstool_x86.c index 36c175662..339c53a08 100644 --- a/cstool/cstool_x86.c +++ b/cstool/cstool_x86.c @@ -8,27 +8,129 @@ void print_string_hex(char *comment, unsigned char *str, size_t len); +static char *get_eflag_name(uint64_t flag) +{ + switch(flag) { + default: + return NULL; + case X86_EFLAGS_UNDEFINED_OF: + return "UNDEF_OF"; + case X86_EFLAGS_UNDEFINED_SF: + return "UNDEF_SF"; + case X86_EFLAGS_UNDEFINED_ZF: + return "UNDEF_ZF"; + case X86_EFLAGS_MODIFY_AF: + return "MOD_AF"; + case X86_EFLAGS_UNDEFINED_PF: + return "UNDEF_PF"; + case X86_EFLAGS_MODIFY_CF: + return "MOD_CF"; + case X86_EFLAGS_MODIFY_SF: + return "MOD_SF"; + case X86_EFLAGS_MODIFY_ZF: + return "MOD_ZF"; + case X86_EFLAGS_UNDEFINED_AF: + return "UNDEF_AF"; + case X86_EFLAGS_MODIFY_PF: + return "MOD_PF"; + case X86_EFLAGS_UNDEFINED_CF: + return "UNDEF_CF"; + case X86_EFLAGS_MODIFY_OF: + return "MOD_OF"; + case X86_EFLAGS_RESET_OF: + return "RESET_OF"; + case X86_EFLAGS_RESET_CF: + return "RESET_CF"; + case X86_EFLAGS_RESET_DF: + return "RESET_DF"; + case X86_EFLAGS_RESET_IF: + return "RESET_IF"; + case X86_EFLAGS_TEST_OF: + return "TEST_OF"; + case X86_EFLAGS_TEST_SF: + return "TEST_SF"; + case X86_EFLAGS_TEST_ZF: + return "TEST_ZF"; + case X86_EFLAGS_TEST_PF: + return "TEST_PF"; + case X86_EFLAGS_TEST_CF: + return "TEST_CF"; + case X86_EFLAGS_RESET_SF: + return "RESET_SF"; + case X86_EFLAGS_RESET_AF: + return "RESET_AF"; + case X86_EFLAGS_RESET_TF: + return "RESET_TF"; + case X86_EFLAGS_RESET_NT: + return "RESET_NT"; + case X86_EFLAGS_PRIOR_OF: + return "PRIOR_OF"; + case X86_EFLAGS_PRIOR_SF: + return "PRIOR_SF"; + case X86_EFLAGS_PRIOR_ZF: + return "PRIOR_ZF"; + case X86_EFLAGS_PRIOR_AF: + return "PRIOR_AF"; + case X86_EFLAGS_PRIOR_PF: + return "PRIOR_PF"; + case X86_EFLAGS_PRIOR_CF: + return "PRIOR_CF"; + case X86_EFLAGS_PRIOR_TF: + return "PRIOR_TF"; + case X86_EFLAGS_PRIOR_IF: + return "PRIOR_IF"; + case X86_EFLAGS_PRIOR_DF: + return "PRIOR_DF"; + case X86_EFLAGS_TEST_NT: + return "TEST_NT"; + case X86_EFLAGS_TEST_DF: + return "TEST_DF"; + case X86_EFLAGS_RESET_PF: + return "RESET_PF"; + case X86_EFLAGS_PRIOR_NT: + return "PRIOR_NT"; + case X86_EFLAGS_MODIFY_TF: + return "MOD_TF"; + case X86_EFLAGS_MODIFY_IF: + return "MOD_IF"; + case X86_EFLAGS_MODIFY_DF: + return "MOD_DF"; + case X86_EFLAGS_MODIFY_NT: + return "MOD_NT"; + case X86_EFLAGS_MODIFY_RF: + return "MOD_RF"; + case X86_EFLAGS_SET_CF: + return "SET_CF"; + case X86_EFLAGS_SET_DF: + return "SET_DF"; + case X86_EFLAGS_SET_IF: + return "SET_IF"; + } +} + 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%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); @@ -39,27 +141,33 @@ void print_insn_detail_x86(csh ud, cs_mode mode, cs_insn *ins) if (x86->sib_scale != 0) printf("\t\tsib_scale: %d\n", x86->sib_scale); } - + + // XOP code condition + if (x86->xop_cc != X86_XOP_CC_INVALID) { + printf("\txop_cc: %u\n", x86->xop_cc); + } + // SSE code condition if (x86->sse_cc != X86_SSE_CC_INVALID) { printf("\tsse_cc: %u\n", x86->sse_cc); } - + // AVX code condition if (x86->avx_cc != X86_AVX_CC_INVALID) { printf("\tavx_cc: %u\n", x86->avx_cc); } - + // AVX Suppress All Exception if (x86->avx_sae) { printf("\tavx_sae: %u\n", x86->avx_sae); } - + // AVX Rounding Mode if (x86->avx_rm != X86_AVX_RM_INVALID) { printf("\tavx_rm: %u\n", x86->avx_rm); } - + + // Print out all immediate operands count = cs_op_count(ud, ins, X86_OP_IMM); if (count) { printf("\timm_count: %u\n", count); @@ -68,12 +176,14 @@ void print_insn_detail_x86(csh ud, cs_mode mode, cs_insn *ins) 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)); @@ -97,17 +207,61 @@ void print_insn_detail_x86(csh ud, cs_mode mode, cs_insn *ins) 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) { + printf("\tEFLAGS:"); + for(i = 0; i <= 45; i++) + if (x86->eflags & ((uint64_t)1 << i)) { + printf(" %s", get_eflag_name((uint64_t)1 << i)); + } + printf("\n"); + } + printf("\n"); }