2014-01-19 23:14:00 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2014 - pancake, nibble */
|
2013-04-18 01:58:44 +00:00
|
|
|
|
|
|
|
#include <r_anal.h>
|
|
|
|
#include <sdb.h>
|
|
|
|
|
|
|
|
#define DB anal->sdb_xrefs
|
|
|
|
|
2014-06-18 23:11:53 +00:00
|
|
|
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 = "unk";
|
|
|
|
switch (type) {
|
|
|
|
case R_ANAL_REF_TYPE_NULL:
|
|
|
|
_sdb_type = "unk";
|
|
|
|
break;
|
|
|
|
case R_ANAL_REF_TYPE_CODE:
|
|
|
|
_sdb_type = "code.jmp";
|
|
|
|
break;
|
|
|
|
case R_ANAL_REF_TYPE_CALL:
|
|
|
|
_sdb_type = "code.call";
|
|
|
|
break;
|
|
|
|
case R_ANAL_REF_TYPE_DATA:
|
|
|
|
_sdb_type = "data.mem";
|
|
|
|
break;
|
|
|
|
case R_ANAL_REF_TYPE_STRING:
|
|
|
|
_sdb_type = "data.string";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
snprintf (key, key_len, "%s.%s.0x%"PFMT64x, kind, _sdb_type, addr);
|
2014-05-05 15:31:10 +00:00
|
|
|
}
|
|
|
|
|
2014-09-21 23:39:24 +00:00
|
|
|
R_API int r_anal_xrefs_load(RAnal *anal, const char *prjfile) {
|
2014-05-05 15:31:10 +00:00
|
|
|
char *path, *db = r_str_newf (R2_HOMEDIR"/projects/%s.d", prjfile);
|
2014-09-21 23:39:24 +00:00
|
|
|
if (!db) return R_FALSE;
|
2013-04-18 01:58:44 +00:00
|
|
|
path = r_str_home (db);
|
2014-09-21 23:39:24 +00:00
|
|
|
if (!path) {
|
|
|
|
free (db);
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
2013-04-18 01:58:44 +00:00
|
|
|
sdb_free (DB);
|
2014-01-23 00:56:35 +00:00
|
|
|
DB = sdb_new (path, "xrefs", 0);
|
2014-09-21 23:39:24 +00:00
|
|
|
if (!DB) {
|
|
|
|
free (db);
|
|
|
|
free (path);
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
2014-03-12 02:23:50 +00:00
|
|
|
sdb_ns_set (anal->sdb, "xrefs", DB);
|
2014-04-24 11:27:52 +00:00
|
|
|
free (path);
|
2013-04-18 01:58:44 +00:00
|
|
|
free (db);
|
2014-09-21 23:39:24 +00:00
|
|
|
return R_TRUE;
|
2013-04-18 01:58:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_anal_xrefs_save(RAnal *anal, const char *prjfile) {
|
|
|
|
sdb_sync (anal->sdb_xrefs);
|
|
|
|
}
|
|
|
|
|
2014-09-21 23:39:24 +00:00
|
|
|
R_API int r_anal_xrefs_set (RAnal *anal, const RAnalRefType type,
|
2014-05-05 15:31:10 +00:00
|
|
|
ut64 from, ut64 to) {
|
2013-04-18 01:58:44 +00:00
|
|
|
char key[32];
|
2014-09-21 23:39:24 +00:00
|
|
|
if (!anal || !DB)
|
|
|
|
return R_FALSE;
|
2014-06-18 23:11:53 +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);
|
2014-06-18 23:11:53 +00:00
|
|
|
XREFKEY (key, sizeof (key), "xref", type, to);
|
2014-03-26 03:16:03 +00:00
|
|
|
sdb_array_add_num (DB, key, from, 0);
|
2014-09-21 23:39:24 +00:00
|
|
|
return R_TRUE;
|
2013-04-18 01:58:44 +00:00
|
|
|
}
|
|
|
|
|
2014-09-21 23:39:24 +00:00
|
|
|
R_API int r_anal_xrefs_deln (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to) {
|
2013-04-18 01:58:44 +00:00
|
|
|
char key[32];
|
2014-09-21 23:39:24 +00:00
|
|
|
if (!anal || !DB)
|
|
|
|
return R_FALSE;
|
2014-06-18 23:11:53 +00:00
|
|
|
XREFKEY (key, sizeof (key), "ref", type, from);
|
2014-03-31 02:42:55 +00:00
|
|
|
sdb_array_remove_num (DB, key, to, 0);
|
2014-06-18 23:11:53 +00:00
|
|
|
XREFKEY (key, sizeof (key), "xref", type, to);
|
2014-05-05 15:31:10 +00:00
|
|
|
sdb_array_remove_num (DB, key, from, 0);
|
2014-09-21 23:39:24 +00:00
|
|
|
return R_TRUE;
|
2013-04-18 01:58:44 +00:00
|
|
|
}
|
|
|
|
|
2014-09-03 21:40:57 +00:00
|
|
|
R_API int r_anal_xrefs_from (RAnal *anal, RList *list, const char *kind, const RAnalRefType type, ut64 addr) {
|
2014-03-06 01:31:31 +00:00
|
|
|
char *next, *s, *str, *ptr, key[256];
|
2013-07-19 01:35:45 +00:00
|
|
|
RAnalRef *ref = NULL;
|
2014-06-18 23:11:53 +00:00
|
|
|
XREFKEY(key, sizeof (key), kind, type, addr);
|
2013-07-19 01:35:45 +00:00
|
|
|
str = sdb_get (DB, key, 0);
|
|
|
|
if (!str) return R_FALSE;
|
2014-03-06 01:31:31 +00:00
|
|
|
for (ptr=str; ; ptr = next) {
|
2014-03-26 03:16:03 +00:00
|
|
|
s = sdb_anext (ptr, &next);
|
2013-07-19 01:35:45 +00:00
|
|
|
if (!(ref = r_anal_ref_new ()))
|
|
|
|
return R_FALSE;
|
2014-05-05 15:31:10 +00:00
|
|
|
ref->addr = r_num_get (NULL, s);
|
|
|
|
ref->at = addr;
|
|
|
|
ref->type = type;
|
2013-07-19 01:35:45 +00:00
|
|
|
r_list_append (list, ref);
|
2014-03-06 01:31:31 +00:00
|
|
|
if (!next)
|
|
|
|
break;
|
2013-07-19 01:35:45 +00:00
|
|
|
}
|
|
|
|
free (str);
|
|
|
|
return R_TRUE;
|
2013-04-18 01:58:44 +00:00
|
|
|
}
|
|
|
|
|
2014-05-05 15:31:10 +00:00
|
|
|
R_API RList *r_anal_xrefs_get (RAnal *anal, ut64 to) {
|
2013-04-18 01:58:44 +00:00
|
|
|
RList *list = r_list_new ();
|
|
|
|
list->free = NULL; // XXX
|
2014-05-05 15:31:10 +00:00
|
|
|
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);
|
2013-04-18 01:58:44 +00:00
|
|
|
if (r_list_length (list)<1) {
|
|
|
|
r_list_free (list);
|
|
|
|
list = NULL;
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2014-09-03 21:40:57 +00:00
|
|
|
R_API RList *r_anal_xrefs_get_from (RAnal *anal, ut64 to) {
|
|
|
|
RList *list = r_list_new ();
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2014-09-21 23:39:24 +00:00
|
|
|
R_API int r_anal_xrefs_init (RAnal *anal) {
|
2014-03-12 02:23:50 +00:00
|
|
|
sdb_reset (DB);
|
2014-09-21 23:39:24 +00:00
|
|
|
if (!DB) return R_FALSE;
|
2014-05-05 15:31:10 +00:00
|
|
|
sdb_array_set (DB, "types", -1, "code.jmp,code.call,data.mem,data.string", 0);
|
2014-09-21 23:39:24 +00:00
|
|
|
return R_TRUE;
|
2013-04-18 01:58:44 +00:00
|
|
|
}
|
2013-07-19 01:35:45 +00:00
|
|
|
|
2014-03-08 00:06:31 +00:00
|
|
|
static int xrefs_list_cb_rad(RAnal *anal, const char *k, const char *v) {
|
2013-10-24 11:59:19 +00:00
|
|
|
ut64 dst, src = r_num_get (NULL, v);
|
|
|
|
if (!strncmp (k, "ref.", 4)) {
|
|
|
|
char *p = strchr (k+4, '.');
|
|
|
|
if (p) {
|
|
|
|
dst = r_num_get (NULL, p+1);
|
2014-06-18 23:11:53 +00:00
|
|
|
anal->printf ("ax 0x%"PFMT64x" 0x%"PFMT64x"\n", src, dst);
|
2013-10-24 11:59:19 +00:00
|
|
|
}
|
|
|
|
}
|
2014-03-08 00:06:31 +00:00
|
|
|
return 1;
|
2013-10-24 11:59:19 +00:00
|
|
|
}
|
2013-07-19 01:35:45 +00:00
|
|
|
|
2014-03-08 00:06:31 +00:00
|
|
|
static int xrefs_list_cb_json(RAnal *anal, const char *k, const char *v) {
|
2013-10-24 11:59:19 +00:00
|
|
|
ut64 dst, src = r_num_get (NULL, v);
|
|
|
|
if (!strncmp (k, "ref.", 4) && (strlen (k)>8)) {
|
|
|
|
char *p = strchr (k+4, '.');
|
|
|
|
if (p) {
|
|
|
|
dst = r_num_get (NULL, p+1);
|
|
|
|
sscanf (p+1, "0x%"PFMT64x, &dst);
|
|
|
|
anal->printf ("%"PFMT64d":%"PFMT64d",", src, dst);
|
|
|
|
}
|
|
|
|
}
|
2014-03-08 00:06:31 +00:00
|
|
|
return 1;
|
2013-10-24 11:59:19 +00:00
|
|
|
}
|
|
|
|
|
2014-03-08 00:06:31 +00:00
|
|
|
static int xrefs_list_cb_plain(RAnal *anal, const char *k, const char *v) {
|
2013-10-24 11:59:19 +00:00
|
|
|
anal->printf ("%s=%s\n", k, v);
|
2014-03-08 00:06:31 +00:00
|
|
|
return 1;
|
2013-10-24 11:59:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_anal_xrefs_list(RAnal *anal, int rad) {
|
|
|
|
switch (rad) {
|
|
|
|
case 1:
|
|
|
|
case '*':
|
2014-02-19 04:02:59 +00:00
|
|
|
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_rad, anal);
|
2013-10-24 11:59:19 +00:00
|
|
|
break;
|
|
|
|
case 'j':
|
|
|
|
anal->printf ("{");
|
2014-02-20 01:11:04 +00:00
|
|
|
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_json, anal);
|
2013-10-24 11:59:19 +00:00
|
|
|
anal->printf ("}\n");
|
|
|
|
break;
|
|
|
|
default:
|
2014-02-20 01:11:04 +00:00
|
|
|
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_plain, anal);
|
2013-10-24 11:59:19 +00:00
|
|
|
break;
|
2013-07-19 01:35:45 +00:00
|
|
|
}
|
|
|
|
}
|
2014-09-23 08:15:19 +00:00
|
|
|
|
|
|
|
R_API const char *r_anal_xrefs_type_tostring (char type) {
|
|
|
|
switch (type) {
|
|
|
|
case R_ANAL_REF_TYPE_NULL:
|
|
|
|
return "UNKNOWN";
|
|
|
|
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";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|