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 = ®->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