1 /* radare - LGPL - Copyright 2020 - Aswin C (officialcjunior) */
2
3 #include <r_lib.h>
4 #include <r_flag.h>
5 #include <r_anal.h>
6 #include <r_parse.h>
7
replace(int argc,const char * argv[],char * newstr)8 static int replace(int argc, const char *argv[], char *newstr) {
9 #define MAXPSEUDOOPS 10
10 int i, j, k, d;
11 char ch;
12 struct {
13 int narg;
14 char *op;
15 char *str;
16 int args[MAXPSEUDOOPS];
17 } ops[] = {
18 { 0, "add", "# = # + #", { 1, 2, 3 } },
19 { 0, "addi", "# = # + #", { 1, 2, 3 } },
20 { 0, "and", "# = # & #", { 1, 2, 3 } },
21 { 0, "andi", "# = # & #", { 1, 2, 3 } },
22 { 0, "beq", "if (# == #) goto #", { 1, 2, 3 } },
23 { 0, "bleu", "if (unsigned)# <= # goto #", { 1, 2, 3 } },
24 { 0, "bltu", "if (unsigned)# < # goto #", { 1, 2, 3 } },
25 { 0, "blt", "if (# < #) goto #", { 1, 2, 3 } },
26 { 0, "beqz", "if (# == 0) goto #", { 1, 2 } },
27 { 0, "bne", "if (# != #) goto #", { 1, 2, 3 } },
28 { 0, "bnez", "if (# != 0) goto #", { 1, 2 } },
29 { 0, "bgez", "if (# >= 0) goto #", { 1, 2 } },
30 { 0, "bgtz", "if (# > 0) goto #", { 1, 2 } },
31 { 0, "fld", "# = #", { 1, 2 } },
32 { 0, "j", "jmp #", { 1 } },
33 { 0, "jr", "jmp #", { 1 } },
34 { 0, "jalr", "jmp #", { 1 } },
35 { 0, "jal", "jmp #", { 1 } },
36 { 0, "ld", "# = (double)[#]", { 1, 2 } },
37 { 0, "li", "# = #", { 1, 2 } },
38 { 0, "lh", "# = [#]", { 1, 2 } },
39 { 0, "lui", "# = #", { 1, 2 } },
40 { 0, "lbu", "# = (unsigned)[#]", { 1, 2 } },
41 { 0, "lhu", "# = (unsigned)[#]", { 1, 2 } },
42 { 0, "lw", "# = [#]", { 1, 2 } },
43 { 0, "mv", "# = #", { 1, 2 } },
44 { 0, "or", "# = # | #", { 1, 2, 3 } },
45 { 0, "sd", "[#] = (double)#", { 2, 1 } },
46 { 0, "sw", "[#] = #", { 2, 1 } },
47 { 0, "sb", "[#] = #", { 2, 1 } },
48 { 0, "sh", "[#] = #", { 2, 1 } },
49 { 0, "sub", "# = # - #", { 1, 2, 3 } },
50 { 0, NULL }
51 };
52 if (!newstr) {
53 return false;
54 }
55
56 for (i = 0; ops[i].op; i++) {
57 if (ops[i].narg) {
58 if (argc - 1 != ops[i].narg) {
59 continue;
60 }
61 }
62 if (!strcmp (ops[i].op, argv[0])) {
63 if (newstr) {
64 d = 0;
65 j = 0;
66 ch = ops[i].str[j];
67 for (j = 0, k = 0; ch != '\0'; j++, k++) {
68 ch = ops[i].str[j];
69 if (ch == '#') {
70 if (d >= MAXPSEUDOOPS) {
71 // XXX Shouldn't ever happen...
72 continue;
73 }
74 int idx = ops[i].args[d];
75 d++;
76 if (idx <= 0) {
77 // XXX Shouldn't ever happen...
78 continue;
79 }
80 const char *w = argv[idx];
81 if (w) {
82 strcpy (newstr + k, w);
83 k += strlen (w) - 1;
84 }
85 } else {
86 newstr[k] = ch;
87 }
88 }
89 newstr[k] = '\0';
90 }
91 r_str_replace_char (newstr, '{', '(');
92 r_str_replace_char (newstr, '}', ')');
93 return true;
94 }
95 }
96
97 /* TODO: this is slow */
98 newstr[0] = '\0';
99 for (i = 0; i < argc; i++) {
100 strcat (newstr, argv[i]);
101 strcat (newstr, (!i || i == argc - 1)? " " : ",");
102 }
103
104 r_str_replace_char (newstr, '{', '(');
105 r_str_replace_char (newstr, '}', ')');
106 return false;
107 }
108
parse(RParse * p,const char * data,char * str)109 static int parse(RParse *p, const char *data, char *str) {
110 char w0[256], w1[256], w2[256], w3[256];
111 int i, len = strlen (data), n;
112 char *buf, *ptr, *optr, *num;
113
114 if (len >= sizeof (w0)) {
115 return false;
116 }
117 // malloc can be slow here :?
118 if (!(buf = malloc (len + 1))) {
119 return false;
120 }
121 memcpy (buf, data, len + 1);
122 if (*buf) {
123 *w0 = *w1 = *w2 = *w3 = '\0';
124 ptr = strchr (buf, ' ');
125 if (!ptr) {
126 ptr = strchr (buf, '\t');
127 }
128 if (ptr) {
129 *ptr = '\0';
130 for (++ptr; *ptr == ' '; ptr++) {
131 ;
132 }
133 strncpy (w0, buf, sizeof (w0) - 1);
134 strncpy (w1, ptr, sizeof (w1) - 1);
135
136 optr = ptr;
137 if (*ptr == '(') {
138 ptr = strchr (ptr+1, ')');
139 }
140 if (ptr && *ptr == '[') {
141 ptr = strchr (ptr+1, ']');
142 }
143 if (ptr && *ptr == '{') {
144 ptr = strchr (ptr+1, '}');
145 }
146 if (!ptr) {
147 eprintf ("Unbalanced bracket\n");
148 free(buf);
149 return false;
150 }
151 ptr = strchr (ptr, ',');
152 if (ptr) {
153 *ptr = '\0';
154 for (++ptr; *ptr == ' '; ptr++) {
155 ;
156 }
157 strncpy (w1, optr, sizeof (w1) - 1);
158 strncpy (w2, ptr, sizeof (w2) - 1);
159 optr = ptr;
160 ptr = strchr (ptr, ',');
161 if (ptr) {
162 *ptr = '\0';
163 for (++ptr; *ptr == ' '; ptr++) {
164 ;
165 }
166 strncpy (w2, optr, sizeof (w2) - 1);
167 strncpy (w3, ptr, sizeof (w3) - 1);
168 }
169 }
170 ptr = strchr (buf, '(');
171 if (ptr) {
172 *ptr = 0;
173 num = (char*)r_str_lchr (buf, ' ');
174 if (!num) {
175 num = (char *)r_str_lchr (buf, ',');
176 }
177 if (num) {
178 n = atoi (num + 1);
179 *ptr = '[';
180 r_str_cpy (num + 1, ptr);
181 ptr = (char*)r_str_lchr (buf, ']');
182 if (n && ptr) {
183 char *rest = strdup (ptr + 1);
184 size_t dist = len + 1 - (ptr - buf);
185 if (n > 0) {
186 snprintf (ptr, dist, "+%d]%s", n, rest);
187 } else {
188 snprintf (ptr, dist, "%d]%s", n, rest);
189 }
190 free (rest);
191 }
192 } else {
193 *ptr = '[';
194 }
195 }
196 }
197 {
198 const char *wa[] = { w0, w1, w2, w3 };
199 int nw = 0;
200 for (i = 0; i < 4; i++) {
201 if (wa[i][0]) {
202 nw++;
203 }
204 }
205 replace (nw, wa, str);
206 }
207 }
208 {
209 char *s = strdup (str);
210 s = r_str_replace (s, "+ -", "- ", 1);
211 s = r_str_replace (s, "- -", "+ ", 1);
212 strcpy (str, s);
213 free (s);
214 }
215 free (buf);
216 return true;
217 }
218
219 RParsePlugin r_parse_plugin_riscv_pseudo = {
220 .name = "riscv.pseudo",
221 .desc = "riscv pseudo syntax",
222 .parse = parse,
223 };
224
225 #ifndef R2_PLUGIN_INCORE
226 R_API RLibStruct radare_plugin = {
227 .type = R_LIB_TYPE_PARSE,
228 .data = &r_parse_plugin_riscv_pseudo,
229 .version = R2_VERSION};
230 #endif
231