1 /* radare - LGPL - Copyright 2009-2020 - pancake */
2 
3 #include <r_reg.h>
4 #include <r_util.h>
5 
6 R_LIB_VERSION (r_reg);
7 
8 static const char *types[R_REG_TYPE_LAST + 1] = {
9 	"gpr", "drx", "fpu", "mmx", "xmm", "ymm", "flg", "seg", NULL
10 };
11 
12 // Take the 32bits name of a register, and return the 64 bit name of it.
13 // If there is no equivalent 64 bit register return NULL.
14 // SLOW
r_reg_32_to_64(RReg * reg,const char * rreg32)15 R_API const char *r_reg_32_to_64(RReg *reg, const char *rreg32) {
16 	int i, j = -1;
17 	RListIter *iter;
18 	RRegItem *item;
19 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
20 		r_list_foreach (reg->regset[i].regs, iter, item) {
21 			if (item->size == 32 && !r_str_casecmp (rreg32, item->name)) {
22 				j = item->offset;
23 				break;
24 			}
25 		}
26 	}
27 	if (j != -1) {
28 		for (i = 0; i < R_REG_TYPE_LAST; i++) {
29 			r_list_foreach (reg->regset[i].regs, iter, item) {
30 				if (item->offset == j && item->size == 64) {
31 					return item->name;
32 				}
33 			}
34 		}
35 	}
36 	return NULL;
37 }
38 
39 // Take the 64 bits name of a register, and return the 32 bit name of it.
40 // If there is no equivalent 32 bit register return NULL.
41 // SLOW
r_reg_64_to_32(RReg * reg,const char * rreg64)42 R_API const char *r_reg_64_to_32(RReg *reg, const char *rreg64) {
43 	int i, j = -1;
44 	RListIter *iter;
45 	RRegItem *item;
46 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
47 		r_list_foreach (reg->regset[i].regs, iter, item) {
48 			if (item->size == 64 && !r_str_casecmp (rreg64, item->name)) {
49 				j = item->offset;
50 				break;
51 			}
52 		}
53 	}
54 	if (j != -1) {
55 		for (i = 0; i < R_REG_TYPE_LAST; i++) {
56 			r_list_foreach (reg->regset[i].regs, iter, item) {
57 				if (item->offset == j && item->size == 32) {
58 					return item->name;
59 				}
60 			}
61 		}
62 	}
63 	return NULL;
64 }
65 
r_reg_get_type(int idx)66 R_API const char *r_reg_get_type(int idx) {
67 	return (idx >= 0 && idx < R_REG_TYPE_LAST) ? types[idx] : NULL;
68 }
69 
r_reg_get_name_by_type(RReg * reg,const char * alias_name)70 R_API const char *r_reg_get_name_by_type(RReg *reg, const char *alias_name) {
71 	const int n = r_reg_get_name_idx (alias_name);
72 	return (n != -1)? r_reg_get_name (reg, n): NULL;
73 }
74 
r_reg_type_by_name(const char * str)75 R_API int r_reg_type_by_name(const char *str) {
76 	r_return_val_if_fail (str, -1);
77 	int i;
78 	for (i = 0; i < R_REG_TYPE_LAST && types[i]; i++) {
79 		if (!strcmp (types[i], str)) {
80 			return i;
81 		}
82 	}
83 	if (!strcmp (str, "all")) {
84 		return R_REG_TYPE_ALL;
85 	}
86 	return -1;
87 }
88 
r_reg_item_free(RRegItem * item)89 R_API void r_reg_item_free(RRegItem *item) {
90 	free (item->name);
91 	free (item->flags);
92 	free (item);
93 }
94 
r_reg_get_name_idx(const char * type)95 R_API int r_reg_get_name_idx(const char *type) {
96 	r_return_val_if_fail (type, -1);
97 	if (type[0] && type[1] && !type[2])
98 	switch (*type | (type[1] << 8)) {
99 	/* flags */
100 	case 'Z' + ('F' << 8): return R_REG_NAME_ZF;
101 	case 'S' + ('F' << 8): return R_REG_NAME_SF;
102 	case 'C' + ('F' << 8): return R_REG_NAME_CF;
103 	case 'O' + ('F' << 8): return R_REG_NAME_OF;
104 	/* gpr */
105 	case 'P' + ('C' << 8): return R_REG_NAME_PC;
106 	case 'S' + ('R' << 8): return R_REG_NAME_SR;
107 	case 'L' + ('R' << 8): return R_REG_NAME_LR;
108 	case 'S' + ('P' << 8): return R_REG_NAME_SP;
109 	case 'B' + ('P' << 8): return R_REG_NAME_BP;
110 	case 'S' + ('N' << 8): return R_REG_NAME_SN;
111 	/* args */
112 	case 'A' + ('0' << 8): return R_REG_NAME_A0;
113 	case 'A' + ('1' << 8): return R_REG_NAME_A1;
114 	case 'A' + ('2' << 8): return R_REG_NAME_A2;
115 	case 'A' + ('3' << 8): return R_REG_NAME_A3;
116 	case 'A' + ('4' << 8): return R_REG_NAME_A4;
117 	case 'A' + ('5' << 8): return R_REG_NAME_A5;
118 	case 'A' + ('6' << 8): return R_REG_NAME_A6;
119 	case 'A' + ('7' << 8): return R_REG_NAME_A7;
120 	case 'A' + ('8' << 8): return R_REG_NAME_A8;
121 	case 'A' + ('9' << 8): return R_REG_NAME_A9;
122 	/* return values */
123 	case 'R' + ('0' << 8): return R_REG_NAME_R0;
124 	case 'R' + ('1' << 8): return R_REG_NAME_R1;
125 	case 'R' + ('2' << 8): return R_REG_NAME_R2;
126 	case 'R' + ('3' << 8): return R_REG_NAME_R3;
127 	}
128 	return -1;
129 }
130 
r_reg_set_name(RReg * reg,int role,const char * name)131 R_API bool r_reg_set_name(RReg *reg, int role, const char *name) {
132 	r_return_val_if_fail (reg && name, false);
133 	if (role >= 0 && role < R_REG_NAME_LAST) {
134 		reg->name[role] = r_str_dup (reg->name[role], name);
135 		return true;
136 	}
137 	return false;
138 }
139 
r_reg_get_name(RReg * reg,int role)140 R_API const char *r_reg_get_name(RReg *reg, int role) {
141 	if (reg && role >= 0 && role < R_REG_NAME_LAST) {
142 		return reg->name[role];
143 	}
144 	return NULL;
145 }
146 
147 static const char *roles[R_REG_NAME_LAST + 1] = {
148 	"PC", "SP", "SR", "BP", "LR",
149 	"A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9",
150 	"R0", "R1", "R2", "R3",
151 	"ZF", "SF", "CF", "OF",
152 	"SN",
153 	NULL
154 };
155 
r_reg_get_role(int role)156 R_API const char *r_reg_get_role(int role) {
157 	if (role >= 0 && role < R_REG_NAME_LAST) {
158 		return roles[role];
159 	}
160 	return NULL;
161 }
162 
r_reg_free_internal(RReg * reg,bool init)163 R_API void r_reg_free_internal(RReg *reg, bool init) {
164 	r_return_if_fail (reg);
165 	ut32 i;
166 
167 	r_list_free (reg->roregs);
168 	reg->roregs = NULL;
169 	R_FREE (reg->reg_profile_str);
170 	R_FREE (reg->reg_profile_cmt);
171 
172 	for (i = 0; i < R_REG_NAME_LAST; i++) {
173 		if (reg->name[i]) {
174 			R_FREE (reg->name[i]);
175 		}
176 	}
177 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
178 		ht_pp_free (reg->regset[i].ht_regs);
179 		reg->regset[i].ht_regs = NULL;
180 		if (!reg->regset[i].pool) {
181 			continue;
182 		}
183 		if (init) {
184 			r_list_free (reg->regset[i].regs);
185 			reg->regset[i].regs = r_list_newf ((RListFree)r_reg_item_free);
186 		} else {
187 			r_list_free (reg->regset[i].regs);
188 			reg->regset[i].regs = NULL;
189 			// Ensure arena is freed and its registered in the pool
190 			if (!r_list_delete_data (reg->regset[i].pool, reg->regset[i].arena)) {
191 				r_reg_arena_free (reg->regset[i].arena);
192 			}
193 			reg->regset[i].arena = NULL;
194 			r_list_free (reg->regset[i].pool);
195 			reg->regset[i].pool = NULL;
196 		}
197 	}
198 	if (!init) {
199 		r_list_free (reg->allregs);
200 		reg->allregs = NULL;
201 	}
202 	reg->size = 0;
203 }
204 
regcmp(RRegItem * a,RRegItem * b)205 static int regcmp(RRegItem *a, RRegItem *b) {
206 	int offa = (a->offset * 16) + a->size;
207 	int offb = (b->offset * 16) + b->size;
208 	return (offa > offb) - (offa < offb);
209 }
210 
r_reg_reindex(RReg * reg)211 R_API void r_reg_reindex(RReg *reg) {
212 	int i, index;
213 	RListIter *iter;
214 	RRegItem *r;
215 	RList *all = r_list_newf (NULL);
216 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
217 		r_list_foreach (reg->regset[i].regs, iter, r) {
218 			r_list_append (all, r);
219 		}
220 	}
221 	r_list_sort (all, (RListComparator)regcmp);
222 	index = 0;
223 	r_list_foreach (all, iter, r) {
224 		r->index = index++;
225 	}
226 	r_list_free (reg->allregs);
227 	reg->allregs = all;
228 }
229 
r_reg_index_get(RReg * reg,int idx)230 R_API RRegItem *r_reg_index_get(RReg *reg, int idx) {
231 	RRegItem *r;
232 	RListIter *iter;
233 	if (idx < 0) {
234 		return NULL;
235 	}
236 	if (!reg->allregs) {
237 		r_reg_reindex (reg);
238 	}
239 	r_list_foreach (reg->allregs, iter, r) {
240 		if (r->index == idx) {
241 			return r;
242 		}
243 	}
244 	return NULL;
245 }
246 
r_reg_free(RReg * reg)247 R_API void r_reg_free(RReg *reg) {
248 	if (reg) {
249 		r_reg_free_internal (reg, false);
250 		free (reg);
251 	}
252 }
253 
r_reg_new(void)254 R_API RReg *r_reg_new(void) {
255 	RRegArena *arena;
256 	RReg *reg = R_NEW0 (RReg);
257 	int i;
258 	if (!reg) {
259 		return NULL;
260 	}
261 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
262 		arena = r_reg_arena_new (0);
263 		if (!arena) {
264 			free (reg);
265 			return NULL;
266 		}
267 		reg->regset[i].pool = r_list_newf ((RListFree)r_reg_arena_free);
268 		reg->regset[i].regs = r_list_newf ((RListFree)r_reg_item_free);
269 		r_list_push (reg->regset[i].pool, arena);
270 		reg->regset[i].arena = arena;
271 	}
272 	r_reg_arena_push (reg);
273 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
274 		reg->regset[i].cur = r_list_tail (reg->regset[i].pool);
275 	}
276 	return reg;
277 }
278 
r_reg_is_readonly(RReg * reg,RRegItem * item)279 R_API bool r_reg_is_readonly(RReg *reg, RRegItem *item) {
280 	const char *name;
281 	RListIter *iter;
282 	if (!reg->roregs) {
283 		return false;
284 	}
285 	// XXX O(n)
286 	r_list_foreach (reg->roregs, iter, name) {
287 		if (!strcmp (item->name, name)) {
288 			return true;
289 		}
290 	}
291 	return false;
292 }
293 
r_reg_setv(RReg * reg,const char * name,ut64 val)294 R_API ut64 r_reg_setv(RReg *reg, const char *name, ut64 val) {
295 	r_return_val_if_fail (reg && name, UT64_MAX);
296 	RRegItem *ri = r_reg_get (reg, name, -1);
297 	return ri? r_reg_set_value (reg, ri, val): UT64_MAX;
298 }
299 
r_reg_getv(RReg * reg,const char * name)300 R_API ut64 r_reg_getv(RReg *reg, const char *name) {
301 	r_return_val_if_fail (reg && name, UT64_MAX);
302 	RRegItem *ri = r_reg_get (reg, name, -1);
303 	return ri? r_reg_get_value (reg, ri): UT64_MAX;
304 }
305 
r_reg_get(RReg * reg,const char * name,int type)306 R_API RRegItem *r_reg_get(RReg *reg, const char *name, int type) {
307 	int i, e;
308 	r_return_val_if_fail (reg && name, NULL);
309 	//TODO: define flag register as R_REG_TYPE_FLG
310 	if (type == R_REG_TYPE_FLG) {
311 		type = R_REG_TYPE_GPR;
312 	}
313 	if (type == -1) {
314 		i = 0;
315 		e = R_REG_TYPE_LAST;
316 		int alias = r_reg_get_name_idx (name);
317 		if (alias != -1) {
318 			const char *nname = r_reg_get_name (reg, alias);
319 			if (nname) {
320 				name = nname;
321 			}
322 		}
323 	} else {
324 		i = type;
325 		e = type + 1;
326 	}
327 	for (; i < e; i++) {
328 		HtPP *pp = reg->regset[i].ht_regs;
329 		if (pp) {
330 			bool found = false;
331 			RRegItem *item = ht_pp_find (pp, name, &found);
332 			if (found) {
333 				return item;
334 			}
335 		}
336 	}
337 	return NULL;
338 }
339 
r_reg_get_list(RReg * reg,int type)340 R_API RList *r_reg_get_list(RReg *reg, int type) {
341 	if (type == R_REG_TYPE_ALL) {
342 		return reg->allregs;
343 	}
344 
345 	RList *regs;
346 	int i, mask;
347 	if (type < 0 || type > (R_REG_TYPE_LAST - 1)) {
348 		return NULL;
349 	}
350 
351 	regs = reg->regset[type].regs;
352 	if (r_list_length (regs) == 0) {
353 		mask = ((int)1 << type);
354 		for (i = 0; i < R_REG_TYPE_LAST; i++) {
355 			if (reg->regset[i].maskregstype & mask) {
356 				regs = reg->regset[i].regs;
357 			}
358 		}
359 	}
360 
361 	return regs;
362 }
363 
364 // TODO regsize is in bits, delta in bytes, maybe we should standarize this..
r_reg_get_at(RReg * reg,int type,int regsize,int delta)365 R_API RRegItem *r_reg_get_at(RReg *reg, int type, int regsize, int delta) {
366 	r_return_val_if_fail (reg, NULL);
367 	RList *list = r_reg_get_list (reg, type);
368 	RRegItem *ri;
369 	RListIter *iter;
370 	r_list_foreach (list, iter, ri) {
371 		if (ri->size == regsize) {
372 			if (BITS2BYTES (ri->offset) == delta) {
373 				return ri;
374 			}
375 		}
376 	}
377 	return NULL;
378 }
379 
380 /* return the next register in the current regset that differs from */
r_reg_next_diff(RReg * reg,int type,const ut8 * buf,int buflen,RRegItem * prev_ri,int regsize)381 R_API RRegItem *r_reg_next_diff(RReg *reg, int type, const ut8 *buf, int buflen, RRegItem *prev_ri, int regsize) {
382 	r_return_val_if_fail (reg && buf, NULL);
383 	if (type < 0 || type > (R_REG_TYPE_LAST - 1)) {
384 		return NULL;
385 	}
386 	RRegArena *arena = reg->regset[type].arena;
387 	int prev_offset = prev_ri ? (prev_ri->offset / 8) + (prev_ri->size / 8) : 0;
388 	RList *list = reg->regset[type].regs;
389 	RRegItem *ri;
390 	RListIter *iter;
391 	int offset;
392 	r_list_foreach (list, iter, ri) {
393 		offset = ri->offset / 8;
394 		if (offset > prev_offset) {
395 			if (memcmp (arena->bytes + offset, buf + offset, ri->size / 8)) {
396 				return ri;
397 			}
398 		}
399 	}
400 	return NULL;
401 }
402 
r_reg_regset_get(RReg * r,int type)403 R_API RRegSet *r_reg_regset_get(RReg *r, int type) {
404 	r_return_val_if_fail (r, NULL);
405 	if (type < 0 || type >= R_REG_TYPE_LAST) {
406 		return NULL;
407 	}
408 	RRegSet *rs = &r->regset[type];
409 	return rs->arena ? rs : NULL;
410 }
411