1 /* radare - LGPL - Copyright 2016-2020 - pancake */
2
3 #include <r_flag.h>
4 #include <r_util.h>
5
6 #define DB f->zones
7
8 #if !R_FLAG_ZONE_USE_SDB
9
r_flag_zone_get(RFlag * f,const char * name)10 static RFlagZoneItem *r_flag_zone_get (RFlag *f, const char *name) {
11 RListIter *iter;
12 RFlagZoneItem *zi;
13 r_list_foreach (DB, iter, zi) {
14 if (!strcmp (name, zi->name)) {
15 return zi;
16 }
17 }
18 return NULL;
19 }
20 #endif
21
r_flag_zone_get_inrange(RFlag * f,ut64 from,ut64 to)22 static RFlagZoneItem *r_flag_zone_get_inrange (RFlag *f, ut64 from, ut64 to) {
23 RListIter *iter;
24 RFlagZoneItem *zi;
25 r_list_foreach (DB, iter, zi) {
26 if (R_BETWEEN (from, zi->from, to)) {
27 return zi;
28 }
29 }
30 return NULL;
31 }
32
r_flag_zone_add(RFlag * f,const char * name,ut64 addr)33 R_API bool r_flag_zone_add(RFlag *f, const char *name, ut64 addr) {
34 r_return_val_if_fail (f && name && *name, false);
35 #if R_FLAG_ZONE_USE_SDB
36 RFlagZoneItem zi = { 0, 0, (const char *)name };
37 if (!DB) {
38 return false;
39 }
40 const char *bound = sdb_const_get (DB, name, NULL);
41 if (bound) {
42 sdb_fmt_tobin (bound, "qq", &zi);
43 if (addr < zi.from) {
44 zi.from = addr;
45 }
46 if (addr > zi.to) {
47 zi.to = addr;
48 }
49 char *newBounds = sdb_fmt_tostr (&zi, "qq");
50 sdb_set (DB, name, newBounds, 0);
51 free (newBounds);
52 } else {
53 sdb_set (DB, name, sdb_fmt ("%"PFMT64d",%"PFMT64d, addr, addr), 0);
54 }
55 #else
56 RFlagZoneItem *zi = r_flag_zone_get (f, name);
57 if (zi) {
58 if (addr < zi->from) {
59 zi->from = addr;
60 }
61 if (addr > zi->to) {
62 zi->to = addr;
63 }
64 } else {
65 if (!DB) {
66 r_flag_zone_reset (f);
67 }
68 zi = R_NEW0 (RFlagZoneItem);
69 zi->name = strdup (name);
70 zi->from = zi->to = addr;
71 r_list_append (DB, zi);
72 }
73 #endif
74 return true;
75 }
76
r_flag_zone_reset(RFlag * f)77 R_API bool r_flag_zone_reset(RFlag *f) {
78 #if R_FLAG_ZONE_USE_SDB
79 return sdb_reset (DB);
80 #else
81 r_list_free (f->zones);
82 f->zones = r_list_newf (r_flag_zone_item_free);
83 return true;
84 #endif
85 }
86
r_flag_zone_del(RFlag * f,const char * name)87 R_API bool r_flag_zone_del(RFlag *f, const char *name) {
88 #if R_FLAG_ZONE_USE_SDB
89 return sdb_unset (DB, name, 0);
90 #else
91 RListIter *iter;
92 RFlagZoneItem *zi;
93 r_list_foreach (DB, iter, zi) {
94 if (!strcmp (name, zi->name)) {
95 r_list_delete (DB, iter);
96 return true;
97 }
98 }
99 return false;
100 #endif
101 }
102
103 #if R_FLAG_ZONE_USE_SDB
104
105 typedef struct r_flag_zone_context_t {
106 RFlag *f;
107 ut64 addr;
108 ut64 l, h; // lower, higher closest offsets
109 const char **prev;
110 const char **next;
111 } RFlagZoneContext;
112
cb(void * user,const char * name,const char * from_to)113 static bool cb(void *user, const char *name, const char *from_to) {
114 RFlagZoneContext *zc = (RFlagZoneContext*)user;
115 RFlagZoneItem zi = { 0, 0, name };
116 sdb_fmt_tobin (from_to, "qq", &zi);
117 if (zi.from > zc->addr) {
118 if (zc->h == UT64_MAX) {
119 zc->h = zi.from;
120 *zc->next = name;
121 } else {
122 if (zi.from < zc->h) {
123 zc->h = zi.from;
124 *zc->next = name;
125 }
126 }
127 }
128 if (zi.from < zc->addr) {
129 if (zc->l == UT64_MAX) {
130 zc->l = zi.from;
131 *zc->prev = name;
132 } else {
133 if (zi.from >= zc->l) {
134 zc->l = zi.from;
135 *zc->prev = name;
136 }
137 }
138 }
139 if (zi.to <= zc->addr) {
140 if (zc->l == UT64_MAX) {
141 zc->l = zi.to;
142 *zc->prev = name;
143 } else {
144 if (zi.to >= zc->l) {
145 zc->l = zi.to;
146 *zc->prev = name;
147 }
148 }
149 }
150 if (zi.to > zc->addr) {
151 if (zc->h == UT64_MAX) {
152 zc->h = zi.to;
153 *zc->next = name;
154 } else {
155 if (zi.to < zc->h) {
156 zc->h = zi.to;
157 *zc->next = name;
158 }
159 }
160 }
161 return true;
162 }
163
r_flag_zone_around(RFlag * f,ut64 addr,const char ** prev,const char ** next)164 R_API bool r_flag_zone_around(RFlag *f, ut64 addr, const char **prev, const char **next) {
165 RFlagZoneContext ctx = { f, addr, 0, UT64_MAX, prev, next };
166 *prev = *next = NULL;
167 sdb_foreach (DB, cb, &ctx);
168 return true;
169 }
170
cb_list(void * user,const char * name,const char * from_to)171 static bool cb_list(void *user, const char *name, const char *from_to) {
172 eprintf ("%s%s %s\n", name, r_str_pad (' ', 10 - strlen (name)), from_to);
173 return true;
174 }
175
r_flag_zone_list(RFlag * f,int mode)176 R_API bool r_flag_zone_list(RFlag *f, int mode) {
177 sdb_foreach (DB, cb_list, NULL);
178 return true;
179 }
180
181 #else
182
r_flag_zone_item_free(void * a)183 R_API void r_flag_zone_item_free(void *a) {
184 RFlagZoneItem *zi = a;
185 free (zi->name);
186 free (zi);
187 }
188
r_flag_zone_around(RFlag * f,ut64 addr,const char ** prev,const char ** next)189 R_API bool r_flag_zone_around(RFlag *f, ut64 addr, const char **prev, const char **next) {
190 RListIter *iter;
191 RFlagZoneItem *zi;
192 *prev = *next = NULL;
193 ut64 h = UT64_MAX, l = 0LL;
194
195 r_list_foreach (DB, iter, zi) {
196 if (zi->from > addr) {
197 if (h == UT64_MAX) {
198 h = zi->from;
199 *next = zi->name;
200 } else {
201 if (zi->from < h) {
202 h = zi->from;
203 *next = zi->name;
204 }
205 }
206 }
207 if (zi->from < addr) {
208 if (l == UT64_MAX) {
209 l = zi->from;
210 *prev = zi->name;
211 } else {
212 if (zi->from >= l) {
213 l = zi->from;
214 *prev = zi->name;
215 }
216 }
217 }
218 if (zi->to <= addr) {
219 if (l == UT64_MAX) {
220 l = zi->to;
221 *prev = zi->name;
222 } else {
223 if (zi->to >= l) {
224 l = zi->to;
225 *prev = zi->name;
226 }
227 }
228 }
229 if (zi->to > addr) {
230 if (h == UT64_MAX) {
231 h = zi->to;
232 *next = zi->name;
233 } else {
234 if (zi->to < h) {
235 h = zi->to;
236 *next = zi->name;
237 }
238 }
239 }
240 }
241 return true;
242 }
243
r_flag_zone_barlist(RFlag * f,ut64 from,ut64 bsize,int rows)244 R_API RList *r_flag_zone_barlist(RFlag *f, ut64 from, ut64 bsize, int rows) {
245 RList *list = r_list_newf (NULL);
246 int i;
247 for (i = 0; i < rows; i++) {
248 RFlagZoneItem *zi = r_flag_zone_get_inrange (f, from, from + bsize);
249 if (zi) {
250 r_list_append (list, zi->name);
251 } else {
252 r_list_append (list, "");
253 }
254 from += bsize;
255 }
256 return list;
257 }
258
r_flag_zone_list(RFlag * f,int mode)259 R_API bool r_flag_zone_list(RFlag *f, int mode) {
260 RListIter *iter;
261 RFlagZoneItem *zi;
262 r_list_foreach (DB, iter, zi) {
263 if (mode == '*') {
264 f->cb_printf ("fz %s @ 0x08%"PFMT64x"\n", zi->name, zi->from);
265 f->cb_printf ("f %s %"PFMT64d" 0x08%"PFMT64x"\n", zi->name,
266 zi->to - zi->from, zi->from);
267 } else {
268 f->cb_printf ("0x08%"PFMT64x" 0x%08"PFMT64x" %s\n",
269 zi->from, zi->to, zi->name);
270 }
271 }
272 return true;
273 }
274 #endif
275
276 // #define __MAIN__ 1
277 #if __MAIN__
278 #define FZ(x) r_flag_zone_##x
279
main()280 int main() {
281 const char *a, *b;
282 RFlagZone *fz = r_flag_zone_new ();
283
284 FZ(add)(fz, "main", 0x80000);
285 FZ(add)(fz, "network", 0x85000);
286 FZ(add)(fz, "libc", 0x90000);
287
288 FZ(add)(fz, "network", 0x000);
289
290 FZ(around)(fz, 0x83000, &a, &b);
291 printf ("%s %s\n", a, b);
292
293 FZ(around)(fz, 0x50000, &a, &b);
294 printf ("%s %s\n", a, b);
295
296 FZ(around)(fz, 0x500000, &a, &b);
297 printf ("%s %s\n", a, b);
298
299 FZ(list)(fz);
300
301 r_flag_zone_free (fz);
302 return 0;
303 }
304 #endif
305