1 /* radare - LGPL - Copyright 2008-2020 - nibble, pancake, thestr4ng3r */
2 
3 #include <r_anal.h>
4 #include <r_core.h>
5 
item_matches_filter(RAnalMetaItem * item,RAnalMetaType type,R_NULLABLE const RSpace * space)6 static bool item_matches_filter(RAnalMetaItem *item, RAnalMetaType type, R_NULLABLE const RSpace *space) {
7 	return (type == R_META_TYPE_ANY || item->type == type)
8 		   && (!space || item->space == space);
9 }
10 
11 typedef struct {
12 	RAnalMetaType type;
13 	const RSpace *space;
14 
15 	RIntervalNode *node;
16 } FindCtx;
17 
find_node_cb(RIntervalNode * node,void * user)18 static bool find_node_cb(RIntervalNode *node, void *user) {
19 	FindCtx *ctx = user;
20 	if (item_matches_filter (node->data, ctx->type, ctx->space)) {
21 		ctx->node = node;
22 		return false;
23 	}
24 	return true;
25 }
26 
find_node_at(RAnal * anal,RAnalMetaType type,R_NULLABLE const RSpace * space,ut64 addr)27 static RIntervalNode *find_node_at(RAnal *anal, RAnalMetaType type, R_NULLABLE const RSpace *space, ut64 addr) {
28 	FindCtx ctx = {
29 		.type = type,
30 		.space = space,
31 		.node = NULL
32 	};
33 	r_interval_tree_all_at (&anal->meta, addr, find_node_cb, &ctx);
34 	return ctx.node;
35 }
36 
find_node_in(RAnal * anal,RAnalMetaType type,R_NULLABLE const RSpace * space,ut64 addr)37 static RIntervalNode *find_node_in(RAnal *anal, RAnalMetaType type, R_NULLABLE const RSpace *space, ut64 addr) {
38 	FindCtx ctx = {
39 		.type = type,
40 		.space = space,
41 		.node = NULL
42 	};
43 	r_interval_tree_all_in (&anal->meta, addr, true, find_node_cb, &ctx);
44 	return ctx.node;
45 }
46 
47 typedef struct {
48 	RAnalMetaType type;
49 	const RSpace *space;
50 
51 	RPVector/*RIntervalNode*/ *result;
52 } CollectCtx;
53 
collect_nodes_cb(RIntervalNode * node,void * user)54 static bool collect_nodes_cb(RIntervalNode *node, void *user) {
55 	CollectCtx *ctx = user;
56 	if (item_matches_filter (node->data, ctx->type, ctx->space)) {
57 		r_pvector_push (ctx->result, node);
58 	}
59 	return true;
60 }
61 
collect_nodes_at(RAnal * anal,RAnalMetaType type,R_NULLABLE const RSpace * space,ut64 addr)62 static RPVector *collect_nodes_at(RAnal *anal, RAnalMetaType type, R_NULLABLE const RSpace *space, ut64 addr) {
63 	CollectCtx ctx = {
64 		.type = type,
65 		.space = space,
66 		.result = r_pvector_new (NULL)
67 	};
68 	if (!ctx.result) {
69 		return NULL;
70 	}
71 	r_interval_tree_all_at (&anal->meta, addr, collect_nodes_cb, &ctx);
72 	return ctx.result;
73 }
74 
collect_nodes_in(RAnal * anal,RAnalMetaType type,R_NULLABLE const RSpace * space,ut64 addr)75 static RPVector *collect_nodes_in(RAnal *anal, RAnalMetaType type, R_NULLABLE const RSpace *space, ut64 addr) {
76 	CollectCtx ctx = {
77 		.type = type,
78 		.space = space,
79 		.result = r_pvector_new (NULL)
80 	};
81 	if (!ctx.result) {
82 		return NULL;
83 	}
84 	r_interval_tree_all_in (&anal->meta, addr, true, collect_nodes_cb, &ctx);
85 	return ctx.result;
86 }
87 
collect_nodes_intersect(RAnal * anal,RAnalMetaType type,R_NULLABLE const RSpace * space,ut64 start,ut64 end)88 static RPVector *collect_nodes_intersect(RAnal *anal, RAnalMetaType type, R_NULLABLE const RSpace *space, ut64 start, ut64 end) {
89 	CollectCtx ctx = {
90 		.type = type,
91 		.space = space,
92 		.result = r_pvector_new (NULL)
93 	};
94 	if (!ctx.result) {
95 		return NULL;
96 	}
97 	r_interval_tree_all_intersect (&anal->meta, start, end, true, collect_nodes_cb, &ctx);
98 	return ctx.result;
99 }
100 
meta_set(RAnal * a,RAnalMetaType type,int subtype,ut64 from,ut64 to,const char * str)101 static bool meta_set(RAnal *a, RAnalMetaType type, int subtype, ut64 from, ut64 to, const char *str) {
102 	if (to < from) {
103 		return false;
104 	}
105 	RSpace *space = r_spaces_current (&a->meta_spaces);
106 	RIntervalNode *node = find_node_at (a, type, space, from);
107 	RAnalMetaItem *item = node ? node->data : R_NEW0 (RAnalMetaItem);
108 	if (!item) {
109 		return false;
110 	}
111 	item->type = type;
112 	item->subtype = subtype;
113 	item->space = space;
114 	free (item->str);
115 	item->str = str ? strdup (str) : NULL;
116 	if (str && !item->str) {
117 		if (!node) { // If we just created this
118 			free (item);
119 		}
120 		return false;
121 	}
122 	if (!node) {
123 		r_interval_tree_insert (&a->meta, from, to, item);
124 	} else if (node->end != to) {
125 		r_interval_tree_resize (&a->meta, node, from, to);
126 	}
127 	return true;
128 }
129 
r_meta_set_string(RAnal * a,RAnalMetaType type,ut64 addr,const char * s)130 R_API bool r_meta_set_string(RAnal *a, RAnalMetaType type, ut64 addr, const char *s) {
131 	return meta_set (a, type, 0, addr, addr, s);
132 }
133 
r_meta_get_string(RAnal * a,RAnalMetaType type,ut64 addr)134 R_API const char *r_meta_get_string(RAnal *a, RAnalMetaType type, ut64 addr) {
135 	RIntervalNode *node = find_node_at (a, type, r_spaces_current (&a->meta_spaces), addr);
136 	if (!node) {
137 		return NULL;
138 	}
139 	RAnalMetaItem *item = node->data;
140 	return item->str;
141 }
142 
143 
del(RAnal * a,RAnalMetaType type,const RSpace * space,ut64 addr,ut64 size)144 static void del(RAnal *a, RAnalMetaType type, const RSpace *space, ut64 addr, ut64 size) {
145 	RPVector *victims = NULL;
146 	if (size == UT64_MAX) {
147 		// delete everything
148 		victims = r_pvector_new (NULL);
149 		if (!victims) {
150 			return;
151 		}
152 		RIntervalTreeIter it;
153 		RAnalMetaItem *item;
154 		r_interval_tree_foreach (&a->meta, it, item) {
155 			if (item_matches_filter (item, type, space)) {
156 				r_pvector_push (victims, r_interval_tree_iter_get (&it));
157 			}
158 		}
159 	} else {
160 		ut64 end = size ? addr + size - 1 : addr;
161 		if (end < addr) {
162 			end = UT64_MAX;
163 		}
164 		victims = collect_nodes_intersect (a, type, space, addr, end);
165 		if (!victims) {
166 			return;
167 		}
168 	}
169 	void **it;
170 	r_pvector_foreach (victims, it) {
171 		r_interval_tree_delete (&a->meta, *it, true);
172 	}
173 	r_pvector_free (victims);
174 }
175 
r_meta_del(RAnal * a,RAnalMetaType type,ut64 addr,ut64 size)176 R_API void r_meta_del(RAnal *a, RAnalMetaType type, ut64 addr, ut64 size) {
177 	del (a, type, r_spaces_current (&a->meta_spaces), addr, size);
178 }
179 
r_meta_set(RAnal * a,RAnalMetaType type,ut64 addr,ut64 size,const char * str)180 R_API bool r_meta_set(RAnal *a, RAnalMetaType type, ut64 addr, ut64 size, const char *str) {
181 	return r_meta_set_with_subtype (a, type, 0, addr, size, str);
182 }
183 
r_meta_set_with_subtype(RAnal * m,RAnalMetaType type,int subtype,ut64 addr,ut64 size,const char * str)184 R_API bool r_meta_set_with_subtype(RAnal *m, RAnalMetaType type, int subtype, ut64 addr, ut64 size, const char *str) {
185 	r_return_val_if_fail (m && size, false);
186 	ut64 end = addr + size - 1;
187 	if (end < addr) {
188 		end = UT64_MAX;
189 	}
190 	return meta_set (m, type, subtype, addr, end, str);
191 }
192 
r_meta_get_at(RAnal * a,ut64 addr,RAnalMetaType type,R_OUT R_NULLABLE ut64 * size)193 R_API RAnalMetaItem *r_meta_get_at(RAnal *a, ut64 addr, RAnalMetaType type, R_OUT R_NULLABLE ut64 *size) {
194 	RIntervalNode *node = find_node_at (a, type, r_spaces_current (&a->meta_spaces), addr);
195 	if (node && size) {
196 		*size = r_meta_item_size (node->start, node->end);
197 	}
198 	return node ? node->data : NULL;
199 }
200 
r_meta_get_in(RAnal * a,ut64 addr,RAnalMetaType type)201 R_API RIntervalNode *r_meta_get_in(RAnal *a, ut64 addr, RAnalMetaType type) {
202 	return find_node_in (a, type, r_spaces_current (&a->meta_spaces), addr);
203 }
204 
r_meta_get_all_at(RAnal * a,ut64 at)205 R_API RPVector/*<RIntervalNode<RMetaItem> *>*/ *r_meta_get_all_at(RAnal *a, ut64 at) {
206 	return collect_nodes_at (a, R_META_TYPE_ANY, r_spaces_current (&a->meta_spaces), at);
207 }
208 
r_meta_get_all_in(RAnal * a,ut64 at,RAnalMetaType type)209 R_API RPVector *r_meta_get_all_in(RAnal *a, ut64 at, RAnalMetaType type) {
210 	return collect_nodes_in (a, type, r_spaces_current (&a->meta_spaces), at);
211 }
212 
r_meta_get_all_intersect(RAnal * a,ut64 start,ut64 size,RAnalMetaType type)213 R_API RPVector *r_meta_get_all_intersect(RAnal *a, ut64 start, ut64 size, RAnalMetaType type) {
214 	r_return_val_if_fail (size, NULL);
215 	ut64 end = start + size - 1;
216 	if (end < start) {
217 		end = UT64_MAX;
218 	}
219 	return collect_nodes_intersect (a, type, r_spaces_current (&a->meta_spaces), start, end);
220 }
221 
r_meta_type_to_string(int type)222 R_API const char *r_meta_type_to_string(int type) {
223 	// XXX: use type as '%c'
224 	switch (type) {
225 	case R_META_TYPE_DATA: return "Cd";
226 	case R_META_TYPE_CODE: return "Cc";
227 	case R_META_TYPE_STRING: return "Cs";
228 	case R_META_TYPE_FORMAT: return "Cf";
229 	case R_META_TYPE_MAGIC: return "Cm";
230 	case R_META_TYPE_HIDE: return "Ch";
231 	case R_META_TYPE_COMMENT: return "CCu";
232 	case R_META_TYPE_RUN: return "Cr"; // not in C? help
233 	case R_META_TYPE_HIGHLIGHT: return "ecHi"; // not in C?
234 	case R_META_TYPE_VARTYPE: return "Ct";
235 	}
236 	return "# unknown meta # ";
237 }
238 
r_meta_print(RAnal * a,RAnalMetaItem * d,ut64 start,ut64 size,int rad,PJ * pj,bool show_full)239 R_API void r_meta_print(RAnal *a, RAnalMetaItem *d, ut64 start, ut64 size, int rad, PJ *pj, bool show_full) {
240 	r_return_if_fail (!(rad == 'j' && !pj)); // rad == 'j' => pj != NULL
241 	char *pstr, *base64_str;
242 	RCore *core = a->coreb.core;
243 	bool esc_bslash = core ? core->print->esc_bslash : false;
244 	if (r_spaces_current (&a->meta_spaces) &&
245 	    r_spaces_current (&a->meta_spaces) != d->space) {
246 		return;
247 	}
248 	char *str = NULL;
249 	if (d->str) {
250 		if (d->type == R_META_TYPE_STRING) {
251 			if (d->subtype == R_STRING_ENC_UTF8) {
252 				str = r_str_escape_utf8 (d->str, false, esc_bslash);
253 			} else {
254 				if (!d->subtype) {  /* temporary legacy workaround */
255 					esc_bslash = false;
256 				}
257 				str = r_str_escape_latin1 (d->str, false, esc_bslash, false);
258 			}
259 		} else {
260 			str = r_str_escape (d->str);
261 		}
262 	}
263 	if (str || d->type == R_META_TYPE_DATA) {
264 		if (d->type == R_META_TYPE_STRING && !*str) {
265 			free (str);
266 			return;
267 		}
268 		if (!str) {
269 			pstr = "";
270 		} else if (d->type == 'f') {
271 			pstr = str;
272 		} else if (d->type == 's') {
273 			pstr = str;
274 		} else if (d->type == 't') {
275 			// Sanitize (don't escape) Ct comments so we can see "char *", etc.
276 			free (str);
277 			str = strdup (d->str);
278 			r_str_sanitize (str);
279 			pstr = str;
280 		} else if (d->type != 'C') {
281 			r_name_filter (str, 0);
282 			pstr = str;
283 		} else {
284 			pstr = d->str;
285 		}
286 //		r_str_sanitize (str);
287 		switch (rad) {
288 		case 'j':
289 			pj_o (pj);
290 			pj_kn (pj, "offset", start);
291 			pj_ks (pj, "type", r_meta_type_to_string (d->type));
292 
293 			if (d->type == 'H') {
294 				pj_k (pj, "color");
295 				ut8 r = 0, g = 0, b = 0, A = 0;
296 				const char *esc = strchr (d->str, '\x1b');
297 				if (esc) {
298 					r_cons_rgb_parse (esc, &r, &g, &b, &A);
299 					char *rgb_str = r_cons_rgb_tostring (r, g, b);
300 					base64_str = r_base64_encode_dyn (rgb_str, -1);
301 					if (d->type == 's' && base64_str) {
302 						pj_s (pj, base64_str);
303 						free (base64_str);
304 					} else {
305 						pj_s (pj, rgb_str);
306 					}
307 					free (rgb_str);
308 				} else {
309 					pj_s (pj, str);
310 				}
311 			} else {
312 				pj_k (pj, "name");
313 				if (d->type == 's' && (base64_str = r_base64_encode_dyn (d->str, -1))) {
314 					pj_s (pj, base64_str);
315 				} else {
316 					pj_s (pj, str);
317 				}
318 			}
319 			if (d->type == 'd') {
320 				pj_kn (pj, "size", size);
321 			} else if (d->type == 's') {
322 				const char *enc;
323 				switch (d->subtype) {
324 				case R_STRING_ENC_UTF8:
325 					enc = "utf8";
326 					break;
327 				case 0:  /* temporary legacy encoding */
328 					enc = "iz";
329 					break;
330 				default:
331 					enc = "latin1";
332 				}
333 				pj_ks (pj, "enc", enc);
334 				pj_kb (pj, "ascii", r_str_is_ascii (d->str));
335 			}
336 
337 			pj_end (pj);
338 			break;
339 		case 0:
340 		case 1:
341 		case '*':
342 		default:
343 			switch (d->type) {
344 			case R_META_TYPE_COMMENT:
345 				{
346 				const char *type = r_meta_type_to_string (d->type);
347 				char *s = sdb_encode ((const ut8*)pstr, -1);
348 				if (!s) {
349 					s = strdup (pstr);
350 				}
351 				if (rad) {
352 					if (!strcmp (type, "CCu")) {
353 						a->cb_printf ("%s base64:%s @ 0x%08"PFMT64x"\n",
354 							type, s, start);
355 					} else {
356 						a->cb_printf ("%s %s @ 0x%08"PFMT64x"\n",
357 							type, pstr, start);
358 					}
359 				} else {
360 					if (!strcmp (type, "CCu")) {
361 						char *mys = r_str_escape (pstr);
362 						a->cb_printf ("0x%08"PFMT64x" %s \"%s\"\n",
363 								start, type, mys);
364 						free (mys);
365 					} else {
366 						a->cb_printf ("0x%08"PFMT64x" %s \"%s\"\n",
367 								start, type, pstr);
368 					}
369 				}
370 				free (s);
371 				}
372 				break;
373 			case R_META_TYPE_STRING:
374 				if (rad) {
375 					char cmd[] = "Cs#";
376 					switch (d->subtype) {
377 					case 'a':
378 					case '8':
379 						cmd[2] = d->subtype;
380 						break;
381 					default:
382 						cmd[2] = 0;
383 					}
384 					a->cb_printf ("%s %"PFMT64u" @ 0x%08"PFMT64x" # %s\n",
385 							cmd, size, start, pstr);
386 				} else {
387 					const char *enc;
388 					switch (d->subtype) {
389 					case '8':
390 						enc = "utf8";
391 						break;
392 					default:
393 						enc = r_str_is_ascii (d->str) ? "ascii" : "latin1";
394 					}
395 					if (show_full) {
396 						a->cb_printf ("0x%08"PFMT64x" %s[%"PFMT64u"] \"%s\"\n",
397 						              start, enc, size, pstr);
398 					} else {
399 						a->cb_printf ("%s[%"PFMT64u"] \"%s\"\n",
400 						              enc, size, pstr);
401 					}
402 				}
403 				break;
404 			case R_META_TYPE_HIDE:
405 			case R_META_TYPE_DATA:
406 				if (rad) {
407 					a->cb_printf ("%s %"PFMT64u" @ 0x%08"PFMT64x"\n",
408 							r_meta_type_to_string (d->type),
409 							size, start);
410 				} else {
411 					if (show_full) {
412 						const char *dtype = d->type == 'h' ? "hidden" : "data";
413 						a->cb_printf ("0x%08" PFMT64x " %s %s %"PFMT64u"\n",
414 						              start, dtype,
415 						              r_meta_type_to_string (d->type), size);
416 					} else {
417 						a->cb_printf ("%"PFMT64u"\n", size);
418 					}
419 				}
420 				break;
421 			case R_META_TYPE_MAGIC:
422 			case R_META_TYPE_FORMAT:
423 				if (rad) {
424 					a->cb_printf ("%s %"PFMT64u" %s @ 0x%08"PFMT64x"\n",
425 							r_meta_type_to_string (d->type),
426 							size, pstr, start);
427 				} else {
428 					if (show_full) {
429 						const char *dtype = d->type == 'm' ? "magic" : "format";
430 						a->cb_printf ("0x%08" PFMT64x " %s %"PFMT64u" %s\n",
431 						              start, dtype, size, pstr);
432 					} else {
433 						a->cb_printf ("%"PFMT64u" %s\n", size, pstr);
434 					}
435 				}
436 				break;
437 			case R_META_TYPE_VARTYPE:
438 				if (rad) {
439 					a->cb_printf ("%s %s @ 0x%08"PFMT64x"\n",
440 						r_meta_type_to_string (d->type), pstr, start);
441 				} else {
442 					a->cb_printf ("0x%08"PFMT64x" %s\n", start, pstr);
443 				}
444 				break;
445 			case R_META_TYPE_HIGHLIGHT:
446 				{
447 					ut8 r = 0, g = 0, b = 0, A = 0;
448 					const char *esc = strchr (d->str, '\x1b');
449 					r_cons_rgb_parse (esc, &r, &g, &b, &A);
450 					a->cb_printf ("%s rgb:%02x%02x%02x @ 0x%08"PFMT64x"\n",
451 						r_meta_type_to_string (d->type), r, g, b, start);
452 					// TODO: d->size
453 				}
454 				break;
455 			default:
456 				if (rad) {
457 					a->cb_printf ("%s %"PFMT64u" 0x%08"PFMT64x" # %s\n",
458 						r_meta_type_to_string (d->type),
459 						size, start, pstr);
460 				} else {
461 					// TODO: use b64 here
462 					a->cb_printf ("0x%08"PFMT64x" array[%"PFMT64u"] %s %s\n",
463 						start, size,
464 						r_meta_type_to_string (d->type), pstr);
465 				}
466 				break;
467 			}
468 			break;
469 		}
470 		if (str) {
471 			free (str);
472 		}
473 	}
474 }
475 
r_meta_print_list_at(RAnal * a,ut64 addr,int rad,const char * tq)476 R_API void r_meta_print_list_at(RAnal *a, ut64 addr, int rad, const char *tq) {
477 	RPVector *nodes = collect_nodes_at (a, R_META_TYPE_ANY, r_spaces_current (&a->meta_spaces), addr);
478 	if (!nodes) {
479 		return;
480 	}
481 	void **it;
482 	r_pvector_foreach (nodes, it) {
483 		RIntervalNode *node = *it;
484 		r_meta_print (a, node->data, node->start, r_meta_node_size (node), rad, NULL, true);
485 	}
486 	r_pvector_free (nodes);
487 }
488 
print_meta_list(RAnal * a,int type,int rad,ut64 addr,const char * tq)489 static void print_meta_list(RAnal *a, int type, int rad, ut64 addr, const char *tq) {
490 	PJ *pj = NULL;
491 	RTable *t = NULL;
492 	if (rad == ',') {
493 		t = r_table_new ("meta");
494 		RTableColumnType *s = r_table_type ("string");
495 		RTableColumnType *n = r_table_type ("number");
496 		r_table_add_column (t, n, "addr", 0);
497 		r_table_add_column (t, n, "size", 0);
498 		r_table_add_column (t, s, "type", 0);
499 		r_table_add_column (t, s, "string", 0);
500 	} else if (rad == 'j') {
501 		pj = pj_new ();
502 		if (!pj) {
503 			return;
504 		}
505 		pj_a (pj);
506 	}
507 
508 	RAnalFunction *fcn = NULL;
509 	if (addr != UT64_MAX) {
510 		fcn = r_anal_get_fcn_in (a, addr, 0);
511 		if (!fcn) {
512 			goto beach;
513 		}
514 	}
515 
516 	RIntervalTreeIter it;
517 	RAnalMetaItem *item;
518 	r_interval_tree_foreach (&a->meta, it, item) {
519 		RIntervalNode *node = r_interval_tree_iter_get (&it);
520 		if (type != R_META_TYPE_ANY && item->type != type) {
521 			continue;
522 		}
523 		if (fcn && !r_anal_function_contains (fcn, node->start)) {
524 			continue;
525 		}
526 		if (t) {
527 			const char *type = r_meta_type_to_string (item->type);
528 			const char *name = item->str;
529 			r_table_add_rowf (t, "xxss",
530 				node->start,
531 				r_meta_node_size (node),
532 				type, name);
533 		} else {
534 			r_meta_print (a, item, node->start, r_meta_node_size (node), rad, pj, true);
535 		}
536 	}
537 
538 beach:
539 	if (t) {
540 		if (tq) {
541 			r_table_query (t, tq);
542 		}
543 		char *s = r_table_tostring (t);
544 		r_cons_printf ("%s\n", s);
545 		free (s);
546 	} else if (pj) {
547 		pj_end (pj);
548 		r_cons_printf ("%s\n", pj_string (pj));
549 		pj_free (pj);
550 	}
551 }
552 
r_meta_print_list_all(RAnal * a,int type,int rad,const char * tq)553 R_API void r_meta_print_list_all(RAnal *a, int type, int rad, const char *tq) {
554 	print_meta_list (a, type, rad, UT64_MAX, tq);
555 }
556 
r_meta_print_list_in_function(RAnal * a,int type,int rad,ut64 addr,const char * tq)557 R_API void r_meta_print_list_in_function(RAnal *a, int type, int rad, ut64 addr, const char *tq) {
558 	print_meta_list (a, type, rad, addr, tq);
559 }
560 
r_meta_rebase(RAnal * anal,ut64 diff)561 R_API void r_meta_rebase(RAnal *anal, ut64 diff) {
562 	if (!diff) {
563 		return;
564 	}
565 	RIntervalTree old = anal->meta;
566 	r_interval_tree_init (&anal->meta, old.free);
567 	RIntervalTreeIter it;
568 	RAnalMetaItem *item;
569 	r_interval_tree_foreach (&old, it, item) {
570 		RIntervalNode *node = r_interval_tree_iter_get (&it);
571 		ut64 newstart = node->start + diff;
572 		ut64 newend = node->end + diff;
573 		if (newend < newstart) {
574 			// Can't rebase this
575 			newstart = node->start;
576 			newend = node->end;
577 		}
578 		r_interval_tree_insert (&anal->meta, newstart, newend, item);
579 	}
580 	old.free = NULL;
581 	r_interval_tree_fini (&old);
582 }
583 
r_meta_space_unset_for(RAnal * a,const RSpace * space)584 R_API void r_meta_space_unset_for(RAnal *a, const RSpace *space) {
585 	del (a, R_META_TYPE_ANY, space, 0, UT64_MAX);
586 }
587 
r_meta_get_size(RAnal * a,RAnalMetaType type)588 R_API ut64 r_meta_get_size(RAnal *a, RAnalMetaType type) {
589 	ut64 sum = 0;
590 	RIntervalTreeIter it;
591 	RAnalMetaItem *item;
592 	RIntervalNode *prev = NULL;
593 	r_interval_tree_foreach (&a->meta, it, item) {
594 		RIntervalNode *node = r_interval_tree_iter_get (&it);
595 		if (type != R_META_TYPE_ANY && item->type != type) {
596 			continue;
597 		}
598 		ut64 start = R_MAX (prev ? prev->end : 0, node->start);
599 		sum += node->end - start + 1;
600 		prev = node;
601 	}
602 	return sum;
603 }
604 
r_meta_space_count_for(RAnal * a,const RSpace * space)605 R_API int r_meta_space_count_for(RAnal *a, const RSpace *space) {
606 	int r = 0;
607 	RIntervalTreeIter it;
608 	RAnalMetaItem *item;
609 	r_interval_tree_foreach (&a->meta, it, item) {
610 		if (item->space == space) {
611 			r++;
612 		}
613 	}
614 	return r;
615 }
616 
r_meta_set_data_at(RAnal * a,ut64 addr,ut64 wordsz)617 R_API void r_meta_set_data_at(RAnal *a, ut64 addr, ut64 wordsz) {
618 	r_return_if_fail (wordsz);
619 	r_meta_set (a, R_META_TYPE_DATA, addr, wordsz, NULL);
620 }
621