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