Add new API and start to provide access information for instruction operands

- New API cs_regs_access() that provide registers being read & modified by instruction

- New field cs_x86_op.access provides access info (READ, WRITE) for each operand

- New field cs_x86.eflags provides EFLAGS affected by instruction

- Extend cs_detail.{regs_read, regs_write} from uint8_t to uint16_t type
This commit is contained in:
Nguyen Anh Quynh 2015-03-25 15:02:13 +08:00
parent bb171fa861
commit efffe787d1
22 changed files with 8274 additions and 1465 deletions

View File

@ -86,6 +86,7 @@ DEP_ARM += arch/ARM/ARMGenDisassemblerTables.inc
DEP_ARM += arch/ARM/ARMGenInstrInfo.inc
DEP_ARM += arch/ARM/ARMGenRegisterInfo.inc
DEP_ARM += arch/ARM/ARMGenSubtargetInfo.inc
DEP_ARM += arch/ARM/ARMMappingInsn.inc
LIBOBJ_ARM =
ifneq (,$(findstring arm,$(CAPSTONE_ARCHS)))
@ -102,6 +103,7 @@ DEP_ARM64 += arch/AArch64/AArch64GenInstrInfo.inc
DEP_ARM64 += arch/AArch64/AArch64GenSubtargetInfo.inc
DEP_ARM64 += arch/AArch64/AArch64GenDisassemblerTables.inc
DEP_ARM64 += arch/AArch64/AArch64GenRegisterInfo.inc
DEP_ARM64 += arch/AArch64/AArch64MappingInsn.inc
LIBOBJ_ARM64 =
ifneq (,$(findstring aarch64,$(CAPSTONE_ARCHS)))
@ -120,6 +122,7 @@ DEP_MIPS += arch/Mips/MipsGenDisassemblerTables.inc
DEP_MIPS += arch/Mips/MipsGenInstrInfo.inc
DEP_MIPS += arch/Mips/MipsGenRegisterInfo.inc
DEP_MIPS += arch/Mips/MipsGenSubtargetInfo.inc
DEP_MIPS += arch/Mips/MipsMappingInsn.inc
LIBOBJ_MIPS =
ifneq (,$(findstring mips,$(CAPSTONE_ARCHS)))
@ -137,6 +140,7 @@ DEP_PPC += arch/PowerPC/PPCGenInstrInfo.inc
DEP_PPC += arch/PowerPC/PPCGenSubtargetInfo.inc
DEP_PPC += arch/PowerPC/PPCGenDisassemblerTables.inc
DEP_PPC += arch/PowerPC/PPCGenRegisterInfo.inc
DEP_PPC += arch/PowerPC/PPCMappingInsn.inc
LIBOBJ_PPC =
ifneq (,$(findstring powerpc,$(CAPSTONE_ARCHS)))
@ -154,6 +158,7 @@ DEP_SPARC += arch/Sparc/SparcGenInstrInfo.inc
DEP_SPARC += arch/Sparc/SparcGenSubtargetInfo.inc
DEP_SPARC += arch/Sparc/SparcGenDisassemblerTables.inc
DEP_SPARC += arch/Sparc/SparcGenRegisterInfo.inc
DEP_SPARC += arch/Sparc/SparcMappingInsn.inc
LIBOBJ_SPARC =
ifneq (,$(findstring sparc,$(CAPSTONE_ARCHS)))
@ -171,6 +176,7 @@ DEP_SYSZ += arch/SystemZ/SystemZGenInstrInfo.inc
DEP_SYSZ += arch/SystemZ/SystemZGenSubtargetInfo.inc
DEP_SYSZ += arch/SystemZ/SystemZGenDisassemblerTables.inc
DEP_SYSZ += arch/SystemZ/SystemZGenRegisterInfo.inc
DEP_SYSZ += arch/SystemZ/SystemZMappingInsn.inc
LIBOBJ_SYSZ =
ifneq (,$(findstring systemz,$(CAPSTONE_ARCHS)))
@ -196,6 +202,9 @@ DEP_X86 += arch/X86/X86GenAsmWriter1$(X86_REDUCE).inc
DEP_X86 += arch/X86/X86GenDisassemblerTables$(X86_REDUCE).inc
DEP_X86 += arch/X86/X86GenInstrInfo$(X86_REDUCE).inc
DEP_X86 += arch/X86/X86GenRegisterInfo.inc
DEP_X86 += arch/X86/X86MappingInsn.inc
DEP_X86 += arch/X86/X86MappingInsn_reduce.inc
DEP_X86 += arch/X86/X86MappingInsnOp.inc
LIBOBJ_X86 =
ifneq (,$(findstring x86,$(CAPSTONE_ARCHS)))
@ -219,6 +228,7 @@ DEP_XCORE += arch/XCore/XCoreGenAsmWriter.inc
DEP_XCORE += arch/XCore/XCoreGenInstrInfo.inc
DEP_XCORE += arch/XCore/XCoreGenDisassemblerTables.inc
DEP_XCORE += arch/XCore/XCoreGenRegisterInfo.inc
DEP_XCORE += arch/XCore/XCoreMappingInsn.inc
LIBOBJ_XCORE =
ifneq (,$(findstring xcore,$(CAPSTONE_ARCHS)))

