Squashed 'external/capstone/' content from commit e46f64fa
git-subtree-dir: external/capstone git-subtree-split: e46f64fadb351e9ecd05264fab26f2772feb0994
This commit is contained in:
@@ -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
|
||||
@@ -0,0 +1,53 @@
|
||||
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
|
||||
+1110
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,28 @@
|
||||
#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);
|
||||
void print_insn_detail_xtensa(csh handle, cs_insn *ins);
|
||||
void print_insn_detail_arc(csh handle, cs_insn *ins);
|
||||
|
||||
#endif //CAPSTONE_CSTOOL_CSTOOL_H_
|
||||
@@ -0,0 +1,310 @@
|
||||
/* 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 ||
|
||||
op->mem.base == AARCH64_REG_INVALID)
|
||||
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);
|
||||
printf("\t\toperands[%u].fp = %.1f\n", i,
|
||||
op->fp);
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
#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%" PRIx64 "\n",
|
||||
i, op->imm);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#include <stdio.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
void print_insn_detail_arc(csh handle, cs_insn *ins)
|
||||
{
|
||||
cs_arc *arc;
|
||||
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;
|
||||
|
||||
arc = &(ins->detail->arc);
|
||||
if (arc->op_count)
|
||||
printf("\top_count: %u\n", arc->op_count);
|
||||
|
||||
for (i = 0; i < arc->op_count; i++) {
|
||||
cs_arc_op *op = &(arc->operands[i]);
|
||||
switch ((int)op->type) {
|
||||
default:
|
||||
break;
|
||||
case ARC_OP_REG:
|
||||
printf("\t\toperands[%u].type: REG = %s\n", i,
|
||||
cs_reg_name(handle, op->reg));
|
||||
break;
|
||||
case ARC_OP_IMM:
|
||||
printf("\t\toperands[%u].type: IMM = 0x%lx\n", i,
|
||||
(long)op->imm);
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,236 @@
|
||||
#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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
/* 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);
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/* 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;
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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(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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/* 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) {
|
||||
char const *msg = NULL;
|
||||
switch (ppc->bc.bh) {
|
||||
case PPC_BH_SUBROUTINE_RET:
|
||||
msg = "subroutine return";
|
||||
break;
|
||||
case PPC_BH_NO_SUBROUTINE_RET:
|
||||
msg = "not a subroutine return";
|
||||
break;
|
||||
case PPC_BH_NOT_PREDICTABLE:
|
||||
msg = "unpredictable";
|
||||
break;
|
||||
case PPC_BH_RESERVED:
|
||||
msg = "reserved";
|
||||
break;
|
||||
case PPC_BH_INVALID:
|
||||
break;
|
||||
}
|
||||
printf("\t\tbh: %s\n", msg);
|
||||
}
|
||||
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 (at bits): %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");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/* Capstone Disassembler Engine */
|
||||
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include "cstool.h"
|
||||
|
||||
#include "../arch/RISCV/RISCVInstPrinter.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;
|
||||
case RISCV_OP_FP:
|
||||
printf("\t\toperands[%u].type: FP_IMM %f \n", i,
|
||||
op->dimm);
|
||||
break;
|
||||
case RISCV_OP_CSR:
|
||||
printf("\t\toperands[%u].type: CSR = %s\n", i,
|
||||
getSysRegName(op->csr));
|
||||
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");
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/* 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_ASI:
|
||||
printf("\t\toperands[%u].type: ASI = 0x%" PRIx64 "\n",
|
||||
i, (uint64_t)op->asi);
|
||||
break;
|
||||
case SPARC_OP_MEMBAR_TAG:
|
||||
printf("\t\toperands[%u].type: MEMBAR TAG = 0x%" PRIx64
|
||||
"\n",
|
||||
i, (uint64_t)op->membar_tag);
|
||||
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 != SPARC_REG_INVALID)
|
||||
printf("\t\t\toperands[%u].mem.base: REG = %s\n",
|
||||
i, cs_reg_name(handle, op->mem.base));
|
||||
if (op->mem.index != SPARC_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;
|
||||
}
|
||||
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 (sparc->cc != SPARC_CC_UNDEF)
|
||||
printf("\tCode condition: %s\n",
|
||||
SPARCCondCodeToString(sparc->cc));
|
||||
if (sparc->cc_field != SPARC_CC_FIELD_NONE)
|
||||
printf("\tCC field: %" PRId32 "\n", sparc->cc_field);
|
||||
|
||||
if (sparc->hint != 0)
|
||||
printf("\tHint code: %u\n", sparc->hint);
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/* 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);
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/* 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");
|
||||
}
|
||||
@@ -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");
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
#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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
/* 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/* 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");
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/* Capstone Disassembly Engine */
|
||||
/* By billow <billow.fun@gmail.com>, 2024 */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include <capstone/xtensa.h>
|
||||
|
||||
static const char *xtensa_insn_form_strs[] = {
|
||||
[XTENSA_INSN_FORM_INVALID] = "XTENSA_INSN_FORM_INVALID",
|
||||
[XTENSA_INSN_FORM_RRR] = "XTENSA_INSN_FORM_RRR",
|
||||
[XTENSA_INSN_FORM_RRI8] = "XTENSA_INSN_FORM_RRI8",
|
||||
[XTENSA_INSN_FORM_RRRN] = "XTENSA_INSN_FORM_RRRN",
|
||||
[XTENSA_INSN_FORM_AEINST24] = "XTENSA_INSN_FORM_AEINST24",
|
||||
[XTENSA_INSN_FORM_BRI12] = "XTENSA_INSN_FORM_BRI12",
|
||||
[XTENSA_INSN_FORM_CALL] = "XTENSA_INSN_FORM_CALL",
|
||||
[XTENSA_INSN_FORM_CALLX] = "XTENSA_INSN_FORM_CALLX",
|
||||
[XTENSA_INSN_FORM_EE_INST24] = "XTENSA_INSN_FORM_EE_INST24",
|
||||
[XTENSA_INSN_FORM_RRI4] = "XTENSA_INSN_FORM_RRI4",
|
||||
[XTENSA_INSN_FORM_RI16] = "XTENSA_INSN_FORM_RI16",
|
||||
[XTENSA_INSN_FORM_RI7] = "XTENSA_INSN_FORM_RI7",
|
||||
[XTENSA_INSN_FORM_RSR] = "XTENSA_INSN_FORM_RSR",
|
||||
};
|
||||
|
||||
void print_insn_detail_xtensa(csh handle, cs_insn *ins)
|
||||
{
|
||||
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;
|
||||
|
||||
cs_xtensa *detail = &(ins->detail->xtensa);
|
||||
|
||||
if (detail->format && detail->format < XTENSA_INSN_FORM_MAX) {
|
||||
printf("\tformat: %s\n", xtensa_insn_form_strs[detail->format]);
|
||||
}
|
||||
|
||||
if (detail->op_count)
|
||||
printf("\top_count: %u\n", detail->op_count);
|
||||
|
||||
for (i = 0; i < detail->op_count; i++) {
|
||||
cs_xtensa_op *op = &(detail->operands[i]);
|
||||
if (op->type == XTENSA_OP_REG)
|
||||
printf("\t\toperands[%u].type: REG = %s\n", i,
|
||||
cs_reg_name(handle, op->reg));
|
||||
else if (op->type == XTENSA_OP_IMM)
|
||||
printf("\t\toperands[%u].type: IMM = 0x%" PRIx32 "\n",
|
||||
i, op->imm);
|
||||
else if (op->type == XTENSA_OP_MEM)
|
||||
printf("\t\toperands[%u].type: MEM\n"
|
||||
"\t\t\t.mem.base: REG = %s\n"
|
||||
"\t\t\t.mem.disp: 0x%" PRIx32 "\n",
|
||||
i, cs_reg_name(handle, op->mem.base),
|
||||
op->mem.disp);
|
||||
else if (op->type == XTENSA_OP_L32R) {
|
||||
printf("\t\toperands[%u].type: L32R\n"
|
||||
"\t\t\t.l32r = %" PRIx32 "\n",
|
||||
i, op->imm);
|
||||
}
|
||||
|
||||
if (op->access & CS_AC_READ)
|
||||
printf("\t\t\t.access: READ\n");
|
||||
else if (op->access & CS_AC_WRITE)
|
||||
printf("\t\t\t.access: WRITE\n");
|
||||
else if (op->access & (CS_AC_READ | CS_AC_WRITE))
|
||||
printf("\t\t\t.access: READ | WRITE\n");
|
||||
}
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
#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 */
|
||||
}
|
||||
@@ -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