radare2/libr/anal/meta.c

312 lines
6.7 KiB
C

/* radare - LGPL - Copyright 2008-2012 nibble<develsec.org>, pancake<nopcode.org> */
#include <r_anal.h>
R_API RMeta *r_meta_new() {
RMeta *m = R_NEW (RMeta);
if (m) {
m->data = r_list_new ();
m->data->free = r_meta_item_free;
m->printf = (PrintfCallback) printf;
}
return m;
}
R_API void r_meta_free(RMeta *m) {
r_list_free (m->data);
/* TODO: memory leak */
free (m);
}
R_API int r_meta_count(RMeta *m, int type, ut64 from, ut64 to) {
RMetaItem *d;
RListIter *iter;
int count = 0;
r_list_foreach (m->data, iter, d) {
if (d->type == type || type == R_META_TYPE_ANY)
if (from >= d->from && d->to < to)
count++;
}
return count;
}
R_API int r_meta_set_string(RMeta *m, int type, ut64 addr, const char *s) {
RMetaItem *mi = r_meta_find (m, addr, type, R_META_WHERE_HERE);
if (mi) {
free (mi->str);
mi->str = strdup (s);
return R_TRUE;
}
r_meta_add (m, type, addr, addr+1, s);
return R_FALSE;
}
R_API char *r_meta_get_string(RMeta *m, int type, ut64 addr) {
char *str = NULL;
RListIter *iter;
RMetaItem *d;
switch(type) {
case R_META_TYPE_COMMENT:
case R_META_TYPE_ANY:
break;
case R_META_TYPE_CODE:
case R_META_TYPE_DATA:
case R_META_TYPE_STRING:
case R_META_TYPE_FORMAT:
case R_META_TYPE_MAGIC:
/* we should remove overlapped types and so on.. */
return "(Unsupported meta type)";
default:
eprintf ("r_meta_get_string: unhandled meta type\n");
return "(Unhandled meta type)";
}
r_list_foreach (m->data, iter, d) {
if (d->type == type || type == R_META_TYPE_ANY) {
if (d->from == addr)
switch (d->type) {
case R_META_TYPE_COMMENT:
str = r_str_concatf (str, "%s\n", d->str);
break;
}
}
}
return str;
}
R_API int r_meta_del(RMeta *m, int type, ut64 from, ut64 size, const char *str) {
int ret = 0;
RListIter *iter, *iter_tmp;
RMetaItem *d;
r_list_foreach_safe (m->data, iter, iter_tmp, d) {
if (d->type == type || type == R_META_TYPE_ANY) {
if (str != NULL && !strstr (d->str, str))
continue;
if (size==UT64_MAX || (from+size >= d->from && from <= d->to+size)) {
free (d->str);
r_list_delete (m->data, iter);
ret++;
}
}
}
return ret;
}
R_API int r_meta_cleanup(RMeta *m, ut64 from, ut64 to) {
RMetaItem *d;
RListIter *iter;
int ret = R_FALSE;
if (from == 0LL && to == UT64_MAX) {
RMeta *m2 = r_meta_new ();
r_list_free (m->data);
m->data = m2->data;
free (m2);
return R_TRUE;
}
/* No _safe loop necessary because we break immediately after the delete. */
r_list_foreach (m->data, iter, d) {
switch (d->type) {
case R_META_TYPE_CODE:
case R_META_TYPE_DATA:
case R_META_TYPE_STRING:
case R_META_TYPE_FORMAT:
#if 0
|__| |__| |___| |_|
|__| |_| |_| |___|
====== ===== ===== =====
#endif
if (to>d->from && to<d->to) {
d->from = to;
ret= R_TRUE;
} else
if (from>d->from && from<d->to &&to>d->to) {
d->to = from;
ret = R_TRUE;
} else
if (from>d->from&&from<d->to&&to<d->to) {
// XXX split!
d->to = from;
ret = R_TRUE;
} else
if (from>d->from&&to<d->to) {
r_list_delete (m->data, iter);
ret = R_TRUE;
}
break;
}
}
return ret;
}
R_API void r_meta_item_free(void *_item) {
RMetaItem *item = _item;
free (item);
}
R_API RMetaItem *r_meta_item_new(int type) {
RMetaItem *mi = R_NEW (RMetaItem);
memset (mi, 0, sizeof (RMetaItem));
mi->type = type;
return mi;
}
// TODO: This is ultraslow. must accelerate with hashtables
R_API int r_meta_comment_check (RMeta *m, const char *s) {
RMetaItem *d;
RListIter *iter;
r_list_foreach (m->data, iter, d) {
if (d->type == R_META_TYPE_COMMENT && (!strcmp (s, d->str)))
return R_TRUE;
}
return R_FALSE;
}
R_API int r_meta_add(RMeta *m, int type, ut64 from, ut64 to, const char *str) {
RMetaItem *mi;
if (to<from)
to = from+to;
switch (type) {
case R_META_TYPE_CODE:
case R_META_TYPE_DATA:
case R_META_TYPE_STRING:
case R_META_TYPE_FORMAT:
/* we should remove overlapped types and so on.. */
r_meta_cleanup (m, from, to);
case R_META_TYPE_COMMENT:
if (type == R_META_TYPE_COMMENT)
if (r_meta_comment_check (m, str))
return R_FALSE;
mi = r_meta_item_new (type);
mi->size = R_ABS (to-from);//size;
mi->type = type;
mi->from = from;
mi->to = to;
mi->str = str? strdup (str): NULL;
r_list_append (m->data, mi);
break;
default:
eprintf ("r_meta_add: Unsupported type '%c'\n", type);
return R_FALSE;
}
return R_TRUE;
}
/* snippet from data.c */
R_API RMetaItem *r_meta_find(RMeta *m, ut64 off, int type, int where) {
RMetaItem *d, *it = NULL;
RListIter *iter;
r_list_foreach (m->data, iter, d) {
if (d->type == type || type == R_META_TYPE_ANY) {
switch (where) {
case R_META_WHERE_PREV:
if (d->from < off)
it = d;
break;
case R_META_WHERE_HERE:
if (off>=d->from && (!off || (off<d->to)))
it = d;
break;
case R_META_WHERE_NEXT:
if (d->from > off)
it = d;
break;
}
}
}
return it;
}
#if 0
/* not necessary */
//int data_get_fun_for(ut64 addr, ut64 *from, ut64 *to)
int r_meta_get_bounds(RMeta *m, ut64 addr, int type, ut64 *from, ut64 *to)
{
struct list_head *pos;
int n_functions = 0;
int n_xrefs = 0;
int n_dxrefs = 0;
struct r_meta_item_t *rd = NULL;
ut64 lastfrom = 0LL;
list_for_each(pos, &m->data) {
struct r_meta_item_t *d = (struct r_meta_item_t *)
list_entry(pos, struct r_meta_item_t, list);
if (d->type == type) {
if (d->from < addr && d->from > lastfrom)
rd = d;
}
}
if (rd) {
*from = rd->from;
*to = rd->to;
return 1;
}
return 0;
}
#endif
R_API const char *r_meta_type_to_string(int type) {
// XXX: use type as '%c'
switch(type) {
case R_META_TYPE_CODE: return "Cc";
case R_META_TYPE_DATA: return "Cd";
case R_META_TYPE_STRING: return "Cs";
case R_META_TYPE_FORMAT: return "Cf";
case R_META_TYPE_COMMENT: return "CC";
}
return "(...)";
}
#if 0
#include <r_util.h>
struct r_range_t *r_meta_ranges(RMeta *m)
{
struct r_range_t *r;
struct list_head *pos;
r = r_range_new();
list_for_each(pos, &m->data) {
struct r_meta_item_t *d = (struct r_meta_item_t *)
list_entry(pos, struct r_meta_item_t, list);
r_range_add(r, d->from, d->to, 1); //d->type);
}
return r;
}
#endif
static void printmetaitem(RMeta *m, RMetaItem *d, int rad) {
char *str = r_str_unscape (d->str);
if (str) {
if (d->type=='s' && !*str)
return;
r_str_sanitize (str);
if (rad)
m->printf ("%s %d %s @ 0x%08"PFMT64x"\n",
r_meta_type_to_string (d->type),
(int)(d->to-d->from), str, d->from);
else
m->printf ("0x%08"PFMT64x" %s\n",
d->from, str);
free (str);
}
}
// TODO: Deprecate
R_API int r_meta_list(RMeta *m, int type, int rad) {
int count = 0;
RListIter *iter;
RMetaItem *d;
r_list_foreach (m->data, iter, d) {
if (d->type == type || type == R_META_TYPE_ANY) {
printmetaitem (m, d, rad);
count++;
}
}
return count;
}