radare2/libr/anal/xrefs.c

237 lines
6.0 KiB
C
Raw Normal View History

/* radare - LGPL - Copyright 2009-2016 - pancake, nibble */
#include <r_anal.h>
#include <sdb.h>
#define DB anal->sdb_xrefs
static const char *analref_toString(RAnalRefType type) {
switch (type) {
case R_ANAL_REF_TYPE_NULL:
/* do nothing */
break;
case R_ANAL_REF_TYPE_CODE:
return "code.jmp";
case R_ANAL_REF_TYPE_CALL:
return "code.call";
case R_ANAL_REF_TYPE_DATA:
return "data.mem";
case R_ANAL_REF_TYPE_STRING:
return "data.string";
}
return "unk";
}
static void XREFKEY(char * const key, const size_t key_len,
char const * const kind, const RAnalRefType type, const ut64 addr) {
char const * _sdb_type = analref_toString (type);
snprintf (key, key_len, "%s.%s.0x%"PFMT64x, kind, _sdb_type, addr);
}
2016-06-13 23:40:46 +00:00
R_API bool r_anal_xrefs_save(RAnal *anal, const char *prjfile) {
sdb_file (anal->sdb_xrefs, prjfile);
2016-06-13 23:40:46 +00:00
return sdb_sync (anal->sdb_xrefs);
}
R_API int r_anal_xrefs_set (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to) {
char key[33];
if (!anal || !DB) {
2015-09-14 00:08:31 +00:00
return false;
}
if (!anal->iob.is_valid_offset (anal->iob.io, to, 0)) {
return false;
}
2014-10-20 23:02:25 +00:00
// unknown refs should not be stored. seems wrong
if (type == R_ANAL_REF_TYPE_NULL) {
2015-09-14 00:08:31 +00:00
return false;
2014-10-20 23:02:25 +00:00
}
XREFKEY (key, sizeof (key), "ref", type, from);
2014-03-26 03:16:03 +00:00
sdb_array_add_num (DB, key, to, 0);
XREFKEY (key, sizeof (key), "xref", type, to);
2014-03-26 03:16:03 +00:00
sdb_array_add_num (DB, key, from, 0);
2015-09-14 00:08:31 +00:00
return true;
}
R_API int r_anal_xrefs_deln (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to) {
char key[33];
if (!anal || !DB) {
2015-09-14 00:08:31 +00:00
return false;
}
XREFKEY (key, sizeof (key), "ref", type, from);
sdb_array_remove_num (DB, key, to, 0);
XREFKEY (key, sizeof (key), "xref", type, to);
sdb_array_remove_num (DB, key, from, 0);
2015-09-14 00:08:31 +00:00
return true;
}
static int _type = -1;
static RList *_list = NULL;
static char *_kpfx = NULL;
static int xrefs_list_cb_any(RAnal *anal, const char *k, const char *v) {
//ut64 dst, src = r_num_get (NULL, v);
if (!strncmp (_kpfx, k, strlen (_kpfx))) {
RAnalRef *ref = r_anal_ref_new ();
if (ref) {
ref->addr = r_num_get (NULL, k + strlen (_kpfx) + 1);
ref->at = r_num_get (NULL, v); // XXX
ref->type = _type;
r_list_append (_list, ref);
}
}
return true;
}
R_API int r_anal_xrefs_from (RAnal *anal, RList *list, const char *kind, const RAnalRefType type, ut64 addr) {
char *next, *s, *str, *ptr, key[256];
RAnalRef *ref = NULL;
if (addr == UT64_MAX) {
_type = type;
_list = list;
_kpfx = r_str_newf ("xref.%s", analref_toString (type));
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_any, anal);
free (_kpfx);
return true;
}
XREFKEY(key, sizeof (key), kind, type, addr);
str = sdb_get (DB, key, 0);
if (!str) {
return false;
}
for (next = ptr = str; next; ptr = next) {
2014-03-26 03:16:03 +00:00
s = sdb_anext (ptr, &next);
if (!(ref = r_anal_ref_new ())) {
2015-09-14 00:08:31 +00:00
return false;
}
ref->addr = r_num_get (NULL, s);
ref->at = addr;
ref->type = type;
r_list_append (list, ref);
}
free (str);
2015-09-14 00:08:31 +00:00
return true;
}
R_API RList *r_anal_xrefs_get (RAnal *anal, ut64 to) {
RList *list = r_list_new ();
if (!list) {
return NULL;
}
list->free = NULL; // XXX
r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_NULL, to);
r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_CODE, to);
r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_CALL, to);
r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_DATA, to);
r_anal_xrefs_from (anal, list, "xref", R_ANAL_REF_TYPE_STRING, to);
2014-10-20 23:02:25 +00:00
if (r_list_empty (list)) {
r_list_free (list);
list = NULL;
}
return list;
}
R_API RList *r_anal_xrefs_get_from (RAnal *anal, ut64 to) {
RList *list = r_list_new ();
2015-06-20 11:38:11 +00:00
if (!list) return NULL;
list->free = NULL; // XXX
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_NULL, to);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CODE, to);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CALL, to);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_DATA, to);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_STRING, to);
if (r_list_length (list)<1) {
r_list_free (list);
list = NULL;
}
return list;
}
2016-06-13 23:40:46 +00:00
R_API bool r_anal_xrefs_init (RAnal *anal) {
sdb_reset (DB);
2016-06-13 23:40:46 +00:00
if (DB) {
sdb_array_set (DB, "types", -1, "code.jmp,code.call,data.mem,data.string", 0);
return true;
}
return false;
}
static int xrefs_list_cb_rad(RAnal *anal, const char *k, const char *v) {
ut64 dst, src = r_num_get (NULL, v);
if (!strncmp (k, "ref.", 4)) {
const char *p = r_str_rchr (k, NULL, '.');
if (p) {
dst = r_num_get (NULL, p + 1);
anal->cb_printf ("ax 0x%"PFMT64x" 0x%"PFMT64x"\n", src, dst);
}
}
return 1;
}
static int xrefs_list_cb_json(RAnal *anal, const char *k, const char *v) {
ut64 dst, src = r_num_get (NULL, v);
if (!strncmp (k, "ref.", 4) && (strlen (k) > 8)) {
const char *p = r_str_rchr (k, NULL, '.');
if (p) {
dst = r_num_get (NULL, p + 1);
sscanf (p + 1, "0x%"PFMT64x, &dst);
anal->cb_printf ("%"PFMT64d":%"PFMT64d",", src, dst);
}
}
return 1;
}
static int xrefs_list_cb_plain(RAnal *anal, const char *k, const char *v) {
anal->cb_printf ("%s=%s\n", k, v);
return 1;
}
R_API void r_anal_xrefs_list(RAnal *anal, int rad) {
switch (rad) {
case 1:
case '*':
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_rad, anal);
break;
case 'j':
anal->cb_printf ("{");
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_json, anal);
anal->cb_printf ("}\n");
break;
default:
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_plain, anal);
break;
}
}
R_API const char *r_anal_xrefs_type_tostring (char type) {
switch (type) {
case R_ANAL_REF_TYPE_CODE:
return "JMP";
case R_ANAL_REF_TYPE_CALL:
return "CALL";
case R_ANAL_REF_TYPE_DATA:
return "DATA";
case R_ANAL_REF_TYPE_STRING:
return "STRING";
2014-09-24 11:03:03 +00:00
case R_ANAL_REF_TYPE_NULL:
default:
return "UNKNOWN";
}
}
2016-03-28 23:13:00 +00:00
typedef struct {
RAnal *anal;
int count;
} CountState;
static int countcb(CountState *cs, const char *k, const char *v) {
if (!strncmp (k, "ref.", 4))
cs->count ++;
return 1;
}
R_API int r_anal_xrefs_count(RAnal *anal) {
CountState cs = { anal, 0 };
sdb_foreach (DB, (SdbForeachCallback)countcb, &cs);
return cs.count;
}