1 /* radare - LGPL - Copyright 2009-2020 - pancake */
2 
3 #include <r_reg.h>
4 #include <r_util/r_str.h>
5 
6 /* non-endian safe - used for raw mapping with system registers */
r_reg_get_bytes(RReg * reg,int type,int * size)7 R_API ut8 *r_reg_get_bytes(RReg *reg, int type, int *size) {
8 	RRegArena *arena;
9 	int i, sz, osize;
10 	ut8 *buf, *newbuf;
11 	if (size) {
12 		*size = 0;
13 	}
14 	if (type == -1) {
15 		/* serialize ALL register types in a single buffer */
16 		// owned buffer is returned
17 		osize = sz = 0;
18 		buf = malloc (8);
19 		if (!buf) {
20 			return NULL;
21 		}
22 		for (i = 0; i < R_REG_TYPE_LAST; i++) {
23 			arena = reg->regset[i].arena;
24 			sz += arena->size;
25 			newbuf = realloc (buf, sz);
26 			if (!newbuf) {
27 				break;
28 			}
29 			buf = newbuf;
30 			memcpy (buf + osize, arena->bytes, arena->size);
31 			osize = sz;
32 		}
33 		if (size) {
34 			*size = sz;
35 		}
36 		return buf;
37 	}
38 	if (type < 0 || type > (R_REG_TYPE_LAST - 1)) {
39 		return NULL;
40 	}
41 	sz = reg->regset[type].arena->size;
42 	if (size) {
43 		*size = sz;
44 	}
45 	if (!sz) {
46 		return NULL;
47 	}
48 	buf = malloc (sz);
49 	if (buf) {
50 		memcpy (buf, reg->regset[type].arena->bytes, sz);
51 	}
52 	return buf;
53 }
54 
55 /* deserialize ALL register types into buffer */
56 /* XXX does the same as r_reg_get_bytes? */
r_reg_read_regs(RReg * reg,ut8 * buf,const int len)57 R_API bool r_reg_read_regs(RReg *reg, ut8 *buf, const int len) {
58 	int i, off = 0;
59 	RRegArena *arena;
60 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
61 		if (reg->regset[i].arena) {
62 			arena = reg->regset[i].arena;
63 		} else {
64 			arena = reg->regset[i].arena = R_NEW0 (RRegArena);
65 			if (!arena) {
66 				return false;
67 			}
68 			arena->size = len;
69 			arena->bytes = calloc (1, len);
70 			if (!arena->bytes) {
71 				r_reg_arena_free (arena);
72 				return false;
73 			}
74 		}
75 		if (!arena->bytes) {
76 			arena->size = 0;
77 			return false;
78 		}
79 		memset (arena->bytes, 0, arena->size);
80 		memcpy (arena->bytes, buf + off,
81 			R_MIN (len - off, arena->size));
82 		off += arena->size;
83 		if (off > len) {
84 			return false;
85 		}
86 	}
87 	return true;
88 }
89 
90 /* TODO reduce number of return statements */
r_reg_set_bytes(RReg * reg,int type,const ut8 * buf,const int len)91 R_API bool r_reg_set_bytes(RReg *reg, int type, const ut8 *buf, const int len) {
92 	int maxsz, minsz;
93 	struct r_reg_set_t *regset;
94 	RRegArena *arena;
95 	if (len < 1 || !buf) {
96 		return false;
97 	}
98 	if (type < 0 || type >= R_REG_TYPE_LAST) {
99 		return false;
100 	}
101 	regset = &reg->regset[type];
102 	arena = regset->arena;
103 	if (!arena) {
104 		return false;
105 	}
106 	maxsz = R_MAX (arena->size, len);
107 	minsz = R_MIN (arena->size, len);
108 	if ((arena->size != len) || (!arena->bytes)) {
109 		free (arena->bytes);
110 		arena->bytes = calloc (1, maxsz);
111 		if (!arena->bytes) {
112 			arena->size = 0;
113 			return false;
114 		}
115 		arena->size = maxsz;
116 	}
117 	if (arena->size != maxsz) {
118 		ut8 *tmp = realloc (arena->bytes, maxsz);
119 		if (!tmp) {
120 			eprintf ("Error resizing arena to %d\n", len);
121 			return false;
122 		}
123 		arena->size = maxsz;
124 		arena->bytes = tmp;
125 	}
126 	if (arena->bytes) {
127 		memset (arena->bytes, 0, arena->size);
128 		memcpy (arena->bytes, buf, minsz);
129 		return true;
130 	}
131 	return false;
132 }
133 
r_reg_fit_arena(RReg * reg)134 R_API int r_reg_fit_arena(RReg *reg) {
135 	RRegArena *arena;
136 	RListIter *iter;
137 	RRegItem *r;
138 	int size, i, newsize;
139 
140 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
141 		arena = reg->regset[i].arena;
142 		if (!arena) {
143 			continue;
144 		}
145 		newsize = 0;
146 		r_list_foreach (reg->regset[i].regs, iter, r) {
147 			// XXX: bits2bytes doesnt seems to work fine
148 			size = BITS2BYTES (r->offset + r->size);
149 			newsize = R_MAX (size, newsize);
150 		}
151 		if (newsize < 1) {
152 			R_FREE (arena->bytes);
153 			arena->size = 0;
154 		} else {
155 			ut8 *buf = realloc (arena->bytes, newsize);
156 			if (buf) {
157 				arena->size = newsize;
158 				arena->bytes = buf;
159 				memset (arena->bytes, 0, arena->size);
160 			} else {
161 				arena->bytes = NULL;
162 				arena->size = 0;
163 			}
164 		}
165 	}
166 	return true;
167 }
168 
r_reg_arena_new(int size)169 R_API RRegArena *r_reg_arena_new(int size) {
170 	RRegArena *arena = R_NEW0 (RRegArena);
171 	if (arena) {
172 		if (size < 1) {
173 			size = 1;
174 		}
175 		if (!(arena->bytes = calloc (1, size + 8))) {
176 			R_FREE (arena);
177 		} else {
178 			arena->size = size;
179 		}
180 	}
181 	return arena;
182 }
183 
r_reg_arena_free(RRegArena * ra)184 R_API void r_reg_arena_free(RRegArena *ra) {
185 	if (ra) {
186 		free (ra->bytes);
187 		free (ra);
188 	}
189 }
190 
r_reg_arena_swap(RReg * reg,int copy)191 R_API void r_reg_arena_swap(RReg *reg, int copy) {
192 	/* XXX: swap current arena to head(previous arena) */
193 	int i;
194 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
195 		if (!reg->regset[i].pool) {
196 			continue;
197 		}
198 		if (r_list_length (reg->regset[i].pool) > 1) {
199 			RListIter *ia = reg->regset[i].cur;
200 			RListIter *ib = reg->regset[i].pool->head;
201 			void *tmp = ia->data;
202 			ia->data = ib->data;
203 			ib->data = tmp;
204 			reg->regset[i].arena = ia->data;
205 		} else {
206 			break;
207 		}
208 	}
209 }
210 
r_reg_arena_pop(RReg * reg)211 R_API void r_reg_arena_pop(RReg *reg) {
212 	RRegArena *a;
213 	int i;
214 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
215 		if (!reg->regset[i].pool) {
216 			continue;
217 		}
218 		if (r_list_length (reg->regset[i].pool) < 2) {
219 			continue;
220 		}
221 		a = r_list_pop (reg->regset[i].pool);
222 		r_reg_arena_free (a);
223 		a = reg->regset[i].pool->tail->data;
224 		if (a) {
225 			reg->regset[i].arena = a;
226 			reg->regset[i].cur = reg->regset[i].pool->tail;
227 		}
228 	}
229 }
230 
r_reg_arena_push(RReg * reg)231 R_API int r_reg_arena_push(RReg *reg) {
232 	int i;
233 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
234 		RRegArena *a = reg->regset[i].arena; // current arena
235 		if (!a) {
236 			continue;
237 		}
238 		RRegArena *b = r_reg_arena_new (a->size); // new arena
239 		if (!b) {
240 			continue;
241 		}
242 		//b->size == a->size always because of how r_reg_arena_new behave
243 		if (a->bytes) {
244 			memcpy (b->bytes, a->bytes, b->size);
245 		}
246 		r_list_push (reg->regset[i].pool, b);
247 		reg->regset[i].arena = b;
248 		reg->regset[i].cur = reg->regset[i].pool->tail;
249 	}
250 	if (reg->regset[0].pool) {
251 		return r_list_length (reg->regset[0].pool);
252 	}
253 	return 0;
254 }
255 
r_reg_arena_zero(RReg * reg)256 R_API void r_reg_arena_zero(RReg *reg) {
257 	int i;
258 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
259 		RRegArena *a = reg->regset[i].arena;
260 		if (a->size > 0) {
261 			memset (reg->regset[i].arena->bytes, 0, a->size);
262 		}
263 	}
264 }
265 
r_reg_arena_peek(RReg * reg)266 R_API ut8 *r_reg_arena_peek(RReg *reg) {
267 	RRegSet *regset = r_reg_regset_get (reg, R_REG_TYPE_GPR);
268 	if (!reg || !regset || !regset->arena || (regset->arena->size < 1)) {
269 		return NULL;
270 	}
271 	ut8 *ret = malloc (regset->arena->size);
272 	if (!ret) {
273 		return NULL;
274 	}
275 	memcpy (ret, regset->arena->bytes, regset->arena->size);
276 	return ret;
277 }
278 
r_reg_arena_poke(RReg * reg,const ut8 * ret)279 R_API void r_reg_arena_poke(RReg *reg, const ut8 *ret) {
280 	RRegSet *regset = r_reg_regset_get (reg, R_REG_TYPE_GPR);
281 	if (!ret || !regset || !regset->arena || !regset->arena->bytes) {
282 		return;
283 	}
284 	memcpy (regset->arena->bytes, ret, regset->arena->size);
285 }
286 
r_reg_arena_dup(RReg * reg,const ut8 * source)287 R_API ut8 *r_reg_arena_dup(RReg *reg, const ut8 *source) {
288 	RRegSet *regset = r_reg_regset_get (reg, R_REG_TYPE_GPR);
289 	if (!reg || !regset || !regset->arena || (regset->arena->size < 1)) {
290 		return NULL;
291 	}
292 	ut8 *ret = malloc (regset->arena->size);
293 	if (!ret) {
294 		return NULL;
295 	}
296 	memcpy (ret, source, regset->arena->size);
297 	return ret;
298 }
299 
r_reg_arena_set_bytes(RReg * reg,const char * str)300 R_API int r_reg_arena_set_bytes(RReg *reg, const char *str) {
301 	str = r_str_trim_head_ro (str);
302 	int len = r_hex_str_is_valid (str);
303 	if (len == -1) {
304 		eprintf ("Invalid input\n");
305 		return -1;
306 	}
307 	int bin_str_len = (len + 1) / 2; //2 hex chrs for 1 byte
308 	ut8 *bin_str = malloc (bin_str_len);
309 	if (!bin_str) {
310 		eprintf ("Failed to decode hex str.\n");
311 		return -1;
312 	}
313 	r_hex_str2bin (str, bin_str);
314 
315 	int i, n = 0; //n - cumulative sum of arena's sizes
316 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
317 		int sz = reg->regset[i].arena->size;
318 		int bl = bin_str_len - n; //bytes left
319 		int bln = bl - n;
320 		if (bln > 0 && bln < sz) {
321 			r_reg_set_bytes (reg, i, bin_str + n, bln);
322 			break;
323 		}
324 		r_reg_set_bytes (reg, i, bin_str + n, bin_str_len - n);
325 		n += sz;
326 	}
327 	free (bin_str);
328 	return 0;
329 }
330 
r_reg_arena_shrink(RReg * reg)331 R_API void r_reg_arena_shrink(RReg *reg) {
332 	RListIter *iter;
333 	RRegArena *a;
334 	int i;
335 	for (i = 0; i < R_REG_TYPE_LAST; i++) {
336 		r_list_foreach (reg->regset[i].pool, iter, a) {
337 			free (a->bytes);
338 			/* ha ha ha */
339 			a->bytes = calloc (1024, 1);
340 			a->size = 1024;
341 			/* looks like sizing down the arena breaks the regsync */
342 			/* and sizing it up fixes reallocation when fit() is called */
343 		}
344 	}
345 }
346