1 /* radare - LGPL - Copyright 2015-2019 - qnix */
2
3 #include <string.h>
4 #include <r_types.h>
5 #include <r_lib.h>
6 #include <r_asm.h>
7 #include <r_anal.h>
8 #include "../../asm/arch/riscv/riscv-opc.c"
9 #include "../../asm/arch/riscv/riscv.h"
10 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a))
11 #define RISCVARGSMAX (8)
12 #define RISCVARGSIZE (64)
13 #define RISCVARGN(x) ((x)->arg[(x)->num++])
14
15 static bool init = false;
16 static const char * const *riscv_gpr_names = riscv_gpr_names_abi;
17 static const char * const *riscv_fpr_names = riscv_fpr_names_abi;
18
19 typedef struct riscv_args {
20 int num;
21 char arg[RISCVARGSMAX][RISCVARGSIZE];
22 } riscv_args_t;
23
24 #define is_any(...) _is_any(o->name, __VA_ARGS__, NULL)
_is_any(const char * str,...)25 static bool _is_any(const char *str, ...) {
26 char *cur;
27 va_list va;
28 va_start (va, str);
29 while (true) {
30 cur = va_arg (va, char *);
31 if (!cur) {
32 break;
33 }
34 if (!strcmp (str, cur)) {
35 va_end (va);
36 return true;
37 }
38 }
39 va_end (va);
40 return false;
41 }
42
arg_p2(char * buf,unsigned long val,const char * const * array,size_t size)43 static void arg_p2(char *buf, unsigned long val, const char* const* array, size_t size) {
44 const char *s = (val >= size || array[val]) ? array[val] : "unknown";
45 snprintf (buf, RISCVARGSIZE, "%s", s);
46 }
47
get_opcode(insn_t word)48 static struct riscv_opcode *get_opcode(insn_t word) {
49 struct riscv_opcode *op = NULL;
50 static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1] = {0};
51
52 #define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 3 : OP_MASK_OP))
53
54 if (!init) {
55 size_t i;
56 for (i=0;i<OP_MASK_OP+1; i++) {
57 riscv_hash[i] = 0;
58 }
59 for (op=riscv_opcodes; op <= &riscv_opcodes[NUMOPCODES - 1]; op++) {
60 if (!riscv_hash[OP_HASH_IDX (op->match)]) {
61 riscv_hash[OP_HASH_IDX (op->match)] = op;
62 }
63 }
64 init = true;
65 }
66 return (struct riscv_opcode *)riscv_hash[OP_HASH_IDX (word)];
67 }
68
69 /* Print insn arguments for 32/64-bit code. */
get_insn_args(riscv_args_t * args,const char * d,insn_t l,uint64_t pc)70 static void get_insn_args(riscv_args_t *args, const char *d, insn_t l, uint64_t pc) {
71 int rs1 = (l >> OP_SH_RS1) & OP_MASK_RS1;
72 int rd = (l >> OP_SH_RD) & OP_MASK_RD;
73 uint64_t target;
74 args->num = 0;
75
76 for (; *d != '\0' && args->num < RISCVARGSMAX; d++) {
77 switch (*d) {
78 /* Xcustom */
79 case '^':
80 switch (*++d) {
81 case 'd':
82 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", rd);
83 break;
84 case 's':
85 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", rs1);
86 break;
87 case 't':
88 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int) EXTRACT_OPERAND (RS2, l));
89 break;
90 case 'j':
91 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int) EXTRACT_OPERAND (CUSTOM_IMM, l));
92 break;
93 }
94 break;
95
96 case 'C': /* RVC */
97 switch (*++d) {
98 case 's': /* RS1 x8-x15 */
99 case 'w': /* RS1 x8-x15 */
100 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s",
101 riscv_gpr_names[EXTRACT_OPERAND (CRS1S, l) + 8]);
102 break;
103 case 't': /* RS2 x8-x15 */
104 case 'x': /* RS2 x8-x15 */
105 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s",
106 riscv_gpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
107 break;
108 case 'U': /* RS1, constrained to equal RD in CI format*/
109 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s", riscv_gpr_names[rd]);
110 break;
111 case 'c': /* RS1, constrained to equal sp */
112 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s", riscv_gpr_names[X_SP]);
113 break;
114 case 'V': /* RS2 */
115 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s",
116 riscv_gpr_names[EXTRACT_OPERAND (CRS2, l)]);
117 break;
118 case 'i':
119 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int)EXTRACT_RVC_SIMM3 (l));
120 break;
121 case 'j':
122 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int)EXTRACT_RVC_IMM (l));
123 break;
124 case 'k':
125 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int)EXTRACT_RVC_LW_IMM (l));
126 break;
127 case 'l':
128 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int)EXTRACT_RVC_LD_IMM (l));
129 break;
130 case 'm':
131 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int)EXTRACT_RVC_LWSP_IMM (l));
132 break;
133 case 'n':
134 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int)EXTRACT_RVC_LDSP_IMM (l));
135 break;
136 case 'K':
137 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int)EXTRACT_RVC_ADDI4SPN_IMM (l));
138 break;
139 case 'L':
140 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int)EXTRACT_RVC_ADDI16SP_IMM (l));
141 break;
142 case 'M':
143 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int)EXTRACT_RVC_SWSP_IMM (l));
144 break;
145 case 'N':
146 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int)EXTRACT_RVC_SDSP_IMM (l));
147 break;
148 case 'p':
149 target = EXTRACT_RVC_B_IMM (l) + pc;
150 snprintf (RISCVARGN(args), RISCVARGSIZE , "0x%"PFMT64x, (ut64) target);
151 break;
152 case 'a':
153 target = EXTRACT_RVC_J_IMM (l) + pc;
154 snprintf (RISCVARGN(args), RISCVARGSIZE , "0x%"PFMT64x, (ut64)target);
155 break;
156 case 'u':
157 snprintf (RISCVARGN(args), RISCVARGSIZE , "0x%x",
158 (int) (EXTRACT_RVC_IMM (l) & (RISCV_BIGIMM_REACH-1)));
159 break;
160 case '>':
161 snprintf (RISCVARGN(args), RISCVARGSIZE , "0x%x", (int) EXTRACT_RVC_IMM (l) & 0x3f);
162 break;
163 case '<':
164 snprintf (RISCVARGN(args), RISCVARGSIZE , "0x%x", (int) EXTRACT_RVC_IMM (l) & 0x1f);
165 break;
166 case 'T': /* floating-point RS2 */
167 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s",
168 riscv_fpr_names[EXTRACT_OPERAND (CRS2, l)]);
169 break;
170 case 'D': /* floating-point RS2 x8-x15 */
171 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s",
172 riscv_fpr_names[EXTRACT_OPERAND (CRS2S, l) + 8]);
173 break;
174 }
175 break;
176
177 case ',':
178 case '(':
179 case ')':
180 case '[':
181 case ']':
182 break;
183 case '0':
184 /* Only print constant 0 if it is the last argument */
185 if (!d[1]) {
186 snprintf (RISCVARGN(args), RISCVARGSIZE , "0");
187 }
188 break;
189
190 case 'b':
191 case 's':
192 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s", riscv_gpr_names[rs1]);
193 break;
194
195 case 't':
196 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s",
197 riscv_gpr_names[EXTRACT_OPERAND (RS2, l)]);
198 break;
199
200 case 'u':
201 snprintf (RISCVARGN(args), RISCVARGSIZE , "0x%x",
202 (unsigned) EXTRACT_UTYPE_IMM (l) >> RISCV_IMM_BITS);
203 break;
204
205 case 'm':
206 arg_p2 (RISCVARGN(args), EXTRACT_OPERAND (RM, l),
207 riscv_rm, ARRAY_SIZE (riscv_rm));
208 break;
209
210 case 'P':
211 arg_p2 (RISCVARGN(args), EXTRACT_OPERAND (PRED, l),
212 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
213 break;
214
215 case 'Q':
216 arg_p2 (RISCVARGN(args), EXTRACT_OPERAND (SUCC, l),
217 riscv_pred_succ, ARRAY_SIZE (riscv_pred_succ));
218 break;
219 case 'o':
220 case 'j':
221 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int) EXTRACT_ITYPE_IMM (l));
222 break;
223 case 'q':
224 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", (int) EXTRACT_STYPE_IMM (l));
225 break;
226 case 'a':
227 target = EXTRACT_UJTYPE_IMM (l) + pc;
228 snprintf (RISCVARGN(args), RISCVARGSIZE , "0x%"PFMT64x, (ut64)target);
229 break;
230 case 'p':
231 target = EXTRACT_SBTYPE_IMM (l) + pc;
232 snprintf (RISCVARGN(args), RISCVARGSIZE , "0x%"PFMT64x, (ut64)target);
233 break;
234 case 'd':
235 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s", riscv_gpr_names[rd]);
236 break;
237 case 'z':
238 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s", riscv_gpr_names[0]);
239 break;
240 case '>':
241 snprintf (RISCVARGN(args), RISCVARGSIZE , "0x%x", (int) EXTRACT_OPERAND (SHAMT, l));
242 break;
243 case '<':
244 snprintf (RISCVARGN(args), RISCVARGSIZE , "0x%x", (int) EXTRACT_OPERAND (SHAMTW, l));
245 break;
246 case 'S':
247 case 'U':
248 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s", riscv_fpr_names[rs1]);
249 break;
250 case 'T':
251 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s", riscv_fpr_names[EXTRACT_OPERAND (RS2, l)]);
252 break;
253 case 'D':
254 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s", riscv_fpr_names[rd]);
255 break;
256 case 'R':
257 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s", riscv_fpr_names[EXTRACT_OPERAND (RS3, l)]);
258 break;
259 case 'E':
260 {
261 const char* csr_name = NULL;
262 unsigned int csr = EXTRACT_OPERAND (CSR, l);
263 switch (csr)
264 {
265 #define DECLARE_CSR(name, num) case num: csr_name = #name; break;
266 #include "../../asm/arch/riscv/riscv-opc.h"
267 #undef DECLARE_CSR
268 }
269 if (csr_name) {
270 snprintf (RISCVARGN(args), RISCVARGSIZE , "%s", csr_name);
271 } else {
272 snprintf (RISCVARGN(args), RISCVARGSIZE , "0x%x", csr);
273 }
274 break;
275 }
276 case 'Z':
277 snprintf (RISCVARGN(args), RISCVARGSIZE , "%d", rs1);
278 break;
279 default:
280 /* xgettext:c-format */
281 snprintf (RISCVARGN(args), RISCVARGSIZE , "# internal error, undefined modifier (%c)",
282 *d);
283 return;
284 }
285 }
286 }
287
arg_n(riscv_args_t * args,int n)288 static const char* arg_n(riscv_args_t* args, int n) {
289 if (n >= args->num || !strcmp (args->arg[n], "zero")) {
290 return "0";
291 }
292 return args->arg[n];
293 }
294
riscv_op(RAnal * anal,RAnalOp * op,ut64 addr,const ut8 * data,int len,RAnalOpMask mask)295 static int riscv_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) {
296 const int no_alias = 1;
297 riscv_args_t args = {0};
298 ut64 word = 0;
299 int xlen = anal->bits;
300 op->size = 4;
301 op->addr = addr;
302 op->type = R_ANAL_OP_TYPE_UNK;
303
304 if (len >= sizeof (ut64)) {
305 word = r_read_ble64 (data, anal->big_endian);
306 } else if (len >= sizeof (ut32)) {
307 word = r_read_ble16 (data, anal->big_endian);
308 } else {
309 op->type = R_ANAL_OP_TYPE_ILL;
310 return -1;
311 }
312
313 struct riscv_opcode *o = get_opcode (word);
314 if (word == UT64_MAX) {
315 op->type = R_ANAL_OP_TYPE_ILL;
316 return -1;
317 }
318 if (!o || !o->name) {
319 return op->size;
320 }
321 if (mask & R_ANAL_OP_MASK_DISASM) {
322 op->mnemonic = strdup (o->name);
323 }
324
325 for (; o <= &riscv_opcodes[NUMOPCODES - 1]; o++) {
326 if (no_alias && (o->pinfo & INSN_ALIAS)) {
327 continue;
328 }
329 if (isdigit ((ut8)(o->subset[0])) && atoi (o->subset) != xlen) {
330 continue;
331 }
332 if (o->match_func && !(o->match_func)(o, word)) {
333 continue;
334 }
335 break;
336 }
337
338 if (o > &riscv_opcodes[NUMOPCODES - 1]) {
339 return -1;
340 }
341
342 if (o->args) {
343 const char *name = o->name;
344 // Test for compressed instruction
345 if (!strncmp ("c.", o->name, 2)) {
346 name += 2;
347 op->size = 2;
348 }
349 #define ARG(x) (arg_n (&args, (x)))
350 get_insn_args (&args, o->args, word, addr);
351 if (!strcmp (name, "nop")) {
352 esilprintf (op, ",");
353 }
354 // math
355 else if (!strncmp (name, "addi16sp", 8)) {
356 esilprintf (op, "%s,sp,+,%s,=", ARG (1), ARG (0));
357 if (!strcmp (ARG (0), riscv_gpr_names[X_SP])) {
358 op->stackop = R_ANAL_STACK_INC;
359 op->stackptr = r_num_math (NULL, ARG (1));
360 }
361 } else if (!strncmp (name, "addiw", 5)) {
362 r_strbuf_appendf (&op->esil, "%s,0xffffffff,%s,&,", ARG (2), ARG (1));
363 r_strbuf_appendf (&op->esil, "+,%s,=,", ARG (0));
364 r_strbuf_appendf (&op->esil, "32,%s,~=", ARG (0));
365 if (!strcmp (ARG (0), riscv_gpr_names[X_SP]) &&
366 !strcmp (ARG (1), riscv_gpr_names[X_SP])) {
367 op->stackop = R_ANAL_STACK_INC;
368 op->stackptr = r_num_math (NULL, ARG (2));
369 }
370 } else if (!strncmp (name, "addw", 4)) {
371 esilprintf (op, "0xffffffff,%s,&,", ARG (2));
372 r_strbuf_appendf (&op->esil, "0xffffffff,%s,&,", ARG (1));
373 r_strbuf_appendf (&op->esil, "+,%s,=,", ARG (0));
374 r_strbuf_appendf (&op->esil, "32,%s,~=", ARG (0));
375 } else if (!strncmp (name, "add", 3)) {
376 esilprintf (op, "%s,%s,+,%s,=", ARG (2), ARG (1), ARG (0));
377 if (name[3] == 'i' && !strcmp (ARG (0), riscv_gpr_names[X_SP]) &&
378 !strcmp (ARG (1), riscv_gpr_names[X_SP])) {
379 op->stackop = R_ANAL_STACK_INC;
380 op->stackptr = -(signed)r_num_math (NULL, ARG (2));
381 }
382 } else if (!strncmp (name, "subw", 4)) {
383 esilprintf (op, "0xffffffff,%s,&,", ARG (2));
384 r_strbuf_appendf (&op->esil, "0xffffffff,%s,&,", ARG (1));
385 r_strbuf_appendf (&op->esil, "-,%s,=,", ARG (0));
386 r_strbuf_appendf (&op->esil, "32,%s,~=", ARG (0));
387 } else if (!strncmp (name, "sub", 3)) {
388 esilprintf (op, "%s,%s,-,%s,=", ARG (2), ARG (1), ARG (0));
389 if (name[3] == 'i' && !strcmp (ARG (0), riscv_gpr_names[X_SP]) &&
390 !strcmp (ARG (1), riscv_gpr_names[X_SP])) {
391 op->stackop = R_ANAL_STACK_INC;
392 op->stackptr = r_num_math (NULL, ARG (2));
393 }
394 } else if (!strncmp (name, "mulw", 4)) {
395 esilprintf (op, "0xffffffff,%s,&,", ARG (2));
396 r_strbuf_appendf (&op->esil, "0xffffffff,%s,&,", ARG (1));
397 r_strbuf_appendf (&op->esil, "*,%s,=,", ARG (0));
398 r_strbuf_appendf (&op->esil, "32,%s,~=", ARG (0));
399 } else if (!strncmp (name, "mul", 3)) {
400 esilprintf (op, "%s,%s,*,%s,=", ARG (2), ARG (1), ARG (0));
401 } else if (!strncmp (name, "div", 3)) {
402 esilprintf (op, "%s,%s,/,%s,=", ARG (2), ARG (1), ARG (0));
403 } else if (!strncmp (name, "rem", 3)) {
404 esilprintf (op, "%s,%s,%%,%s,=", ARG (2), ARG (1), ARG (0));
405 } else if (!strncmp (name, "xor", 3)) {
406 esilprintf (op, "%s,%s,^,%s,=", ARG (2), ARG (1), ARG (0));
407 } else if (!strncmp (name, "or", 2)) {
408 esilprintf (op, "%s,%s,|,%s,=", ARG (2), ARG (1), ARG (0));
409 } else if (!strncmp (name, "and", 3)) {
410 esilprintf (op, "%s,%s,&,%s,=", ARG (2), ARG (1), ARG (0));
411 } else if (!strcmp (name, "auipc")) {
412 esilprintf (op, "%s000,$$,+,%s,=", ARG (1), ARG (0));
413 } else if (!strncmp (name, "sll", 3)) {
414 esilprintf (op, "%s,%s,<<,%s,=", ARG (2), ARG (1), ARG (0));
415 if (name[3] == 'w' || !strncmp (name, "slliw", 5)) {
416 r_strbuf_appendf (&op->esil, ",32,%s,~=", ARG (0));
417 }
418 } else if (!strcmp (name, "srlw") || !strcmp (name, "srliw")) {
419 esilprintf (op, "%s,0xffffffff,%s,&,>>,%s,=", ARG (2), ARG (1), ARG (0));
420 } else if (!strncmp (name, "srl", 3)) {
421 esilprintf (op, "%s,%s,>>,%s,=", ARG (2), ARG (1), ARG (0));
422 } else if (!strcmp (name, "sraiw")) {
423 esilprintf (op, "%s,%s,>>>>,%s,=,", ARG (2), ARG (1), ARG (0));
424 r_strbuf_appendf (&op->esil, "%s,64,-,%s,~=", ARG (2), ARG(0));
425 } else if (!strncmp (name, "sra", 3)) {
426 esilprintf (op, "%s,%s,>>>>,%s,=", ARG (2), ARG (1), ARG (0));
427 }
428 // assigns
429 else if (!strcmp (name, "mv")) {
430 esilprintf (op, "%s,%s,=", ARG (1), ARG (0));
431 } else if (!strcmp (name, "li")) {
432 esilprintf (op, "%s,%s,=", ARG (1), ARG (0));
433 } else if (!strcmp (name, "lui")) {
434 esilprintf (op, "%s000,%s,=", ARG (1), ARG (0));
435 if (anal->bits == 64) {
436 r_strbuf_appendf (&op->esil, ",32,%s,~=", ARG (0));
437 }
438 }
439 // csr instrs
440 // <csr op> rd, rs1, CSR
441 else if (!strncmp (name, "csrrw", 5)) {
442 // Writes rs1 into CSR, places the old value in rd
443 esilprintf (op, "%s,0,+,%s,%s,=,%s,=", ARG (1), ARG (2), ARG (1), ARG (0));
444 } else if (!strncmp (name, "csrrs", 5)) {
445 // Ors rs1 with CSR, places old value in rd
446 esilprintf (op, "%s,0,+,%s,%s,|=,%s,=", ARG (1), ARG (2), ARG (1), ARG (0));
447 } else if (!strncmp (name, "csrrc", 5)) {
448 // Ands the inverse of rs1 with CSR, places old value in rd
449 esilprintf (op, "%s,0,+,%s,1,+,0,-,%s,&=,%s,=", ARG (1), ARG (1), ARG (2), ARG (0));
450 }
451 // stores
452 else if (!strcmp (name, "sd") || !strcmp (name, "sdsp")) {
453 esilprintf (op, "%s,%s,%s,+,=[8]", ARG (0), ARG (2), ARG (1));
454 } else if (!strcmp (name, "sw") || !strcmp (name, "swsp")) {
455 esilprintf (op, "%s,%s,%s,+,=[4]", ARG (0), ARG (2), ARG (1));
456 } else if (!strcmp (name, "sh") || !strcmp (name, "shsp")) {
457 esilprintf (op, "%s,%s,%s,+,=[2]", ARG (0), ARG (2), ARG (1));
458 } else if (!strcmp (name, "sb") || !strcmp (name, "sbsp")) {
459 esilprintf (op, "%s,%s,%s,+,=[1]", ARG (0), ARG (2), ARG (1));
460 } else if (!strcmp (name, "fsq") || !strcmp (name, "fsqsp")) {
461 esilprintf (op, "%s,%s,+,[16],%s,=", ARG (2), ARG (1), ARG (0));
462 } else if (!strcmp (name, "fsd") || !strcmp (name, "fsdsp")) {
463 esilprintf (op, "%s,%s,%s,+,=[8]", ARG (0), ARG (2), ARG (1));
464 } else if (!strcmp (name, "fsw") || !strcmp (name, "fswsp")) {
465 esilprintf (op, "%s,%s,%s,+,=[4]", ARG (0), ARG (2), ARG (1));
466 } else if (!strcmp (name, "fsh") || !strcmp (name, "fshsp")) {
467 esilprintf (op, "%s,%s,%s,+,=[2]", ARG (0), ARG (2), ARG (1));
468 } else if (!strcmp (name, "fsb") || !strcmp (name, "fsbsp")) {
469 esilprintf (op, "%s,%s,%s,+,=[1]", ARG (0), ARG (2), ARG (1));
470 }
471 // loads
472 else if (!strcmp (name, "ld") || !strcmp (name, "ldsp")) {
473 esilprintf (op, "%s,%s,+,[8],%s,=", ARG (2), ARG (1), ARG (0));
474 } else if (!strcmp (name, "lw") || !strcmp (name, "lwu") || !strcmp (name, "lwsp")) {
475 esilprintf (op, "%s,%s,+,[4],%s,=", ARG (2), ARG (1), ARG (0));
476 if ((anal->bits == 64) && strcmp (name, "lwu")) {
477 r_strbuf_appendf (&op->esil, ",32,%s,~=", ARG (0));
478 }
479 } else if (!strcmp (name, "lh") || !strcmp (name, "lhu") || !strcmp (name, "lhsp")) {
480 esilprintf (op, "%s,%s,+,[2],%s,=", ARG (2), ARG (1), ARG (0));
481 if (strcmp (name, "lwu")) {
482 r_strbuf_appendf (&op->esil, ",16,%s,~=", ARG (0));
483 }
484 } else if (!strcmp (name, "lb") || !strcmp (name, "lbu") || !strcmp (name, "lbsp")) {
485 esilprintf (op, "%s,%s,+,[1],%s,=", ARG (2), ARG (1), ARG (0));
486 if (strcmp (name, "lbu")) {
487 r_strbuf_appendf (&op->esil, ",8,%s,~=", ARG (0));
488 }
489 } else if (!strcmp (name, "flq") || !strcmp (name, "flqsp")) {
490 esilprintf (op, "%s,%s,+,[16],%s,=", ARG (2), ARG (1), ARG (0));
491 } else if (!strcmp (name, "fld") || !strcmp (name, "fldsp")) {
492 esilprintf (op, "%s,%s,+,[8],%s,=", ARG (2), ARG (1), ARG (0));
493 } else if (!strcmp (name, "flw") || !strcmp (name, "flwsp")) {
494 esilprintf (op, "%s,%s,+,[4],%s,=", ARG (2), ARG (1), ARG (0));
495 } else if (!strcmp (name, "flh") || !strcmp (name, "flhsp")) {
496 esilprintf (op, "%s,%s,+,[2],%s,=", ARG (2), ARG (1), ARG (0));
497 } else if (!strcmp (name, "flb") || !strcmp (name, "flbsp")) {
498 esilprintf (op, "%s,%s,+,[1],%s,=", ARG (2), ARG (1), ARG (0));
499 }
500 // jumps
501 else if (!strcmp (name, "jalr")) {
502 if (strcmp (ARG (0), "0")) {
503 esilprintf (op, "%s,%s,+,pc,=,%d,$$,+,%s,=", ARG (2), ARG (1), op->size, ARG (0));
504 } else {
505 esilprintf (op, "%s,%s,+,pc,=", ARG (2), ARG (1));
506 }
507 } else if (!strcmp (name, "jal")) {
508 if (strcmp (ARG (0), "0")) {
509 if (args.num == 1) {
510 esilprintf (op, "%d,$$,+,ra,=,%s,pc,=", op->size, ARG (0));
511 } else {
512 esilprintf (op, "%d,$$,+,%s,=,%s,pc,=", op->size, ARG (0), ARG (1));
513 }
514 } else {
515 esilprintf (op, "%s,pc,=", ARG (1));
516 }
517 } else if (!strcmp (name, "jr") || !strcmp (name, "j")) {
518 esilprintf (op, "%s,pc,=", ARG (0));
519 } else if (!strcmp (name, "ecall") || !strcmp (name, "ebreak")) {
520 esilprintf (op, "TRAP");
521 }
522 // Branches & cmps
523 else if (!strcmp (name, "beq")) {
524 esilprintf (op, "%s,%s,==,$z,?{,%s,pc,=,},", ARG (1), ARG (0), ARG (2));
525 } else if (!strcmp (name, "bne")) {
526 esilprintf (op, "%s,%s,==,$z,!,?{,%s,pc,=,},", ARG (1), ARG (0), ARG (2));
527 } else if (!strcmp (name, "ble") || !strcmp (name, "bleu")) {
528 esilprintf (op, "%s,%s,<=,?{,%s,pc,=,},", ARG (1), ARG (0), ARG (2));
529 } else if (!strcmp (name, "blt") || !strcmp (name, "bltu")) {
530 esilprintf (op, "%s,%s,<,?{,%s,pc,=,},", ARG (1), ARG (0), ARG (2));
531 } else if (!strcmp (name, "bge") || !strcmp (name, "bgeu")) {
532 esilprintf (op, "%s,%s,>=,?{,%s,pc,=,},", ARG (1), ARG (0), ARG (2));
533 } else if (!strcmp (name, "bgt") || !strcmp (name, "bgtu")) {
534 esilprintf (op, "%s,%s,>,?{,%s,pc,=,},", ARG (1), ARG (0), ARG (2));
535 } else if (!strcmp (name, "beqz")) {
536 esilprintf (op, "%s,0,==,$z,?{,%s,pc,=,},", ARG (0), ARG (1));
537 } else if (!strcmp (name, "bnez")) {
538 esilprintf (op, "%s,0,==,$z,!,?{,%s,pc,=,},", ARG (0), ARG (1));
539 } else if (!strcmp (name, "blez")) {
540 esilprintf (op, "%s,0,<=,?{,%s,pc,=,},", ARG (0), ARG (1));
541 } else if (!strcmp (name, "bltz")) {
542 esilprintf (op, "%s,0,<,?{,%s,pc,=,},", ARG (0), ARG (1));
543 } else if (!strcmp (name, "bgez")) {
544 esilprintf (op, "%s,0,>=,?{,%s,pc,=,},", ARG (0), ARG (1));
545 } else if (!strcmp (name, "bgtz")) {
546 esilprintf (op, "%s,0,>,?{,%s,pc,=,},", ARG (0), ARG (1));
547 } else if (!strncmp (name, "seq", 3)) {
548 esilprintf (op, "%s,%s,==,%s,=", ARG (2), ARG (1), ARG (0));
549 } else if (!strncmp (name, "sne", 3)) {
550 esilprintf (op, "%s,%s,!=,%s,=", ARG (2), ARG (1), ARG (0));
551 } else if (!strncmp (name, "sle", 3)) {
552 esilprintf (op, "%s,%s,<=,%s,=", ARG (2), ARG (1), ARG (0));
553 } else if (!strncmp (name, "slt", 3)) {
554 esilprintf (op, "%s,%s,<,%s,=", ARG (2), ARG (1), ARG (0));
555 } else if (!strncmp (name, "sge", 3)) {
556 esilprintf (op, "%s,%s,>=,%s,=", ARG (2), ARG (1), ARG (0));
557 } else if (!strncmp (name, "sgt", 3)) {
558 esilprintf (op, "%s,%s,>,%s,=", ARG (2), ARG (1), ARG (0));
559 }
560 // debug
561 //else if (strcmp (name, "unimp") != 0 && name[0] != 'f' && name[1] != 'm') {
562 // int i;
563 // eprintf("[esil] missing risc v esil: %s", name);
564 // for (i = 0; i < args.num; i++) {
565 // eprintf(" %s", ARG(i));
566 // }
567 // eprintf("\n");
568 //}
569 #undef ARG
570 }
571
572 // branch/jumps/calls/rets
573 if (is_any ("jal")) {
574 // decide whether it's jump or call
575 int rd = (word >> OP_SH_RD) & OP_MASK_RD;
576 op->type = (rd == 0) ? R_ANAL_OP_TYPE_JMP: R_ANAL_OP_TYPE_CALL;
577 op->jump = EXTRACT_UJTYPE_IMM (word) + addr;
578 op->fail = addr + op->size;
579 } else if (is_any ("c.jal")) {
580 op->type = R_ANAL_OP_TYPE_CALL;
581 op->jump = EXTRACT_RVC_IMM (word) + addr;
582 op->fail = addr + op->size;
583 } else if (is_any ("jr")) {
584 op->type = R_ANAL_OP_TYPE_JMP;
585 } else if (is_any ("c.j", "jump")) {
586 op->type = R_ANAL_OP_TYPE_JMP;
587 op->jump = EXTRACT_RVC_J_IMM (word) + addr;
588 } else if (is_any ("jalr")) {
589 // decide whether it's ret or call
590 int rd = (word >> OP_SH_RD) & OP_MASK_RD;
591 op->type = (rd == 0) ? R_ANAL_OP_TYPE_RET: R_ANAL_OP_TYPE_UCALL;
592 } else if (is_any ("c.ret")) {
593 op->type = R_ANAL_OP_TYPE_RET;
594 } else if (is_any ("c.jalr")) {
595 op->type = R_ANAL_OP_TYPE_UCALL;
596 } else if (is_any ("c.jr")) {
597 op->type = R_ANAL_OP_TYPE_RET;
598 } else if (is_any ("beqz", "beq", "blez", "bgez", "ble",
599 "bleu", "bge", "bgeu", "bltz", "bgtz", "blt", "bltu",
600 "bgt", "bgtu", "bnez", "bne")) {
601 op->type = R_ANAL_OP_TYPE_CJMP;
602 op->jump = EXTRACT_SBTYPE_IMM (word) + addr;
603 op->fail = addr + op->size;
604 } else if (is_any ("c.beqz", "c.bnez")) {
605 op->type = R_ANAL_OP_TYPE_CJMP;
606 op->jump = EXTRACT_RVC_B_IMM (word) + addr;
607 op->fail = addr + op->size;
608 // math
609 } else if (is_any ("addi", "addw", "addiw", "add", "auipc", "c.addi",
610 "c.addw", "c.add", "c.addiw", "c.addi4spn", "c.addi16sp")) {
611 op->type = R_ANAL_OP_TYPE_ADD;
612 } else if (is_any ("c.mv", "csrrw", "csrrc", "csrrs")) {
613 op->type = R_ANAL_OP_TYPE_MOV;
614 } else if (is_any ("subi", "subw", "sub", "c.sub", "c.subw")) {
615 op->type = R_ANAL_OP_TYPE_SUB;
616 } else if (is_any ("xori", "xor", "c.xor")) {
617 op->type = R_ANAL_OP_TYPE_XOR;
618 } else if (is_any ("andi", "and", "c.andi", "c.and")) {
619 op->type = R_ANAL_OP_TYPE_AND;
620 } else if (is_any ("ori", "or", "c.or")) {
621 op->type = R_ANAL_OP_TYPE_OR;
622 } else if (is_any ("not")) {
623 op->type = R_ANAL_OP_TYPE_NOT;
624 } else if (is_any ("c.nop")) {
625 op->type = R_ANAL_OP_TYPE_NOP;
626 } else if (is_any ("mul", "mulh", "mulhu", "mulhsu", "mulw")) {
627 op->type = R_ANAL_OP_TYPE_MUL;
628 } else if (is_any ("div", "divu", "divw", "divuw")) {
629 op->type = R_ANAL_OP_TYPE_DIV;
630 } else if (is_any ("sll", "slli", "sllw", "slliw", "c.slli")) {
631 op->type = R_ANAL_OP_TYPE_SHL;
632 } else if (is_any ("srl", "srlw", "srliw", "c.srli")) {
633 op->type = R_ANAL_OP_TYPE_SHR;
634 } else if (is_any ("sra", "sra", "srai", "sraiw", "c.srai")) {
635 op->type = R_ANAL_OP_TYPE_SAR;
636 // memory
637 } else if (is_any ("sd", "sb", "sh", "sw", "c.sd", "c.sw",
638 "c.swsp", "c.sdsp")) {
639 op->type = R_ANAL_OP_TYPE_STORE;
640 } else if (is_any ("ld", "lw", "lwu", "lui", "li",
641 "lb", "lbu", "lh", "lhu", "la", "lla", "c.ld",
642 "c.lw", "c.lwsp", "c.li", "c.lui")) {
643 op->type = R_ANAL_OP_TYPE_LOAD;
644 }
645 if (mask & R_ANAL_OP_MASK_VAL && args.num) {
646 int i, j = 1;
647 op->dst = R_NEW0 (RAnalValue);
648 char *argf = strdup (o->args);
649 char *comma = strtok (argf, ",");
650 if (comma && strchr (comma, '(')) {
651 op->dst->delta = (st64)r_num_get (NULL, args.arg[0]);
652 op->dst->reg = r_reg_get (anal->reg, args.arg[1], -1);
653 j = 2;
654 } else if (isdigit ((unsigned char)args.arg[j][0])) {
655 op->dst->imm = r_num_get (NULL, args.arg[0]);
656 } else {
657 op->dst->reg = r_reg_get (anal->reg, args.arg[0], -1);
658 }
659 for (i = 0; j < args.num; i++, j++) {
660 op->src[i] = R_NEW0 (RAnalValue);
661 comma = strtok (NULL, ",");
662 if (comma && strchr (comma, '(')) {
663 op->src[i]->delta = (st64)r_num_get (NULL, args.arg[j]);
664 op->src[i]->reg = r_reg_get (anal->reg, args.arg[j + 1], -1);
665 j++;
666 } else if (isalpha ((unsigned char)args.arg[j][0])) {
667 op->src[i]->reg = r_reg_get (anal->reg, args.arg[j], -1);
668 } else {
669 op->src[i]->imm = r_num_get (NULL, args.arg[j]);
670 }
671 }
672 free (argf);
673 }
674 return op->size;
675 }
676
get_reg_profile(RAnal * anal)677 static char *get_reg_profile(RAnal *anal) {
678 const char *p = NULL;
679 switch (anal->bits) {
680 case 32: p =
681 "=PC pc\n"
682 "=A0 a0\n"
683 "=A1 a1\n"
684 "=A2 a2\n"
685 "=A3 a3\n"
686 "=A4 a4\n"
687 "=A5 a5\n"
688 "=A6 a6\n"
689 "=A7 a7\n"
690 "=R0 a0\n"
691 "=R1 a1\n"
692 "=SP sp\n" // ABI: stack pointer
693 "=LR ra\n" // ABI: return address
694 "=BP s0\n" // ABI: frame pointer
695 "=SN a7\n" // ABI: syscall numer
696 "gpr pc .32 0 0\n"
697 // RV32I regs (ABI names)
698 // From user-Level ISA Specification, section 2.1
699 // "zero" has been left out as it ignores writes and always reads as zero
700 "gpr ra .32 4 0\n" // =x1
701 "gpr sp .32 8 0\n" // =x2
702 "gpr gp .32 12 0\n" // =x3
703 "gpr tp .32 16 0\n" // =x4
704 "gpr t0 .32 20 0\n" // =x5
705 "gpr t1 .32 24 0\n" // =x6
706 "gpr t2 .32 28 0\n" // =x7
707 "gpr s0 .32 32 0\n" // =x8
708 "gpr s1 .32 36 0\n" // =x9
709 "gpr a0 .32 40 0\n" // =x10
710 "gpr a1 .32 44 0\n" // =x11
711 "gpr a2 .32 48 0\n" // =x12
712 "gpr a3 .32 52 0\n" // =x13
713 "gpr a4 .32 56 0\n" // =x14
714 "gpr a5 .32 60 0\n" // =x15
715 "gpr a6 .32 64 0\n" // =x16
716 "gpr a7 .32 68 0\n" // =x17
717 "gpr s2 .32 72 0\n" // =x18
718 "gpr s3 .32 76 0\n" // =x19
719 "gpr s4 .32 80 0\n" // =x20
720 "gpr s5 .32 84 0\n" // =x21
721 "gpr s6 .32 88 0\n" // =x22
722 "gpr s7 .32 92 0\n" // =x23
723 "gpr s8 .32 96 0\n" // =x24
724 "gpr s9 .32 100 0\n" // =x25
725 "gpr s10 .32 104 0\n" // =x26
726 "gpr s11 .32 108 0\n" // =x27
727 "gpr t3 .32 112 0\n" // =x28
728 "gpr t4 .32 116 0\n" // =x29
729 "gpr t5 .32 120 0\n" // =x30
730 "gpr t6 .32 124 0\n" // =x31
731 // RV32F/D regs (ABI names)
732 // From user-Level ISA Specification, section 8.1 and 9.1
733 "fpu ft0 .64 128 0\n" // =f0
734 "fpu ft1 .64 136 0\n" // =f1
735 "fpu ft2 .64 144 0\n" // =f2
736 "fpu ft3 .64 152 0\n" // =f3
737 "fpu ft4 .64 160 0\n" // =f4
738 "fpu ft5 .64 168 0\n" // =f5
739 "fpu ft6 .64 176 0\n" // =f6
740 "fpu ft7 .64 184 0\n" // =f7
741 "fpu fs0 .64 192 0\n" // =f8
742 "fpu fs1 .64 200 0\n" // =f9
743 "fpu fa0 .64 208 0\n" // =f10
744 "fpu fa1 .64 216 0\n" // =f11
745 "fpu fa2 .64 224 0\n" // =f12
746 "fpu fa3 .64 232 0\n" // =f13
747 "fpu fa4 .64 240 0\n" // =f14
748 "fpu fa5 .64 248 0\n" // =f15
749 "fpu fa6 .64 256 0\n" // =f16
750 "fpu fa7 .64 264 0\n" // =f17
751 "fpu fs2 .64 272 0\n" // =f18
752 "fpu fs3 .64 280 0\n" // =f19
753 "fpu fs4 .64 288 0\n" // =f20
754 "fpu fs5 .64 296 0\n" // =f21
755 "fpu fs6 .64 304 0\n" // =f22
756 "fpu fs7 .64 312 0\n" // =f23
757 "fpu fs8 .64 320 0\n" // =f24
758 "fpu fs9 .64 328 0\n" // =f25
759 "fpu fs10 .64 336 0\n" // =f26
760 "fpu fs11 .64 344 0\n" // =f27
761 "fpu ft8 .64 352 0\n" // =f28
762 "fpu ft9 .64 360 0\n" // =f29
763 "fpu ft10 .64 368 0\n" // =f30
764 "fpu ft11 .64 376 0\n" // =f31
765 "fpu fcsr .32 384 0\n"
766 "flg nx .1 3072 0\n"
767 "flg uf .1 3073 0\n"
768 "flg of .1 3074 0\n"
769 "flg dz .1 3075 0\n"
770 "flg nv .1 3076 0\n"
771 "flg frm .3 3077 0\n"
772 ;
773
774 break;
775 case 64: p =
776 "=PC pc\n"
777 "=SP sp\n" // ABI: stack pointer
778 "=LR ra\n" // ABI: return address
779 "=BP s0\n" // ABI: frame pointer
780 "=A0 a0\n"
781 "=A1 a1\n"
782 "=A2 a2\n"
783 "=A3 a3\n"
784 "=A4 a4\n"
785 "=A5 a5\n"
786 "=A6 a6\n"
787 "=A7 a7\n"
788 "=R0 a0\n"
789 "=R1 a1\n"
790 "=SN a7\n" // ABI: syscall numer
791 "gpr pc .64 0 0\n"
792 // RV64I regs (ABI names)
793 // From user-Level ISA Specification, section 2.1 and 4.1
794 // "zero" has been left out as it ignores writes and always reads as zero
795 "gpr ra .64 8 0\n" // =x1
796 "gpr sp .64 16 0\n" // =x2
797 "gpr gp .64 24 0\n" // =x3
798 "gpr tp .64 32 0\n" // =x4
799 "gpr t0 .64 40 0\n" // =x5
800 "gpr t1 .64 48 0\n" // =x6
801 "gpr t2 .64 56 0\n" // =x7
802 "gpr s0 .64 64 0\n" // =x8
803 "gpr s1 .64 72 0\n" // =x9
804 "gpr a0 .64 80 0\n" // =x10
805 "gpr a1 .64 88 0\n" // =x11
806 "gpr a2 .64 96 0\n" // =x12
807 "gpr a3 .64 104 0\n" // =x13
808 "gpr a4 .64 112 0\n" // =x14
809 "gpr a5 .64 120 0\n" // =x15
810 "gpr a6 .64 128 0\n" // =x16
811 "gpr a7 .64 136 0\n" // =x17
812 "gpr s2 .64 144 0\n" // =x18
813 "gpr s3 .64 152 0\n" // =x19
814 "gpr s4 .64 160 0\n" // =x20
815 "gpr s5 .64 168 0\n" // =x21
816 "gpr s6 .64 176 0\n" // =x22
817 "gpr s7 .64 184 0\n" // =x23
818 "gpr s8 .64 192 0\n" // =x24
819 "gpr s9 .64 200 0\n" // =x25
820 "gpr s10 .64 208 0\n" // =x26
821 "gpr s11 .64 216 0\n" // =x27
822 "gpr t3 .64 224 0\n" // =x28
823 "gpr t4 .64 232 0\n" // =x29
824 "gpr t5 .64 240 0\n" // =x30
825 "gpr t6 .64 248 0\n" // =x31
826 // RV64F/D regs (ABI names)
827 "fpu ft0 .64 256 0\n" // =f0
828 "fpu ft1 .64 264 0\n" // =f1
829 "fpu ft2 .64 272 0\n" // =f2
830 "fpu ft3 .64 280 0\n" // =f3
831 "fpu ft4 .64 288 0\n" // =f4
832 "fpu ft5 .64 296 0\n" // =f5
833 "fpu ft6 .64 304 0\n" // =f6
834 "fpu ft7 .64 312 0\n" // =f7
835 "fpu fs0 .64 320 0\n" // =f8
836 "fpu fs1 .64 328 0\n" // =f9
837 "fpu fa0 .64 336 0\n" // =f10
838 "fpu fa1 .64 344 0\n" // =f11
839 "fpu fa2 .64 352 0\n" // =f12
840 "fpu fa3 .64 360 0\n" // =f13
841 "fpu fa4 .64 368 0\n" // =f14
842 "fpu fa5 .64 376 0\n" // =f15
843 "fpu fa6 .64 384 0\n" // =f16
844 "fpu fa7 .64 392 0\n" // =f17
845 "fpu fs2 .64 400 0\n" // =f18
846 "fpu fs3 .64 408 0\n" // =f19
847 "fpu fs4 .64 416 0\n" // =f20
848 "fpu fs5 .64 424 0\n" // =f21
849 "fpu fs6 .64 432 0\n" // =f22
850 "fpu fs7 .64 440 0\n" // =f23
851 "fpu fs8 .64 448 0\n" // =f24
852 "fpu fs9 .64 456 0\n" // =f25
853 "fpu fs10 .64 464 0\n" // =f26
854 "fpu fs11 .64 472 0\n" // =f27
855 "fpu ft8 .64 480 0\n" // =f28
856 "fpu ft9 .64 488 0\n" // =f29
857 "fpu ft10 .64 496 0\n" // =f30
858 "fpu ft11 .64 504 0\n" // =f31
859 "fpu fcsr .32 512 0\n"
860 "flg nx .1 4096 0\n"
861 "flg uf .1 4097 0\n"
862 "flg of .1 4098 0\n"
863 "flg dz .1 4099 0\n"
864 "flg nv .1 4100 0\n"
865 "flg frm .3 4101 0\n"
866 ;
867
868 break;
869 }
870 return (p && *p)? strdup (p): NULL;
871 }
872
873 RAnalPlugin r_anal_plugin_riscv = {
874 .name = "riscv",
875 .desc = "RISC-V analysis plugin",
876 .license = "GPL",
877 .arch = "riscv",
878 .bits = 32|64,
879 .op = &riscv_op,
880 .get_reg_profile = &get_reg_profile,
881 };
882
883 #ifndef R2_PLUGIN_INCORE
884 R_API RLibStruct radare_plugin = {
885 .type = R_LIB_TYPE_ANAL,
886 .data = &r_anal_plugin_riscv,
887 .version = R2_VERSION
888 };
889 #endif
890