Skip to content

Commit

Permalink
arm: support cs_regs_access() API
Browse files Browse the repository at this point in the history
  • Loading branch information
aquynh committed Apr 7, 2015
1 parent 5f22deb commit 29f777b
Show file tree
Hide file tree
Showing 12 changed files with 668 additions and 2,399 deletions.
1 change: 1 addition & 0 deletions MCInst.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ void MCInst_Init(MCInst *inst)
inst->has_imm = false;
inst->op1_size = 0;
inst->writeback = false;
inst->ac_idx = 0;
}

void MCInst_clear(MCInst *inst)
Expand Down
2 changes: 2 additions & 0 deletions MCInst.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ struct MCInst {
uint8_t x86_prefix[4];
uint8_t imm_size; // immediate size for X86_OP_IMM operand
bool writeback; // writeback for ARM
// operand access index for list of registers sharing the same access right (for ARM)
uint8_t ac_idx;
};

void MCInst_Init(MCInst *inst);
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ DEP_ARM += arch/ARM/ARMGenInstrInfo.inc
DEP_ARM += arch/ARM/ARMGenRegisterInfo.inc
DEP_ARM += arch/ARM/ARMGenSubtargetInfo.inc
DEP_ARM += arch/ARM/ARMMappingInsn.inc
DEP_ARM += arch/ARM/ARMMappingInsnOp.inc

LIBOBJ_ARM =
ifneq (,$(findstring arm,$(CAPSTONE_ARCHS)))
Expand Down
8 changes: 6 additions & 2 deletions arch/ARM/ARMDisassembler.c
Original file line number Diff line number Diff line change
Expand Up @@ -472,8 +472,10 @@ static DecodeStatus _ARM_getInstruction(cs_struct *ud, MCInst *MI, const uint8_t

if (MI->flat_insn->detail) {
memset(&MI->flat_insn->detail->arm, 0, sizeof(cs_arm));
for (i = 0; i < ARR_SIZE(MI->flat_insn->detail->arm.operands); i++)
for (i = 0; i < ARR_SIZE(MI->flat_insn->detail->arm.operands); i++) {
MI->flat_insn->detail->arm.operands[i].vector_index = -1;
MI->flat_insn->detail->arm.operands[i].neon_lane = -1;
}
}

if (ud->big_endian)
Expand Down Expand Up @@ -713,8 +715,10 @@ static DecodeStatus _Thumb_getInstruction(cs_struct *ud, MCInst *MI, const uint8

if (MI->flat_insn->detail) {
memset(&MI->flat_insn->detail->arm, 0, sizeof(cs_arm));
for (i = 0; i < ARR_SIZE(MI->flat_insn->detail->arm.operands); i++)
for (i = 0; i < ARR_SIZE(MI->flat_insn->detail->arm.operands); i++) {
MI->flat_insn->detail->arm.operands[i].vector_index = -1;
MI->flat_insn->detail->arm.operands[i].neon_lane = -1;
}
}

if (ud->big_endian)
Expand Down
359 changes: 355 additions & 4 deletions arch/ARM/ARMInstPrinter.c

Large diffs are not rendered by default.

69 changes: 64 additions & 5 deletions arch/ARM/ARMMapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -877,24 +877,83 @@ bool ARM_blx_to_arm_mode(cs_struct *h, unsigned int id) {

}

#if 0

#ifndef CAPSTONE_DIET
// map instruction to its characteristics
typedef struct insn_op {
unsigned int eflags_update; // how this instruction update status flags
cs_ac_type operands[4];
uint8_t access[7];
} insn_op;

static insn_op insn_ops[] = {
{
// NULL item
0,
{ 0 }
},

#include "ARMMappingInsnOp.inc"
};

// given internal insn id, return operand access info
uint8_t *ARM_get_op_access(cs_struct *h, unsigned int id)
{
int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
if (i != 0) {
return insn_ops[i].access;
}

return NULL;
}

void ARM_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_arm *arm = &(insn->detail->arm);

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 < arm->op_count; i++) {
cs_arm_op *op = &(arm->operands[i]);
switch((int)op->type) {
case ARM_OP_REG:
if ((op->access & CS_AC_READ) && !arr_exist(regs_read, read_count, op->reg)) {
regs_read[read_count] = op->reg;
read_count++;
}
if ((op->access & CS_AC_WRITE) && !arr_exist(regs_write, write_count, op->reg)) {
regs_write[write_count] = op->reg;
write_count++;
}
break;
case ARM_OP_MEM:
// registers appeared in memory references always being read
if ((op->mem.base != ARM_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.base)) {
regs_read[read_count] = op->mem.base;
read_count++;
}
if ((op->mem.index != ARM_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.index)) {
regs_read[read_count] = op->mem.index;
read_count++;
}
if ((arm->writeback) && (op->mem.base != ARM_REG_INVALID) && !arr_exist(regs_write, write_count, op->mem.base)) {
regs_write[write_count] = op->mem.base;
write_count++;
}
default:
break;
}
}

*regs_read_count = read_count;
*regs_write_count = write_count;
}
#endif

#endif
6 changes: 6 additions & 0 deletions arch/ARM/ARMMapping.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,10 @@ bool ARM_rel_branch(cs_struct *h, unsigned int insn_id);

bool ARM_blx_to_arm_mode(cs_struct *h, unsigned int insn_id);

uint8_t *ARM_get_op_access(cs_struct *h, unsigned int id);

void ARM_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
Loading

0 comments on commit 29f777b

Please sign in to comment.