6 #include <capstone/capstone.h>
7 #include <capstone/mips.h>
12 #define OPERAND(x) insn->detail->mips.operands[x]
13 #define REGID(x) insn->detail->mips.operands[x].reg
14 #define REG(x) cs_reg_name(*handle, insn->detail->mips.operands[x].reg)
15 #define IMM(x) insn->detail->mips.operands[x].imm
16 #define MEMBASE(x) cs_reg_name(*handle, insn->detail->mips.operands[x].mem.base)
17 #define MEMINDEX(x) insn->detail->mips.operands[x].mem.index
18 #define MEMDISP(x) insn->detail->mips.operands[x].mem.disp
19 #define OPCOUNT() insn->detail->mips.op_count
22 #define SET_VAL(op, i) \
23 if ((i) < OPCOUNT() && OPERAND(i).type == MIPS_OP_IMM) { \
24 (op)->val = OPERAND(i).imm; \
27 #define CREATE_SRC_DST_3(op) \
28 (op)->src[0] = rz_analysis_value_new(); \
29 (op)->src[1] = rz_analysis_value_new(); \
30 (op)->dst = rz_analysis_value_new();
32 #define CREATE_SRC_DST_2(op) \
33 (op)->src[0] = rz_analysis_value_new(); \
34 (op)->dst = rz_analysis_value_new();
36 #define SET_SRC_DST_3_REGS(op) \
37 CREATE_SRC_DST_3(op); \
38 (op)->dst->reg = rz_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \
39 (op)->dst->type = RZ_ANALYSIS_VAL_REG; \
40 (op)->src[0]->reg = rz_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); \
41 (op)->src[0]->type = RZ_ANALYSIS_VAL_REG; \
42 (op)->src[1]->reg = rz_reg_get(analysis->reg, REG(2), RZ_REG_TYPE_GPR); \
43 (op)->src[1]->type = RZ_ANALYSIS_VAL_REG;
45 #define SET_SRC_DST_3_IMM(op) \
46 CREATE_SRC_DST_3(op); \
47 (op)->dst->reg = rz_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \
48 (op)->dst->type = RZ_ANALYSIS_VAL_REG; \
49 (op)->src[0]->reg = rz_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR); \
50 (op)->src[0]->type = RZ_ANALYSIS_VAL_REG; \
51 (op)->src[1]->imm = IMM(2); \
52 (op)->src[1]->type = RZ_ANALYSIS_VAL_IMM;
54 #define SET_SRC_DST_2_REGS(op) \
55 CREATE_SRC_DST_2(op); \
56 (op)->dst->reg = rz_reg_get(analysis->reg, REG(0), RZ_REG_TYPE_GPR); \
57 (op)->src[0]->reg = rz_reg_get(analysis->reg, REG(1), RZ_REG_TYPE_GPR);
59 #define SET_SRC_DST_3_REG_OR_IMM(op) \
60 if (OPERAND(2).type == MIPS_OP_IMM) { \
61 SET_SRC_DST_3_IMM(op); \
62 } else if (OPERAND(2).type == MIPS_OP_REG) { \
63 SET_SRC_DST_3_REGS(op); \
69 #define ES_IS_NEGATIVE(arg) "1," arg ",<<<,1,&"
72 #define ES_CALL_DR(ra, addr) "pc,4,+," ra ",=," ES_J(addr)
73 #define ES_CALL_D(addr) ES_CALL_DR("ra", addr)
76 #define ES_CALL_NDR(ra, addr) "pc," ra ",=," ES_J(addr)
77 #define ES_CALL_ND(addr) ES_CALL_NDR("ra", addr)
82 #define ES_TRAP_DS() "$ds,!,!,?{,$$,1,TRAP,BREAK,},"
84 #define ES_J(addr) addr ",SETJT,1,SETD"
86 #define ES_TRAP_DS() ""
87 #define ES_J(addr) addr ",pc,="
90 #define ES_B(x) "0xff," x ",&"
91 #define ES_H(x) "0xffff," x ",&"
92 #define ES_W(x) "0xffffffff," x ",&"
95 #define ES_SIGN32_64(arg) es_sign_n_64(a, op, arg, 32)
96 #define ES_SIGN16_64(arg) es_sign_n_64(a, op, arg, 16)
98 #define ES_ADD_CK32_OVERF(x, y, z) es_add_ck(op, x, y, z, 32)
99 #define ES_ADD_CK64_OVERF(x, y, z) es_add_ck(op, x, y, z, 64)
103 rz_strbuf_appendf(&
op->esil,
",%d,%s,~,%s,=,",
bit,
arg,
arg);
112 "%d,0x%" PFMT64x ",%s,%s,^,&,>>,%d,0x%" PFMT64x ",%s,%s,+,&,>>,|,1,==,$z,?{,$$,1,TRAP,}{,%s,%s,+,%s,=,}",
113 bit - 2,
mask, a1, a2,
bit - 1,
mask, a1, a2, a1, a2, re);
116 #define PROTECT_ZERO() \
117 if (REG(0)[0] == 'z') { \
118 rz_strbuf_appendf(&op->esil, ","); \
121 #define ESIL_LOAD(size) \
123 rz_strbuf_appendf(&op->esil, "%s,[" size "],%s,=", \
134 pj_ka(pj,
"operands");
136 for (
i = 0;
i <
x->op_count;
i++) {
141 pj_ks(pj,
"type",
"reg");
145 pj_ks(pj,
"type",
"imm");
149 pj_ks(pj,
"type",
"mem");
153 pj_kN(pj,
"disp",
op->mem.disp);
156 pj_ks(pj,
"type",
"invalid");
171 switch (insn->detail->mips.operands[
n].type) {
177 insn->detail->mips.operands[
n].reg));
180 st64 x = (
st64)insn->detail->mips.operands[
n].imm;
184 int disp = insn->detail->mips.operands[
n].mem.disp;
187 (
ut64)-insn->detail->mips.operands[
n].mem.disp,
189 insn->detail->mips.operands[
n].mem.base));
192 (
ut64)insn->detail->mips.operands[
n].mem.disp,
194 insn->detail->mips.operands[
n].mem.base));
201 #define ARG(x) (*str[x] != 0) ? str[x] : arg(handle, insn, str[x], x)
204 char str[8][32] = { { 0 } };
212 for (
i = 0;
i < insn->detail->mips.op_count &&
i < 8;
i++) {
257 "%s,%s,>>,31,%s,>>,?{,32,%s,32,-,0xffffffff,<<,0xffffffff,&,<<,}{,0,},|,%s,=",
266 "0xffffffff,%s,%s,>>,&,31,%s,>>,?{,%s,32,-,0xffffffff,<<,0xffffffff,&,}{,0,},|,%s,=",
340 rz_strbuf_appendf(&
op->esil,
ES_TRAP_DS()
"0,%s,==,$z,?{," ES_J(
"%s")
",BREAK,},",
395 rz_strbuf_appendf(&
op->esil,
"0,%s,==,$z,?{,%s,%s,=,}",
401 rz_strbuf_appendf(&
op->esil,
"1,%s,==,$z,?{,%s,%s,=,}",
441 const char *arg0 =
ARG(0);
442 const char *arg1 =
ARG(1);
443 const char *arg2 =
ARG(2);
447 arg2 + 1, arg1, arg0);
496 const char *arg0 =
ARG(0);
497 const char *arg1 =
ARG(1);
498 const char *arg2 =
ARG(2);
499 if (!strcmp(arg0, arg1)) {
507 const char *arg0 =
ARG(0);
508 const char *arg1 =
ARG(1);
509 const char *arg2 =
ARG(2);
517 const char *arg0 =
ARG(0);
518 const char *arg1 =
ARG(1);
519 const char *arg2 =
ARG(2);
526 const char *arg0 =
ARG(0);
527 const char *arg1 =
ARG(1);
528 const char *arg2 =
ARG(2);
589 rz_strbuf_appendf (&
op->esil,
"%s,%s,/,lo,=,%s,%s,%%,hi,=",
REG(1),
REG(0),
REG(1),
REG(0));
626 op->src[0]->reg = &
reg;
658 $
r2 -
a mips -
e cfg.bigendian=1 -
c "wx 0083001b" -
663 "opcode":
"divu zero, a0, v1",
664 "disasm":
"divu zero, a0, v1",
719 int n, ret, opsize = -1;
721 static int omode = -1;
722 static int obits = 32;
726 if (analysis->
cpu && *analysis->
cpu) {
727 if (!strcmp(analysis->
cpu,
"micro")) {
729 }
else if (!strcmp(analysis->
cpu,
"r6")) {
731 }
else if (!strcmp(analysis->
cpu,
"v3")) {
733 }
else if (!strcmp(analysis->
cpu,
"v2")) {
740 if (
mode != omode || analysis->
bits != obits) {
744 obits = analysis->
bits;
760 if (n < 1 || insn->
size < 1) {
769 insn->op_str[0] ?
" " :
"",
773 opsize =
op->size = insn->size;
913 op->stackptr = -
IMM(2);
1038 if (insn->detail->mips.operands[0].reg ==
MIPS_REG_RA) {
1079 opex(&
op->opex, hndl, insn);
1096 const char *
p =
NULL;
1097 switch (analysis->
bits) {
1111 "gpr zero .32 ? 0\n"
1136 "gpr t9 .32 100 0\n"
1137 "gpr k0 .32 104 0\n"
1138 "gpr k1 .32 108 0\n"
1139 "gpr gp .32 112 0\n"
1140 "gpr sp .32 116 0\n"
1141 "gpr fp .32 120 0\n"
1142 "gpr ra .32 124 0\n"
1143 "gpr pc .32 128 0\n"
1144 "gpr hi .32 132 0\n"
1145 "gpr lo .32 136 0\n"
1146 "gpr t .32 140 0\n";
1160 "gpr zero .64 ? 0\n"
1173 "gpr t5 .64 104 0\n"
1174 "gpr t6 .64 112 0\n"
1175 "gpr t7 .64 120 0\n"
1176 "gpr s0 .64 128 0\n"
1177 "gpr s1 .64 136 0\n"
1178 "gpr s2 .64 144 0\n"
1179 "gpr s3 .64 152 0\n"
1180 "gpr s4 .64 160 0\n"
1181 "gpr s5 .64 168 0\n"
1182 "gpr s6 .64 176 0\n"
1183 "gpr s7 .64 184 0\n"
1184 "gpr t8 .64 192 0\n"
1185 "gpr t9 .64 200 0\n"
1186 "gpr k0 .64 208 0\n"
1187 "gpr k1 .64 216 0\n"
1188 "gpr gp .64 224 0\n"
1189 "gpr sp .64 232 0\n"
1190 "gpr fp .64 240 0\n"
1191 "gpr ra .64 248 0\n"
1192 "gpr pc .64 256 0\n"
1193 "gpr hi .64 264 0\n"
1194 "gpr lo .64 272 0\n"
1195 "gpr t .64 280 0\n";
1206 #define KW(d, ds, m, ms) rz_list_append(l, rz_search_keyword_new((const ut8 *)d, ds, (const ut8 *)m, ms, NULL))
1208 KW(
"\x27\xbd\x00", 3,
NULL, 0);
1214 .desc =
"Capstone MIPS analyzer",
1221 .bits = 16 | 32 | 64,
1225 #ifndef RZ_PLUGIN_INCORE
RZ_API RzAnalysisValue * rz_analysis_value_new(void)
static int parse_reg_name(RzRegItem *reg, csh handle, cs_insn *insn, int reg_num)
static char * get_reg_profile(RzAnalysis *analysis)
static void opex(RzStrBuf *buf, csh handle, cs_insn *insn)
#define SET_SRC_DST_3_REGS(op)
#define ES_CALL_DR(ra, addr)
#define ES_ADD_CK32_OVERF(x, y, z)
static const char * arg(csh *handle, cs_insn *insn, char *buf, int n)
#define ES_ADD_CK64_OVERF(x, y, z)
static void es_sign_n_64(RzAnalysis *a, RzAnalysisOp *op, const char *arg, int bit)
RZ_API RzLibStruct rizin_plugin
#define ES_SIGN32_64(arg)
RzAnalysisPlugin rz_analysis_plugin_mips_cs
#define ES_CALL_NDR(ra, addr)
#define ES_IS_NEGATIVE(arg)
#define SET_SRC_DST_3_IMM(op)
static void es_add_ck(RzAnalysisOp *op, const char *a1, const char *a2, const char *re, int bit)
#define SET_SRC_DST_2_REGS(op)
static int analop_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn)
static void op_fillval(RzAnalysis *analysis, RzAnalysisOp *op, csh *handle, cs_insn *insn)
static void set_opdir(RzAnalysisOp *op)
static int analop(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask)
static int archinfo(RzAnalysis *analysis, int q)
#define SET_SRC_DST_3_REG_OR_IMM(op)
static RzList * analysis_preludes(RzAnalysis *analysis)
static mcore_handle handle
@ CS_ARCH_MIPS
Mips architecture.
@ CS_MODE_MIPS64
Mips64 ISA (Mips)
@ CS_MODE_MICRO
MicroMips mode (MIPS)
@ CS_MODE_MIPS3
Mips III ISA.
@ CS_MODE_MIPS32
Mips32 ISA (Mips)
@ CS_MODE_MIPS32R6
Mips32r6 ISA.
@ CS_MODE_BIG_ENDIAN
big-endian mode
@ CS_MODE_LITTLE_ENDIAN
little-endian mode (default mode)
@ CS_MODE_MIPS2
Mips II ISA.
@ CS_OPT_DETAIL
Break down instruction structure into details.
@ CS_OPT_ON
Turn ON an option (CS_OPT_DETAIL, CS_OPT_SKIPDATA).
CAPSTONE_EXPORT size_t CAPSTONE_API cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn)
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
CAPSTONE_EXPORT void CAPSTONE_API cs_free(cs_insn *insn, size_t count)
CAPSTONE_EXPORT const char *CAPSTONE_API cs_reg_name(csh ud, unsigned int reg)
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_close(csh *handle)
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
RZ_API void rz_search_keyword_free(RzSearchKeyword *kw)
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
@ RZ_ANALYSIS_STACK_ALIGN
@ RZ_ANALYSIS_OP_DIR_READ
@ RZ_ANALYSIS_OP_DIR_EXEC
@ RZ_ANALYSIS_OP_DIR_WRITE
@ RZ_ANALYSIS_OP_MASK_DISASM
@ RZ_ANALYSIS_OP_MASK_VAL
@ RZ_ANALYSIS_OP_MASK_OPEX
@ RZ_ANALYSIS_OP_MASK_ESIL
#define RZ_ANALYSIS_OP_TYPE_MASK
@ RZ_ANALYSIS_OP_TYPE_CMP
@ RZ_ANALYSIS_OP_TYPE_SUB
@ RZ_ANALYSIS_OP_TYPE_LOAD
@ RZ_ANALYSIS_OP_TYPE_MUL
@ RZ_ANALYSIS_OP_TYPE_JMP
@ RZ_ANALYSIS_OP_TYPE_AND
@ RZ_ANALYSIS_OP_TYPE_UJMP
@ RZ_ANALYSIS_OP_TYPE_SWI
@ RZ_ANALYSIS_OP_TYPE_SAR
@ RZ_ANALYSIS_OP_TYPE_TRAP
@ RZ_ANALYSIS_OP_TYPE_CALL
@ RZ_ANALYSIS_OP_TYPE_ADD
@ RZ_ANALYSIS_OP_TYPE_STORE
@ RZ_ANALYSIS_OP_TYPE_SHR
@ RZ_ANALYSIS_OP_TYPE_RJMP
@ RZ_ANALYSIS_OP_TYPE_CJMP
@ RZ_ANALYSIS_OP_TYPE_DIV
@ RZ_ANALYSIS_OP_TYPE_MOV
@ RZ_ANALYSIS_OP_TYPE_SHL
@ RZ_ANALYSIS_OP_TYPE_ILL
@ RZ_ANALYSIS_OP_TYPE_UCALL
@ RZ_ANALYSIS_OP_TYPE_NOT
@ RZ_ANALYSIS_OP_TYPE_RET
@ RZ_ANALYSIS_OP_TYPE_NOP
@ RZ_ANALYSIS_OP_TYPE_LEA
@ RZ_ANALYSIS_OP_TYPE_RCALL
@ RZ_ANALYSIS_OP_TYPE_XOR
void(* RzListFree)(void *ptr)
#define RZ_LOG_ERROR(fmtstr,...)
RZ_API PJ * pj_ka(PJ *j, const char *k)
RZ_API PJ * pj_end(PJ *j)
RZ_API const char * pj_string(PJ *pj)
RZ_API void pj_free(PJ *j)
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
RZ_API PJ * pj_kN(PJ *j, const char *k, st64 n)
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API const char * rz_strbuf_set(RzStrBuf *sb, const char *s)
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
RZ_API const char * rz_strbuf_setf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_fini(RzStrBuf *sb)
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_init(RzStrBuf *sb)
@ MIPS_OP_REG
= CS_OP_REG (Register operand).
@ MIPS_OP_IMM
= CS_OP_IMM (Immediate operand).
@ MIPS_OP_MEM
= CS_OP_MEM (Memory operand).
@ MIPS_OP_INVALID
= CS_OP_INVALID (Uninitialized).
ut64(WINAPI *w32_GetEnabledXStateFeatures)()