2014-01-15 00:56:28 +00:00
|
|
|
/* radare - LGPL - Copyright 2008-2014 - nibble, pancake */
|
2009-02-15 00:48:11 +00:00
|
|
|
|
2014-03-04 11:23:52 +00:00
|
|
|
// TODO: rename to r_anal_meta_get() ??
|
2014-03-04 17:36:04 +00:00
|
|
|
#if 0
|
|
|
|
TODO
|
|
|
|
====
|
|
|
|
- handle sync to synchronize all the data on disk.
|
|
|
|
- actually listing only works in memory
|
|
|
|
- array_add doesnt needs index, right?
|
2014-05-08 21:20:42 +00:00
|
|
|
- remove unused arguments from r_meta_find (where ?)
|
2014-03-04 17:36:04 +00:00
|
|
|
- implement r_meta_find
|
|
|
|
#endif
|
|
|
|
|
2011-03-01 18:06:22 +00:00
|
|
|
#include <r_anal.h>
|
2013-02-12 01:42:34 +00:00
|
|
|
#include <r_print.h>
|
2009-02-15 00:48:11 +00:00
|
|
|
|
2014-03-04 11:23:52 +00:00
|
|
|
#define META_RANGE_BASE(x) ((x)>>12)
|
|
|
|
#define META_RANGE_SIZE 0xfff
|
|
|
|
#undef DB
|
|
|
|
#define DB a->sdb_meta
|
2014-03-12 01:44:49 +00:00
|
|
|
|
|
|
|
static char *meta_inrange_get (RAnal *a, ut64 addr, int size) {
|
2014-03-04 11:23:52 +00:00
|
|
|
char key[64];
|
|
|
|
ut64 base, base2;
|
|
|
|
base = META_RANGE_BASE (addr);
|
|
|
|
base2 = META_RANGE_BASE (addr+size);
|
|
|
|
// return string array of all the offsets where there are stuff
|
|
|
|
for (; base<base2; base += META_RANGE_SIZE) {
|
|
|
|
snprintf (key, sizeof (key)-1, "range.0x%"PFMT64x, base);
|
|
|
|
sdb_array_get (DB, key, 0, 0);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int meta_inrange_add (RAnal *a, ut64 addr, int size) {
|
|
|
|
int set = 0;
|
|
|
|
char key[64];
|
|
|
|
ut64 base, base2;
|
|
|
|
base = META_RANGE_BASE (addr);
|
|
|
|
base2 = META_RANGE_BASE (addr+size);
|
|
|
|
for (; base<base2; base += META_RANGE_SIZE) {
|
|
|
|
snprintf (key, sizeof (key)-1, "range.0x%"PFMT64x, base);
|
2014-03-26 03:16:03 +00:00
|
|
|
if (sdb_array_add_num (DB, key, addr, 0))
|
2014-03-04 11:23:52 +00:00
|
|
|
set = 1;
|
|
|
|
}
|
|
|
|
return set;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int meta_inrange_del (RAnal *a, ut64 addr, int size) {
|
|
|
|
int set = 0;
|
|
|
|
char key[64];
|
|
|
|
ut64 base, base2;
|
|
|
|
base = META_RANGE_BASE (addr);
|
|
|
|
base2 = META_RANGE_BASE (addr+size);
|
|
|
|
// TODO: optimize this thing?
|
|
|
|
for (; base<base2; base += META_RANGE_SIZE) {
|
|
|
|
snprintf (key, sizeof (key)-1, "range.0x%"PFMT64x, base);
|
2014-03-31 02:42:55 +00:00
|
|
|
if (sdb_array_remove_num (DB, key, addr, 0))
|
2014-03-04 11:23:52 +00:00
|
|
|
set = 1;
|
|
|
|
}
|
|
|
|
//sdb_array_del (DB);
|
|
|
|
return set;
|
|
|
|
}
|
2009-02-15 00:48:11 +00:00
|
|
|
|
2014-03-04 11:23:52 +00:00
|
|
|
// TODO: Add APIs to resize meta? nope, just del and add
|
2014-03-12 01:44:49 +00:00
|
|
|
R_API int r_meta_set_string(RAnal *a, int type, ut64 addr, const char *s) {
|
2014-03-04 11:23:52 +00:00
|
|
|
char key[100], val[2048], *e_str;
|
|
|
|
int ret;
|
|
|
|
ut64 size;
|
|
|
|
snprintf (key, sizeof (key)-1, "meta.%c", type);
|
2014-03-26 03:16:03 +00:00
|
|
|
sdb_array_add_num (DB, key, addr, 0);
|
2014-03-04 11:23:52 +00:00
|
|
|
snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x, type, addr);
|
|
|
|
size = sdb_array_get_num (DB, key, 0, 0);
|
|
|
|
if (!size) {
|
|
|
|
size = strlen (s);
|
2014-03-12 01:44:49 +00:00
|
|
|
meta_inrange_add (a, addr, size);
|
2014-03-04 11:23:52 +00:00
|
|
|
ret = R_TRUE;
|
|
|
|
} else ret = R_FALSE;
|
2014-03-31 01:05:48 +00:00
|
|
|
e_str = sdb_encode ((const void*)s, -1);
|
2014-03-04 11:23:52 +00:00
|
|
|
snprintf (val, sizeof (val)-1, "%d,%s", (int)size, e_str);
|
|
|
|
sdb_set (DB, key, val, 0);
|
|
|
|
free ((void*)e_str);
|
|
|
|
return ret;
|
2011-05-21 12:27:46 +00:00
|
|
|
}
|
|
|
|
|
2014-03-12 01:44:49 +00:00
|
|
|
R_API char *r_meta_get_string(RAnal *a, int type, ut64 addr) {
|
2014-03-04 11:23:52 +00:00
|
|
|
char key[100];
|
|
|
|
const char *k, *p;
|
|
|
|
snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x, 'C', addr);
|
|
|
|
k = sdb_const_get (DB, key, NULL);
|
|
|
|
if (!k) return NULL;
|
|
|
|
p = strchr (k, SDB_RS);
|
|
|
|
if (!p) return NULL;
|
|
|
|
k = p+1;
|
|
|
|
// TODO : comment append has been deprecated
|
|
|
|
return (char *)sdb_decode (k, NULL);
|
2009-02-16 02:14:19 +00:00
|
|
|
}
|
|
|
|
|
2014-03-04 11:23:52 +00:00
|
|
|
R_API int r_meta_del(RAnal *a, int type, ut64 addr, ut64 size, const char *str) {
|
2014-03-06 01:31:31 +00:00
|
|
|
char key[100], key2[100], *dtr, *s, *p, *next;
|
2014-03-04 11:23:52 +00:00
|
|
|
const char *ptr;
|
2014-03-06 01:31:31 +00:00
|
|
|
int i;
|
2014-03-04 11:23:52 +00:00
|
|
|
if (size == UT64_MAX) {
|
|
|
|
// FULL CLEANUP
|
|
|
|
// XXX: this thing ignores the type
|
|
|
|
if (type == R_META_TYPE_ANY) {
|
|
|
|
sdb_reset (DB);
|
|
|
|
} else {
|
|
|
|
snprintf (key, sizeof (key)-1, "meta.%c", type);
|
|
|
|
dtr = sdb_get (DB, key, 0);
|
2014-03-06 01:31:31 +00:00
|
|
|
for (p = dtr; p; p = next) {
|
2014-03-26 03:16:03 +00:00
|
|
|
s = sdb_anext (p, &next);
|
2014-03-06 01:31:31 +00:00
|
|
|
snprintf (key, sizeof (key)-1,
|
|
|
|
"meta.%c.0x%"PFMT64x,
|
2014-03-04 11:23:52 +00:00
|
|
|
type, sdb_atoi (s));
|
|
|
|
eprintf ("--> %s\n", key);
|
|
|
|
sdb_unset (DB, key, 0);
|
2014-03-06 01:31:31 +00:00
|
|
|
if (!next) break;
|
2014-03-04 11:23:52 +00:00
|
|
|
}
|
|
|
|
free (dtr);
|
|
|
|
}
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
meta_inrange_del (a, addr, size);
|
2014-05-06 16:17:54 +00:00
|
|
|
snprintf (key, sizeof (key)-1, type==R_META_TYPE_COMMENT ? "meta.C.0x%"PFMT64x : "meta.0x%"PFMT64x, addr);
|
2014-03-04 11:23:52 +00:00
|
|
|
ptr = sdb_const_get (DB, key, 0);
|
2014-03-05 02:52:42 +00:00
|
|
|
if (ptr) {
|
|
|
|
for (i=0; ptr[i]; i++) {
|
|
|
|
if (ptr[i] != SDB_RS) {
|
2014-03-06 01:31:31 +00:00
|
|
|
snprintf (key2, sizeof (key2)-1,
|
|
|
|
"meta.%c.0x%"PFMT64x, ptr[i], addr);
|
2014-03-05 02:52:42 +00:00
|
|
|
sdb_unset (DB, key2, 0);
|
|
|
|
}
|
2014-03-04 11:23:52 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
sdb_unset (DB, key, 0);
|
|
|
|
return R_FALSE;
|
2009-02-16 02:14:19 +00:00
|
|
|
}
|
|
|
|
|
2014-01-23 02:28:25 +00:00
|
|
|
R_API int r_meta_cleanup(RAnal *a, ut64 from, ut64 to) {
|
2014-04-21 20:17:22 +00:00
|
|
|
return r_meta_del (a, R_META_TYPE_ANY, from, (to-from), NULL);
|
2009-02-16 10:24:45 +00:00
|
|
|
}
|
|
|
|
|
2010-06-27 22:43:07 +00:00
|
|
|
R_API void r_meta_item_free(void *_item) {
|
2014-01-23 03:34:59 +00:00
|
|
|
RAnalMetaItem *item = _item;
|
2010-06-27 22:43:07 +00:00
|
|
|
free (item);
|
|
|
|
}
|
|
|
|
|
2014-01-23 03:34:59 +00:00
|
|
|
R_API RAnalMetaItem *r_meta_item_new(int type) {
|
|
|
|
RAnalMetaItem *mi = R_NEW (RAnalMetaItem);
|
|
|
|
memset (mi, 0, sizeof (RAnalMetaItem));
|
2010-06-27 22:43:07 +00:00
|
|
|
mi->type = type;
|
|
|
|
return mi;
|
|
|
|
}
|
|
|
|
|
2014-03-12 01:44:49 +00:00
|
|
|
R_API int r_meta_add(RAnal *a, int type, ut64 from, ut64 to, const char *str) {
|
2014-05-22 00:15:26 +00:00
|
|
|
int exists;
|
2014-03-04 11:23:52 +00:00
|
|
|
char *e_str, key[100], val[2048];
|
2014-03-04 17:36:04 +00:00
|
|
|
if (from>to)
|
2014-03-04 11:23:52 +00:00
|
|
|
return R_FALSE;
|
2014-03-04 17:36:04 +00:00
|
|
|
if (from == to)
|
|
|
|
to = from+1;
|
2014-05-16 12:56:08 +00:00
|
|
|
if (type == 100) {
|
|
|
|
if ((to-from)<3) {
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
}
|
2014-03-04 11:23:52 +00:00
|
|
|
/* set entry */
|
2014-03-31 01:05:48 +00:00
|
|
|
e_str = sdb_encode ((const void*)str, -1);
|
2014-03-04 11:23:52 +00:00
|
|
|
snprintf (key, sizeof (key)-1, "meta.%c.0x%"PFMT64x, type, from);
|
|
|
|
snprintf (val, sizeof (val)-1, "%d,%s", (int)(to-from), e_str);
|
2014-05-22 00:15:26 +00:00
|
|
|
exists = sdb_exists (DB, key);
|
2014-03-04 11:23:52 +00:00
|
|
|
sdb_set (DB, key, val, 0);
|
|
|
|
free (e_str);
|
|
|
|
|
2014-05-22 00:15:26 +00:00
|
|
|
// XXX: This is totally inefficient, using array_add withuot
|
|
|
|
// checking return value is wrong practice, also it may lead
|
|
|
|
// to inconsistent DB, and pretty bad performance. We should
|
|
|
|
// store this list in a different storage that doesnt have
|
|
|
|
// those limits and it's O(1) instead of O(n)
|
|
|
|
if (!exists) {
|
|
|
|
/* set type index */
|
|
|
|
snprintf (key, sizeof (key)-1, "meta.0x%"PFMT64x, from);
|
|
|
|
snprintf (val, sizeof (val)-1, "%c", type);
|
|
|
|
sdb_array_add (DB, key, val, 0);
|
|
|
|
/* set type index */
|
|
|
|
snprintf (key, sizeof (key)-1, "meta.%c", type);
|
|
|
|
sdb_array_add_num (DB, key, from, 0);
|
|
|
|
}
|
2014-03-04 11:23:52 +00:00
|
|
|
|
|
|
|
return R_TRUE;
|
2009-02-15 00:48:11 +00:00
|
|
|
}
|
|
|
|
|
2014-03-12 01:44:49 +00:00
|
|
|
R_API RAnalMetaItem *r_meta_find(RAnal *a, ut64 off, int type, int where) {
|
2014-03-04 11:23:52 +00:00
|
|
|
static RAnalMetaItem it = {0};
|
|
|
|
// XXX: return allocated item? wtf
|
|
|
|
if (where != R_META_WHERE_HERE) {
|
|
|
|
eprintf ("THIS WAS NOT SUPOSED TO HAPPEN\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
//char *range = get_in_range (off);
|
|
|
|
if (type == R_META_TYPE_ANY) {
|
2014-07-02 15:14:32 +00:00
|
|
|
const char *p;
|
|
|
|
char key [100];
|
2014-03-04 11:23:52 +00:00
|
|
|
snprintf (key, sizeof (key)-1, "meta.0x%"PFMT64x, off);
|
2014-03-08 01:36:33 +00:00
|
|
|
p = sdb_const_get (DB, key, 0);
|
|
|
|
// XXX: TODO unimplemented. see core/disasm.c:1070
|
2014-03-04 11:23:52 +00:00
|
|
|
} else {
|
|
|
|
// snprintf (key, sizeof (key)-1, "meta.
|
|
|
|
}
|
|
|
|
return ⁢
|
2009-02-15 00:48:11 +00:00
|
|
|
}
|
|
|
|
|
2010-06-20 22:48:06 +00:00
|
|
|
R_API const char *r_meta_type_to_string(int type) {
|
|
|
|
// XXX: use type as '%c'
|
2009-02-16 02:14:19 +00:00
|
|
|
switch(type) {
|
2013-03-01 11:20:18 +00:00
|
|
|
case R_META_TYPE_HIDE: return "Ch";
|
2011-03-01 18:06:22 +00:00
|
|
|
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";
|
2014-01-19 23:14:00 +00:00
|
|
|
case R_META_TYPE_MAGIC: return "Cm";
|
2011-03-01 18:06:22 +00:00
|
|
|
case R_META_TYPE_COMMENT: return "CC";
|
2009-02-16 02:14:19 +00:00
|
|
|
}
|
|
|
|
return "(...)";
|
|
|
|
}
|
|
|
|
|
2014-03-12 01:44:49 +00:00
|
|
|
static void printmetaitem(RAnal *a, RAnalMetaItem *d, int rad) {
|
2014-02-23 00:56:26 +00:00
|
|
|
char *pstr, *str = r_str_escape (d->str);
|
2011-05-11 17:19:53 +00:00
|
|
|
if (str) {
|
2014-04-29 00:46:36 +00:00
|
|
|
if (d->type=='s' && !*str) {
|
|
|
|
free (str);
|
2011-06-04 11:29:15 +00:00
|
|
|
return;
|
2014-04-29 00:46:36 +00:00
|
|
|
}
|
2013-05-23 08:33:21 +00:00
|
|
|
if (d->type != 'C') {
|
2013-03-08 00:03:37 +00:00
|
|
|
r_name_filter (str, 0);
|
2013-05-23 08:33:21 +00:00
|
|
|
pstr = str;
|
|
|
|
} else pstr = d->str;
|
2013-03-08 00:03:37 +00:00
|
|
|
// r_str_sanitize (str);
|
2013-03-01 11:20:18 +00:00
|
|
|
switch (rad) {
|
|
|
|
case 'j':
|
2014-03-12 01:44:49 +00:00
|
|
|
a->printf ("{\"offset\":%"PFMT64d", \"type\":\"%s\", \"name\":\"%s\"}",
|
2013-03-01 11:20:18 +00:00
|
|
|
d->from, r_meta_type_to_string (d->type), str);
|
|
|
|
break;
|
|
|
|
case 0:
|
2014-03-12 01:44:49 +00:00
|
|
|
a->printf ("0x%08"PFMT64x" %s\n",
|
2012-02-01 01:22:43 +00:00
|
|
|
d->from, str);
|
2013-03-01 11:20:18 +00:00
|
|
|
case 1:
|
|
|
|
case '*':
|
|
|
|
default:
|
2014-01-20 00:42:16 +00:00
|
|
|
if (d->type == 'C') {
|
2014-03-12 01:44:49 +00:00
|
|
|
a->printf ("\"%s %s\" @ 0x%08"PFMT64x"\n",
|
2014-01-20 00:42:16 +00:00
|
|
|
r_meta_type_to_string (d->type), pstr, d->from);
|
|
|
|
} else {
|
2014-03-12 01:44:49 +00:00
|
|
|
a->printf ("%s %d 0x%08"PFMT64x" # %s\n",
|
2014-05-16 12:56:08 +00:00
|
|
|
r_meta_type_to_string (d->type),
|
|
|
|
d->size, d->from, pstr);
|
2014-01-20 00:42:16 +00:00
|
|
|
}
|
2013-03-01 11:20:18 +00:00
|
|
|
break;
|
|
|
|
}
|
2011-05-11 17:19:53 +00:00
|
|
|
free (str);
|
|
|
|
}
|
2010-06-27 22:43:07 +00:00
|
|
|
}
|
|
|
|
|
2014-03-04 11:23:52 +00:00
|
|
|
typedef struct {
|
|
|
|
RAnal *anal;
|
|
|
|
int type;
|
|
|
|
int rad;
|
|
|
|
} RAnalMetaUserItem;
|
|
|
|
|
|
|
|
static int meta_print_item(void *user, const char *k, const char *v) {
|
|
|
|
RAnalMetaUserItem *ui = user;
|
|
|
|
RAnalMetaItem it;
|
|
|
|
if (strlen (k)<8)
|
2014-03-08 00:06:31 +00:00
|
|
|
return 1;
|
2014-03-04 11:23:52 +00:00
|
|
|
if (k[6]!='.')
|
2014-03-08 00:06:31 +00:00
|
|
|
return 1;
|
2014-03-04 11:23:52 +00:00
|
|
|
it.type = k[5];
|
|
|
|
it.size = sdb_atoi (v);
|
|
|
|
it.from = sdb_atoi (k+7);
|
|
|
|
it.to = it.from + it.size;
|
|
|
|
it.str = strchr (v, ',');
|
|
|
|
if (it.str)
|
|
|
|
it.str = (char *)sdb_decode ((const char*)it.str+1, 0);
|
|
|
|
printmetaitem (ui->anal, &it, ui->rad);
|
|
|
|
free (it.str);
|
2014-03-08 00:06:31 +00:00
|
|
|
return 1;
|
2014-03-04 11:23:52 +00:00
|
|
|
}
|
|
|
|
|
2010-06-25 16:00:17 +00:00
|
|
|
// TODO: Deprecate
|
2014-03-12 01:44:49 +00:00
|
|
|
R_API int r_meta_list(RAnal *a, int type, int rad) {
|
|
|
|
RAnalMetaUserItem ui = { a, type, rad };
|
|
|
|
if (rad=='j') a->printf ("[");
|
2014-03-04 11:23:52 +00:00
|
|
|
sdb_foreach (DB, meta_print_item, &ui);
|
2014-03-12 01:44:49 +00:00
|
|
|
if (rad=='j') a->printf ("]\n");
|
2014-03-04 11:23:52 +00:00
|
|
|
return 0;
|
2009-02-16 02:14:19 +00:00
|
|
|
}
|
2012-11-20 02:59:00 +00:00
|
|
|
|
2014-03-12 01:44:49 +00:00
|
|
|
#if 0
|
2012-11-20 02:59:00 +00:00
|
|
|
R_API char *r_anal_meta_bar (RAnal *anal, ut64 from, ut64 to, int blocks) {
|
2013-01-22 04:06:12 +00:00
|
|
|
int i, n, blocksize;
|
2012-11-20 02:59:00 +00:00
|
|
|
char *res;
|
|
|
|
ut64 f, t;
|
|
|
|
if (blocks<1 || from > to)
|
|
|
|
return NULL;
|
|
|
|
blocksize = (to-from)/blocks;
|
2014-03-04 11:23:52 +00:00
|
|
|
res = malloc (blocks*4);
|
2012-11-20 02:59:00 +00:00
|
|
|
for (i=0; i< blocks; i++) {
|
|
|
|
f = from + (blocksize*i);
|
|
|
|
t = f+blocksize;
|
2013-01-22 04:06:12 +00:00
|
|
|
n = r_anal_fcn_count (anal, f, t);
|
|
|
|
if (n>0) res[i++] = 'f';
|
2012-11-20 02:59:00 +00:00
|
|
|
res[i++] = ',';
|
|
|
|
}
|
|
|
|
return res;
|
|
|
|
}
|
2014-03-12 01:44:49 +00:00
|
|
|
#endif
|