View File

@ -329,7 +329,7 @@ void AArch64_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
insn->detail->groups_count = (uint8_t)count_positive(insns[i].groups);
insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
insn->detail->arm64.update_flags = cs_reg_write((csh)&handle, insn, ARM64_REG_NZCV);
#endif

View File

@ -296,7 +296,7 @@ void ARM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
insn->detail->groups_count = (uint8_t)count_positive(insns[i].groups);
insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
insn->detail->arm.update_flags = cs_reg_write((csh)&handle, insn, ARM_REG_CPSR);

View File

@ -256,7 +256,7 @@ void Mips_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
insn->detail->regs_write_count = (uint8_t)count_positive(alias_insns[i].regs_mod);
memcpy(insn->detail->groups, alias_insns[i].groups, sizeof(alias_insns[i].groups));
insn->detail->groups_count = (uint8_t)count_positive(alias_insns[i].groups);
insn->detail->groups_count = (uint8_t)count_positive8(alias_insns[i].groups);
if (alias_insns[i].branch || alias_insns[i].indirect_branch) {
// this insn also belongs to JUMP group. add JUMP group
@ -283,7 +283,7 @@ void Mips_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
insn->detail->groups_count = (uint8_t)count_positive(insns[i].groups);
insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
if (insns[i].branch || insns[i].indirect_branch) {
// this insn also belongs to JUMP group. add JUMP group

View File

@ -276,7 +276,7 @@ void PPC_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
insn->detail->groups_count = (uint8_t)count_positive(insns[i].groups);
insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
if (insns[i].branch || insns[i].indirect_branch) {
// this insn also belongs to JUMP group. add JUMP group

View File

@ -175,7 +175,7 @@ void Sparc_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
insn->detail->groups_count = (uint8_t)count_positive(insns[i].groups);
insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
if (insns[i].branch || insns[i].indirect_branch) {
// this insn also belongs to JUMP group. add JUMP group

View File

@ -96,7 +96,7 @@ void SystemZ_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
insn->detail->groups_count = (uint8_t)count_positive(insns[i].groups);
insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
if (insns[i].branch || insns[i].indirect_branch) {
// this insn also belongs to JUMP group. add JUMP group

View File

@ -266,12 +266,39 @@ static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
}
}
// convert Intel access info to AT&T access info
static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access, uint64_t *eflags)
{
uint8_t *arr = X86_get_op_access(h, id, eflags);
uint8_t count, i;
// find the non-zero last entry
for(count = 0; arr[count]; count++);
// mark the end of array
access[count] = 0;
if (count == 0)
return;
// copy in reverse order this access array from Intel syntax -> AT&T syntax
count--;
for(i = 0; i <= count; i++) {
if (arr[count -1] != CS_AC_IGNORE)
access[i] = arr[count - i];
else
access[i] = 0;
}
}
static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
{
MCOperand *SegReg;
int reg;
if (MI->csh->detail) {
uint8_t access[6];
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
@ -279,6 +306,9 @@ static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
}
SegReg = MCInst_getOperand(MI, Op+1);
@ -306,6 +336,8 @@ static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
{
if (MI->csh->detail) {
uint8_t access[6];
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
@ -313,6 +345,9 @@ static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
}
// DI accesses are always ES-based on non-64bit mode
@ -387,6 +422,8 @@ static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
int reg;
if (MI->csh->detail) {
uint8_t access[6];
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
@ -394,6 +431,9 @@ static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
}
// If this has a segment register, print it.
@ -506,9 +546,15 @@ static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
if (MI->csh->doing_mem) {
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg;
} else {
uint8_t access[6];
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg];
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
MI->flat_insn->detail->x86.op_count++;
}
}
@ -572,6 +618,8 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
int reg;
if (MI->csh->detail) {
uint8_t access[6];
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
@ -579,6 +627,9 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = MCOperand_getReg(IndexReg);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
}
// If this has a segment register, print it.
@ -725,21 +776,31 @@ void X86_ATT_printInst(MCInst *MI, SStream *OS, void *info)
// so we have to add the missing register as the first operand
reg = X86_insn_reg_att(MCInst_getOpcode(MI));
if (reg) {
uint8_t access[6];
// shift all the ops right to leave 1st slot for this new register op
memmove(&(MI->flat_insn->detail->x86.operands[1]), &(MI->flat_insn->detail->x86.operands[0]),
sizeof(MI->flat_insn->detail->x86.operands[0]) * (ARR_SIZE(MI->flat_insn->detail->x86.operands) - 1));
MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
MI->flat_insn->detail->x86.operands[0].reg = reg;
MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[0].access = access[0];
MI->flat_insn->detail->x86.op_count++;
} else {
if (X86_insn_reg_att2(MCInst_getOpcode(MI), &reg, &reg2)) {
uint8_t access[6];
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[0].type = X86_OP_REG;
MI->flat_insn->detail->x86.operands[0].reg = reg;
MI->flat_insn->detail->x86.operands[0].size = MI->csh->regsize_map[reg];
MI->flat_insn->detail->x86.operands[0].access = access[0];
MI->flat_insn->detail->x86.operands[1].type = X86_OP_REG;
MI->flat_insn->detail->x86.operands[1].reg = reg2;
MI->flat_insn->detail->x86.operands[1].size = MI->csh->regsize_map[reg2];
MI->flat_insn->detail->x86.operands[1].access = access[1];
MI->flat_insn->detail->x86.op_count = 2;
}
}

View File

@ -284,12 +284,38 @@ static void _printOperand(MCInst *MI, unsigned OpNo, SStream *O)
}
}
#ifndef CAPSTONE_DIET
// convert Intel access info to AT&T access info
static void get_op_access(cs_struct *h, unsigned int id, uint8_t *access, uint64_t *eflags)
{
#ifndef CAPSTONE_DIET
uint8_t *arr = X86_get_op_access(h, id, eflags);
uint8_t i;
// copy to access but zero out CS_AC_IGNORE
for(i = 0; arr[i]; i++) {
if (arr[i] != CS_AC_IGNORE)
access[i] = arr[i];
else
access[i] = 0;
}
// mark the end of array
access[i] = 0;
#endif
}
#endif
static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
{
MCOperand *SegReg;
int reg;
if (MI->csh->detail) {
#ifndef CAPSTONE_DIET
uint8_t access[6];
#endif
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
@ -297,6 +323,11 @@ static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
#ifndef CAPSTONE_DIET
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
#endif
}
SegReg = MCInst_getOperand(MI, Op+1);
@ -321,6 +352,10 @@ static void printSrcIdx(MCInst *MI, unsigned Op, SStream *O)
static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
{
if (MI->csh->detail) {
#ifndef CAPSTONE_DIET
uint8_t access[6];
#endif
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
@ -328,6 +363,11 @@ static void printDstIdx(MCInst *MI, unsigned Op, SStream *O)
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
#ifndef CAPSTONE_DIET
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
#endif
}
// DI accesses are always ES-based on non-64bit mode
@ -408,6 +448,10 @@ static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
int reg;
if (MI->csh->detail) {
#ifndef CAPSTONE_DIET
uint8_t access[6];
#endif
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
@ -415,6 +459,11 @@ static void printMemOffset(MCInst *MI, unsigned Op, SStream *O)
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = X86_REG_INVALID;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = 1;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
#ifndef CAPSTONE_DIET
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
#endif
}
// If this has a segment register, print it.
@ -463,8 +512,18 @@ static void printU8Imm(MCInst *MI, unsigned Op, SStream *O)
SStream_concat(O, "%u", val);
if (MI->csh->detail) {
#ifndef CAPSTONE_DIET
uint8_t access[6];
#endif
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = val;
#ifndef CAPSTONE_DIET
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
#endif
MI->flat_insn->detail->x86.op_count++;
}
}
@ -514,6 +573,10 @@ void X86_Intel_printInst(MCInst *MI, SStream *O, void *Info)
reg = X86_insn_reg_intel(MCInst_getOpcode(MI));
if (MI->csh->detail) {
#ifndef CAPSTONE_DIET
uint8_t access[6];
#endif
// first op can be embedded in the asm by llvm.
// so we have to add the missing register as the first operand
if (reg) {
@ -536,6 +599,12 @@ void X86_Intel_printInst(MCInst *MI, SStream *O, void *Info)
MI->flat_insn->detail->x86.op_count = 2;
}
}
#ifndef CAPSTONE_DIET
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[0].access = access[0];
MI->flat_insn->detail->x86.operands[1].access = access[1];
#endif
}
if (MI->op1_size == 0 && reg)
@ -562,6 +631,10 @@ static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
SStream_concat(O, "%"PRIu64, imm);
}
if (MI->csh->detail) {
#ifndef CAPSTONE_DIET
uint8_t access[6];
#endif
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
// if op_count > 0, then this operand's size is taken from the destination op
if (MI->flat_insn->detail->x86.op_count > 0)
@ -569,6 +642,12 @@ static void printPCRelImm(MCInst *MI, unsigned OpNo, SStream *O)
else
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
#ifndef CAPSTONE_DIET
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
#endif
MI->flat_insn->detail->x86.op_count++;
}
@ -588,9 +667,19 @@ static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
if (MI->csh->doing_mem) {
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.base = reg;
} else {
#ifndef CAPSTONE_DIET
uint8_t access[6];
#endif
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_REG;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].reg = reg;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->csh->regsize_map[reg];
#ifndef CAPSTONE_DIET
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
#endif
MI->flat_insn->detail->x86.op_count++;
}
}
@ -647,12 +736,22 @@ static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
if (MI->csh->doing_mem) {
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = imm;
} else {
#ifndef CAPSTONE_DIET
uint8_t access[6];
#endif
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_IMM;
if (MI->flat_insn->detail->x86.op_count > 0)
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->flat_insn->detail->x86.operands[0].size;
else
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->imm_size;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].imm = imm;
#ifndef CAPSTONE_DIET
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
#endif
MI->flat_insn->detail->x86.op_count++;
}
}
@ -673,6 +772,10 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
int reg;
if (MI->csh->detail) {
#ifndef CAPSTONE_DIET
uint8_t access[6];
#endif
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].type = X86_OP_MEM;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].size = MI->x86opsize;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.segment = X86_REG_INVALID;
@ -680,6 +783,11 @@ static void printMemReference(MCInst *MI, unsigned Op, SStream *O)
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.index = MCOperand_getReg(IndexReg);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.scale = (int)ScaleVal;
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].mem.disp = 0;
#ifndef CAPSTONE_DIET
get_op_access(MI->csh, MCInst_getOpcode(MI), access, &MI->flat_insn->detail->x86.eflags);
MI->flat_insn->detail->x86.operands[MI->flat_insn->detail->x86.op_count].access = access[MI->flat_insn->detail->x86.op_count];
#endif
}
// If this has a segment register, print it.

