Skip to content

Commit

Permalink
cstool: add x86 debug information
Browse files Browse the repository at this point in the history
  • Loading branch information
YUHANG TANG authored and YUHANG TANG committed Oct 14, 2016
1 parent ae02bf1 commit abc28b5
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 25 deletions.
14 changes: 10 additions & 4 deletions cstool/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@

include ../functions.mk

.PHONY: clean
.PHONY: clean all

LIBNAME = capstone

CFLAGS = -I../include
LDFLAGS = -O3 -Wall -L.. -l$(LIBNAME)

cstool: cstool.o
TARGET = cstool
SOURCES := $(wildcard *.c)
OBJECTS := $(SOURCES:.c=.o)

all: $(TARGET)

$(TARGET): $(OBJECTS)
ifeq ($(V),0)
$(call log,LINK,$@)
@${CC} $< $(LDFLAGS) -o $@
@${CC} $(OBJECTS) $(LDFLAGS) -o $@
else
${CC} $< $(LDFLAGS) -o $@
${CC} $(OBJECTS) $(LDFLAGS) -o $@
endif

clean:
Expand Down
80 changes: 59 additions & 21 deletions cstool/cstool.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#define VERSION "1.0"

void print_insn_detail_x86(csh ud, cs_mode mode, cs_insn *ins);

