Support op->family and some op->cycle for anal.arm64

This commit is contained in:
pancake 2016-06-16 01:43:41 +02:00
parent 2f6d778aef
commit 5c14841299
3 changed files with 123 additions and 18 deletions

View File

@ -410,7 +410,7 @@ R_API char *r_anal_op_to_string(RAnal *anal, RAnalOp *op) {
return strdup (ret);
}
R_API const char *r_anal_stackop_tostring (int s) {
R_API const char *r_anal_stackop_tostring(int s) {
switch (s) {
case R_ANAL_STACK_NULL:
return "null";
@ -428,7 +428,7 @@ R_API const char *r_anal_stackop_tostring (int s) {
return "unk";
}
R_API const char *r_anal_op_family_to_string (int n) {
R_API const char *r_anal_op_family_to_string(int n) {
static char num[32];
switch (n) {
case R_ANAL_OP_FAMILY_UNKNOWN: return "unk";
@ -436,9 +436,19 @@ R_API const char *r_anal_op_family_to_string (int n) {
case R_ANAL_OP_FAMILY_FPU: return "fpu";
case R_ANAL_OP_FAMILY_MMX: return "mmx";
case R_ANAL_OP_FAMILY_PRIV: return "priv";
case R_ANAL_OP_FAMILY_VIRT: return "virt";
default:
snprintf (num, sizeof (num), "%d", n);
break;
}
return num;
}
R_API int r_anal_op_family_from_string(const char *f) {
if (!strcmp (f, "cpu")) return R_ANAL_OP_FAMILY_CPU;
if (!strcmp (f, "fpu")) return R_ANAL_OP_FAMILY_FPU;
if (!strcmp (f, "mmx")) return R_ANAL_OP_FAMILY_MMX;
if (!strcmp (f, "priv")) return R_ANAL_OP_FAMILY_PRIV;
if (!strcmp (f, "virt")) return R_ANAL_OP_FAMILY_VIRT;
return R_ANAL_OP_FAMILY_UNKNOWN;
}

View File

@ -268,23 +268,56 @@ static int analop64_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int l
r_strbuf_setf (&op->esil,
"%s,%s,*,%s,+,%s,=",REG64(2),REG64(1),REG64(3), REG64(0));
break;
case ARM64_INS_ADD: OPCALL("+"); break;
case ARM64_INS_SUB: OPCALL("-"); break;
case ARM64_INS_MUL: OPCALL("*"); break;
case ARM64_INS_AND: OPCALL("&"); break;
case ARM64_INS_ORR: OPCALL("|"); break;
case ARM64_INS_EOR: OPCALL("^"); break;
case ARM64_INS_ORN: OPCALL_NEG("|"); break;
case ARM64_INS_EON: OPCALL_NEG("^"); break;
case ARM64_INS_LSR: OPCALL(">>"); break;
case ARM64_INS_LSL: OPCALL("<<"); break;
case ARM64_INS_ADD:
op->cycles = 1;
op->type = R_ANAL_OP_TYPE_ADD;
OPCALL("+");
break;
case ARM64_INS_SUB:
op->cycles = 1;
op->type = R_ANAL_OP_TYPE_ADD;
OPCALL("-");
break;
case ARM64_INS_MUL:
op->type = R_ANAL_OP_TYPE_MUL;
OPCALL("*");
break;
case ARM64_INS_AND:
op->type = R_ANAL_OP_TYPE_AND;
OPCALL("&");
break;
case ARM64_INS_ORR:
op->type = R_ANAL_OP_TYPE_OR;
OPCALL("|");
break;
case ARM64_INS_EOR:
op->type = R_ANAL_OP_TYPE_XOR;
OPCALL("^");
break;
case ARM64_INS_ORN:
op->type = R_ANAL_OP_TYPE_OR;
OPCALL_NEG("|");
break;
case ARM64_INS_EON:
op->type = R_ANAL_OP_TYPE_NOT;
OPCALL_NEG("^");
break;
case ARM64_INS_LSR:
op->cycles = 1;
op->type = R_ANAL_OP_TYPE_SHR;
OPCALL(">>");
break;
case ARM64_INS_LSL:
op->cycles = 1;
op->type = R_ANAL_OP_TYPE_SHL;
OPCALL("<<");
break;
case ARM64_INS_STURB: // sturb wzr, [x9, 0xffffffffffffffff]
// TODO
break;
case ARM64_INS_NOP:
r_strbuf_setf (&op->esil, ",");
op->cycles = 1;
break;
case ARM64_INS_FDIV:
case ARM64_INS_SDIV:
@ -405,6 +438,9 @@ static int analop64_esil(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int l
case ARM64_INS_STUR:
case ARM64_INS_STR: // str x6, [x6,0xf90]
case ARM64_INS_STRH:
case ARM64_INS_STXR:
case ARM64_INS_STXRH:
case ARM64_INS_STXRB:
if ((int)MEMDISP64(1) < 0) {
r_strbuf_setf (&op->esil, "%s,%s,%"PFMT64d",-,=[]",
REG64(0), MEMBASE64(1), -(int)MEMDISP64(1));
@ -865,8 +901,24 @@ r4,r5,r6,3,sp,[*],12,sp,+=
return 0;
}
static void anop64 (RAnalOp *op, cs_insn *insn) {
static void anop64 (csh handle, RAnalOp *op, cs_insn *insn) {
ut64 addr = op->addr;
/* grab family */
if (cs_insn_group (handle, insn, ARM64_GRP_CRYPTO)) {
op->family = R_ANAL_OP_FAMILY_CRYPTO;
} else if (cs_insn_group (handle, insn, ARM64_GRP_CRC)) {
op->family = R_ANAL_OP_FAMILY_CRYPTO;
} else if (cs_insn_group (handle, insn, ARM64_GRP_PRIVILEGE)) {
op->family = R_ANAL_OP_FAMILY_PRIV;
} else if (cs_insn_group (handle, insn, ARM64_GRP_NEON)) {
op->family = R_ANAL_OP_FAMILY_MMX;
} else if (cs_insn_group (handle, insn, ARM64_GRP_FPARMV8)) {
op->family = R_ANAL_OP_FAMILY_FPU;
} else {
op->family = R_ANAL_OP_FAMILY_CPU;
}
switch (insn->id) {
case ARM64_INS_SVC:
op->type = R_ANAL_OP_TYPE_SWI;
@ -879,6 +931,7 @@ static void anop64 (RAnalOp *op, cs_insn *insn) {
op->type = R_ANAL_OP_TYPE_NOP;
break;
case ARM64_INS_SUB:
op->cycles = 1;
op->type = R_ANAL_OP_TYPE_SUB;
if (REGID64(0) == ARM64_REG_SP) {
if (REGID64(1) == ARM64_REG_SP) {
@ -890,7 +943,21 @@ static void anop64 (RAnalOp *op, cs_insn *insn) {
}
}
break;
case ARM64_INS_FDIV:
case ARM64_INS_SDIV:
case ARM64_INS_UDIV:
op->cycles = 4;
op->type = R_ANAL_OP_TYPE_DIV;
break;
case ARM64_INS_MUL:
case ARM64_INS_FMUL:
/* TODO: if next instruction is also a MUL, cycles are /=2 */
/* also known as Register Indexing Addressing */
op->cycles = 4;
op->type = R_ANAL_OP_TYPE_MUL;
break;
case ARM64_INS_ADD:
op->cycles = 1;
op->type = R_ANAL_OP_TYPE_ADD;
break;
case ARM64_INS_CSEL:
@ -958,6 +1025,11 @@ static void anop64 (RAnalOp *op, cs_insn *insn) {
case ARM64_INS_STUR:
case ARM64_INS_STR:
case ARM64_INS_STP:
case ARM64_INS_STNP:
case ARM64_INS_STXR:
case ARM64_INS_STXRH:
case ARM64_INS_STLXRH:
case ARM64_INS_STXRB:
op->type = R_ANAL_OP_TYPE_STORE;
if (REGBASE64(1) == ARM64_REG_X29) {
op->stackop = R_ANAL_STACK_SET;
@ -970,6 +1042,8 @@ static void anop64 (RAnalOp *op, cs_insn *insn) {
case ARM64_INS_LDRSW:
case ARM64_INS_LDR:
case ARM64_INS_LDP:
case ARM64_INS_LDNP:
case ARM64_INS_LDPSW:
case ARM64_INS_LDRH:
case ARM64_INS_LDRB:
op->type = R_ANAL_OP_TYPE_LOAD;
@ -1054,7 +1128,7 @@ static int cond_cs2r2(int cc) {
return cc;
}
static void anop32 (RAnalOp *op, cs_insn *insn, bool thumb) {
static void anop32 (csh handle, RAnalOp *op, cs_insn *insn, bool thumb) {
const ut64 addr = op->addr;
int i;
op->cond = cond_cs2r2 (insn->detail->arm.cc);
@ -1062,6 +1136,24 @@ static void anop32 (RAnalOp *op, cs_insn *insn, bool thumb) {
op->type = R_ANAL_OP_TYPE_NOP;
return;
}
/* grab family */
if (cs_insn_group (handle, insn, ARM_GRP_CRYPTO)) {
op->family = R_ANAL_OP_FAMILY_CRYPTO;
} else if (cs_insn_group (handle, insn, ARM_GRP_CRC)) {
op->family = R_ANAL_OP_FAMILY_CRYPTO;
} else if (cs_insn_group (handle, insn, ARM_GRP_PRIVILEGE)) {
op->family = R_ANAL_OP_FAMILY_PRIV;
} else if (cs_insn_group (handle, insn, ARM_GRP_VIRTUALIZATION)) {
op->family = R_ANAL_OP_FAMILY_VIRT;
} else if (cs_insn_group (handle, insn, ARM_GRP_NEON)) {
op->family = R_ANAL_OP_FAMILY_MMX;
} else if (cs_insn_group (handle, insn, ARM_GRP_FPARMV8)) {
op->family = R_ANAL_OP_FAMILY_FPU;
} else if (cs_insn_group (handle, insn, ARM_GRP_THUMB2DSP)) {
op->family = R_ANAL_OP_FAMILY_MMX;
} else {
op->family = R_ANAL_OP_FAMILY_CPU;
}
switch (insn->id) {
#if 0
@ -1085,6 +1177,7 @@ jmp $$ + 4 + ( [delta] * 2 )
break;
case ARM_INS_NOP:
op->type = R_ANAL_OP_TYPE_NOP;
op->cycles = 1;
break;
case ARM_INS_POP:
case ARM_INS_FLDMDBX:
@ -1322,12 +1415,12 @@ static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
bool thumb = cs_insn_group (handle, insn, ARM_GRP_THUMB);
op->size = insn->size;
if (a->bits == 64) {
anop64 (op, insn);
anop64 (handle, op, insn);
if (a->decode) {
analop64_esil (a, op, addr, buf, len, &handle, insn);
}
} else {
anop32 (op, insn, thumb);
anop32 (handle, op, insn, thumb);
if (a->decode) {
analop_esil (a, op, addr, buf, len, &handle, insn, thumb);
}

View File

@ -371,6 +371,7 @@ enum {
R_ANAL_OP_FAMILY_MMX, /* multimedia instruction (packed data) */
R_ANAL_OP_FAMILY_PRIV, /* priviledged instruction */
R_ANAL_OP_FAMILY_CRYPTO, /* cryptographic instructions */
R_ANAL_OP_FAMILY_VIRT, /* virtualization instructions */
R_ANAL_OP_FAMILY_LAST
};
@ -1163,6 +1164,7 @@ R_API RAnalType *r_anal_str_to_type(RAnal *a, const char* s);
R_API char *r_anal_type_to_str(RAnal *a, const char *name);
R_API const char *r_anal_optype_to_string(int t);
R_API const char *r_anal_op_family_to_string (int n);
R_API int r_anal_op_family_from_string(const char *f);
R_API RAnalType *r_anal_type_free(RAnalType *t);
R_API RAnalType *r_anal_type_loadfile(RAnal *a, const char *path);
R_API void r_anal_type_define (RAnal *anal, const char *key, const char *value);