Rizin
unix-like reverse engineering framework and cli tools
arena.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2009-2020 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_reg.h>
5 #include <rz_util/rz_str.h>
6 
7 /* non-endian safe - used for raw mapping with system registers */
9  RzRegArena *arena;
10  int i, sz, osize;
11  ut8 *buf, *newbuf;
12  if (size) {
13  *size = 0;
14  }
15  if (type == -1) {
16  /* serialize ALL register types in a single buffer */
17  // owned buffer is returned
18  osize = sz = 0;
19  buf = malloc(8);
20  if (!buf) {
21  return NULL;
22  }
23  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
24  arena = reg->regset[i].arena;
25  sz += arena->size;
26  newbuf = realloc(buf, sz);
27  if (!newbuf) {
28  break;
29  }
30  buf = newbuf;
31  memcpy(buf + osize, arena->bytes, arena->size);
32  osize = sz;
33  }
34  if (size) {
35  *size = sz;
36  }
37  return buf;
38  }
39  if (type < 0 || type > (RZ_REG_TYPE_LAST - 1)) {
40  return NULL;
41  }
42  sz = reg->regset[type].arena->size;
43  if (size) {
44  *size = sz;
45  }
46  if (!sz) {
47  return NULL;
48  }
49  buf = malloc(sz);
50  if (buf) {
51  memcpy(buf, reg->regset[type].arena->bytes, sz);
52  }
53  return buf;
54 }
55 
56 /* deserialize ALL register types into buffer */
57 /* XXX does the same as rz_reg_get_bytes? */
58 RZ_API bool rz_reg_read_regs(RzReg *reg, ut8 *buf, const int len) {
59  int i, off = 0;
60  RzRegArena *arena;
61  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
62  if (reg->regset[i].arena) {
63  arena = reg->regset[i].arena;
64  } else {
65  arena = reg->regset[i].arena = RZ_NEW0(RzRegArena);
66  if (!arena) {
67  return false;
68  }
69  arena->size = len;
70  arena->bytes = calloc(1, len);
71  if (!arena->bytes) {
72  rz_reg_arena_free(arena);
73  return false;
74  }
75  }
76  if (!arena->bytes) {
77  arena->size = 0;
78  return false;
79  }
80  memset(arena->bytes, 0, arena->size);
81  memcpy(arena->bytes, buf + off,
82  RZ_MIN(len - off, arena->size));
83  off += arena->size;
84  if (off > len) {
85  return false;
86  }
87  }
88  return true;
89 }
90 
91 /* TODO reduce number of return statements */
92 RZ_API bool rz_reg_set_bytes(RzReg *reg, int type, const ut8 *buf, const int len) {
93  int maxsz, minsz;
94  struct rz_reg_set_t *regset;
96  if (len < 1 || !buf) {
97  return false;
98  }
99  if (type < 0 || type >= RZ_REG_TYPE_LAST) {
100  return false;
101  }
102  regset = &reg->regset[type];
103  arena = regset->arena;
104  if (!arena) {
105  return false;
106  }
107  maxsz = RZ_MAX(arena->size, len);
108  minsz = RZ_MIN(arena->size, len);
109  if ((arena->size != len) || (!arena->bytes)) {
110  free(arena->bytes);
111  arena->bytes = calloc(1, maxsz);
112  if (!arena->bytes) {
113  arena->size = 0;
114  return false;
115  }
116  arena->size = maxsz;
117  }
118  if (arena->size != maxsz) {
119  ut8 *tmp = realloc(arena->bytes, maxsz);
120  if (!tmp) {
121  eprintf("Error resizing arena to %d\n", len);
122  return false;
123  }
124  arena->size = maxsz;
125  arena->bytes = tmp;
126  }
127  if (arena->bytes) {
128  memset(arena->bytes, 0, arena->size);
129  memcpy(arena->bytes, buf, minsz);
130  return true;
131  }
132  return false;
133 }
134 
136  RzRegArena *arena;
137  RzListIter *iter;
138  RzRegItem *r;
139  int size, i, newsize;
140 
141  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
142  arena = reg->regset[i].arena;
143  if (!arena) {
144  continue;
145  }
146  newsize = 0;
147  rz_list_foreach (reg->regset[i].regs, iter, r) {
148  // XXX: bits2bytes doesnt seems to work fine
149  size = BITS2BYTES(r->offset + r->size);
150  newsize = RZ_MAX(size, newsize);
151  }
152  if (newsize < 1) {
153  RZ_FREE(arena->bytes);
154  arena->size = 0;
155  } else {
156  ut8 *buf = realloc(arena->bytes, newsize);
157  if (buf) {
158  arena->size = newsize;
159  arena->bytes = buf;
160  memset(arena->bytes, 0, arena->size);
161  } else {
162  arena->bytes = NULL;
163  arena->size = 0;
164  }
165  }
166  }
167  return true;
168 }
169 
172  if (!arena) {
173  RZ_LOG_ERROR("Failed to allocate RzRegArena.\n");
174  return NULL;
175  }
176 
177  arena->size = size;
178  if (size < 1) {
179  return arena;
180  }
181 
182  if (!(arena->bytes = calloc(1, size + 8))) {
183  RZ_LOG_ERROR("Failed to allocate arena bytes.\n");
184  RZ_FREE(arena);
185  }
186  return arena;
187 }
188 
190  if (ra) {
191  free(ra->bytes);
192  free(ra);
193  }
194 }
195 
196 RZ_API void rz_reg_arena_swap(RzReg *reg, int copy) {
197  /* XXX: swap current arena to head(previous arena) */
198  int i;
199  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
200  if (!reg->regset[i].pool) {
201  continue;
202  }
203  if (rz_list_length(reg->regset[i].pool) > 1) {
204  RzListIter *ia = reg->regset[i].cur;
205  RzListIter *ib = reg->regset[i].pool->head;
206  void *tmp = ia->data;
207  ia->data = ib->data;
208  ib->data = tmp;
209  reg->regset[i].arena = ia->data;
210  } else {
211  break;
212  }
213  }
214 }
215 
217  RzRegArena *a;
218  int i;
219  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
220  if (!reg->regset[i].pool) {
221  continue;
222  }
223  if (rz_list_length(reg->regset[i].pool) < 2) {
224  continue;
225  }
226  a = rz_list_pop(reg->regset[i].pool);
228  a = reg->regset[i].pool->tail->data;
229  if (a) {
230  reg->regset[i].arena = a;
231  reg->regset[i].cur = reg->regset[i].pool->tail;
232  }
233  }
234 }
235 
237  int i;
238  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
239  RzRegArena *a = reg->regset[i].arena; // current arena
240  if (!a) {
241  continue;
242  }
243  RzRegArena *b = rz_reg_arena_new(a->size); // new arena
244  if (!b) {
245  continue;
246  }
247  // b->size == a->size always because of how rz_reg_arena_new behave
248  if (a->bytes) {
249  memcpy(b->bytes, a->bytes, b->size);
250  }
251  rz_list_push(reg->regset[i].pool, b);
252  reg->regset[i].arena = b;
253  reg->regset[i].cur = reg->regset[i].pool->tail;
254  }
255  if (reg->regset[0].pool) {
256  return rz_list_length(reg->regset[0].pool);
257  }
258  return 0;
259 }
260 
263  if (type >= 0 && type < RZ_REG_TYPE_LAST) {
264  RzRegArena *a = reg->regset[type].arena;
265  if (!a || !a->bytes) {
266  return;
267  }
268  memset(a->bytes, 0, a->size);
269  return;
270  }
271  int i;
272  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
273  RzRegArena *a = reg->regset[i].arena;
274  if (a && a->bytes) {
275  memset(a->bytes, 0, a->size);
276  }
277  }
278 }
279 
282  if (!reg || !regset || !regset->arena || (regset->arena->size < 1)) {
283  return NULL;
284  }
285  ut8 *ret = malloc(regset->arena->size);
286  if (!ret) {
287  return NULL;
288  }
289  memcpy(ret, regset->arena->bytes, regset->arena->size);
290  return ret;
291 }
292 
293 RZ_API void rz_reg_arena_poke(RzReg *reg, const ut8 *ret) {
295  if (!ret || !regset || !regset->arena || !regset->arena->bytes) {
296  return;
297  }
298  memcpy(regset->arena->bytes, ret, regset->arena->size);
299 }
300 
303  if (!reg || !regset || !regset->arena || (regset->arena->size < 1)) {
304  return NULL;
305  }
306  ut8 *ret = malloc(regset->arena->size);
307  if (!ret) {
308  return NULL;
309  }
310  memcpy(ret, source, regset->arena->size);
311  return ret;
312 }
313 
316  int len = rz_hex_str_is_valid(str);
317  if (len == -1) {
318  eprintf("Invalid input\n");
319  return -1;
320  }
321  int bin_str_len = (len + 1) / 2; // 2 hex chrs for 1 byte
322  ut8 *bin_str = malloc(bin_str_len);
323  if (!bin_str) {
324  eprintf("Failed to decode hex str.\n");
325  return -1;
326  }
327  rz_hex_str2bin(str, bin_str);
328 
329  int i, n = 0; // n - cumulative sum of arena's sizes
330  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
331  int sz = reg->regset[i].arena->size;
332  int bl = bin_str_len - n; // bytes left
333  int bln = bl - n;
334  if (bln > 0 && bln < sz) {
335  rz_reg_set_bytes(reg, i, bin_str + n, bln);
336  break;
337  }
338  rz_reg_set_bytes(reg, i, bin_str + n, bin_str_len - n);
339  n += sz;
340  }
341  free(bin_str);
342  return 0;
343 }
344 
346  RzListIter *iter;
347  RzRegArena *a;
348  int i;
349  for (i = 0; i < RZ_REG_TYPE_LAST; i++) {
350  rz_list_foreach (reg->regset[i].pool, iter, a) {
351  free(a->bytes);
352  /* ha ha ha */
353  a->bytes = calloc(1024, 1);
354  a->size = 1024;
355  /* looks like sizing down the arena breaks the regsync */
356  /* and sizing it up fixes reallocation when fit() is called */
357  }
358  }
359 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
RZ_API bool rz_reg_set_bytes(RzReg *reg, int type, const ut8 *buf, const int len)
Definition: arena.c:92
RZ_API ut8 * rz_reg_arena_dup(RzReg *reg, const ut8 *source)
Definition: arena.c:301
RZ_API bool rz_reg_read_regs(RzReg *reg, ut8 *buf, const int len)
Definition: arena.c:58
RZ_API int rz_reg_fit_arena(RzReg *reg)
Definition: arena.c:135
RZ_API ut8 * rz_reg_arena_peek(RzReg *reg)
Definition: arena.c:280
RZ_API int rz_reg_arena_push(RzReg *reg)
Definition: arena.c:236
RZ_API ut8 * rz_reg_get_bytes(RzReg *reg, int type, int *size)
Definition: arena.c:8
RZ_API void rz_reg_arena_pop(RzReg *reg)
Definition: arena.c:216
RZ_API void rz_reg_arena_shrink(RzReg *reg)
Definition: arena.c:345
RZ_API void rz_reg_arena_zero(RzReg *reg, RzRegisterType type)
Definition: arena.c:261
RZ_API void rz_reg_arena_swap(RzReg *reg, int copy)
Definition: arena.c:196
RZ_API RzRegArena * rz_reg_arena_new(size_t size)
Definition: arena.c:170
RZ_API void rz_reg_arena_poke(RzReg *reg, const ut8 *ret)
Definition: arena.c:293
RZ_API void rz_reg_arena_free(RzRegArena *ra)
Definition: arena.c:189
RZ_API int rz_reg_arena_set_bytes(RzReg *reg, const char *str)
Definition: arena.c:314
static RzILOpEffect * bl(cs_insn *insn, bool is_thumb)
Definition: arm_il32.c:1098
#define RZ_API
#define NULL
Definition: cris-opc.c:27
#define r
Definition: crypto_rc6.c:12
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf void * buf
Definition: ioapi.h:138
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API RZ_OWN void * rz_list_pop(RZ_NONNULL RzList *list)
Removes and returns the last element of the list.
Definition: list.c:376
RZ_API RZ_BORROW RzListIter * rz_list_push(RZ_NONNULL RzList *list, void *item)
Alias for rz_list_append.
Definition: list.c:60
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
void * realloc(void *ptr, size_t size)
Definition: malloc.c:144
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
const char * source
Definition: lz4.h:699
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
int off
Definition: pal.c:13
RZ_API RzRegSet * rz_reg_regset_get(RzReg *r, int type)
Definition: reg.c:452
#define eprintf(x, y...)
Definition: rlcc.c:7
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
RZ_API int rz_hex_str_is_valid(const char *s)
Definition: hex.c:549
RZ_API int rz_hex_str2bin(const char *in, ut8 *out)
Convert an input string in into the binary form in out.
Definition: hex.c:444
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RzRegisterType
Definition: rz_reg.h:20
@ RZ_REG_TYPE_GPR
Definition: rz_reg.h:21
@ RZ_REG_TYPE_LAST
Definition: rz_reg.h:34
@ RZ_REG_TYPE_ANY
Definition: rz_reg.h:35
RZ_API const char * rz_str_trim_head_ro(const char *str)
Definition: str_trim.c:86
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define BITS2BYTES(x)
Definition: rz_types.h:280
#define RZ_FREE(x)
Definition: rz_types.h:369
#define RZ_MIN(x, y)
#define RZ_MAX(x, y)
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
void * data
Definition: rz_list.h:14
ut8 * bytes
Definition: rz_reg.h:131
RzRegArena * arena
Definition: rz_reg.h:136