diff --git a/libr/anal/op.c b/libr/anal/op.c index e4739bed8a..affb430dd9 100644 --- a/libr/anal/op.c +++ b/libr/anal/op.c @@ -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; +} diff --git a/libr/anal/p/anal_arm_cs.c b/libr/anal/p/anal_arm_cs.c index 18b6682870..9267a52b30 100644 --- a/libr/anal/p/anal_arm_cs.c +++ b/libr/anal/p/anal_arm_cs.c @@ -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); } diff --git a/libr/include/r_anal.h b/libr/include/r_anal.h index 1f3ad44e21..8da49107bd 100644 --- a/libr/include/r_anal.h +++ b/libr/include/r_anal.h @@ -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);