Rizin
unix-like reverse engineering framework and cli tools
analysis_mips_cs.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2013-2019 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_asm.h>
5 #include <rz_lib.h>
6 #include <capstone/capstone.h>
7 #include <capstone/mips.h>
8 
9 static ut64 t9_pre = UT64_MAX;
10 // http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html
11 
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
20 // TODO scale and disp
21 
22 #define SET_VAL(op, i) \
23  if ((i) < OPCOUNT() && OPERAND(i).type == MIPS_OP_IMM) { \
24  (op)->val = OPERAND(i).imm; \
25  }
26 
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();
31 
32 #define CREATE_SRC_DST_2(op) \
33  (op)->src[0] = rz_analysis_value_new(); \
34  (op)->dst = rz_analysis_value_new();
35 
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;
44 
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;
53 
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);
58 
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); \
64  }
65 
66 // ESIL macros:
67 
68 // put the sign bit on the stack
69 #define ES_IS_NEGATIVE(arg) "1," arg ",<<<,1,&"
70 
71 // call with delay slot
72 #define ES_CALL_DR(ra, addr) "pc,4,+," ra ",=," ES_J(addr)
73 #define ES_CALL_D(addr) ES_CALL_DR("ra", addr)
74 
75 // call without delay slot
76 #define ES_CALL_NDR(ra, addr) "pc," ra ",=," ES_J(addr)
77 #define ES_CALL_ND(addr) ES_CALL_NDR("ra", addr)
78 
79 #define USE_DS 0
80 #if USE_DS
81 // emit ERR trap if executed in a delay slot
82 #define ES_TRAP_DS() "$ds,!,!,?{,$$,1,TRAP,BREAK,},"
83 // jump to address
84 #define ES_J(addr) addr ",SETJT,1,SETD"
85 #else
86 #define ES_TRAP_DS() ""
87 #define ES_J(addr) addr ",pc,="
88 #endif
89 
90 #define ES_B(x) "0xff," x ",&"
91 #define ES_H(x) "0xffff," x ",&"
92 #define ES_W(x) "0xffffffff," x ",&"
93 
94 // sign extend 32 -> 64
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)
97 
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)
100 
101 static inline void es_sign_n_64(RzAnalysis *a, RzAnalysisOp *op, const char *arg, int bit) {
102  if (a->bits == 64) {
103  rz_strbuf_appendf(&op->esil, ",%d,%s,~,%s,=,", bit, arg, arg);
104  } else {
105  rz_strbuf_append(&op->esil, ",");
106  }
107 }
108 
109 static inline void es_add_ck(RzAnalysisOp *op, const char *a1, const char *a2, const char *re, int bit) {
110  ut64 mask = 1ULL << (bit - 1);
111  rz_strbuf_appendf(&op->esil,
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);
114 }
115 
116 #define PROTECT_ZERO() \
117  if (REG(0)[0] == 'z') { \
118  rz_strbuf_appendf(&op->esil, ","); \
119  } else
120 
121 #define ESIL_LOAD(size) \
122  PROTECT_ZERO() { \
123  rz_strbuf_appendf(&op->esil, "%s,[" size "],%s,=", \
124  ARG(1), REG(0)); \
125  }
126 
127 static void opex(RzStrBuf *buf, csh handle, cs_insn *insn) {
128  int i;
129  PJ *pj = pj_new();
130  if (!pj) {
131  return;
132  }
133  pj_o(pj);
134  pj_ka(pj, "operands");
135  cs_mips *x = &insn->detail->mips;
136  for (i = 0; i < x->op_count; i++) {
137  cs_mips_op *op = x->operands + i;
138  pj_o(pj);
139  switch (op->type) {
140  case MIPS_OP_REG:
141  pj_ks(pj, "type", "reg");
142  pj_ks(pj, "value", cs_reg_name(handle, op->reg));
143  break;
144  case MIPS_OP_IMM:
145  pj_ks(pj, "type", "imm");
146  pj_kN(pj, "value", op->imm);
147  break;
148  case MIPS_OP_MEM:
149  pj_ks(pj, "type", "mem");
150  if (op->mem.base != MIPS_REG_INVALID) {
151  pj_ks(pj, "base", cs_reg_name(handle, op->mem.base));
152  }
153  pj_kN(pj, "disp", op->mem.disp);
154  break;
155  default:
156  pj_ks(pj, "type", "invalid");
157  break;
158  }
159  pj_end(pj); /* o operand */
160  }
161  pj_end(pj); /* a operands */
162  pj_end(pj);
163 
166  pj_free(pj);
167 }
168 
169 static const char *arg(csh *handle, cs_insn *insn, char *buf, int n) {
170  *buf = 0;
171  switch (insn->detail->mips.operands[n].type) {
172  case MIPS_OP_INVALID:
173  break;
174  case MIPS_OP_REG:
175  sprintf(buf, "%s",
177  insn->detail->mips.operands[n].reg));
178  break;
179  case MIPS_OP_IMM: {
180  st64 x = (st64)insn->detail->mips.operands[n].imm;
181  sprintf(buf, "%" PFMT64d, x);
182  } break;
183  case MIPS_OP_MEM: {
184  int disp = insn->detail->mips.operands[n].mem.disp;
185  if (disp < 0) {
186  sprintf(buf, "%" PFMT64d ",%s,-",
187  (ut64)-insn->detail->mips.operands[n].mem.disp,
189  insn->detail->mips.operands[n].mem.base));
190  } else {
191  sprintf(buf, "0x%" PFMT64x ",%s,+",
192  (ut64)insn->detail->mips.operands[n].mem.disp,
194  insn->detail->mips.operands[n].mem.base));
195  }
196  } break;
197  }
198  return buf;
199 }
200 
201 #define ARG(x) (*str[x] != 0) ? str[x] : arg(handle, insn, str[x], x)
202 
203 static int analop_esil(RzAnalysis *a, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, csh *handle, cs_insn *insn) {
204  char str[8][32] = { { 0 } };
205  int i;
206 
207  rz_strbuf_init(&op->esil);
208  rz_strbuf_set(&op->esil, "");
209 
210  if (insn) {
211  // caching operands
212  for (i = 0; i < insn->detail->mips.op_count && i < 8; i++) {
213  *str[i] = 0;
214  ARG(i);
215  }
216  }
217 
218  if (insn) {
219  switch (insn->id) {
220  case MIPS_INS_NOP:
221  rz_strbuf_setf(&op->esil, ",");
222  break;
223  case MIPS_INS_BREAK:
224  rz_strbuf_setf(&op->esil, "%" PFMT64d ",%" PFMT64d ",TRAP", (st64)IMM(0), (st64)IMM(0));
225  break;
226  case MIPS_INS_SD:
227  rz_strbuf_appendf(&op->esil, "%s,%s,=[8]",
228  ARG(0), ARG(1));
229  break;
230  case MIPS_INS_SW:
231  case MIPS_INS_SWL:
232  case MIPS_INS_SWR:
233  rz_strbuf_appendf(&op->esil, "%s,%s,=[4]",
234  ARG(0), ARG(1));
235  break;
236  case MIPS_INS_SH:
237  rz_strbuf_appendf(&op->esil, "%s,%s,=[2]",
238  ARG(0), ARG(1));
239  break;
240  case MIPS_INS_SWC1:
241  case MIPS_INS_SWC2:
242  rz_strbuf_setf(&op->esil, "%s,$", ARG(1));
243  break;
244  case MIPS_INS_SB:
245  rz_strbuf_appendf(&op->esil, "%s,%s,=[1]",
246  ARG(0), ARG(1));
247  break;
248  case MIPS_INS_CMP:
249  case MIPS_INS_CMPU:
250  case MIPS_INS_CMPGU:
251  case MIPS_INS_CMPGDU:
252  case MIPS_INS_CMPI:
253  rz_strbuf_appendf(&op->esil, "%s,%s,==", ARG(1), ARG(0));
254  break;
255  case MIPS_INS_DSRA:
256  rz_strbuf_appendf(&op->esil,
257  "%s,%s,>>,31,%s,>>,?{,32,%s,32,-,0xffffffff,<<,0xffffffff,&,<<,}{,0,},|,%s,=",
258  ARG(2), ARG(1), ARG(1), ARG(2), ARG(0));
259  break;
260  case MIPS_INS_SHRAV:
261  case MIPS_INS_SHRAV_R:
262  case MIPS_INS_SHRA:
263  case MIPS_INS_SHRA_R:
264  case MIPS_INS_SRA:
265  rz_strbuf_appendf(&op->esil,
266  "0xffffffff,%s,%s,>>,&,31,%s,>>,?{,%s,32,-,0xffffffff,<<,0xffffffff,&,}{,0,},|,%s,=",
267  ARG(2), ARG(1), ARG(1), ARG(2), ARG(0));
268  break;
269  case MIPS_INS_SHRL:
270  // suffix 'S' forces conditional flag to be updated
271  case MIPS_INS_SRLV:
272  case MIPS_INS_SRL:
273  rz_strbuf_appendf(&op->esil, "%s,%s,>>,%s,=", ARG(2), ARG(1), ARG(0));
274  break;
275  case MIPS_INS_SLLV:
276  case MIPS_INS_SLL:
277  rz_strbuf_appendf(&op->esil, "%s,%s,<<,%s,=", ARG(2), ARG(1), ARG(0));
278  break;
279  case MIPS_INS_BAL:
280  case MIPS_INS_JAL:
281  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_D("%s"), ARG(0));
282  break;
283  case MIPS_INS_JALR:
284  case MIPS_INS_JALRS:
285  if (OPCOUNT() < 2) {
286  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_D("%s"), ARG(0));
287  } else {
288  PROTECT_ZERO() {
289  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_DR("%s", "%s"), ARG(0), ARG(1));
290  }
291  }
292  break;
293  case MIPS_INS_JALRC: // no delay
294  if (OPCOUNT() < 2) {
295  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_ND("%s"), ARG(0));
296  } else {
297  PROTECT_ZERO() {
298  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_CALL_NDR("%s", "%s"), ARG(0), ARG(1));
299  }
300  }
301  break;
302  case MIPS_INS_JRADDIUSP:
303  // increment stackpointer in X and jump to %ra
304  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,sp,+=," ES_J("ra"), ARG(0));
305  break;
306  case MIPS_INS_JR:
307  case MIPS_INS_JRC:
308  case MIPS_INS_J:
309  case MIPS_INS_B: // ???
310  // jump to address with conditional
311  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "" ES_J("%s"), ARG(0));
312  break;
313  case MIPS_INS_BNE: // bne $s, $t, offset
314  case MIPS_INS_BNEL:
315  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,%s,==,$z,!,?{," ES_J("%s") ",}",
316  ARG(0), ARG(1), ARG(2));
317  break;
318  case MIPS_INS_BEQ:
319  case MIPS_INS_BEQL:
320  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,%s,==,$z,?{," ES_J("%s") ",}",
321  ARG(0), ARG(1), ARG(2));
322  break;
323  case MIPS_INS_BZ:
324  case MIPS_INS_BEQZ:
325  case MIPS_INS_BEQZC:
326  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,0,==,$z,?{," ES_J("%s") ",}",
327  ARG(0), ARG(1));
328  break;
329  case MIPS_INS_BNEZ:
330  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,0,==,$z,!,?{," ES_J("%s") ",}",
331  ARG(0), ARG(1));
332  break;
333  case MIPS_INS_BEQZALC:
334  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "%s,0,==,$z,?{," ES_CALL_ND("%s") ",}",
335  ARG(0), ARG(1));
336  break;
337  case MIPS_INS_BLEZ:
338  case MIPS_INS_BLEZC:
339  case MIPS_INS_BLEZL:
340  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,%s,==,$z,?{," ES_J("%s") ",BREAK,},",
341  ARG(0), ARG(1));
342  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}",
343  ARG(0), ARG(1));
344  break;
345  case MIPS_INS_BGEZ:
346  case MIPS_INS_BGEZC:
347  case MIPS_INS_BGEZL:
348  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}",
349  ARG(0), ARG(1));
350  break;
351  case MIPS_INS_BGEZAL:
352  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_D("%s") ",}",
353  ARG(0), ARG(1));
354  break;
355  case MIPS_INS_BGEZALC:
356  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_ND("%s") ",}",
357  ARG(0), ARG(1));
358  break;
359  case MIPS_INS_BGTZALC:
360  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,%s,==,$z,?{,BREAK,},", ARG(0));
361  rz_strbuf_appendf(&op->esil, "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_ND("%s") ",}",
362  ARG(0), ARG(1));
363  break;
364  case MIPS_INS_BLTZAL:
365  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_CALL_D("%s") ",}", ARG(0), ARG(1));
366  break;
367  case MIPS_INS_BLTZ:
368  case MIPS_INS_BLTZC:
369  case MIPS_INS_BLTZL:
370  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "1," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}",
371  ARG(0), ARG(1));
372  break;
373  case MIPS_INS_BGTZ:
374  case MIPS_INS_BGTZC:
375  case MIPS_INS_BGTZL:
376  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,%s,==,$z,?{,BREAK,},", ARG(0));
377  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0," ES_IS_NEGATIVE("%s") ",==,$z,?{," ES_J("%s") ",}",
378  ARG(0), ARG(1));
379  break;
380  case MIPS_INS_BTEQZ:
381  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,t,==,$z,?{," ES_J("%s") ",}", ARG(0));
382  break;
383  case MIPS_INS_BTNEZ:
384  rz_strbuf_appendf(&op->esil, ES_TRAP_DS() "0,t,==,$z,!,?{," ES_J("%s") ",}", ARG(0));
385  break;
386  case MIPS_INS_MOV:
387  case MIPS_INS_MOVE:
388  PROTECT_ZERO() {
389  rz_strbuf_appendf(&op->esil, "%s,%s,=", ARG(1), REG(0));
390  }
391  break;
392  case MIPS_INS_MOVZ:
393  case MIPS_INS_MOVF:
394  PROTECT_ZERO() {
395  rz_strbuf_appendf(&op->esil, "0,%s,==,$z,?{,%s,%s,=,}",
396  ARG(2), ARG(1), REG(0));
397  }
398  break;
399  case MIPS_INS_MOVT:
400  PROTECT_ZERO() {
401  rz_strbuf_appendf(&op->esil, "1,%s,==,$z,?{,%s,%s,=,}",
402  ARG(2), ARG(1), REG(0));
403  }
404  break;
405  case MIPS_INS_FSUB:
406  case MIPS_INS_SUB:
407  case MIPS_INS_SUBU:
408  case MIPS_INS_DSUB:
409  case MIPS_INS_DSUBU:
410  PROTECT_ZERO() {
411  rz_strbuf_appendf(&op->esil, "%s,%s,-,%s,=",
412  ARG(2), ARG(1), ARG(0));
413  }
414  break;
415  case MIPS_INS_NEG:
416  case MIPS_INS_NEGU:
417  rz_strbuf_appendf(&op->esil, "%s,0,-,%s,=,",
418  ARG(1), ARG(0));
419  break;
420 
422  case MIPS_INS_ADD: {
423  PROTECT_ZERO() {
424  ES_ADD_CK32_OVERF(ARG(1), ARG(2), ARG(0));
425  }
426  } break;
427  case MIPS_INS_ADDI:
428  PROTECT_ZERO() {
429  ES_ADD_CK32_OVERF(ARG(1), ARG(2), ARG(0));
430  }
431  break;
432  case MIPS_INS_DADD:
433  case MIPS_INS_DADDI:
434  ES_ADD_CK64_OVERF(ARG(1), ARG(2), ARG(0));
435  break;
437  case MIPS_INS_DADDU:
438  case MIPS_INS_ADDU:
439  case MIPS_INS_ADDIU:
440  case MIPS_INS_DADDIU: {
441  const char *arg0 = ARG(0);
442  const char *arg1 = ARG(1);
443  const char *arg2 = ARG(2);
444  PROTECT_ZERO() {
445  if (*arg2 == '-') {
446  rz_strbuf_appendf(&op->esil, "%s,%s,-,%s,=",
447  arg2 + 1, arg1, arg0);
448  } else {
449  rz_strbuf_appendf(&op->esil, "%s,%s,+,%s,=",
450  arg2, arg1, arg0);
451  }
452  }
453  } break;
454  case MIPS_INS_LI:
455  case MIPS_INS_LDI:
456  rz_strbuf_appendf(&op->esil, "0x%" PFMT64x ",%s,=", (ut64)IMM(1), ARG(0));
457  break;
458  case MIPS_INS_LUI:
459  rz_strbuf_appendf(&op->esil, "0x%" PFMT64x "0000,%s,=", (ut64)IMM(1), ARG(0));
460  break;
461  case MIPS_INS_LB:
462  op->sign = true;
463  ESIL_LOAD("1");
464  break;
465  case MIPS_INS_LBU:
466  // one of these is wrong
467  ESIL_LOAD("1");
468  break;
469  case MIPS_INS_LW:
470  case MIPS_INS_LWC1:
471  case MIPS_INS_LWC2:
472  case MIPS_INS_LWL:
473  case MIPS_INS_LWR:
474  case MIPS_INS_LWU:
475  case MIPS_INS_LL:
476  ESIL_LOAD("4");
477  break;
478 
479  case MIPS_INS_LDL:
480  case MIPS_INS_LDC1:
481  case MIPS_INS_LDC2:
482  case MIPS_INS_LLD:
483  case MIPS_INS_LD:
484  ESIL_LOAD("8");
485  break;
486 
487  case MIPS_INS_LWX:
488  case MIPS_INS_LH:
489  case MIPS_INS_LHU:
490  case MIPS_INS_LHX:
491  ESIL_LOAD("2");
492  break;
493 
494  case MIPS_INS_AND:
495  case MIPS_INS_ANDI: {
496  const char *arg0 = ARG(0);
497  const char *arg1 = ARG(1);
498  const char *arg2 = ARG(2);
499  if (!strcmp(arg0, arg1)) {
500  rz_strbuf_appendf(&op->esil, "%s,%s,&=", arg2, arg1);
501  } else {
502  rz_strbuf_appendf(&op->esil, "%s,%s,&,%s,=", arg2, arg1, arg0);
503  }
504  } break;
505  case MIPS_INS_OR:
506  case MIPS_INS_ORI: {
507  const char *arg0 = ARG(0);
508  const char *arg1 = ARG(1);
509  const char *arg2 = ARG(2);
510  PROTECT_ZERO() {
511  rz_strbuf_appendf(&op->esil, "%s,%s,|,%s,=",
512  arg2, arg1, arg0);
513  }
514  } break;
515  case MIPS_INS_XOR:
516  case MIPS_INS_XORI: {
517  const char *arg0 = ARG(0);
518  const char *arg1 = ARG(1);
519  const char *arg2 = ARG(2);
520  PROTECT_ZERO() {
521  rz_strbuf_appendf(&op->esil, "%s,%s,^,%s,=",
522  arg2, arg1, arg0);
523  }
524  } break;
525  case MIPS_INS_NOR: {
526  const char *arg0 = ARG(0);
527  const char *arg1 = ARG(1);
528  const char *arg2 = ARG(2);
529  PROTECT_ZERO() {
530  rz_strbuf_appendf(&op->esil, "%s,%s,|,0xffffffff,^,%s,=",
531  arg2, arg1, arg0);
532  }
533  } break;
534  case MIPS_INS_SLT:
535  case MIPS_INS_SLTI:
536  if (OPCOUNT() < 3) {
537  rz_strbuf_appendf(&op->esil, "%s,%s,<,t,=", ARG(1), ARG(0));
538  } else {
539  rz_strbuf_appendf(&op->esil, "%s,%s,<,%s,=", ARG(2), ARG(1), ARG(0));
540  }
541  break;
542  case MIPS_INS_SLTU:
543  case MIPS_INS_SLTIU:
544  if (OPCOUNT() < 3) {
545  rz_strbuf_appendf(&op->esil, ES_W("%s") "," ES_W("%s") ",<,t,=",
546  ARG(1), ARG(0));
547  } else {
548  rz_strbuf_appendf(&op->esil, ES_W("%s") "," ES_W("%s") ",<,%s,=",
549  ARG(2), ARG(1), ARG(0));
550  }
551  break;
552  case MIPS_INS_MUL:
553  rz_strbuf_appendf(&op->esil, ES_W("%s,%s,*") ",%s,=", ARG(1), ARG(2), ARG(0));
554  ES_SIGN32_64(ARG(0));
555  break;
556  case MIPS_INS_MULT:
557  case MIPS_INS_MULTU:
558  rz_strbuf_appendf(&op->esil, ES_W("%s,%s,*") ",lo,=", ARG(0), ARG(1));
559  ES_SIGN32_64("lo");
560  rz_strbuf_appendf(&op->esil, ES_W("32,%s,%s,*,>>") ",hi,=", ARG(0), ARG(1));
561  ES_SIGN32_64("hi");
562  break;
563  case MIPS_INS_MFLO:
564  PROTECT_ZERO() {
565  rz_strbuf_appendf(&op->esil, "lo,%s,=", REG(0));
566  }
567  break;
568  case MIPS_INS_MFHI:
569  PROTECT_ZERO() {
570  rz_strbuf_appendf(&op->esil, "hi,%s,=", REG(0));
571  }
572  break;
573  case MIPS_INS_MTLO:
574  rz_strbuf_appendf(&op->esil, "%s,lo,=", REG(0));
575  ES_SIGN32_64("lo");
576  break;
577  case MIPS_INS_MTHI:
578  rz_strbuf_appendf(&op->esil, "%s,hi,=", REG(0));
579  ES_SIGN32_64("hi");
580  break;
581 #if 0
582  // could not test div
583  case MIPS_INS_DIV:
584  case MIPS_INS_DIVU:
585  case MIPS_INS_DDIV:
586  case MIPS_INS_DDIVU:
587  PROTECT_ZERO () {
588  // 32 bit needs sign extend
589  rz_strbuf_appendf (&op->esil, "%s,%s,/,lo,=,%s,%s,%%,hi,=", REG(1), REG(0), REG(1), REG(0));
590  }
591  break;
592 #endif
593  default:
594  return -1;
595  }
596  }
597  return 0;
598 }
599 
600 static int parse_reg_name(RzRegItem *reg, csh handle, cs_insn *insn, int reg_num) {
601  if (!reg) {
602  return -1;
603  }
604  switch (OPERAND(reg_num).type) {
605  case MIPS_OP_REG:
606  reg->name = (char *)cs_reg_name(handle, OPERAND(reg_num).reg);
607  break;
608  case MIPS_OP_MEM:
609  if (OPERAND(reg_num).mem.base != MIPS_REG_INVALID) {
610  reg->name = (char *)cs_reg_name(handle, OPERAND(reg_num).mem.base);
611  }
612  default:
613  break;
614  }
615  return 0;
616 }
617 
618 static void op_fillval(RzAnalysis *analysis, RzAnalysisOp *op, csh *handle, cs_insn *insn) {
619  static RzRegItem reg;
620  switch (op->type & RZ_ANALYSIS_OP_TYPE_MASK) {
622  if (OPERAND(1).type == MIPS_OP_MEM) {
623  ZERO_FILL(reg);
624  op->src[0] = rz_analysis_value_new();
625  op->src[0]->type = RZ_ANALYSIS_VAL_MEM;
626  op->src[0]->reg = &reg;
627  parse_reg_name(op->src[0]->reg, *handle, insn, 1);
628  op->src[0]->delta = OPERAND(1).mem.disp;
629  }
630  break;
632  if (OPERAND(1).type == MIPS_OP_MEM) {
633  ZERO_FILL(reg);
634  op->dst = rz_analysis_value_new();
635  op->dst->type = RZ_ANALYSIS_VAL_MEM;
636  op->dst->reg = &reg;
637  parse_reg_name(op->dst->reg, *handle, insn, 1);
638  op->dst->delta = OPERAND(1).mem.disp;
639  }
640  break;
650  break;
653  break;
654  case RZ_ANALYSIS_OP_TYPE_DIV: // UDIV
655 #if 0
656 capstone bug
657 ------------
658  $ r2 -a mips -e cfg.bigendian=1 -c "wx 0083001b" -
659  // should be 3 regs, right?
660  [0x00000000]> aoj~{}
661  [
662  {
663  "opcode": "divu zero, a0, v1",
664  "disasm": "divu zero, a0, v1",
665  "mnemonic": "divu",
666  "sign": false,
667  "prefix": 0,
668  "id": 192,
669  "opex": {
670  "operands": [
671  {
672  "type": "reg",
673  "value": "a0"
674  },
675  {
676  "type": "reg",
677  "value": "v1"
678  }
679  ]
680  },
681 #endif
682  if (OPERAND(0).type == MIPS_OP_REG && OPERAND(1).type == MIPS_OP_REG && OPERAND(2).type == MIPS_OP_REG) {
684  } else if (OPERAND(0).type == MIPS_OP_REG && OPERAND(1).type == MIPS_OP_REG) {
686  } else {
687  RZ_LOG_ERROR("mips: unknown div opcode at 0x%08" PFMT64x "\n", op->addr);
688  }
689  break;
690  }
691  if (insn && (insn->id == MIPS_INS_SLTI || insn->id == MIPS_INS_SLTIU)) {
693  }
694 }
695 
696 static void set_opdir(RzAnalysisOp *op) {
697  switch (op->type & RZ_ANALYSIS_OP_TYPE_MASK) {
699  op->direction = RZ_ANALYSIS_OP_DIR_READ;
700  break;
702  op->direction = RZ_ANALYSIS_OP_DIR_WRITE;
703  break;
705  op->direction = RZ_ANALYSIS_OP_DIR_REF;
706  break;
711  op->direction = RZ_ANALYSIS_OP_DIR_EXEC;
712  break;
713  default:
714  break;
715  }
716 }
717 
718 static int analop(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask) {
719  int n, ret, opsize = -1;
720  static csh hndl = 0;
721  static int omode = -1;
722  static int obits = 32;
723  cs_insn *insn;
725 
726  if (analysis->cpu && *analysis->cpu) {
727  if (!strcmp(analysis->cpu, "micro")) {
728  mode |= CS_MODE_MICRO;
729  } else if (!strcmp(analysis->cpu, "r6")) {
731  } else if (!strcmp(analysis->cpu, "v3")) {
732  mode |= CS_MODE_MIPS3;
733  } else if (!strcmp(analysis->cpu, "v2")) {
734 #if CS_API_MAJOR > 3
735  mode |= CS_MODE_MIPS2;
736 #endif
737  }
738  }
739  mode |= (analysis->bits == 64) ? CS_MODE_MIPS64 : CS_MODE_MIPS32;
740  if (mode != omode || analysis->bits != obits) {
741  cs_close(&hndl);
742  hndl = 0;
743  omode = mode;
744  obits = analysis->bits;
745  }
746  // XXX no arch->cpu ?!?! CS_MODE_MICRO, N64
747  op->addr = addr;
748  if (len < 4) {
749  return -1;
750  }
751  op->size = 4;
752  if (hndl == 0) {
753  ret = cs_open(CS_ARCH_MIPS, mode, &hndl);
754  if (ret != CS_ERR_OK) {
755  goto fin;
756  }
758  }
759  n = cs_disasm(hndl, (ut8 *)buf, len, addr, 1, &insn);
760  if (n < 1 || insn->size < 1) {
762  op->mnemonic = strdup("invalid");
763  }
764  goto beach;
765  }
767  op->mnemonic = rz_str_newf("%s%s%s",
768  insn->mnemonic,
769  insn->op_str[0] ? " " : "",
770  insn->op_str);
771  }
772  op->id = insn->id;
773  opsize = op->size = insn->size;
774  op->refptr = 0;
775  switch (insn->id) {
776  case MIPS_INS_INVALID:
777  op->type = RZ_ANALYSIS_OP_TYPE_ILL;
778  break;
779  case MIPS_INS_LB:
780  case MIPS_INS_LBU:
781  case MIPS_INS_LBUX:
782  op->refptr = 1;
783  /* fallthrough */
784  case MIPS_INS_LW:
785  case MIPS_INS_LWC1:
786  case MIPS_INS_LWC2:
787  case MIPS_INS_LWL:
788  case MIPS_INS_LWR:
789  case MIPS_INS_LWXC1:
790  if (!op->refptr) {
791  op->refptr = 4;
792  }
793  /* fallthrough */
794  case MIPS_INS_LD:
795  case MIPS_INS_LDC1:
796  case MIPS_INS_LDC2:
797  case MIPS_INS_LDL:
798  case MIPS_INS_LDR:
799  case MIPS_INS_LDXC1:
801  if (!op->refptr) {
802  op->refptr = 8;
803  }
804  switch (OPERAND(1).type) {
805  case MIPS_OP_MEM:
806  if (OPERAND(1).mem.base == MIPS_REG_GP) {
807  op->ptr = analysis->gp + OPERAND(1).mem.disp;
808  if (REGID(0) == MIPS_REG_T9) {
809  t9_pre = op->ptr;
810  }
811  } else if (REGID(0) == MIPS_REG_T9) {
812  t9_pre = UT64_MAX;
813  }
814  break;
815  case MIPS_OP_IMM:
816  op->ptr = OPERAND(1).imm;
817  break;
818  case MIPS_OP_REG:
819  break;
820  default:
821  break;
822  }
823  // TODO: fill
824  break;
825  case MIPS_INS_SD:
826  case MIPS_INS_SW:
827  case MIPS_INS_SB:
828  case MIPS_INS_SH:
829  case MIPS_INS_SWC1:
830  case MIPS_INS_SWC2:
831  case MIPS_INS_SWL:
832  case MIPS_INS_SWR:
833  case MIPS_INS_SWXC1:
835  break;
836  case MIPS_INS_NOP:
837  op->type = RZ_ANALYSIS_OP_TYPE_NOP;
838  break;
839  case MIPS_INS_SYSCALL:
840  op->type = RZ_ANALYSIS_OP_TYPE_SWI;
841  break;
842  case MIPS_INS_BREAK:
844  break;
845  case MIPS_INS_JALR:
847  op->delay = 1;
848  if (REGID(0) == MIPS_REG_25) {
849  op->jump = t9_pre;
850  t9_pre = UT64_MAX;
852  }
853  break;
854  case MIPS_INS_JAL:
855  case MIPS_INS_JALS:
856  case MIPS_INS_JALX:
857  case MIPS_INS_JRADDIUSP:
858  case MIPS_INS_BAL:
859  // (no blezal/bgtzal or blezall/bgtzall, only blezalc/bgtzalc)
860  case MIPS_INS_BLTZAL: // Branch on <0 and link
861  case MIPS_INS_BGEZAL: // Branch on >=0 and link
862  case MIPS_INS_BLTZALL: // "likely" versions
863  case MIPS_INS_BGEZALL:
864  case MIPS_INS_BLTZALC: // compact versions
865  case MIPS_INS_BLEZALC:
866  case MIPS_INS_BGEZALC:
867  case MIPS_INS_BGTZALC:
868  case MIPS_INS_JIALC:
869  case MIPS_INS_JIC:
871  op->jump = IMM(0);
872 
873  switch (insn->id) {
874  case MIPS_INS_JIALC:
875  case MIPS_INS_JIC:
876  case MIPS_INS_BLTZALC:
877  case MIPS_INS_BLEZALC:
878  case MIPS_INS_BGEZALC:
879  case MIPS_INS_BGTZALC:
880  // compact versions (no delay)
881  op->delay = 0;
882  op->fail = addr + 4;
883  break;
884  default:
885  op->delay = 1;
886  op->fail = addr + 8;
887  break;
888  }
889  break;
890  case MIPS_INS_LI:
891  case MIPS_INS_LUI:
892  SET_VAL(op, 1);
893  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
894  break;
895  case MIPS_INS_MOVE:
896  op->type = RZ_ANALYSIS_OP_TYPE_MOV;
897  break;
898  case MIPS_INS_ADD:
899  case MIPS_INS_ADDI:
900  case MIPS_INS_ADDU:
901  case MIPS_INS_ADDIU:
902  case MIPS_INS_DADD:
903  case MIPS_INS_DADDI:
904  case MIPS_INS_DADDIU:
905  SET_VAL(op, 2);
906  op->sign = (insn->id == MIPS_INS_ADDI || insn->id == MIPS_INS_ADD);
907  op->type = RZ_ANALYSIS_OP_TYPE_ADD;
908  if (REGID(0) == MIPS_REG_T9) {
909  t9_pre += IMM(2);
910  }
911  if (REGID(0) == MIPS_REG_SP) {
912  op->stackop = RZ_ANALYSIS_STACK_INC;
913  op->stackptr = -IMM(2);
914  }
915  break;
916  case MIPS_INS_SUB:
917  case MIPS_INS_SUBV:
918  case MIPS_INS_SUBVI:
919  case MIPS_INS_DSUBU:
920  case MIPS_INS_FSUB:
921  case MIPS_INS_FMSUB:
922  case MIPS_INS_SUBU:
923  case MIPS_INS_DSUB:
924  case MIPS_INS_SUBS_S:
925  case MIPS_INS_SUBS_U:
926  case MIPS_INS_SUBUH:
927  case MIPS_INS_SUBUH_R:
928  SET_VAL(op, 2);
929  op->sign = insn->id == MIPS_INS_SUB;
930  op->type = RZ_ANALYSIS_OP_TYPE_SUB;
931  break;
932  case MIPS_INS_MULV:
933  case MIPS_INS_MULT:
934  case MIPS_INS_MULSA:
935  case MIPS_INS_FMUL:
936  case MIPS_INS_MUL:
937  case MIPS_INS_DMULT:
938  case MIPS_INS_DMULTU:
939  op->type = RZ_ANALYSIS_OP_TYPE_MUL;
940  break;
941  case MIPS_INS_XOR:
942  case MIPS_INS_XORI:
943  SET_VAL(op, 2);
944  op->type = RZ_ANALYSIS_OP_TYPE_XOR;
945  break;
946  case MIPS_INS_AND:
947  case MIPS_INS_ANDI:
948  SET_VAL(op, 2);
949  op->type = RZ_ANALYSIS_OP_TYPE_AND;
950  if (REGID(0) == MIPS_REG_SP) {
951  op->stackop = RZ_ANALYSIS_STACK_ALIGN;
952  }
953  break;
954  case MIPS_INS_NOT:
955  op->type = RZ_ANALYSIS_OP_TYPE_NOT;
956  break;
957  case MIPS_INS_OR:
958  case MIPS_INS_ORI:
959  SET_VAL(op, 2);
960  op->type = RZ_ANALYSIS_OP_TYPE_OR;
961  break;
962  case MIPS_INS_DIV:
963  case MIPS_INS_DIVU:
964  case MIPS_INS_DDIV:
965  case MIPS_INS_DDIVU:
966  case MIPS_INS_FDIV:
967  case MIPS_INS_DIV_S:
968  case MIPS_INS_DIV_U:
969  op->type = RZ_ANALYSIS_OP_TYPE_DIV;
970  break;
971  case MIPS_INS_CMPGDU:
972  case MIPS_INS_CMPGU:
973  case MIPS_INS_CMPU:
974  case MIPS_INS_CMPI:
975  op->type = RZ_ANALYSIS_OP_TYPE_CMP;
976  break;
977  case MIPS_INS_J:
978  case MIPS_INS_B:
979  case MIPS_INS_BZ:
980  case MIPS_INS_BEQ:
981  case MIPS_INS_BNZ:
982  case MIPS_INS_BNE:
983  case MIPS_INS_BNEL:
984  case MIPS_INS_BEQL:
985  case MIPS_INS_BEQZ:
986  case MIPS_INS_BNEG:
987  case MIPS_INS_BNEGI:
988  case MIPS_INS_BNEZ:
989  case MIPS_INS_BTEQZ:
990  case MIPS_INS_BTNEZ:
991  case MIPS_INS_BLTZ:
992  case MIPS_INS_BLTZL:
993  case MIPS_INS_BLEZ:
994  case MIPS_INS_BLEZL:
995  case MIPS_INS_BGEZ:
996  case MIPS_INS_BGEZL:
997  case MIPS_INS_BGTZ:
998  case MIPS_INS_BGTZL:
999  case MIPS_INS_BLEZC:
1000  case MIPS_INS_BGEZC:
1001  case MIPS_INS_BLTZC:
1002  case MIPS_INS_BGTZC:
1003  if (insn->id == MIPS_INS_J || insn->id == MIPS_INS_B) {
1004  op->type = RZ_ANALYSIS_OP_TYPE_JMP;
1005  } else {
1006  op->type = RZ_ANALYSIS_OP_TYPE_CJMP;
1007  }
1008 
1009  if (OPERAND(0).type == MIPS_OP_IMM) {
1010  op->jump = IMM(0);
1011  } else if (OPERAND(1).type == MIPS_OP_IMM) {
1012  op->jump = IMM(1);
1013  } else if (OPERAND(2).type == MIPS_OP_IMM) {
1014  op->jump = IMM(2);
1015  }
1016 
1017  switch (insn->id) {
1018  case MIPS_INS_BLEZC:
1019  case MIPS_INS_BGEZC:
1020  case MIPS_INS_BLTZC:
1021  case MIPS_INS_BGTZC:
1022  // compact versions (no delay)
1023  op->delay = 0;
1024  op->fail = addr + 4;
1025  break;
1026  default:
1027  op->delay = 1;
1028  op->fail = addr + 8;
1029  break;
1030  }
1031 
1032  break;
1033  case MIPS_INS_JR:
1034  case MIPS_INS_JRC:
1035  op->type = RZ_ANALYSIS_OP_TYPE_RJMP;
1036  op->delay = 1;
1037  // register is $ra, so jmp is a return
1038  if (insn->detail->mips.operands[0].reg == MIPS_REG_RA) {
1039  op->type = RZ_ANALYSIS_OP_TYPE_RET;
1040  t9_pre = UT64_MAX;
1041  }
1042  if (REGID(0) == MIPS_REG_25) {
1043  op->jump = t9_pre;
1044  t9_pre = UT64_MAX;
1045  }
1046 
1047  break;
1048  case MIPS_INS_SLT:
1049  case MIPS_INS_SLTI:
1050  op->sign = true;
1051  SET_VAL(op, 2);
1052  break;
1053  case MIPS_INS_SLTIU:
1054  SET_VAL(op, 2);
1055  break;
1056  case MIPS_INS_SHRAV:
1057  case MIPS_INS_SHRAV_R:
1058  case MIPS_INS_SHRA:
1059  case MIPS_INS_SHRA_R:
1060  case MIPS_INS_SRA:
1061  op->type = RZ_ANALYSIS_OP_TYPE_SAR;
1062  SET_VAL(op, 2);
1063  break;
1064  case MIPS_INS_SHRL:
1065  case MIPS_INS_SRLV:
1066  case MIPS_INS_SRL:
1067  op->type = RZ_ANALYSIS_OP_TYPE_SHR;
1068  SET_VAL(op, 2);
1069  break;
1070  case MIPS_INS_SLLV:
1071  case MIPS_INS_SLL:
1072  op->type = RZ_ANALYSIS_OP_TYPE_SHL;
1073  SET_VAL(op, 2);
1074  break;
1075  }
1076 beach:
1077  set_opdir(op);
1078  if (insn && mask & RZ_ANALYSIS_OP_MASK_OPEX) {
1079  opex(&op->opex, hndl, insn);
1080  }
1082  if (analop_esil(analysis, op, addr, buf, len, &hndl, insn) != 0) {
1083  rz_strbuf_fini(&op->esil);
1084  }
1085  }
1086  if (mask & RZ_ANALYSIS_OP_MASK_VAL) {
1087  op_fillval(analysis, op, &hndl, insn);
1088  }
1089  cs_free(insn, n);
1090  // cs_close (&handle);
1091 fin:
1092  return opsize;
1093 }
1094 
1095 static char *get_reg_profile(RzAnalysis *analysis) {
1096  const char *p = NULL;
1097  switch (analysis->bits) {
1098  default:
1099  case 32:
1100  p =
1101  "=PC pc\n"
1102  "=SP sp\n"
1103  "=BP fp\n"
1104  "=SN v0\n"
1105  "=A0 a0\n"
1106  "=A1 a1\n"
1107  "=A2 a2\n"
1108  "=A3 a3\n"
1109  "=R0 v0\n"
1110  "=R1 v1\n"
1111  "gpr zero .32 ? 0\n"
1112  "gpr at .32 4 0\n"
1113  "gpr v0 .32 8 0\n"
1114  "gpr v1 .32 12 0\n"
1115  "gpr a0 .32 16 0\n"
1116  "gpr a1 .32 20 0\n"
1117  "gpr a2 .32 24 0\n"
1118  "gpr a3 .32 28 0\n"
1119  "gpr t0 .32 32 0\n"
1120  "gpr t1 .32 36 0\n"
1121  "gpr t2 .32 40 0\n"
1122  "gpr t3 .32 44 0\n"
1123  "gpr t4 .32 48 0\n"
1124  "gpr t5 .32 52 0\n"
1125  "gpr t6 .32 56 0\n"
1126  "gpr t7 .32 60 0\n"
1127  "gpr s0 .32 64 0\n"
1128  "gpr s1 .32 68 0\n"
1129  "gpr s2 .32 72 0\n"
1130  "gpr s3 .32 76 0\n"
1131  "gpr s4 .32 80 0\n"
1132  "gpr s5 .32 84 0\n"
1133  "gpr s6 .32 88 0\n"
1134  "gpr s7 .32 92 0\n"
1135  "gpr t8 .32 96 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";
1147  break;
1148  case 64:
1149  p =
1150  "=PC pc\n"
1151  "=SP sp\n"
1152  "=BP fp\n"
1153  "=A0 a0\n"
1154  "=A1 a1\n"
1155  "=A2 a2\n"
1156  "=A3 a3\n"
1157  "=SN v0\n"
1158  "=R0 v0\n"
1159  "=R1 v1\n"
1160  "gpr zero .64 ? 0\n"
1161  "gpr at .64 8 0\n"
1162  "gpr v0 .64 16 0\n"
1163  "gpr v1 .64 24 0\n"
1164  "gpr a0 .64 32 0\n"
1165  "gpr a1 .64 40 0\n"
1166  "gpr a2 .64 48 0\n"
1167  "gpr a3 .64 56 0\n"
1168  "gpr t0 .64 64 0\n"
1169  "gpr t1 .64 72 0\n"
1170  "gpr t2 .64 80 0\n"
1171  "gpr t3 .64 88 0\n"
1172  "gpr t4 .64 96 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";
1196  break;
1197  }
1198  return p ? strdup(p) : NULL;
1199 }
1200 
1201 static int archinfo(RzAnalysis *analysis, int q) {
1202  return 4;
1203 }
1204 
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);
1209  return l;
1210 }
1211 
1213  .name = "mips",
1214  .desc = "Capstone MIPS analyzer",
1215  .license = "BSD",
1216  .esil = true,
1217  .arch = "mips",
1218  .get_reg_profile = get_reg_profile,
1219  .archinfo = archinfo,
1220  .preludes = analysis_preludes,
1221  .bits = 16 | 32 | 64,
1222  .op = &analop,
1223 };
1224 
1225 #ifndef RZ_PLUGIN_INCORE
1228  .data = &rz_analysis_plugin_mips_cs,
1229  .version = RZ_VERSION
1230 };
1231 #endif
size_t len
Definition: 6502dis.c:15
RZ_API RzAnalysisValue * rz_analysis_value_new(void)
Definition: value.c:6
#define e(frag)
#define mask()
static int parse_reg_name(RzRegItem *reg, csh handle, cs_insn *insn, int reg_num)
static char * get_reg_profile(RzAnalysis *analysis)
#define ARG(x)
#define OPCOUNT()
#define OPERAND(x)
#define ES_CALL_ND(addr)
static ut64 t9_pre
static void opex(RzStrBuf *buf, csh handle, cs_insn *insn)
#define SET_SRC_DST_3_REGS(op)
#define ESIL_LOAD(size)
#define ES_CALL_DR(ra, addr)
#define KW(d, ds, m, ms)
#define IMM(x)
#define ES_ADD_CK32_OVERF(x, y, z)
#define ES_CALL_D(addr)
#define ES_TRAP_DS()
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_J(addr)
#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)
#define PROTECT_ZERO()
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)
#define REG(x)
static int analop(RzAnalysis *analysis, RzAnalysisOp *op, ut64 addr, const ut8 *buf, int len, RzAnalysisOpMask mask)
#define REGID(x)
static int archinfo(RzAnalysis *analysis, int q)
#define SET_SRC_DST_3_REG_OR_IMM(op)
static RzList * analysis_preludes(RzAnalysis *analysis)
#define SET_VAL(op, i)
#define ES_W(x)
@ MIPS_INS_JRADDIUSP
@ MIPS_INS_DDIVU
@ MIPS_INS_BEQZC
@ MIPS_INS_CMPU
@ MIPS_INS_BGEZL
@ MIPS_INS_XORI
@ MIPS_INS_BLTZ
@ MIPS_INS_FMSUB
@ MIPS_INS_LDC1
@ MIPS_INS_SHRA
@ MIPS_INS_BGTZ
@ MIPS_INS_DMULT
@ MIPS_INS_MOV
@ MIPS_INS_BLTZALC
@ MIPS_INS_LI
@ MIPS_INS_CMPGDU
@ MIPS_INS_BLTZALL
@ MIPS_INS_SWL
@ MIPS_INS_SLT
@ MIPS_INS_SWC1
@ MIPS_INS_NOP
@ MIPS_INS_BNE
@ MIPS_INS_DSRA
@ MIPS_INS_BGTZC
@ MIPS_INS_MOVF
@ MIPS_INS_BREAK
@ MIPS_INS_LDC2
@ MIPS_INS_LDL
@ MIPS_INS_SW
@ MIPS_INS_BNZ
@ MIPS_INS_JIALC
@ MIPS_INS_ORI
@ MIPS_INS_LUI
@ MIPS_INS_DIV_S
@ MIPS_INS_CMPGU
@ MIPS_INS_INVALID
@ MIPS_INS_BEQL
@ MIPS_INS_BGEZALC
@ MIPS_INS_BLEZALC
@ MIPS_INS_JALRS
@ MIPS_INS_DSUBU
@ MIPS_INS_LWL
@ MIPS_INS_SWXC1
@ MIPS_INS_FMUL
@ MIPS_INS_SUBUH
@ MIPS_INS_MUL
@ MIPS_INS_BNEG
@ MIPS_INS_DIV_U
@ MIPS_INS_SH
@ MIPS_INS_MTHI
@ MIPS_INS_BNEGI
@ MIPS_INS_BEQ
@ MIPS_INS_JAL
@ MIPS_INS_SWR
@ MIPS_INS_LWR
@ MIPS_INS_JIC
@ MIPS_INS_SHRAV_R
@ MIPS_INS_LHX
@ MIPS_INS_JALS
@ MIPS_INS_LD
@ MIPS_INS_LH
@ MIPS_INS_LDXC1
@ MIPS_INS_SHRA_R
@ MIPS_INS_LW
@ MIPS_INS_SRLV
@ MIPS_INS_SRL
@ MIPS_INS_ADD
@ MIPS_INS_SUBS_U
@ MIPS_INS_MFLO
@ MIPS_INS_NOR
@ MIPS_INS_LWX
@ MIPS_INS_MULSA
@ MIPS_INS_LDR
@ MIPS_INS_BGTZL
@ MIPS_INS_NOT
@ MIPS_INS_BLEZL
@ MIPS_INS_ADDU
@ MIPS_INS_SUB
@ MIPS_INS_BGTZALC
@ MIPS_INS_SLTIU
@ MIPS_INS_SRA
@ MIPS_INS_LL
@ MIPS_INS_BLEZC
@ MIPS_INS_JALX
@ MIPS_INS_MFHI
@ MIPS_INS_BNEZ
@ MIPS_INS_LHU
@ MIPS_INS_NEG
@ MIPS_INS_BGEZ
@ MIPS_INS_BAL
@ MIPS_INS_ADDI
@ MIPS_INS_SUBS_S
@ MIPS_INS_DADD
@ MIPS_INS_SLTU
@ MIPS_INS_MOVT
@ MIPS_INS_DMULTU
@ MIPS_INS_DSUB
@ MIPS_INS_FDIV
@ MIPS_INS_NEGU
@ MIPS_INS_AND
@ MIPS_INS_B
@ MIPS_INS_FSUB
@ MIPS_INS_SD
@ MIPS_INS_SHRL
@ MIPS_INS_XOR
@ MIPS_INS_LBU
@ MIPS_INS_SUBU
@ MIPS_INS_DIV
@ MIPS_INS_LWC2
@ MIPS_INS_BLEZ
@ MIPS_INS_LDI
@ MIPS_INS_JALRC
@ MIPS_INS_BEQZALC
@ MIPS_INS_SWC2
@ MIPS_INS_LLD
@ MIPS_INS_J
@ MIPS_INS_LBUX
@ MIPS_INS_BGEZALL
@ MIPS_INS_CMPI
@ MIPS_INS_BTNEZ
@ MIPS_INS_ADDIU
@ MIPS_INS_SUBUH_R
@ MIPS_INS_SUBVI
@ MIPS_INS_BLTZL
@ MIPS_INS_BLTZC
@ MIPS_INS_LWU
@ MIPS_INS_MULV
@ MIPS_INS_DIVU
@ MIPS_INS_SYSCALL
@ MIPS_INS_BTEQZ
@ MIPS_INS_MULTU
@ MIPS_INS_OR
@ MIPS_INS_JALR
@ MIPS_INS_ANDI
@ MIPS_INS_DDIV
@ MIPS_INS_BEQZ
@ MIPS_INS_LB
@ MIPS_INS_MTLO
@ MIPS_INS_SLL
@ MIPS_INS_BGEZAL
@ MIPS_INS_CMP
@ MIPS_INS_MULT
@ MIPS_INS_LWC1
@ MIPS_INS_MOVE
@ MIPS_INS_MOVZ
@ MIPS_INS_LWXC1
@ MIPS_INS_JRC
@ MIPS_INS_DADDIU
@ MIPS_INS_BGEZC
@ MIPS_INS_BZ
@ MIPS_INS_SHRAV
@ MIPS_INS_DADDI
@ MIPS_INS_SLLV
@ MIPS_INS_SLTI
@ MIPS_INS_JR
@ MIPS_INS_SB
@ MIPS_INS_SUBV
@ MIPS_INS_BNEL
@ MIPS_INS_DADDU
@ MIPS_INS_BLTZAL
lzma_index ** i
Definition: index.h:629
r2
Definition: arm-aliases.s.cs:2
static mcore_handle handle
Definition: asm_mcore.c:8
@ CS_ARCH_MIPS
Mips architecture.
Definition: capstone.h:77
@ CS_MODE_MIPS64
Mips64 ISA (Mips)
Definition: capstone.h:125
@ CS_MODE_MICRO
MicroMips mode (MIPS)
Definition: capstone.h:111
@ CS_MODE_MIPS3
Mips III ISA.
Definition: capstone.h:112
@ CS_MODE_MIPS32
Mips32 ISA (Mips)
Definition: capstone.h:124
@ CS_MODE_MIPS32R6
Mips32r6 ISA.
Definition: capstone.h:113
@ CS_MODE_BIG_ENDIAN
big-endian mode
Definition: capstone.h:123
@ CS_MODE_LITTLE_ENDIAN
little-endian mode (default mode)
Definition: capstone.h:103
@ CS_MODE_MIPS2
Mips II ISA.
Definition: capstone.h:114
@ CS_OPT_DETAIL
Break down instruction structure into details.
Definition: capstone.h:171
size_t csh
Definition: capstone.h:71
@ CS_OPT_ON
Turn ON an option (CS_OPT_DETAIL, CS_OPT_SKIPDATA).
Definition: capstone.h:183
#define RZ_API
#define NULL
Definition: cris-opc.c:27
RzCryptoSelector bit
Definition: crypto.c:16
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)
Definition: cs.c:798
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
Definition: cs.c:453
CAPSTONE_EXPORT void CAPSTONE_API cs_free(cs_insn *insn, size_t count)
Definition: cs.c:1017
CAPSTONE_EXPORT const char *CAPSTONE_API cs_reg_name(csh ud, unsigned int reg)
Definition: cs.c:1154
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_close(csh *handle)
Definition: cs.c:501
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
Definition: cs.c:646
voidpf void uLong size
Definition: ioapi.h:138
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
sprintf
Definition: kernel.h:365
RZ_API void rz_search_keyword_free(RzSearchKeyword *kw)
Definition: keyword.c:49
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
void * mem
Definition: libc.cpp:91
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
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")
int x
Definition: mipsasm.c:20
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
Definition: Arm.java:4
int CS_ERR_OK
Definition: __init__.py:235
@ RZ_ANALYSIS_STACK_ALIGN
Definition: rz_analysis.h:461
@ RZ_ANALYSIS_STACK_INC
Definition: rz_analysis.h:457
@ RZ_ANALYSIS_VAL_MEM
Definition: rz_analysis.h:769
@ RZ_ANALYSIS_OP_DIR_READ
Definition: rz_analysis.h:790
@ RZ_ANALYSIS_OP_DIR_EXEC
Definition: rz_analysis.h:792
@ RZ_ANALYSIS_OP_DIR_WRITE
Definition: rz_analysis.h:791
@ RZ_ANALYSIS_OP_DIR_REF
Definition: rz_analysis.h:793
RzAnalysisOpMask
Definition: rz_analysis.h:439
@ RZ_ANALYSIS_OP_MASK_DISASM
Definition: rz_analysis.h:445
@ RZ_ANALYSIS_OP_MASK_VAL
Definition: rz_analysis.h:442
@ RZ_ANALYSIS_OP_MASK_OPEX
Definition: rz_analysis.h:444
@ RZ_ANALYSIS_OP_MASK_ESIL
Definition: rz_analysis.h:441
#define RZ_ANALYSIS_OP_TYPE_MASK
Definition: rz_analysis.h:358
@ RZ_ANALYSIS_OP_TYPE_CMP
Definition: rz_analysis.h:399
@ RZ_ANALYSIS_OP_TYPE_SUB
Definition: rz_analysis.h:402
@ RZ_ANALYSIS_OP_TYPE_LOAD
Definition: rz_analysis.h:416
@ RZ_ANALYSIS_OP_TYPE_MUL
Definition: rz_analysis.h:404
@ RZ_ANALYSIS_OP_TYPE_JMP
Definition: rz_analysis.h:368
@ RZ_ANALYSIS_OP_TYPE_AND
Definition: rz_analysis.h:411
@ RZ_ANALYSIS_OP_TYPE_UJMP
Definition: rz_analysis.h:369
@ RZ_ANALYSIS_OP_TYPE_SWI
Definition: rz_analysis.h:393
@ RZ_ANALYSIS_OP_TYPE_SAR
Definition: rz_analysis.h:409
@ RZ_ANALYSIS_OP_TYPE_TRAP
Definition: rz_analysis.h:392
@ RZ_ANALYSIS_OP_TYPE_CALL
Definition: rz_analysis.h:378
@ RZ_ANALYSIS_OP_TYPE_ADD
Definition: rz_analysis.h:401
@ RZ_ANALYSIS_OP_TYPE_OR
Definition: rz_analysis.h:410
@ RZ_ANALYSIS_OP_TYPE_STORE
Definition: rz_analysis.h:415
@ RZ_ANALYSIS_OP_TYPE_SHR
Definition: rz_analysis.h:406
@ RZ_ANALYSIS_OP_TYPE_RJMP
Definition: rz_analysis.h:370
@ RZ_ANALYSIS_OP_TYPE_CJMP
Definition: rz_analysis.h:373
@ RZ_ANALYSIS_OP_TYPE_DIV
Definition: rz_analysis.h:405
@ RZ_ANALYSIS_OP_TYPE_MOV
Definition: rz_analysis.h:390
@ RZ_ANALYSIS_OP_TYPE_SHL
Definition: rz_analysis.h:407
@ RZ_ANALYSIS_OP_TYPE_ILL
Definition: rz_analysis.h:387
@ RZ_ANALYSIS_OP_TYPE_UCALL
Definition: rz_analysis.h:379
@ RZ_ANALYSIS_OP_TYPE_NOT
Definition: rz_analysis.h:414
@ RZ_ANALYSIS_OP_TYPE_RET
Definition: rz_analysis.h:385
@ RZ_ANALYSIS_OP_TYPE_NOP
Definition: rz_analysis.h:389
@ RZ_ANALYSIS_OP_TYPE_LEA
Definition: rz_analysis.h:417
@ RZ_ANALYSIS_OP_TYPE_RCALL
Definition: rz_analysis.h:380
@ RZ_ANALYSIS_OP_TYPE_XOR
Definition: rz_analysis.h:412
@ RZ_LIB_TYPE_ANALYSIS
Definition: rz_lib.h:73
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API PJ * pj_ka(PJ *j, const char *k)
Definition: pj.c:163
RZ_API PJ * pj_new(void)
Definition: pj.c:25
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API const char * pj_string(PJ *pj)
Definition: pj.c:57
RZ_API void pj_free(PJ *j)
Definition: pj.c:34
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_kN(PJ *j, const char *k, st64 n)
Definition: pj.c:128
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)
Definition: strbuf.c:153
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API const char * rz_strbuf_setf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_fini(RzStrBuf *sb)
Definition: strbuf.c:365
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API void rz_strbuf_init(RzStrBuf *sb)
Definition: strbuf.c:33
#define PFMT64d
Definition: rz_types.h:394
#define ZERO_FILL(x)
Definition: rz_types.h:281
#define PFMT64x
Definition: rz_types.h:393
#define st64
Definition: rz_types_base.h:10
#define UT64_MAX
Definition: rz_types_base.h:86
#define RZ_VERSION
Definition: rz_version.h:8
#define c(i)
Definition: sha256.c:43
#define a(i)
Definition: sha256.c:41
Instruction operand.
Definition: mips.h:240
Instruction structure.
Definition: mips.h:250
Definition: rz_pj.h:12
const char * version
Definition: rz_analysis.h:1239
@ MIPS_OP_REG
= CS_OP_REG (Register operand).
Definition: mips.h:24
@ MIPS_OP_IMM
= CS_OP_IMM (Immediate operand).
Definition: mips.h:25
@ MIPS_OP_MEM
= CS_OP_MEM (Memory operand).
Definition: mips.h:26
@ MIPS_OP_INVALID
= CS_OP_INVALID (Uninitialized).
Definition: mips.h:23
@ MIPS_REG_T9
Definition: mips.h:213
@ MIPS_REG_GP
Definition: mips.h:216
@ MIPS_REG_RA
Definition: mips.h:219
@ MIPS_REG_INVALID
Definition: mips.h:31
@ MIPS_REG_25
Definition: mips.h:60
@ MIPS_REG_SP
Definition: mips.h:217
Definition: dis.c:32
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58