View File

@ -2338,7 +2338,7 @@ void X86_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
}
memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
insn->detail->groups_count = (uint8_t)count_positive(insns[i].groups);
insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
if (insns[i].branch || insns[i].indirect_branch) {
// this insn also belongs to JUMP group. add JUMP group
@ -2970,12 +2970,11 @@ void op_addAvxBroadcast(MCInst *MI, x86_avx_bcast v)
}
}
#if 0
#ifndef CAPSTONE_DIET
// map instruction to its characteristics
typedef struct insn_op {
unsigned int eflags_update; // how this instruction update EFlags
cs_ac_type operands[4];
uint64_t eflags; // how this instruction update EFLAGS
uint8_t access[6];
} insn_op;
static insn_op insn_ops[] = {
@ -2984,8 +2983,76 @@ static insn_op insn_ops[] = {
{ 0 }
},
#ifdef CAPSTONE_X86_REDUCE
#include "X86MappingInsnOp_reduce.inc"
#else
#include "X86MappingInsnOp.inc"
#endif
};
// given internal insn id, return operand access info
uint8_t *X86_get_op_access(cs_struct *h, unsigned int id, uint64_t *eflags)
{
int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
if (i != 0) {
*eflags = insn_ops[i].eflags;
return insn_ops[i].access;
}
return NULL;
}
void X86_reg_access(const cs_insn *insn,
cs_regs regs_read, uint8_t *regs_read_count,
cs_regs regs_write, uint8_t *regs_write_count)
{
uint8_t i;
uint8_t read_count, write_count;
cs_x86 *x86 = &(insn->detail->x86);
read_count = insn->detail->regs_read_count;
write_count = insn->detail->regs_write_count;
// implicit registers
memcpy(regs_read, insn->detail->regs_read, read_count * sizeof(insn->detail->regs_read[0]));
memcpy(regs_write, insn->detail->regs_write, write_count * sizeof(insn->detail->regs_write[0]));
// explicit registers
for (i = 0; i < x86->op_count; i++) {
cs_x86_op *op = &(x86->operands[i]);
switch((int)op->type) {
case X86_OP_REG:
if (op->access & CS_AC_READ) {
regs_read[read_count] = op->reg;
read_count++;
}
if (op->access & CS_AC_WRITE) {
regs_write[write_count] = op->reg;
write_count++;
}
break;
case X86_OP_MEM:
// registers appeared in memory references always being read
if (op->mem.segment != X86_REG_INVALID) {
regs_read[read_count] = op->mem.segment;
read_count++;
}
if (op->mem.base != X86_REG_INVALID) {
regs_read[read_count] = op->mem.base;
read_count++;
}
if (op->mem.index != X86_REG_INVALID) {
regs_read[read_count] = op->mem.index;
read_count++;
}
default:
break;
}
}
*regs_read_count = read_count;
*regs_write_count = write_count;
}
#endif
#endif

