1 /* radare - LGPL - Copyright 2017-2019 - wargio */
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 
7 #include <r_lib.h>
8 #include <r_util.h>
9 #include <r_flag.h>
10 #include <r_anal.h>
11 #include <r_parse.h>
12 
replace(int argc,const char * argv[],char * newstr)13 static bool replace(int argc, const char *argv[], char *newstr) {
14 	int i,j,k;
15 	struct {
16 		char *op;
17 		char *str;
18 	} ops[] = {
19 		{ "add",     "A += B"},
20 		{ "adc",     "A += B + carry"},
21 		{ "adiw",    "A+1:A += B"},
22 		{ "sub",     "A -= B"},
23 		{ "subi",    "A -= B"},
24 		{ "sbc",     "A -= (B + carry)"},
25 		{ "sbci",    "A -= (B + carry)"},
26 		{ "sbiw",    "A+1:A -= B"},
27 		{ "and",     "A &= B"},
28 		{ "andi",    "A &= B"},
29 		{ "or",      "A |= B"},
30 		{ "ori",     "A |= B"},
31 		{ "eor",     "A ^= B"},
32 		{ "com",     "A = 0xff - A"},
33 		{ "neg",     "A = -A"},
34 		{ "sbr",     "A |= B"},
35 		{ "cbr",     "A &= (0xff - B)"},
36 		{ "inc",     "A++"},
37 		{ "dec",     "A--"},
38 		{ "tst",     "A &= A"},
39 		{ "clr",     "A ^= A"},
40 		{ "ser",     "A = 0xff"},
41 		{ "mul",     "r1:r0 = A * B"},
42 		{ "rjmp",    "goto A"},
43 		{ "ijmp",    "goto z"},
44 		{ "jmp",     "goto A"},
45 		{ "rcall",   "goto A"},
46 		{ "icall",   "goto z"},
47 		{ "call",    "goto A"},
48 		{ "ret",     "return"},
49 		{ "iret",    "return_interrupt()"},
50 		{ "cp",      "var = A - B"},
51 		{ "cpc",     "var = A - B - carry"},
52 		{ "cpi",     "var = A - B"},
53 		{ "breq",    "if(!var) goto A"},
54 		{ "brne",    "if(var) goto A"},
55 		{ "brsh",    "if(var >= 0) goto A"},
56 		{ "brlo",    "if(var < 0) goto A"},
57 		{ "brmi",    "if(var < 0) goto A"},
58 		{ "brpl",    "if(var > 0) goto A"},
59 		{ "brge",    "if(var >= 0) goto A"},
60 		{ "brlt",    "if(var < 0) goto A"},
61 		{ "mov",     "A = B"},
62 		{ "movw",    "A+1:A = B+1:B"},
63 		{ "ldi",     "A = B"},
64 		{ "lds",     "A = *(B)"},
65 		{ "ld",      "A = *(B)"},
66 		{ "ldd",     "A = *(B)"},
67 		{ "lpm",     "r0 = z"},
68 		{ "in",      "A = B"},
69 		{ "out",     "A = B"},
70 		{ "push",    "push(A)"},
71 		{ "pop",     "A = pop()"},
72 		{ "lsl",     "A <<= 1"},
73 		{ "lsr",     "A >>= 1"},
74 		{ "rol",     "A = (A << 1) | (A >> 7)"},
75 		{ "ror",     "A = (A << 7) | (A >> 1)"},
76 		{ "asr",     "A >>= 1"},
77 		{ "swap",    "A = ((A & 0xf0) >> 4) | ((A & 0x0f) << 4)"},
78 		{ "sec",     "c = 1"},
79 		{ "clc",     "c = 0"},
80 		{ "sen",     "n = 1"},
81 		{ "cln",     "n = 0"},
82 		{ "sez",     "z = 1"},
83 		{ "clz",     "z = 0"},
84 		{ "sei",     "i = 1"},
85 		{ "cli",     "i = 0"},
86 		{ "ses",     "s = 1"},
87 		{ "cls",     "s = 0"},
88 		{ "sev",     "v = 1"},
89 		{ "clv",     "v = 0"},
90 		{ "set",     "t = 1"},
91 		{ "clt",     "t = 0"},
92 		{ "seh",     "h = 1"},
93 		{ "clh",     "h = 0"},
94 		{ "nop",     ""},
95 		{ "halt",    "_halt()"},
96 		{ "wdr",     "_watchdog_reset()"},
97 		{ "std",     "*(A) = B"},
98 		{ "st",      "*(A) = B"},
99 		{ "sts",     "*(A) = B"},
100 		{ NULL }
101 	};
102 
103 	for (i = 0; ops[i].op != NULL; i++) {
104 		if (!strcmp (ops[i].op, argv[0])) {
105 			if (newstr != NULL) {
106 				for (j = k = 0; ops[i].str[j] != '\0'; j++, k++) {
107 					if (ops[i].str[j] >= 'A' && ops[i].str[j] <= 'J') {
108 						const char *w = argv[ops[i].str[j] - '@'];
109 						if (w != NULL) {
110 							strcpy (newstr + k, w);
111 							k += strlen(w) - 1;
112 						}
113 					} else {
114 						newstr[k] = ops[i].str[j];
115 					}
116 				}
117 				newstr[k] = '\0';
118 			}
119 			return true;
120 		}
121 	}
122 
123 	/* TODO: this is slow */
124 	if (newstr != NULL) {
125 		newstr[0] = '\0';
126 		for (i = 0; i < argc; i++) {
127 			strcat (newstr, argv[i]);
128 			strcat (newstr, (i == 0 || i == argc - 1) ? " ":", ");
129 		}
130 	}
131 
132 	return false;
133 }
134 
135 #define WSZ 128
parse(RParse * p,const char * data,char * str)136 static int parse(RParse *p, const char *data, char *str) {
137 	int i, len = strlen (data);
138 	char w0[WSZ];
139 	char w1[WSZ];
140 	char w2[WSZ];
141 	char w3[WSZ];
142 	char w4[WSZ];
143 	char *buf, *ptr, *optr;
144 
145 	// malloc can be slow here :?
146 	if (!(buf = malloc (len + 1))) {
147 		return false;
148 	}
149 	memcpy (buf, data, len + 1);
150 
151 	r_str_trim (buf);
152 	if (*buf) {
153 		w0[0] = '\0';
154 		w1[0] = '\0';
155 		w2[0] = '\0';
156 		w3[0] = '\0';
157 		w4[0] = '\0';
158 		ptr = strchr (buf, ' ');
159 		if (!ptr) {
160 			ptr = strchr (buf, '\t');
161 		}
162 		if (ptr) {
163 			*ptr = '\0';
164 			for (++ptr; *ptr == ' '; ptr++) {
165 				//nothing to see here
166 			}
167 			strncpy (w0, buf, WSZ - 1);
168 			strncpy (w1, ptr, WSZ - 1);
169 
170 			optr = ptr;
171 			ptr = strchr (ptr, ',');
172 			if (ptr) {
173 				*ptr = '\0';
174 				for (++ptr; *ptr == ' '; ptr++) {
175 					//nothing to see here
176 				}
177 				strncpy (w1, optr, WSZ - 1);
178 				strncpy (w2, ptr, WSZ - 1);
179 				optr = ptr;
180 				ptr = strchr (ptr, ',');
181 				if (ptr) {
182 					*ptr = '\0';
183 					for (++ptr; *ptr == ' '; ptr++) {
184 						//nothing to see here
185 					}
186 					strncpy (w2, optr, WSZ - 1);
187 					strncpy (w3, ptr, WSZ - 1);
188 					optr = ptr;
189 					// bonus
190 					ptr = strchr (ptr, ',');
191 					if (ptr) {
192 						*ptr = '\0';
193 						for (++ptr; *ptr == ' '; ptr++) {
194 							//nothing to see here
195 						}
196 						strncpy (w3, optr, WSZ - 1);
197 						strncpy (w4, ptr, WSZ - 1);
198 					}
199 				}
200 			}
201 		} else {
202 			strncpy (w0, buf, WSZ - 1);
203 		}
204 		{
205 			const char *wa[] = { w0, w1, w2, w3, w4 };
206 			int nw = 0;
207 			for (i = 0; i < 5; i++) {
208 				if (wa[i][0] != '\0') {
209 					nw++;
210 				}
211 			}
212 			(void)replace (nw, wa, str);
213 		}
214 	}
215 	free (buf);
216 	return true;
217 }
218 
219 RParsePlugin r_parse_plugin_avr_pseudo = {
220 	.name = "avr.pseudo",
221 	.desc = "AVR 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_avr_pseudo,
229 	.version = R2_VERSION
230 };
231 #endif
232