Rizin
unix-like reverse engineering framework and cli tools
range.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2008-2020 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_util.h>
5 
6 // TODO: use rz_list instead of list.h
7 // TODO: redesign this api.. why? :)
8 // TODO: add tags to ranges
9 
10 // void (*ranges_new_callback)(struct range_t *r) = NULL;
11 
13  RRange *r = RZ_NEW0(RRange);
14  if (r) {
15  r->count = r->changed = 0;
16  r->ranges = rz_list_new();
17  if (!r->ranges) {
19  return NULL;
20  }
21  r->ranges->free = free;
22  }
23  return r;
24 }
25 
27  rz_list_purge(r->ranges);
28  free(r);
29  return NULL;
30 }
31 
32 // TODO: optimize by just returning the pointers to the internal foo?
35  if (!r) {
36  return 0;
37  }
38  if (r->datalen < len) {
39  len = r->datalen;
40  }
41  memcpy(buf, r->data, len);
42  return len;
43 }
44 
45 RZ_API int rz_range_set_data(RRange *rgs, ut64 addr, const ut8 *buf, int len) {
47  if (!r) {
48  return 0;
49  }
50  r->data = (ut8 *)malloc(len);
51  if (!r->data) {
52  return 0;
53  }
54  r->datalen = len;
55  memcpy(r->data, buf, len);
56  return 1;
57 }
58 
60  RRangeItem *r;
62  rz_list_foreach (rgs->ranges, iter, r) {
63  if (addr >= r->fr && addr < r->to) {
64  return r;
65  }
66  }
67  return NULL;
68 }
69 
70 /* returns the sum of all the ranges contained */
71 // XXX: can be caught while adding/removing elements
73  ut64 sum = 0;
75  RRangeItem *r;
76  rz_list_foreach (rgs->ranges, iter, r) {
77  sum += r->to - r->fr;
78  }
79  return sum;
80 }
81 
82 RZ_API RRange *rz_range_new_from_string(const char *string) {
83  RRange *rgs = rz_range_new();
84  rz_range_add_from_string(rgs, string);
85  return rgs;
86 }
87 
88 RZ_API int rz_range_add_from_string(RRange *rgs, const char *string) {
89  ut64 addr, addr2;
90  int i, len = strlen(string) + 1;
91  char *str, *ostr = malloc(len);
92  if (!ostr) {
93  return 0;
94  }
95  char *p = str = ostr;
96  char *p2 = NULL;
97 
98  memcpy(str, string, len);
99  for (i = 0; i < len; i++) {
100  switch (str[i]) {
101  case '-':
102  str[i] = '\0';
103  p2 = p;
104  p = str + i + 1;
105  break;
106  case ',':
107  str[i] = '\0';
108  if (p2) {
109  addr = rz_num_get(NULL, p);
110  addr2 = rz_num_get(NULL, p2);
111  rz_range_add(rgs, addr, addr2, 1);
112  p2 = NULL;
113  } else {
114  addr = rz_num_get(NULL, p);
115  rz_range_add(rgs, addr, addr + 1, 1);
116  }
117  p = str + i + 1;
118  str[i] = ',';
119  break;
120  }
121  }
122  if (p2) {
123  addr = rz_num_get(NULL, p);
124  addr2 = rz_num_get(NULL, p2);
125  rz_range_add(rgs, addr, addr2, 1);
126  } else if (p) {
127  addr = rz_num_get(NULL, p);
128  rz_range_add(rgs, addr, addr + 1, 1);
129  }
130  free(ostr);
131  return rgs ? rgs->changed : 0;
132 }
133 
134 #if 0
135  update to new one update fr update fr/to ignore
136 
137  |______| |___| |_____| |____| |_______| range_t
138 + |______| + |__| + |___| + |_________| + |__| fr/to
139  ------------ ----------- ----------- ------------- -----------
140 = |_________| = |___||__| = |_______| = |_________| |_______| result
141 #endif
142 
144  RzListIter *iter;
145  RRangeItem *r, *ret = NULL;
146  int add = 1;
147 
148  rz_num_minmax_swap(&fr, &to);
149  rz_list_foreach (rgs->ranges, iter, r) {
150  if (r->fr == fr && r->to == to) {
151  add = 0;
152  } else if (r->fr <= fr && r->fr <= to && r->to >= fr && r->to <= to) {
153  r->to = to;
154  ret = r;
155  add = 0;
156  } else if (r->fr >= fr && r->fr <= to && r->to >= fr && r->to >= to) {
157  r->fr = fr;
158  ret = r;
159  add = 0;
160  } else if (r->fr <= fr && r->fr <= to && r->to >= fr && r->to >= to) {
161  /* ignore */
162  add = 0;
163  } else if (r->fr >= fr && r->fr <= to && r->to >= fr && r->to <= to) {
164  r->fr = fr;
165  r->to = to;
166  ret = r;
167  add = 0;
168  }
169  }
170 
171  if (rw && add) {
172  ret = RZ_NEW(RRangeItem);
173  ret->fr = fr;
174  ret->to = to;
175  ret->datalen = 0;
176  ret->data = NULL;
177  rz_list_append(rgs->ranges, ret);
178  rgs->changed = 1;
179  }
180 
181  return ret;
182 }
183 
184 #if 0
185  update to ignore update fr delete split
186 
187  |______| |___| |_____| |____| |________| range_t
188 - |______| - |__| - |___| - |_________| - |__| fr/to
189  ------------ ----------- ----------- ------------- ------------
190 = |__| = = |___| = |__| |__| result
191 #endif
192 
194  RRangeItem *r;
195  RzListIter *iter;
196 
197  rz_num_minmax_swap(&fr, &to);
198 
199 __reloop:
200  rz_list_foreach (rgs->ranges, iter, r) {
201  /* update to */
202  if (r->fr < fr && r->fr < to && r->to > fr && r->to < to) {
203  r->to = fr;
204  } else if (r->fr > fr && r->fr < to && r->to > fr && r->to > to) {
205  /* update fr */
206  r->fr = to;
207  }
208  /* delete */
209  if (r->fr > fr && r->fr < to && r->to > fr && r->to < to) {
210  /* delete */
211  rz_list_delete(rgs->ranges, iter);
212  rgs->changed = 1;
213  goto __reloop;
214  }
215  /* split */
216  if (r->fr < fr && r->fr < to && r->to > fr && r->to > to) {
217  r->to = fr;
218  rz_range_add(rgs, to, r->to, 1);
219  // ranges_add(rang, to, r->to, 1);
220  goto __reloop;
221  }
222  }
223  return 0;
224 }
225 
226 #if 0
227 /* TODO: should remove some of them right? */
228 RZ_API void rz_range_merge(RRange *rgs, RRange *r) {
229  RzListIter *iter;
230  RRangeItem *r;
231  rz_list_foreach (rgs->ranges, iter, r)
232  rz_range_add (rgs, r->fr, r->to, 0);
233 }
234 #endif
235 
236 // int ranges_is_used(ut64 addr)
238  RRangeItem *r;
239  RzListIter *iter;
240  rz_list_foreach (rgs->ranges, iter, r) {
241  if (addr >= r->fr && addr <= r->to) {
242  return true;
243  }
244  }
245  return false;
246 }
247 
248 static int cmp_ranges(void *a, void *b) {
249  RRangeItem *first = (RRangeItem *)a;
250  RRangeItem *second = (RRangeItem *)b;
251  return (first->fr > second->fr) - (first->fr < second->fr);
252 }
253 
255  bool ch = rgs->ranges->sorted;
256  if (!rgs->changed) {
257  return false;
258  }
259  rgs->changed = false;
261  if (ch != rgs->ranges->sorted) {
262  rgs->changed = true;
263  }
264  return rgs->changed;
265 }
266 
268  RzListIter *iter;
269  RRangeItem *r;
270  int w, i;
271  ut64 seek, step;
272  ut64 dif, fr = -1, to = -1;
273 
274  rz_list_foreach (rgs->ranges, iter, r) {
275  if (fr == -1) {
276  /* init */
277  fr = r->fr;
278  to = r->to;
279  } else {
280  if (fr > r->fr) {
281  fr = r->fr;
282  }
283  if (to < r->to) {
284  to = r->to;
285  }
286  }
287  }
288  w = 65; // columns
289  if (fr != -1) {
290  dif = to - fr;
291  if (dif < w) {
292  step = 1; // XXX
293  } else {
294  step = dif / w;
295  }
296  } else {
297  step = fr = to = 0;
298  }
299  seek = 0;
300  // XXX do not use printf here!
301  printf("0x%08" PFMT64x " [", fr);
302  for (i = 0; i < w; i++) {
303  if (rz_range_contains(rgs, seek)) {
304  printf("#");
305  } else {
306  printf(".");
307  }
308  seek += step;
309  }
310  printf("] 0x%08" PFMT64x "\n", to);
311 }
312 
313 // TODO: total can be cached in rgs!!
314 RZ_API int rz_range_list(RRange *rgs, int rad) {
315  ut64 total = 0;
316  RRangeItem *r;
317  RzListIter *iter;
318  rz_range_sort(rgs);
319  rz_list_foreach (rgs->ranges, iter, r) {
320  if (rad) {
321  printf("ar+ 0x%08" PFMT64x " 0x%08" PFMT64x "\n", r->fr, r->to);
322  } else {
323  printf("0x%08" PFMT64x " 0x%08" PFMT64x " ; %" PFMT64d "\n", r->fr, r->to, r->to - r->fr);
324  }
325  total += (r->to - r->fr);
326  }
327  eprintf("Total bytes: %" PFMT64d "\n", total);
328  return 0;
329 }
330 
331 RZ_API int rz_range_get_n(RRange *rgs, int n, ut64 *fr, ut64 *to) {
332  int count = 0;
333  RRangeItem *r;
334  RzListIter *iter;
335  rz_range_sort(rgs);
336  rz_list_foreach (rgs->ranges, iter, r) {
337  if (count == n) {
338  *fr = r->fr;
339  *to = r->to;
340  return 1;
341  }
342  count++;
343  }
344  return 0;
345 }
346 
347 #if 0
348  .....|______________________|...
349  |_____| |____| |_______|
350  ---------------------------------
351  |__| |__| |_|
352 #endif
354  RzListIter *iter;
355  RRangeItem *r = NULL;
356  RRange *newrgs = rz_range_new();
357 
358  rz_range_sort(rgs);
359 
360  rz_list_foreach (rgs->ranges, iter, r) {
361  if (r->fr > fr && r->fr < to) {
362  rz_range_add(newrgs, fr, r->fr, 1);
363  fr = r->to;
364  }
365  }
366  if (fr < to) {
367  rz_range_add(newrgs, fr, to, 1);
368  }
369  return newrgs;
370 }
371 
372 /*
373  return true if overlap
374  in *d
375 */
376 // TODO: make it a macro
377 // TODO: move to num.c ?
378 RZ_API int rz_range_overlap(ut64 a0, ut64 a1, ut64 b0, ut64 b1, int *d) {
379  // TODO: ensure ranges minmax .. innecesary at runtime?
380  // rz_num_minmax_swap (&a0, &a1);
381  // rz_num_minmax_swap (&b0, &b1);
382  return *d = (b0 - a0), !(a1 < b0 || a0 > b1);
383 #if 0
384  // does not overlap
385  // a |__| |__|
386  // b |__| |__|
387  if (a1<b0 || a0>b1)
388  return 0;
389 
390  // a |____| |_____| |____| |_____|
391  // b |____| |_| |____| |_______|
392  // b needs a needs a needs b needs
393  // delta required
394  return (b0-a0);
395 #endif
396 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static bool update(RzCrypto *cry, const ut8 *buf, int len)
Definition: crypto_aes.c:92
#define r
Definition: crypto_rc6.c:12
#define w
Definition: crypto_rc6.c:13
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static states step(struct re_guts *, sopno, sopno, states, int, states)
Definition: engine.c:888
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
a0
Definition: insn-good.s.cs:704
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API void rz_list_delete(RZ_NONNULL RzList *list, RZ_NONNULL RzListIter *iter)
Removes an entry in the list by using the RzListIter pointer.
Definition: list.c:162
RZ_API RZ_OWN RzList * rz_list_new(void)
Returns a new initialized RzList pointer (free method is not initialized)
Definition: list.c:235
RZ_API void rz_list_sort(RZ_NONNULL RzList *list, RZ_NONNULL RzListComparator cmp)
Sorts via merge sort or via insertion sort a list.
Definition: list.c:743
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_purge(RZ_NONNULL RzList *list)
Empties the list without freeing the list pointer.
Definition: list.c:120
void * malloc(size_t size)
Definition: malloc.c:123
int n
Definition: mipsasm.c:19
#define _(String)
Definition: opintl.h:53
RZ_API RRange * rz_range_new_from_string(const char *string)
Definition: range.c:82
RZ_API int rz_range_list(RRange *rgs, int rad)
Definition: range.c:314
RZ_API int rz_range_sort(RRange *rgs)
Definition: range.c:254
RZ_API RRangeItem * rz_range_item_get(RRange *rgs, ut64 addr)
Definition: range.c:59
RZ_API int rz_range_add_from_string(RRange *rgs, const char *string)
Definition: range.c:88
static int cmp_ranges(void *a, void *b)
Definition: range.c:248
RZ_API int rz_range_sub(RRange *rgs, ut64 fr, ut64 to)
Definition: range.c:193
RZ_API ut64 rz_range_size(RRange *rgs)
Definition: range.c:72
RZ_API int rz_range_contains(RRange *rgs, ut64 addr)
Definition: range.c:237
RZ_API RRange * rz_range_free(RRange *r)
Definition: range.c:26
RZ_API RRange * rz_range_inverse(RRange *rgs, ut64 fr, ut64 to, int flags)
Definition: range.c:353
RZ_API RRangeItem * rz_range_add(RRange *rgs, ut64 fr, ut64 to, int rw)
Definition: range.c:143
RZ_API int rz_range_get_data(RRange *rgs, ut64 addr, ut8 *buf, int len)
Definition: range.c:33
RZ_API int rz_range_set_data(RRange *rgs, ut64 addr, const ut8 *buf, int len)
Definition: range.c:45
RZ_API void rz_range_percent(RRange *rgs)
Definition: range.c:267
RZ_API RRange * rz_range_new(void)
Definition: range.c:12
RZ_API int rz_range_get_n(RRange *rgs, int n, ut64 *fr, ut64 *to)
Definition: range.c:331
RZ_API int rz_range_overlap(ut64 a0, ut64 a1, ut64 b0, ut64 b1, int *d)
Definition: range.c:378
#define eprintf(x, y...)
Definition: rlcc.c:7
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
RZ_API ut64 rz_num_get(RzNum *num, const char *str)
Definition: unum.c:172
RZ_API void rz_num_minmax_swap(ut64 *a, ut64 *b)
Definition: unum.c:59
#define PFMT64d
Definition: rz_types.h:394
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NEW(x)
Definition: rz_types.h:285
#define PFMT64x
Definition: rz_types.h:393
static struct sockaddr static addrlen static backlog const void static flags void struct sockaddr socklen_t static fromlen const void const struct sockaddr to
Definition: sfsocketcall.h:125
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
#define d(i)
Definition: sha256.c:44
#define b(i)
Definition: sha256.c:42
#define a(i)
Definition: sha256.c:41
bool sorted
Definition: rz_list.h:23
RzList * ranges
Definition: rz_range.h:23
int changed
Definition: rz_range.h:22
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58
static int add(char *argv[])
Definition: ziptool.c:84
static int seek(char *argv[])