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