View File

@ -61,4 +61,11 @@ void op_addAvxSae(MCInst *MI);
void op_addAvxRoundingMode(MCInst *MI, int v);
// given internal insn id, return operand access info
uint8_t *X86_get_op_access(cs_struct *h, unsigned int id, uint64_t *eflags);
void X86_reg_access(const cs_insn *insn,
cs_regs regs_read, uint8_t *regs_read_count,
cs_regs regs_write, uint8_t *regs_write_count);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -31,6 +31,9 @@ static cs_err init(cs_struct *ud)
ud->insn_name = X86_insn_name;
ud->group_name = X86_group_name;
ud->post_printer = NULL;;
#ifndef CAPSTONE_DIET
ud->reg_access = X86_reg_access;
#endif
if (ud->mode == CS_MODE_64)
ud->regsize_map = regsize_map_64;

View File

@ -101,7 +101,7 @@ void XCore_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
insn->detail->groups_count = (uint8_t)count_positive(insns[i].groups);
insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
if (insns[i].branch || insns[i].indirect_branch) {
// this insn also belongs to JUMP group. add JUMP group

82
cs.c
View File

@ -157,7 +157,7 @@ const char *cs_strerror(cs_err code)
case CS_ERR_MEM:
return "Out of memory (CS_ERR_MEM)";
case CS_ERR_ARCH:
return "Invalid architecture (CS_ERR_ARCH)";
return "Invalid/unsupported architecture(CS_ERR_ARCH)";
case CS_ERR_HANDLE:
return "Invalid handle (CS_ERR_HANDLE)";
case CS_ERR_CSH:
@ -774,7 +774,19 @@ const char *cs_group_name(csh ud, unsigned int group)
return handle->group_name(ud, group);
}
static bool arr_exist(unsigned char *arr, unsigned char max, unsigned int id)
static bool arr_exist8(unsigned char *arr, unsigned char max, unsigned int id)
{
int i;
for (i = 0; i < max; i++) {
if (arr[i] == id)
return true;
}
return false;
}
static bool arr_exist(uint16_t *arr, unsigned char max, unsigned int id)
{
int i;
@ -800,17 +812,17 @@ bool cs_insn_group(csh ud, const cs_insn *insn, unsigned int group_id)
return false;
}
if(!insn->id) {
if (!insn->id) {
handle->errnum = CS_ERR_SKIPDATA;
return false;
}
if(!insn->detail) {
if (!insn->detail) {
handle->errnum = CS_ERR_DETAIL;
return false;
}
return arr_exist(insn->detail->groups, insn->detail->groups_count, group_id);
return arr_exist8(insn->detail->groups, insn->detail->groups_count, group_id);
}
CAPSTONE_EXPORT
@ -827,12 +839,12 @@ bool cs_reg_read(csh ud, const cs_insn *insn, unsigned int reg_id)
return false;
}
if(!insn->id) {
if (!insn->id) {
handle->errnum = CS_ERR_SKIPDATA;
return false;
}
if(!insn->detail) {
if (!insn->detail) {
handle->errnum = CS_ERR_DETAIL;
return false;
}
@ -854,12 +866,12 @@ bool cs_reg_write(csh ud, const cs_insn *insn, unsigned int reg_id)
return false;
}
if(!insn->id) {
if (!insn->id) {
handle->errnum = CS_ERR_SKIPDATA;
return false;
}
if(!insn->detail) {
if (!insn->detail) {
handle->errnum = CS_ERR_DETAIL;
return false;
}
@ -882,12 +894,12 @@ int cs_op_count(csh ud, const cs_insn *insn, unsigned int op_type)
return -1;
}
if(!insn->id) {
if (!insn->id) {
handle->errnum = CS_ERR_SKIPDATA;
return -1;
}
if(!insn->detail) {
if (!insn->detail) {
handle->errnum = CS_ERR_DETAIL;
return -1;
}
@ -959,12 +971,12 @@ int cs_op_index(csh ud, const cs_insn *insn, unsigned int op_type,
return -1;
}
if(!insn->id) {
if (!insn->id) {
handle->errnum = CS_ERR_SKIPDATA;
return -1;
}
if(!insn->detail) {
if (!insn->detail) {
handle->errnum = CS_ERR_DETAIL;
return -1;
}
@ -1043,3 +1055,47 @@ int cs_op_index(csh ud, const cs_insn *insn, unsigned int op_type,
return -1;
}
CAPSTONE_EXPORT
cs_err cs_regs_access(csh ud, const cs_insn *insn,
cs_regs regs_read, uint8_t *regs_read_count,
cs_regs regs_write, uint8_t *regs_write_count)
{
struct cs_struct *handle;
if (!ud)
return -1;
handle = (struct cs_struct *)(uintptr_t)ud;
#ifdef CAPSTONE_DIET
// This API does not work in DIET mode
handle->errnum = CS_ERR_DIET;
return CS_ERR_DIET;
#else
if (!handle->detail) {
handle->errnum = CS_ERR_DETAIL;
return CS_ERR_DETAIL;
}
if (!insn->id) {
handle->errnum = CS_ERR_SKIPDATA;
return CS_ERR_SKIPDATA;
}
if (!insn->detail) {
handle->errnum = CS_ERR_DETAIL;
return CS_ERR_DETAIL;
}
if (handle->reg_access) {
handle->reg_access(insn, regs_read, regs_read_count, regs_write, regs_write_count);
} else {
// this arch is unsupported yet
handle->errnum = CS_ERR_ARCH;
return CS_ERR_ARCH;
}
return CS_ERR_OK;
#endif
}

View File

@ -24,6 +24,11 @@ typedef void (*GetID_t)(cs_struct *h, cs_insn *insn, unsigned int id);
// return register name, given register ID
typedef char *(*GetRegisterName_t)(unsigned RegNo);
// return registers accessed by instruction
typedef void (*GetRegisterAccess_t)(const cs_insn *insn,
cs_regs regs_read, uint8_t *regs_read_count,
cs_regs regs_write, uint8_t *regs_write_count);
// for ARM only
typedef struct ARM_ITStatus {
unsigned char ITStates[128]; // FIXME
@ -54,6 +59,7 @@ struct cs_struct {
uint8_t skipdata_size; // how many bytes to skip
cs_opt_skipdata skipdata_setup; // user-defined skipdata setup
uint8_t *regsize_map; // map to register size (x86-only for now)
GetRegisterAccess_t reg_access;
};
#define MAX_ARCH 8

View File

@ -146,6 +146,14 @@ typedef enum cs_op_type {
CS_OP_FP, // Floating-Point operand.
} cs_op_type;
//> Common instruction operand access types - to be consistent across all architectures.
//> It is possible to combine access types, for example: CS_AC_READ | CS_AC_WRITE
typedef enum cs_ac_type {
CS_AC_INVALID = 0, // Uninitialized/invalid access type.
CS_AC_READ = 1 << 0, // Operand read from memory or register.
CS_AC_WRITE = 1 << 1, // Operand write to memory or register.
} cs_ac_type;
//> Common instruction groups - to be consistent across all architectures.
typedef enum cs_group_type {
CS_GRP_INVALID = 0, // uninitialized/invalid group.
@ -213,10 +221,10 @@ typedef struct cs_opt_skipdata {
// NOTE: All information in cs_detail is only available when CS_OPT_DETAIL = CS_OPT_ON
typedef struct cs_detail {
uint8_t regs_read[12]; // list of implicit registers read by this insn
uint16_t regs_read[12]; // list of implicit registers read by this insn
uint8_t regs_read_count; // number of implicit registers read by this insn
uint8_t regs_write[20]; // list of implicit registers modified by this insn
uint16_t regs_write[20]; // list of implicit registers modified by this insn
uint8_t regs_write_count; // number of implicit registers modified by this insn
uint8_t groups[8]; // list of group this instruction belong to
@ -657,6 +665,31 @@ CAPSTONE_EXPORT
int cs_op_index(csh handle, const cs_insn *insn, unsigned int op_type,
unsigned int position);
// Type of array to keep the list of registers
typedef uint16_t cs_regs[64];
/*
Retrieve all the registers accessed by an instruction, either explicitly or
implicitly.
WARN: when in 'diet' mode, this API is irrelevant because engine does not
store registers.
@handle: handle returned by cs_open()
@insn: disassembled instruction structure returned from cs_disasm() or cs_disasm_iter()
@regs_read: on return, this array contains all registers read by instruction.
@regs_read_count: number of registers kept inside @regs_read array.
@regs_write: on return, this array contains all registers written by instruction.
@regs_write_count: number of registers kept inside @regs_write array.
@return CS_ERR_OK on success, or other value on failure (refer to cs_err enum
for detailed error).
*/
CAPSTONE_EXPORT
cs_err cs_regs_access(csh handle, const cs_insn *insn,
cs_regs regs_read, uint8_t *regs_read_count,
cs_regs regs_write, uint8_t *regs_write_count);
#ifdef __cplusplus
}
#endif

View File

@ -69,6 +69,56 @@ typedef enum x86_reg {
X86_REG_ENDING // <-- mark the end of the list of registers
} x86_reg;
//> Sub-flags of EFLAGS
typedef enum x86_eflags_type {
X86_EFLAGS_MODIFY_AF = (uint64_t)1 << 0,
X86_EFLAGS_MODIFY_CF = (uint64_t)1 << 1,
X86_EFLAGS_MODIFY_SF = (uint64_t)1 << 2,
X86_EFLAGS_MODIFY_ZF = (uint64_t)1 << 3,
X86_EFLAGS_MODIFY_PF = (uint64_t)1 << 4,
X86_EFLAGS_MODIFY_OF = (uint64_t)1 << 5,
X86_EFLAGS_MODIFY_TF = (uint64_t)1 << 6,
X86_EFLAGS_MODIFY_IF = (uint64_t)1 << 7,
X86_EFLAGS_MODIFY_DF = (uint64_t)1 << 8,
X86_EFLAGS_MODIFY_NT = (uint64_t)1 << 9,
X86_EFLAGS_MODIFY_RF = (uint64_t)1 << 10,
X86_EFLAGS_PRIOR_OF = (uint64_t)1 << 11,
X86_EFLAGS_PRIOR_SF = (uint64_t)1 << 12,
X86_EFLAGS_PRIOR_ZF = (uint64_t)1 << 13,
X86_EFLAGS_PRIOR_AF = (uint64_t)1 << 14,
X86_EFLAGS_PRIOR_PF = (uint64_t)1 << 15,
X86_EFLAGS_PRIOR_CF = (uint64_t)1 << 16,
X86_EFLAGS_PRIOR_TF = (uint64_t)1 << 17,
X86_EFLAGS_PRIOR_IF = (uint64_t)1 << 18,
X86_EFLAGS_PRIOR_DF = (uint64_t)1 << 19,
X86_EFLAGS_PRIOR_NT = (uint64_t)1 << 20,
X86_EFLAGS_RESET_OF = (uint64_t)1 << 21,
X86_EFLAGS_RESET_CF = (uint64_t)1 << 22,
X86_EFLAGS_RESET_DF = (uint64_t)1 << 23,
X86_EFLAGS_RESET_IF = (uint64_t)1 << 24,
X86_EFLAGS_RESET_SF = (uint64_t)1 << 25,
X86_EFLAGS_RESET_AF = (uint64_t)1 << 26,
X86_EFLAGS_RESET_TF = (uint64_t)1 << 27,
X86_EFLAGS_RESET_NT = (uint64_t)1 << 28,
X86_EFLAGS_RESET_PF = (uint64_t)1 << 29,
X86_EFLAGS_SET_CF = (uint64_t)1 << 30,
X86_EFLAGS_SET_DF = (uint64_t)1 << 31,
X86_EFLAGS_SET_IF = (uint64_t)1 << 32,
X86_EFLAGS_TEST_OF = (uint64_t)1 << 33,
X86_EFLAGS_TEST_SF = (uint64_t)1 << 34,
X86_EFLAGS_TEST_ZF = (uint64_t)1 << 35,
X86_EFLAGS_TEST_PF = (uint64_t)1 << 36,
X86_EFLAGS_TEST_CF = (uint64_t)1 << 37,
X86_EFLAGS_TEST_NT = (uint64_t)1 << 38,
X86_EFLAGS_TEST_DF = (uint64_t)1 << 39,
X86_EFLAGS_UNDEFINED_OF = (uint64_t)1 << 40,
X86_EFLAGS_UNDEFINED_SF = (uint64_t)1 << 41,
X86_EFLAGS_UNDEFINED_ZF = (uint64_t)1 << 42,
X86_EFLAGS_UNDEFINED_PF = (uint64_t)1 << 43,
X86_EFLAGS_UNDEFINED_AF = (uint64_t)1 << 44,
X86_EFLAGS_UNDEFINED_CF = (uint64_t)1 << 45,
} x86_eflags_type;
//> Operand type for instruction's operands
typedef enum x86_op_type {
X86_OP_INVALID = 0, // = CS_OP_INVALID (Uninitialized).
@ -200,6 +250,11 @@ typedef struct cs_x86_op {
// size of this operand (in bytes).
uint8_t size;
// How is this operand accessed? (READ, WRITE or READ|WRITE)
// This field is combined of cs_ac_type.
// NOTE: this field is irrelevant if engine is compiled in DIET mode.
uint8_t access;
// AVX broadcast type, or 0 if irrelevant
x86_avx_bcast avx_bcast;
@ -261,6 +316,10 @@ typedef struct cs_x86 {
// AVX static rounding mode
x86_avx_rm avx_rm;
// EFLAGS updated by this instruction.
// This can be formed from OR combination of X86_EFLAGS_* symbols in x86.h
uint64_t eflags;
// Number of operands of this instruction,
// or 0 when instruction has no operand.
uint8_t op_count;

View File

@ -31,10 +31,112 @@ static void print_string_hex(char *comment, unsigned char *str, size_t len)
printf("\n");
}
static char *get_eflag_name(uint64_t flag)
{
switch(flag) {
default:
return NULL;
case X86_EFLAGS_UNDEFINED_OF:
return "UNDEF_OF";
case X86_EFLAGS_UNDEFINED_SF:
return "UNDEF_SF";
case X86_EFLAGS_UNDEFINED_ZF:
return "UNDEF_ZF";
case X86_EFLAGS_MODIFY_AF:
return "MOD_AF";
case X86_EFLAGS_UNDEFINED_PF:
return "UNDEF_PF";
case X86_EFLAGS_MODIFY_CF:
return "MOD_CF";
case X86_EFLAGS_MODIFY_SF:
return "MOD_SF";
case X86_EFLAGS_MODIFY_ZF:
return "MOD_ZF";
case X86_EFLAGS_UNDEFINED_AF:
return "UNDEF_AF";
case X86_EFLAGS_MODIFY_PF:
return "MOD_PF";
case X86_EFLAGS_UNDEFINED_CF:
return "UNDEF_CF";
case X86_EFLAGS_MODIFY_OF:
return "MOD_OF";
case X86_EFLAGS_RESET_OF:
return "RESET_OF";
case X86_EFLAGS_RESET_CF:
return "RESET_CF";
case X86_EFLAGS_RESET_DF:
return "RESET_DF";
case X86_EFLAGS_RESET_IF:
return "RESET_IF";
case X86_EFLAGS_TEST_OF:
return "TEST_OF";
case X86_EFLAGS_TEST_SF:
return "TEST_SF";
case X86_EFLAGS_TEST_ZF:
return "TEST_ZF";
case X86_EFLAGS_TEST_PF:
return "TEST_PF";
case X86_EFLAGS_TEST_CF:
return "TEST_CF";
case X86_EFLAGS_RESET_SF:
return "RESET_SF";
case X86_EFLAGS_RESET_AF:
return "RESET_AF";
case X86_EFLAGS_RESET_TF:
return "RESET_TF";
case X86_EFLAGS_RESET_NT:
return "RESET_NT";
case X86_EFLAGS_PRIOR_OF:
return "PRIOR_OF";
case X86_EFLAGS_PRIOR_SF:
return "PRIOR_SF";
case X86_EFLAGS_PRIOR_ZF:
return "PRIOR_ZF";
case X86_EFLAGS_PRIOR_AF:
return "PRIOR_AF";
case X86_EFLAGS_PRIOR_PF:
return "PRIOR_PF";
case X86_EFLAGS_PRIOR_CF:
return "PRIOR_CF";
case X86_EFLAGS_PRIOR_TF:
return "PRIOR_TF";
case X86_EFLAGS_PRIOR_IF:
return "PRIOR_IF";
case X86_EFLAGS_PRIOR_DF:
return "PRIOR_DF";
case X86_EFLAGS_TEST_NT:
return "TEST_NT";
case X86_EFLAGS_TEST_DF:
return "TEST_DF";
case X86_EFLAGS_RESET_PF:
return "RESET_PF";
case X86_EFLAGS_PRIOR_NT:
return "PRIOR_NT";
case X86_EFLAGS_MODIFY_TF:
return "MOD_TF";
case X86_EFLAGS_MODIFY_IF:
return "MOD_IF";
case X86_EFLAGS_MODIFY_DF:
return "MOD_DF";
case X86_EFLAGS_MODIFY_NT:
return "MOD_NT";
case X86_EFLAGS_MODIFY_RF:
return "MOD_RF";
case X86_EFLAGS_SET_CF:
return "SET_CF";
case X86_EFLAGS_SET_DF:
return "SET_DF";
case X86_EFLAGS_SET_IF:
return "SET_IF";
}
}
static void print_insn_detail(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)
@ -88,6 +190,7 @@ static void print_insn_detail(csh ud, cs_mode mode, cs_insn *ins)
printf("\tavx_rm: %u\n", x86->avx_rm);
}
// Print out all immediate operands
count = cs_op_count(ud, ins, X86_OP_IMM);
if (count) {
printf("\timm_count: %u\n", count);
@ -99,6 +202,8 @@ static void print_insn_detail(csh ud, cs_mode mode, cs_insn *ins)
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]);
@ -138,6 +243,50 @@ static void print_insn_detail(csh ud, cs_mode mode, cs_insn *ins)
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, &regs_read_count,
regs_write, &regs_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 (x86->eflags) {
printf("\tEFLAGS:");
for(i = 0; i <=45; i++)
if (x86->eflags & (1 << i)) {
printf(" %s", get_eflag_name((uint64_t)1 << i));
}
printf("\n");
}
printf("\n");
@ -157,8 +306,8 @@ static void test()
//#define X86_CODE64 "\xe9\x79\xff\xff\xff" // jmp 0xf7e
#define X86_CODE16 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6"
//#define X86_CODE16 "\x67\x00\x18"
#define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x05\x23\x01\x00\x00\x36\x8b\x84\x91\x23\x01\x00\x00\x41\x8d\x84\x39\x89\x67\x00\x00\x8d\x87\x89\x67\x00\x00\xb4\xc6"
//#define X86_CODE32 "\x05\x23\x01\x00\x00\x0f\x01\xda"
//#define X86_CODE32 "\x0f\xa7\xc0" // xstorerng
//#define X86_CODE32 "\x64\xa1\x18\x00\x00\x00" // mov eax, dword ptr fs:[18]
//#define X86_CODE32 "\x64\xa3\x00\x00\x00\x00" // mov [fs:0x0], eax
@ -170,6 +319,7 @@ static void test()
//#define X86_CODE32 "\x24\xb8" // and $0xb8,%al
//#define X86_CODE32 "\xf0\x01\xd8" // lock add eax,ebx
//#define X86_CODE32 "\xf3\xaa" // rep stosb
//#define X86_CODE32 "\x81\xc6\x23\x01\x00\x00"
struct platform platforms[] = {
{
@ -231,7 +381,7 @@ static void test()
printf("Disasm:\n");
for (j = 0; j < count; j++) {
printf("0x%"PRIx64":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
printf("0x%"PRIx64":\t%s\t%s\n\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
print_insn_detail(handle, platforms[i].mode, &insn[j]);
}
printf("0x%"PRIx64":\n", insn[j-1].address + insn[j-1].size);

13
utils.c
View File

@ -50,7 +50,18 @@ int name2id(name_map* map, int max, const char *name)
// count number of positive members in a list.
// NOTE: list must be guaranteed to end in 0
unsigned int count_positive(unsigned char *list)
unsigned int count_positive(uint16_t *list)
{
unsigned int c;
for (c = 0; list[c] > 0; c++);
return c;
}
// count number of positive members in a list.
// NOTE: list must be guaranteed to end in 0
unsigned int count_positive8(unsigned char *list)
{
unsigned int c;

View File

@ -16,8 +16,8 @@ typedef struct insn_map {
unsigned short id;
unsigned short mapid;
#ifndef CAPSTONE_DIET
unsigned char regs_use[12]; // list of implicit registers used by this instruction
unsigned char regs_mod[20]; // list of implicit registers modified by this instruction
uint16_t regs_use[12]; // list of implicit registers used by this instruction
uint16_t regs_mod[20]; // list of implicit registers modified by this instruction
unsigned char groups[8]; // list of group this instruction belong to
bool branch; // branch instruction?
bool indirect_branch; // indirect branch instruction?
@ -40,7 +40,8 @@ int name2id(name_map* map, int max, const char *name);
// count number of positive members in a list.
// NOTE: list must be guaranteed to end in 0
unsigned int count_positive(unsigned char *list);
unsigned int count_positive(uint16_t *list);
unsigned int count_positive8(unsigned char *list);
#define ARR_SIZE(a) (sizeof(a)/sizeof(a[0]))
@ -51,5 +52,7 @@ char *cs_strdup(const char *str);
// we need this since Windows doesnt have snprintf()
int cs_snprintf(char *buffer, size_t size, const char *fmt, ...);
#define CS_AC_IGNORE (1 << 7)
#endif