Skip to content

Commit 29f777b

Browse files
committed
arm: support cs_regs_access() API
1 parent 5f22deb commit 29f777b

12 files changed

+668
-2399
lines changed

MCInst.c

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ void MCInst_Init(MCInst *inst)
1717
inst->has_imm = false;
1818
inst->op1_size = 0;
1919
inst->writeback = false;
20+
inst->ac_idx = 0;
2021
}
2122

2223
void MCInst_clear(MCInst *inst)

MCInst.h

+2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ struct MCInst {
107107
uint8_t x86_prefix[4];
108108
uint8_t imm_size; // immediate size for X86_OP_IMM operand
109109
bool writeback; // writeback for ARM
110+
// operand access index for list of registers sharing the same access right (for ARM)
111+
uint8_t ac_idx;
110112
};
111113

112114
void MCInst_Init(MCInst *inst);

Makefile

+1
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ DEP_ARM += arch/ARM/ARMGenInstrInfo.inc
8787
DEP_ARM += arch/ARM/ARMGenRegisterInfo.inc
8888
DEP_ARM += arch/ARM/ARMGenSubtargetInfo.inc
8989
DEP_ARM += arch/ARM/ARMMappingInsn.inc
90+
DEP_ARM += arch/ARM/ARMMappingInsnOp.inc
9091

9192
LIBOBJ_ARM =
9293
ifneq (,$(findstring arm,$(CAPSTONE_ARCHS)))

arch/ARM/ARMDisassembler.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -472,8 +472,10 @@ static DecodeStatus _ARM_getInstruction(cs_struct *ud, MCInst *MI, const uint8_t
472472

473473
if (MI->flat_insn->detail) {
474474
memset(&MI->flat_insn->detail->arm, 0, sizeof(cs_arm));
475-
for (i = 0; i < ARR_SIZE(MI->flat_insn->detail->arm.operands); i++)
475+
for (i = 0; i < ARR_SIZE(MI->flat_insn->detail->arm.operands); i++) {
476476
MI->flat_insn->detail->arm.operands[i].vector_index = -1;
477+
MI->flat_insn->detail->arm.operands[i].neon_lane = -1;
478+
}
477479
}
478480

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

714716
if (MI->flat_insn->detail) {
715717
memset(&MI->flat_insn->detail->arm, 0, sizeof(cs_arm));
716-
for (i = 0; i < ARR_SIZE(MI->flat_insn->detail->arm.operands); i++)
718+
for (i = 0; i < ARR_SIZE(MI->flat_insn->detail->arm.operands); i++) {
717719
MI->flat_insn->detail->arm.operands[i].vector_index = -1;
720+
MI->flat_insn->detail->arm.operands[i].neon_lane = -1;
721+
}
718722
}
719723

720724
if (ud->big_endian)

arch/ARM/ARMInstPrinter.c

+355-4
Large diffs are not rendered by default.

arch/ARM/ARMMapping.c

+64-5
Original file line numberDiff line numberDiff line change
@@ -877,24 +877,83 @@ bool ARM_blx_to_arm_mode(cs_struct *h, unsigned int id) {
877877

878878
}
879879

880-
#if 0
881-
880+
#ifndef CAPSTONE_DIET
882881
// map instruction to its characteristics
883882
typedef struct insn_op {
884-
unsigned int eflags_update; // how this instruction update status flags
885-
cs_ac_type operands[4];
883+
uint8_t access[7];
886884
} insn_op;
887885

888886
static insn_op insn_ops[] = {
889887
{
890888
// NULL item
891-
0,
892889
{ 0 }
893890
},
894891

895892
#include "ARMMappingInsnOp.inc"
896893
};
897894

895+
// given internal insn id, return operand access info
896+
uint8_t *ARM_get_op_access(cs_struct *h, unsigned int id)
897+
{
898+
int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
899+
if (i != 0) {
900+
return insn_ops[i].access;
901+
}
902+
903+
return NULL;
904+
}
905+
906+
void ARM_reg_access(const cs_insn *insn,
907+
cs_regs regs_read, uint8_t *regs_read_count,
908+
cs_regs regs_write, uint8_t *regs_write_count)
909+
{
910+
uint8_t i;
911+
uint8_t read_count, write_count;
912+
cs_arm *arm = &(insn->detail->arm);
913+
914+
read_count = insn->detail->regs_read_count;
915+
write_count = insn->detail->regs_write_count;
916+
917+
// implicit registers
918+
memcpy(regs_read, insn->detail->regs_read, read_count * sizeof(insn->detail->regs_read[0]));
919+
memcpy(regs_write, insn->detail->regs_write, write_count * sizeof(insn->detail->regs_write[0]));
920+
921+
// explicit registers
922+
for (i = 0; i < arm->op_count; i++) {
923+
cs_arm_op *op = &(arm->operands[i]);
924+
switch((int)op->type) {
925+
case ARM_OP_REG:
926+
if ((op->access & CS_AC_READ) && !arr_exist(regs_read, read_count, op->reg)) {
927+
regs_read[read_count] = op->reg;
928+
read_count++;
929+
}
930+
if ((op->access & CS_AC_WRITE) && !arr_exist(regs_write, write_count, op->reg)) {
931+
regs_write[write_count] = op->reg;
932+
write_count++;
933+
}
934+
break;
935+
case ARM_OP_MEM:
936+
// registers appeared in memory references always being read
937+
if ((op->mem.base != ARM_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.base)) {
938+
regs_read[read_count] = op->mem.base;
939+
read_count++;
940+
}
941+
if ((op->mem.index != ARM_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.index)) {
942+
regs_read[read_count] = op->mem.index;
943+
read_count++;
944+
}
945+
if ((arm->writeback) && (op->mem.base != ARM_REG_INVALID) && !arr_exist(regs_write, write_count, op->mem.base)) {
946+
regs_write[write_count] = op->mem.base;
947+
write_count++;
948+
}
949+
default:
950+
break;
951+
}
952+
}
953+
954+
*regs_read_count = read_count;
955+
*regs_write_count = write_count;
956+
}
898957
#endif
899958

900959
#endif

arch/ARM/ARMMapping.h

+6
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,10 @@ bool ARM_rel_branch(cs_struct *h, unsigned int insn_id);
2323

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

26+
uint8_t *ARM_get_op_access(cs_struct *h, unsigned int id);
27+
28+
void ARM_reg_access(const cs_insn *insn,
29+
cs_regs regs_read, uint8_t *regs_read_count,
30+
cs_regs regs_write, uint8_t *regs_write_count);
31+
2632
#endif

0 commit comments

Comments
 (0)