Skip to content

Commit

Permalink
support to turn on/off building instruction details
Browse files Browse the repository at this point in the history
  • Loading branch information
aquynh committed Dec 13, 2013
1 parent bed9091 commit a209e67
Show file tree
Hide file tree
Showing 10 changed files with 963 additions and 585 deletions.
4 changes: 4 additions & 0 deletions MCInst.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ struct MCInst {
cs_insn pub_insn; // insn to be exposed to public
cs_mode mode; // to be referenced by internal code
unsigned OpcodePub;
cs_opt_value detail;
int insn_size; // instruction size
int x86_segment; // remove when segment mem ref hack is redundant.
uint64_t address; // address of this insn
};

void MCInst_Init(MCInst *inst);
Expand Down
286 changes: 177 additions & 109 deletions arch/AArch64/AArch64InstPrinter.c

Large diffs are not rendered by default.

892 changes: 559 additions & 333 deletions arch/ARM/ARMInstPrinter.c

Large diffs are not rendered by default.

44 changes: 28 additions & 16 deletions arch/Mips/MipsInstPrinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ static void printInstruction(MCInst *MI, SStream *O);
static bool doing_mem = false;
static void set_mem_access(MCInst *MI, bool status)
{
if (MI->detail != CS_OPT_ON)
return;

doing_mem = status;
if (doing_mem) {
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].type = MIPS_OP_MEM;
Expand Down Expand Up @@ -191,12 +194,14 @@ static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
unsigned int reg = MCOperand_getReg(Op);
printRegName(O, reg);
reg = Mips_map_register(reg);
if (doing_mem) {
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].mem.base = reg;
} else {
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].type = MIPS_OP_REG;
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].reg = reg;
MI->pub_insn.mips.op_count++;
if (MI->detail) {
if (doing_mem) {
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].mem.base = reg;
} else {
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].type = MIPS_OP_REG;
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].reg = reg;
MI->pub_insn.mips.op_count++;
}
}
}

Expand All @@ -209,15 +214,18 @@ static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
else
SStream_concat(O, "%"PRIu64, imm);
}
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].mem.disp = imm;
if (MI->detail)
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].mem.disp = imm;
} else {
if (imm > HEX_THRESHOLD)
SStream_concat(O, "0x%"PRIx64, imm);
else
SStream_concat(O, "%"PRIu64, imm);
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].type = MIPS_OP_IMM;
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].imm = imm;
MI->pub_insn.mips.op_count++;
if (MI->detail) {
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].type = MIPS_OP_IMM;
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].imm = imm;
MI->pub_insn.mips.op_count++;
}
}
}
}
Expand All @@ -231,9 +239,11 @@ static void printUnsignedImm(MCInst *MI, int opNum, SStream *O)
SStream_concat(O, "0x%x", (unsigned short int)imm);
else
SStream_concat(O, "%u", (unsigned short int)imm);
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].type = MIPS_OP_IMM;
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].imm = (unsigned short int)imm;
MI->pub_insn.mips.op_count++;
if (MI->detail) {
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].type = MIPS_OP_IMM;
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].imm = (unsigned short int)imm;
MI->pub_insn.mips.op_count++;
}
} else
printOperand(MI, opNum, O);
}
Expand All @@ -247,9 +257,11 @@ static void printUnsignedImm8(MCInst *MI, int opNum, SStream *O)
SStream_concat(O, "0x%x", imm);
else
SStream_concat(O, "%u", imm);
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].type = MIPS_OP_IMM;
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].imm = imm;
MI->pub_insn.mips.op_count++;
if (MI->detail) {
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].type = MIPS_OP_IMM;
MI->pub_insn.mips.operands[MI->pub_insn.mips.op_count].imm = imm;
MI->pub_insn.mips.op_count++;
}
} else
printOperand(MI, opNum, O);
}
Expand Down
115 changes: 66 additions & 49 deletions arch/X86/X86ATTInstPrinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,18 @@ static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)

SStream_concat(O, "%s", markup("<mem:"));

MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_MEM;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.base = X86_REG_INVALID;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.index = X86_REG_INVALID;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.scale = 1;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = 0;
if (MI->detail) {
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_MEM;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.base = X86_REG_INVALID;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.index = X86_REG_INVALID;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.scale = 1;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = 0;
}

if (MCOperand_isImm(DispSpec)) {
int64_t imm = MCOperand_getImm(DispSpec);
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = imm;
if (MI->detail)
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = imm;
if (imm < 0) {
if (imm <= -HEX_THRESHOLD)
SStream_concat(O, "-0x%"PRIx64, -imm);
Expand All @@ -146,15 +149,16 @@ static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)

SStream_concat(O, "%s", markup(">"));

MI->pub_insn.x86.op_count++;
if (MI->detail)
MI->pub_insn.x86.op_count++;
}

