mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-09 15:52:33 +00:00
13547a0bbf
Fix memory leak in r_config_new. cfg->nodes->free should be a custom function that frees RConfigNode structure correctly, but not the ordinary free. Fix memory leak in r_anal_new. In r_anal_free need to call r_meta_free to free the whole RMeta structure, not only it's data list. The r_meta_free doesn't seem to have any leak itself. Fix leaking anal->hints. Fix memory leaks in r_cmd_free Fix memory leak in r_cmd_plugin_init Fix memleak in r_lib_new Fix memory leak in r_io_plugin_init Fix memory leak in r_debug_trace_new Fix memory leaks in r_io_new Fix memory leak in r_graph_new Fix memory leak in r_sys_getdir. Note: calling getcwd with dir=NULL is a Linux-specific extension of POSIX, not sure if works on other non-windows platforms. Fixes a typo
360 lines
7.9 KiB
C
360 lines
7.9 KiB
C
/* radare - LGPL - Copyright 2008-2013 - nibble, pancake */
|
|
|
|
#include <r_anal.h>
|
|
#include <r_print.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);
|
|
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_HIDE:
|
|
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 && d->str && !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 ();
|
|
if (!m2) return R_FALSE;
|
|
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, ut64 addr) {
|
|
RMetaItem *d;
|
|
RListIter *iter;
|
|
|
|
r_list_foreach (m->data, iter, d) {
|
|
if (d->type == R_META_TYPE_COMMENT)
|
|
if (d->from == addr)
|
|
if (!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_HIDE:
|
|
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, from))
|
|
return R_FALSE;
|
|
mi = r_meta_item_new (type);
|
|
mi->size = to-from;
|
|
mi->type = type;
|
|
mi->from = from;
|
|
mi->to = to;
|
|
mi->str = (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;
|
|
}
|
|
if (mi->type == R_META_TYPE_FORMAT)
|
|
mi->size = r_print_format_length (mi->str);
|
|
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_HIDE: return "Ch";
|
|
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 *pstr, *str = r_str_unscape (d->str);
|
|
if (str) {
|
|
if (d->type=='s' && !*str)
|
|
return;
|
|
if (d->type != 'C') {
|
|
r_name_filter (str, 0);
|
|
pstr = str;
|
|
} else pstr = d->str;
|
|
// r_str_sanitize (str);
|
|
switch (rad) {
|
|
case 'j':
|
|
m->printf ("{\"offset\":%"PFMT64d", \"type\":\"%s\", \"name\":\"%s\"}",
|
|
d->from, r_meta_type_to_string (d->type), str);
|
|
break;
|
|
case 0:
|
|
m->printf ("0x%08"PFMT64x" %s\n",
|
|
d->from, str);
|
|
case 1:
|
|
case '*':
|
|
default:
|
|
m->printf ("\"%s %s\" @ 0x%08"PFMT64x"\n",
|
|
r_meta_type_to_string (d->type), pstr, d->from);
|
|
// (int)(d->to-d->from),
|
|
break;
|
|
}
|
|
free (str);
|
|
}
|
|
}
|
|
|
|
// TODO: Deprecate
|
|
R_API int r_meta_list(RMeta *m, int type, int rad) {
|
|
int count = 0;
|
|
RListIter *iter;
|
|
RMetaItem *d;
|
|
if (rad=='j') m->printf ("[");
|
|
r_list_foreach (m->data, iter, d) {
|
|
if (d->type == type || type == R_META_TYPE_ANY) {
|
|
printmetaitem (m, d, rad);
|
|
count++;
|
|
if (rad=='j' && iter->n) m->printf (",");
|
|
}
|
|
}
|
|
if (rad=='j') m->printf ("]\n");
|
|
return count;
|
|
}
|
|
|
|
R_API char *r_anal_meta_bar (RAnal *anal, ut64 from, ut64 to, int blocks) {
|
|
int i, n, blocksize;
|
|
char *res;
|
|
ut64 f, t;
|
|
|
|
if (blocks<1 || from > to)
|
|
return NULL;
|
|
if (from == to && from == 0) {
|
|
// autodetect min and max here
|
|
// from =
|
|
}
|
|
blocksize = (to-from)/blocks;
|
|
res = malloc (blocks*4); //blocksize*5);// use realloc here
|
|
for (i=0; i< blocks; i++) {
|
|
f = from + (blocksize*i);
|
|
t = f+blocksize;
|
|
n = r_anal_fcn_count (anal, f, t);
|
|
if (n>0) res[i++] = 'f';
|
|
res[i++] = ',';
|
|
}
|
|
return res;
|
|
}
|