mirror of
https://github.com/capstone-engine/capstone.git
synced 2025-02-12 18:08:42 +00:00
cstool: add m68k and change cstool_x86
This commit is contained in:
parent
2f92635af9
commit
5e0a15521b
@ -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);
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
125
cstool/cstool_m68k.c
Normal file
125
cstool/cstool_m68k.c
Normal file
@ -0,0 +1,125 @@
|
||||
//
|
||||
// cstool_m68k.c
|
||||
//
|
||||
//
|
||||
// Created by YUHANG TANG on 26/10/16.
|
||||
//
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <capstone/capstone.h>
|
||||
|
||||
void print_string_hex(char *comment, unsigned char *str, size_t len);
|
||||
|
||||
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",
|
||||
};
|
||||
|
||||
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");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user