static void printMemOffs8(MCInst *MI, unsigned OpNo, SStream *O)
{
// If this has a segment register, print it.
// this is a hack. will fix it later
if (MI->pub_insn.x86.segment) {
SStream_concat(O, "%%%s:", X86_reg_name(1, MI->pub_insn.x86.segment));
if (MI->x86_segment) {
SStream_concat(O, "%%%s:", X86_reg_name(1, MI->x86_segment));
}

printMemOffset(MI, OpNo, O);
Expand All @@ -164,8 +168,8 @@ static void printMemOffs16(MCInst *MI, unsigned OpNo, SStream *O)
{
// If this has a segment register, print it.
// this is a hack. will fix it later
if (MI->pub_insn.x86.segment) {
SStream_concat(O, "%%%s:", X86_reg_name(1, MI->pub_insn.x86.segment));
if (MI->x86_segment) {
SStream_concat(O, "%%%s:", X86_reg_name(1, MI->x86_segment));
}

printMemOffset(MI, OpNo, O);
Expand All @@ -175,8 +179,8 @@ static void printMemOffs32(MCInst *MI, unsigned OpNo, SStream *O)
{
// If this has a segment register, print it.
// this is a hack. will fix it later
if (MI->pub_insn.x86.segment) {
SStream_concat(O, "%%%s:", X86_reg_name(1, MI->pub_insn.x86.segment));
if (MI->x86_segment) {
SStream_concat(O, "%%%s:", X86_reg_name(1, MI->x86_segment));
}

printMemOffset(MI, OpNo, O);
Expand Down Expand Up @@ -261,7 +265,7 @@ static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
{
MCOperand *Op = MCInst_getOperand(MI, OpNo);
if (MCOperand_isImm(Op)) {
int64_t imm = MCOperand_getImm(Op) + MI->pub_insn.size + MI->pub_insn.address;
int64_t imm = MCOperand_getImm(Op) + MI->insn_size + MI->address;
if (imm < 0) {
if (imm <= -HEX_THRESHOLD)
SStream_concat(O, "-0x%"PRIx64, -imm);
Expand All @@ -273,9 +277,11 @@ static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
else
SStream_concat(O, "%"PRIu64, imm);
}
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_IMM;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].imm = imm;
MI->pub_insn.x86.op_count++;
if (MI->detail) {
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_IMM;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].imm = imm;
MI->pub_insn.x86.op_count++;
}
}
}

Expand All @@ -284,9 +290,11 @@ static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
MCOperand *Op = MCInst_getOperand(MI, OpNo);
if (MCOperand_isReg(Op)) {
printRegName(O, MCOperand_getReg(Op));
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_REG;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].reg = MCOperand_getReg(Op);
MI->pub_insn.x86.op_count++;
if (MI->detail) {
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_REG;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].reg = MCOperand_getReg(Op);
MI->pub_insn.x86.op_count++;
}
} else if (MCOperand_isImm(Op)) {
// Print X86 immediates as signed values.
int64_t imm = MCOperand_getImm(Op);
Expand All @@ -301,9 +309,11 @@ static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
else
SStream_concat(O, "%s$-%"PRIu64"%s", markup("<imm:"), -imm, markup(">"));
}
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_IMM;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].imm = imm;
MI->pub_insn.x86.op_count++;
if (MI->detail) {
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_IMM;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].imm = imm;
MI->pub_insn.x86.op_count++;
}
}
}

Expand Down Expand Up @@ -337,11 +347,13 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
MCOperand *DispSpec = MCInst_getOperand(MI, Op+3);
MCOperand *SegReg = MCInst_getOperand(MI, Op+4);

MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_MEM;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.base = MCOperand_getReg(BaseReg);
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.index = MCOperand_getReg(IndexReg);
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.scale = 1;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = 0;
if (MI->detail) {
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_MEM;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.base = MCOperand_getReg(BaseReg);
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.index = MCOperand_getReg(IndexReg);
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.scale = 1;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = 0;
}

SStream_concat(O, markup("<mem:"));

Expand All @@ -353,7 +365,8 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)

if (MCOperand_isImm(DispSpec)) {
int64_t DispVal = MCOperand_getImm(DispSpec);
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = DispVal;
if (MI->detail)
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.disp = DispVal;
if (DispVal || (!MCOperand_getReg(IndexReg) && !MCOperand_getReg(BaseReg))) {
if (DispVal < 0) {
if (DispVal <= -HEX_THRESHOLD)
Expand All @@ -379,7 +392,8 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
SStream_concat(O, ", ");
_printOperand(MI, Op+2, O);
unsigned ScaleVal = MCOperand_getImm(MCInst_getOperand(MI, Op+1));
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.scale = ScaleVal;
if (MI->detail)
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].mem.scale = ScaleVal;
if (ScaleVal != 1) {
SStream_concat(O, ", %s%u%s", markup("<imm:"), ScaleVal, markup(">"));
}
Expand All @@ -389,7 +403,8 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)

SStream_concat(O, markup(">"));

MI->pub_insn.x86.op_count++;
if (MI->detail)
MI->pub_insn.x86.op_count++;
}

#include "X86InstPrinter.h"
Expand Down Expand Up @@ -442,24 +457,26 @@ void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info)
} else
printInstruction(MI, OS);