// convert hexchar to hexnum
static uint8_t char_to_hexnum(char c)
{
Expand Down Expand Up @@ -53,7 +55,7 @@ static uint8_t *preprocess(char *code, size_t *size)
static void usage(char *prog)
{
printf("Cstool v%s for Capstone Disassembler Engine (www.capstone-engine.org)\n\n", VERSION);
printf("Syntax: %s <arch+mode> <assembly-hexstring> [start-address-in-hex-format]\n", prog);
printf("Syntax: %s [-d:print all debug information] <arch+mode> <assembly-hexstring> [start-address-in-hex-format]\n", prog);
printf("\nThe following <arch+mode> options are supported:\n");

if (cs_support(CS_ARCH_X86)) {
Expand Down Expand Up @@ -114,30 +116,55 @@ int main(int argc, char **argv)
uint64_t address = 0;
cs_insn *insn;
cs_err err;
bool x86_arch = false;
cs_mode md;
char *platform;
bool x86_arch = false, debug_flag = false;

if (argc != 3 && argc != 4) {
if (argc != 3 && argc != 4 && argc != 5) {
usage(argv[0]);
return -1;
}

mode = argv[1];
assembly = preprocess(argv[2], &size);
if (assembly == NULL) {
printf("ERROR: invalid assembler-string argument, quit!\n");
return -3;
}

if (argc == 4) {
// cstool <arch> <assembly> <address>
char *temp;
address = strtoull(argv[3], &temp, 16);
if (temp == argv[3] || *temp != '\0' || errno == ERANGE) {
printf("ERROR: invalid address argument, quit!\n");
return -2;
}
}

if (!strcmp(argv[1], "-d")) {
if (argc == 3) {
usage(argv[0]);
return -1;
}
debug_flag = true;
mode = argv[2];
assembly = preprocess(argv[3], &size);
if (argc == 5) {
char *temp;
address = strtoull(argv[4], &temp, 16);
if (temp == argv[4] || *temp != '\0' || errno == ERANGE) {
printf("ERROR: invalid address argument, quit!\n");
return -2;
}
}
} else {
if (argc == 5) {
usage(argv[0]);
return -1;
}

mode = argv[1];
assembly = preprocess(argv[2], &size);
if (assembly == NULL) {
printf("ERROR: invalid assembler-string argument, quit!\n");
return -3;
}

if (argc == 4) {
// cstool <arch> <assembly> <address>
char *temp;
address = strtoull(argv[3], &temp, 16);
if (temp == argv[3] || *temp != '\0' || errno == ERANGE) {
printf("ERROR: invalid address argument, quit!\n");
return -2;
}
}
}

if (!strcmp(mode, "arm")) {
err = cs_open(CS_ARCH_ARM, CS_MODE_ARM, &handle);
}
Expand Down Expand Up @@ -188,6 +215,8 @@ int main(int argc, char **argv)
}

if (!strcmp(mode, "x32")) {
md = CS_MODE_32;
platform = "x32";
x86_arch = true;
err = cs_open(CS_ARCH_X86, CS_MODE_32, &handle);
}
Expand Down Expand Up @@ -247,7 +276,11 @@ int main(int argc, char **argv)
return -1;
}

count = cs_disasm(handle, assembly, size, address, 0, &insn);
if (debug_flag) {
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
}

count = cs_disasm(handle, assembly, size, address, 0, &insn);
if (count > 0) {
size_t i;

Expand All @@ -265,6 +298,11 @@ int main(int argc, char **argv)
}
}
printf(" %s\t%s\n", insn[i].mnemonic, insn[i].op_str);
if (debug_flag) {
if (x86_arch) {
print_insn_detail_x86(handle, md, &insn[i]);
}
}
}
cs_free(insn, count);
} else {
Expand Down
126 changes: 126 additions & 0 deletions cstool/cstool_x86.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/* Second-Best Disassembler Engine */
/* By Nguyen Anh Quynh <[email protected]>, 2013> */

#include <stdio.h>
#include <stdlib.h>

#include <platform.h>
#include <capstone.h>



static void print_string_hex(char *comment, unsigned char *str, size_t len)
{
unsigned char *c;

printf("%s", comment);
for (c = str; c < str + len; c++) {
printf("0x%02x ", *c & 0xff);
}

printf("\n");
}

void print_insn_detail_x86(csh ud, cs_mode mode, cs_insn *ins)
{
int count, i;
cs_x86 *x86;

// detail can be NULL on "data" instruction if SKIPDATA option is turned ON
if (ins->detail == NULL)
return;

x86 = &(ins->detail->x86);

print_string_hex("\tPrefix:", x86->prefix, 4);

print_string_hex("\tOpcode:", x86->opcode, 4);

printf("\trex: 0x%x\n", x86->rex);

printf("\taddr_size: %u\n", x86->addr_size);
printf("\tmodrm: 0x%x\n", x86->modrm);
printf("\tdisp: 0x%x\n", x86->disp);

// SIB is not available in 16-bit mode
if ((mode & CS_MODE_16) == 0) {
printf("\tsib: 0x%x\n", x86->sib);
if (x86->sib_base != X86_REG_INVALID)
printf("\t\tsib_base: %s\n", cs_reg_name(ud, x86->sib_base));
if (x86->sib_index != X86_REG_INVALID)
printf("\t\tsib_index: %s\n", cs_reg_name(ud, x86->sib_index));
if (x86->sib_scale != 0)
printf("\t\tsib_scale: %d\n", x86->sib_scale);
}

// SSE code condition
if (x86->sse_cc != X86_SSE_CC_INVALID) {
printf("\tsse_cc: %u\n", x86->sse_cc);
}

// AVX code condition
if (x86->avx_cc != X86_AVX_CC_INVALID) {
printf("\tavx_cc: %u\n", x86->avx_cc);
}

// AVX Suppress All Exception
if (x86->avx_sae) {
printf("\tavx_sae: %u\n", x86->avx_sae);
}

// AVX Rounding Mode
if (x86->avx_rm != X86_AVX_RM_INVALID) {
printf("\tavx_rm: %u\n", x86->avx_rm);
}

count = cs_op_count(ud, ins, X86_OP_IMM);
if (count) {
printf("\timm_count: %u\n", count);
for (i = 1; i < count + 1; i++) {
int index = cs_op_index(ud, ins, X86_OP_IMM, i);
printf("\t\timms[%u]: 0x%" PRIx64 "\n", i, x86->operands[index].imm);
}
}

if (x86->op_count)
printf("\top_count: %u\n", x86->op_count);
for (i = 0; i < x86->op_count; i++) {
cs_x86_op *op = &(x86->operands[i]);

switch((int)op->type) {
case X86_OP_REG:
printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(ud, op->reg));
break;
case X86_OP_IMM:
printf("\t\toperands[%u].type: IMM = 0x%" PRIx64 "\n", i, op->imm);
break;
case X86_OP_MEM:
printf("\t\toperands[%u].type: MEM\n", i);
if (op->mem.segment != X86_REG_INVALID)
printf("\t\t\toperands[%u].mem.segment: REG = %s\n", i, cs_reg_name(ud, op->mem.segment));
if (op->mem.base != X86_REG_INVALID)
printf("\t\t\toperands[%u].mem.base: REG = %s\n", i, cs_reg_name(ud, op->mem.base));
if (op->mem.index != X86_REG_INVALID)
printf("\t\t\toperands[%u].mem.index: REG = %s\n", i, cs_reg_name(ud, op->mem.index));
if (op->mem.scale != 1)
printf("\t\t\toperands[%u].mem.scale: %u\n", i, op->mem.scale);
if (op->mem.disp != 0)
printf("\t\t\toperands[%u].mem.disp: 0x%" PRIx64 "\n", i, op->mem.disp);
break;
default:
break;
}

// AVX broadcast type
if (op->avx_bcast != X86_AVX_BCAST_INVALID)
printf("\t\toperands[%u].avx_bcast: %u\n", i, op->avx_bcast);

// AVX zero opmask {z}
if (op->avx_zero_opmask != false)
printf("\t\toperands[%u].avx_zero_opmask: TRUE\n", i);

printf("\t\toperands[%u].size: %u\n", i, op->size);
}

printf("\n");
}

0 comments on commit abc28b5

Please sign in to comment.