// first op can be embedded in the asm by llvm.
// so we have to handle that case to not miss the first op.
char lastop[32];
get_last_op(OS->buffer, lastop);
char *acc_regs[] = {"al", "ax", "eax", "rax", NULL};
int post;
if (lastop[0] == '%' && ((post = str_in_list(acc_regs, lastop+1)) != -1)) {
// set operand size following register size
MI->pub_insn.x86.op_size = 1 << post;
// this is one of the registers AL, AX, EAX, RAX
// canonicalize the register name first
//int i;
//for (i = 1; lastop[i]; i++)
// lastop[i] = tolower(lastop[i]);
if (MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count - 1].type != X86_OP_REG) {
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_REG;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].reg = x86_map_regname(lastop + 1);
MI->pub_insn.x86.op_count++;
if (MI->detail) {
// first op can be embedded in the asm by llvm.
// so we have to handle that case to not miss the first op.
char lastop[32];
get_last_op(OS->buffer, lastop);
char *acc_regs[] = {"al", "ax", "eax", "rax", NULL};
int post;
if (lastop[0] == '%' && ((post = str_in_list(acc_regs, lastop+1)) != -1)) {
// set operand size following register size
MI->pub_insn.x86.op_size = 1 << post;
// this is one of the registers AL, AX, EAX, RAX
// canonicalize the register name first
//int i;
//for (i = 1; lastop[i]; i++)
// lastop[i] = tolower(lastop[i]);
if (MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count - 1].type != X86_OP_REG) {
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].type = X86_OP_REG;
MI->pub_insn.x86.operands[MI->pub_insn.x86.op_count].reg = x86_map_regname(lastop + 1);
MI->pub_insn.x86.op_count++;
}
}
}
}
Expand Down
24 changes: 9 additions & 15 deletions arch/X86/X86Disassembler.c
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ static bool translateRMRegister(MCInst *mcInst, InternalInstruction *insn)
return true;
#define ENTRY(x) \
case EA_REG_##x: \
MCInst_addOperand(mcInst, MCOperand_CreateReg(X86_##x)); break;
MCInst_addOperand(mcInst, MCOperand_CreateReg(X86_##x)); break;
ALL_REGS
#undef ENTRY
default:
Expand Down Expand Up @@ -240,7 +240,7 @@ static bool translateRMMemory(MCInst *mcInst, InternalInstruction *insn)
switch (insn->sibBase) {
#define ENTRY(x) \
case SIB_BASE_##x: \
baseReg = MCOperand_CreateReg(X86_##x); break;
baseReg = MCOperand_CreateReg(X86_##x); break;
ALL_SIB_BASES
#undef ENTRY
default:
Expand Down Expand Up @@ -288,7 +288,7 @@ static bool translateRMMemory(MCInst *mcInst, InternalInstruction *insn)
return true;
#define ENTRY(x) \
case SIB_INDEX_##x: \
indexReg = MCOperand_CreateReg(X86_##x); break;
indexReg = MCOperand_CreateReg(X86_##x); break;
EA_BASES_32BIT
EA_BASES_64BIT
REGS_XMM
Expand Down Expand Up @@ -343,7 +343,7 @@ static bool translateRMMemory(MCInst *mcInst, InternalInstruction *insn)
// placeholders to keep the compiler happy.
#define ENTRY(x) \
case EA_BASE_##x: \
baseReg = MCOperand_CreateReg(X86_##x); break;
baseReg = MCOperand_CreateReg(X86_##x); break;
ALL_EA_BASES
#undef ENTRY
#define ENTRY(x) case EA_REG_##x:
Expand Down Expand Up @@ -546,14 +546,6 @@ static int reader(const void* arg, uint8_t* byte, uint64_t address)
{
struct reader_info *info = (void *)arg;

/*
char *buf = "\x55";
buf = "\x55"; // push ebp
buf = "\x01\xd8"; // add eax, ebx
buf = "\x8d\x4c\x32\x08"; // lea ecx, [edx + 8 + esi]
*/

if (address - info->offset >= info->size)
// out of buffer range
return -1;
Expand All @@ -563,7 +555,7 @@ static int reader(const void* arg, uint8_t* byte, uint64_t address)
return 0;
}

// update x86 detail information
// copy x86 detail information from internal structure to public structure
static void update_pub_insn(cs_insn *pub, InternalInstruction *inter)
{
int i, c;
Expand Down Expand Up @@ -637,8 +629,10 @@ bool X86_getInstruction(csh ud, const uint8_t *code, size_t code_len, MCInst *in
} else {
*size = insn.length;
result = (!translateInstruction(instr, &insn)) ? true : false;
// update instr->pub_insn
update_pub_insn(&instr->pub_insn, &insn);
// save segment for printing hack
instr->x86_segment = x86_map_segment(insn.segmentOverride);
if (handle->detail)
update_pub_insn(&instr->pub_insn, &insn);
return result;
}
}
Loading

0 comments on commit a209e67

Please sign in to comment.