2022-04-25 20:19:23 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2022 - pancake, nibble, defragger, ret2libc */
|
2013-04-18 01:58:44 +00:00
|
|
|
|
|
|
|
#include <r_anal.h>
|
2016-12-05 17:46:45 +00:00
|
|
|
#include <r_cons.h>
|
2013-04-18 01:58:44 +00:00
|
|
|
|
2018-09-21 22:11:44 +00:00
|
|
|
static RAnalRef *r_anal_ref_new(ut64 addr, ut64 at, ut64 type) {
|
|
|
|
RAnalRef *ref = R_NEW (RAnalRef);
|
2018-02-09 21:25:30 +00:00
|
|
|
if (ref) {
|
2018-09-21 22:11:44 +00:00
|
|
|
ref->addr = addr;
|
|
|
|
ref->at = at;
|
2022-04-25 20:19:23 +00:00
|
|
|
ref->type = (type == UT64_MAX)? R_ANAL_REF_TYPE_CODE: type;
|
2018-02-09 21:25:30 +00:00
|
|
|
}
|
|
|
|
return ref;
|
|
|
|
}
|
|
|
|
|
2018-09-21 22:11:44 +00:00
|
|
|
static void r_anal_ref_free(void *ref) {
|
|
|
|
free (ref);
|
|
|
|
}
|
|
|
|
|
2020-06-14 14:08:32 +00:00
|
|
|
R_API RList *r_anal_ref_list_new(void) {
|
2018-02-09 21:25:30 +00:00
|
|
|
return r_list_newf (r_anal_ref_free);
|
|
|
|
}
|
|
|
|
|
2018-11-14 09:47:28 +00:00
|
|
|
static void xrefs_ht_free(HtUPKv *kv) {
|
|
|
|
ht_up_free (kv->value);
|
2018-02-09 21:25:30 +00:00
|
|
|
}
|
|
|
|
|
2018-11-14 09:47:28 +00:00
|
|
|
static void xrefs_ref_free(HtUPKv *kv) {
|
2018-02-09 21:25:30 +00:00
|
|
|
r_anal_ref_free (kv->value);
|
|
|
|
}
|
|
|
|
|
2018-11-14 09:47:28 +00:00
|
|
|
static bool appendRef(void *u, const ut64 k, const void *v) {
|
|
|
|
RList *list = (RList *)u;
|
|
|
|
RAnalRef *ref = (RAnalRef *)v;
|
2018-09-21 22:11:44 +00:00
|
|
|
RAnalRef *cloned = r_anal_ref_new (ref->addr, ref->at, ref->type);
|
|
|
|
if (cloned) {
|
|
|
|
r_list_append (list, cloned);
|
|
|
|
return true;
|
2017-12-14 11:40:31 +00:00
|
|
|
}
|
2018-09-21 22:11:44 +00:00
|
|
|
return false;
|
2017-12-14 11:40:31 +00:00
|
|
|
}
|
2017-12-11 17:00:14 +00:00
|
|
|
|
2018-11-14 09:47:28 +00:00
|
|
|
static bool mylistrefs_cb(void *list, const ut64 k, const void *v) {
|
|
|
|
HtUP *ht = (HtUP *)v;
|
|
|
|
ht_up_foreach (ht, appendRef, list);
|
2018-02-09 21:25:30 +00:00
|
|
|
return true;
|
2017-12-11 17:00:14 +00:00
|
|
|
}
|
|
|
|
|
2018-05-16 08:18:12 +00:00
|
|
|
static int ref_cmp(const RAnalRef *a, const RAnalRef *b) {
|
|
|
|
if (a->at < b->at) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a->at > b->at) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (a->addr < b->addr) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a->addr > b->addr) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-07-06 14:34:31 +00:00
|
|
|
static void sortxrefs(RList *list) {
|
|
|
|
r_list_sort (list, (RListComparator)ref_cmp);
|
|
|
|
}
|
|
|
|
|
2018-11-14 09:47:28 +00:00
|
|
|
static void listxrefs(HtUP *m, ut64 addr, RList *list) {
|
2017-12-14 11:40:31 +00:00
|
|
|
if (addr == UT64_MAX) {
|
2018-11-14 09:47:28 +00:00
|
|
|
ht_up_foreach (m, mylistrefs_cb, list);
|
2017-12-14 11:40:31 +00:00
|
|
|
} else {
|
2018-02-09 21:25:30 +00:00
|
|
|
bool found;
|
2018-11-14 09:47:28 +00:00
|
|
|
HtUP *d = ht_up_find (m, addr, &found);
|
2018-02-09 21:25:30 +00:00
|
|
|
if (!found) {
|
2017-12-14 11:40:31 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-11-14 09:47:28 +00:00
|
|
|
ht_up_foreach (d, appendRef, list);
|
2017-12-11 17:00:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-10-20 04:03:28 +00:00
|
|
|
// XXX THIS IS HEAVY IN MEMORY USAGE
|
2018-11-14 09:47:28 +00:00
|
|
|
static void setxref(HtUP *m, ut64 from, ut64 to, int type) {
|
2018-02-09 21:25:30 +00:00
|
|
|
bool found;
|
2018-11-14 09:47:28 +00:00
|
|
|
HtUP *ht = ht_up_find (m, from, &found);
|
2018-02-09 21:25:30 +00:00
|
|
|
if (!found) {
|
2018-11-14 09:47:28 +00:00
|
|
|
ht = ht_up_new (NULL, xrefs_ref_free, NULL);
|
2018-02-09 21:25:30 +00:00
|
|
|
if (!ht) {
|
|
|
|
return;
|
2017-12-11 17:00:14 +00:00
|
|
|
}
|
2018-11-14 09:47:28 +00:00
|
|
|
ht_up_insert (m, from, ht);
|
2017-12-11 17:00:14 +00:00
|
|
|
}
|
2018-09-21 22:11:44 +00:00
|
|
|
RAnalRef *ref = r_anal_ref_new (to, from, type);
|
|
|
|
if (ref) {
|
2018-11-14 09:47:28 +00:00
|
|
|
ht_up_update (ht, to, ref);
|
2018-09-21 22:11:44 +00:00
|
|
|
}
|
2017-12-11 17:00:14 +00:00
|
|
|
}
|
|
|
|
|
2018-02-09 21:25:30 +00:00
|
|
|
// set a reference from FROM to TO and a cross-reference(xref) from TO to FROM.
|
2022-04-25 20:19:23 +00:00
|
|
|
R_API bool r_anal_xrefs_set(RAnal *anal, ut64 from, ut64 to, const RAnalRefType _type) {
|
|
|
|
RAnalRefType type = _type;
|
2021-07-30 10:34:13 +00:00
|
|
|
r_return_val_if_fail (anal, false);
|
|
|
|
if (from == to) {
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2016-09-26 21:13:49 +00:00
|
|
|
}
|
2020-04-12 14:42:19 +00:00
|
|
|
if (anal->iob.is_valid_offset) {
|
|
|
|
if (!anal->iob.is_valid_offset (anal->iob.io, from, 0)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!anal->iob.is_valid_offset (anal->iob.io, to, 0)) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-10-20 23:02:25 +00:00
|
|
|
}
|
2022-04-25 20:19:23 +00:00
|
|
|
if (!R_ANAL_REF_TYPE_PERM (type)) {
|
|
|
|
// type |= R_ANAL_REF_TYPE_READ;
|
|
|
|
switch (R_ANAL_REF_TYPE_MASK (type)) {
|
|
|
|
case R_ANAL_REF_TYPE_CODE:
|
|
|
|
case R_ANAL_REF_TYPE_CALL:
|
|
|
|
case R_ANAL_REF_TYPE_JUMP:
|
|
|
|
type |= R_ANAL_REF_TYPE_EXEC;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
type |= R_ANAL_REF_TYPE_READ;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-12-13 12:05:06 +00:00
|
|
|
setxref (anal->dict_xrefs, to, from, type);
|
2018-02-09 21:25:30 +00:00
|
|
|
setxref (anal->dict_refs, from, to, type);
|
2022-01-25 09:39:15 +00:00
|
|
|
R_DIRTY (anal);
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2013-04-18 01:58:44 +00:00
|
|
|
}
|
|
|
|
|
2021-07-30 10:34:13 +00:00
|
|
|
R_API bool r_anal_xrefs_deln(RAnal *anal, ut64 from, ut64 to, const RAnalRefType type) {
|
|
|
|
r_return_val_if_fail (anal, false);
|
|
|
|
#if 0
|
2018-11-14 09:47:28 +00:00
|
|
|
ht_up_delete (anal->dict_refs, from);
|
|
|
|
ht_up_delete (anal->dict_xrefs, to);
|
2021-07-30 10:34:13 +00:00
|
|
|
#else
|
|
|
|
HtUP *d = ht_up_find (anal->dict_refs, from, NULL);
|
|
|
|
if (d) {
|
|
|
|
ht_up_delete (d, to);
|
|
|
|
}
|
|
|
|
d = ht_up_find (anal->dict_xrefs, to, NULL);
|
|
|
|
if (d) {
|
|
|
|
ht_up_delete (d, from);
|
|
|
|
}
|
|
|
|
#endif
|
2022-01-25 09:39:15 +00:00
|
|
|
R_DIRTY (anal);
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2013-04-18 01:58:44 +00:00
|
|
|
}
|
|
|
|
|
2021-07-30 10:34:13 +00:00
|
|
|
R_API bool r_anal_xref_del(RAnal *anal, ut64 from, ut64 to) {
|
|
|
|
r_return_val_if_fail (anal, false);
|
2018-02-09 21:25:30 +00:00
|
|
|
bool res = false;
|
|
|
|
res |= r_anal_xrefs_deln (anal, from, to, R_ANAL_REF_TYPE_NULL);
|
|
|
|
res |= r_anal_xrefs_deln (anal, from, to, R_ANAL_REF_TYPE_CODE);
|
|
|
|
res |= r_anal_xrefs_deln (anal, from, to, R_ANAL_REF_TYPE_CALL);
|
|
|
|
res |= r_anal_xrefs_deln (anal, from, to, R_ANAL_REF_TYPE_DATA);
|
|
|
|
res |= r_anal_xrefs_deln (anal, from, to, R_ANAL_REF_TYPE_STRING);
|
2022-01-25 09:39:15 +00:00
|
|
|
R_DIRTY (anal);
|
2018-02-09 21:25:30 +00:00
|
|
|
return res;
|
2016-08-04 20:52:33 +00:00
|
|
|
}
|
|
|
|
|
2021-07-30 10:34:13 +00:00
|
|
|
R_API bool r_anal_xrefs_from(RAnal *anal, RList *list, const char *kind, const RAnalRefType type, ut64 addr) {
|
|
|
|
r_return_val_if_fail (anal && list, false);
|
2018-02-09 21:25:30 +00:00
|
|
|
listxrefs (anal->dict_refs, addr, list);
|
2019-07-06 14:34:31 +00:00
|
|
|
sortxrefs (list);
|
2017-12-14 11:40:31 +00:00
|
|
|
return true;
|
2017-12-14 10:24:46 +00:00
|
|
|
}
|
2013-04-18 01:58:44 +00:00
|
|
|
|
2018-02-09 21:25:30 +00:00
|
|
|
R_API RList *r_anal_xrefs_get(RAnal *anal, ut64 to) {
|
2021-07-30 10:34:13 +00:00
|
|
|
r_return_val_if_fail (anal, NULL);
|
2018-02-09 21:25:30 +00:00
|
|
|
RList *list = r_anal_ref_list_new ();
|
2016-08-04 20:52:33 +00:00
|
|
|
if (!list) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2017-12-14 11:40:31 +00:00
|
|
|
listxrefs (anal->dict_xrefs, to, list);
|
2019-07-06 14:34:31 +00:00
|
|
|
sortxrefs (list);
|
2014-10-20 23:02:25 +00:00
|
|
|
if (r_list_empty (list)) {
|
2013-04-18 01:58:44 +00:00
|
|
|
r_list_free (list);
|
|
|
|
list = NULL;
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2018-02-09 21:25:30 +00:00
|
|
|
R_API RList *r_anal_refs_get(RAnal *anal, ut64 from) {
|
2021-07-30 10:34:13 +00:00
|
|
|
r_return_val_if_fail (anal, NULL);
|
2018-02-09 21:25:30 +00:00
|
|
|
RList *list = r_anal_ref_list_new ();
|
2017-02-20 11:15:58 +00:00
|
|
|
if (!list) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
listxrefs (anal->dict_refs, from, list);
|
2019-07-06 14:34:31 +00:00
|
|
|
sortxrefs (list);
|
2017-02-20 11:15:58 +00:00
|
|
|
if (r_list_empty (list)) {
|
|
|
|
r_list_free (list);
|
|
|
|
list = NULL;
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2018-02-09 21:25:30 +00:00
|
|
|
R_API RList *r_anal_xrefs_get_from(RAnal *anal, ut64 to) {
|
2021-07-30 10:34:13 +00:00
|
|
|
r_return_val_if_fail (anal, NULL);
|
2018-02-09 21:25:30 +00:00
|
|
|
RList *list = r_anal_ref_list_new ();
|
2016-12-19 11:30:17 +00:00
|
|
|
if (!list) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
listxrefs (anal->dict_refs, to, list);
|
2019-07-06 14:34:31 +00:00
|
|
|
sortxrefs (list);
|
2017-12-11 17:00:14 +00:00
|
|
|
if (r_list_empty (list)) {
|
2014-09-03 21:40:57 +00:00
|
|
|
r_list_free (list);
|
|
|
|
list = NULL;
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2022-05-30 19:13:29 +00:00
|
|
|
R_API void r_anal_xrefs_list(RAnal *anal, int rad, const char *arg) {
|
2021-07-30 10:34:13 +00:00
|
|
|
r_return_if_fail (anal);
|
2018-02-09 21:25:30 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RAnalRef *ref;
|
2019-02-14 00:43:42 +00:00
|
|
|
PJ *pj = NULL;
|
2022-05-30 19:13:29 +00:00
|
|
|
RTable *table = NULL;
|
2021-11-02 17:44:32 +00:00
|
|
|
RList *list = r_anal_ref_list_new ();
|
2018-05-08 06:41:53 +00:00
|
|
|
listxrefs (anal->dict_refs, UT64_MAX, list);
|
2019-07-06 14:34:31 +00:00
|
|
|
sortxrefs (list);
|
2022-05-30 19:13:29 +00:00
|
|
|
if (rad == ',') {
|
|
|
|
table = r_table_new ("xrefs");
|
|
|
|
r_table_set_columnsf (table, "ddssss", "from", "to", "type", "perm", "fromname", "toname");
|
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
if (rad == 'j') {
|
2020-10-27 10:46:27 +00:00
|
|
|
pj = anal->coreb.pjWithEncoding (anal->coreb.core);
|
2019-02-14 00:43:42 +00:00
|
|
|
if (!pj) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
pj_a (pj);
|
2013-10-24 11:59:19 +00:00
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
r_list_foreach (list, iter, ref) {
|
2022-05-18 07:24:09 +00:00
|
|
|
int t = R_ANAL_REF_TYPE_MASK (ref->type);
|
|
|
|
if (!t) {
|
|
|
|
t = ' ';
|
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
switch (rad) {
|
2022-05-30 19:13:29 +00:00
|
|
|
case ',':
|
|
|
|
{
|
|
|
|
char *fromname = anal->coreb.getNameDelta (anal->coreb.core, ref->addr);
|
|
|
|
char *toname = anal->coreb.getNameDelta (anal->coreb.core, ref->at);
|
|
|
|
r_table_add_rowf (table, "ddssss",
|
|
|
|
ref->at, ref->addr,
|
|
|
|
r_anal_ref_type_tostring (t),
|
|
|
|
r_anal_ref_perm_tostring (ref),
|
|
|
|
toname, fromname
|
|
|
|
);
|
|
|
|
}
|
|
|
|
break;
|
2018-02-09 21:25:30 +00:00
|
|
|
case '*':
|
2022-04-25 20:19:23 +00:00
|
|
|
// TODO: export/import the read-write-exec information
|
2018-09-21 00:33:12 +00:00
|
|
|
anal->cb_printf ("ax%c 0x%"PFMT64x" 0x%"PFMT64x"\n", t, ref->addr, ref->at);
|
2018-02-09 21:25:30 +00:00
|
|
|
break;
|
|
|
|
case '\0':
|
|
|
|
{
|
|
|
|
char *name = anal->coreb.getNameDelta (anal->coreb.core, ref->at);
|
2018-09-21 00:33:12 +00:00
|
|
|
if (name) {
|
|
|
|
r_str_replace_ch (name, ' ', 0, true);
|
|
|
|
anal->cb_printf ("%40s", name);
|
|
|
|
free (name);
|
|
|
|
} else {
|
|
|
|
anal->cb_printf ("%40s", "?");
|
|
|
|
}
|
2022-04-25 20:19:23 +00:00
|
|
|
anal->cb_printf (" 0x%"PFMT64x" > %4s:%s > 0x%"PFMT64x, ref->at,
|
|
|
|
r_anal_ref_type_tostring (t), r_anal_ref_perm_tostring (ref), ref->addr);
|
2018-02-09 21:25:30 +00:00
|
|
|
name = anal->coreb.getNameDelta (anal->coreb.core, ref->addr);
|
2018-09-21 00:33:12 +00:00
|
|
|
if (name) {
|
|
|
|
r_str_replace_ch (name, ' ', 0, true);
|
2018-02-09 21:25:30 +00:00
|
|
|
anal->cb_printf (" %s\n", name);
|
2018-09-21 00:33:12 +00:00
|
|
|
free (name);
|
2017-10-09 09:22:43 +00:00
|
|
|
} else {
|
2018-02-09 21:25:30 +00:00
|
|
|
anal->cb_printf ("\n");
|
2017-06-17 00:48:25 +00:00
|
|
|
}
|
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
break;
|
|
|
|
case 'q':
|
2022-04-25 20:19:23 +00:00
|
|
|
anal->cb_printf ("0x%08"PFMT64x" -> 0x%08"PFMT64x" %s:%s\n", ref->at, ref->addr,
|
|
|
|
r_anal_ref_type_tostring (t), r_anal_ref_perm_tostring (ref));
|
2018-02-09 21:25:30 +00:00
|
|
|
break;
|
|
|
|
case 'j':
|
|
|
|
{
|
2019-02-14 00:43:42 +00:00
|
|
|
pj_o (pj);
|
2018-09-21 00:33:12 +00:00
|
|
|
char *name = anal->coreb.getNameDelta (anal->coreb.core, ref->at);
|
|
|
|
if (name) {
|
|
|
|
r_str_replace_ch (name, ' ', 0, true);
|
2019-02-14 00:43:42 +00:00
|
|
|
pj_ks (pj, "name", name);
|
2018-09-21 00:33:12 +00:00
|
|
|
free (name);
|
|
|
|
}
|
2019-02-14 00:43:42 +00:00
|
|
|
pj_kn (pj, "from", ref->at);
|
2022-04-25 20:19:23 +00:00
|
|
|
pj_ks (pj, "type", r_anal_ref_type_tostring (t));
|
|
|
|
pj_ks (pj, "perm", r_anal_ref_perm_tostring (ref));
|
2019-02-14 00:43:42 +00:00
|
|
|
pj_kn (pj, "addr", ref->addr);
|
2018-09-21 00:33:12 +00:00
|
|
|
name = anal->coreb.getNameDelta (anal->coreb.core, ref->addr);
|
|
|
|
if (name) {
|
|
|
|
r_str_replace_ch (name, ' ', 0, true);
|
2019-02-14 00:43:42 +00:00
|
|
|
pj_ks (pj, "refname", name);
|
2018-09-21 00:33:12 +00:00
|
|
|
free (name);
|
|
|
|
}
|
2019-02-14 00:43:42 +00:00
|
|
|
pj_end (pj);
|
2016-10-30 09:23:46 +00:00
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2013-10-24 11:59:19 +00:00
|
|
|
}
|
|
|
|
}
|
2022-05-30 19:13:29 +00:00
|
|
|
if (rad == ',') {
|
|
|
|
if (R_STR_ISNOTEMPTY (arg)) {
|
|
|
|
r_table_query (table, arg);
|
|
|
|
}
|
|
|
|
char *s = r_table_tofancystring (table);
|
|
|
|
r_cons_println (s);
|
|
|
|
free (s);
|
|
|
|
r_table_free (table);
|
|
|
|
} else if (rad == 'j') {
|
2019-02-14 00:43:42 +00:00
|
|
|
pj_end (pj);
|
2019-03-28 12:51:29 +00:00
|
|
|
anal->cb_printf ("%s\n", pj_string (pj));
|
2019-02-14 00:43:42 +00:00
|
|
|
pj_free (pj);
|
2013-07-19 01:35:45 +00:00
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
r_list_free (list);
|
2013-07-19 01:35:45 +00:00
|
|
|
}
|
2014-09-23 08:15:19 +00:00
|
|
|
|
2022-04-25 20:19:23 +00:00
|
|
|
R_API char r_anal_ref_perm_tochar(RAnalRef *ref) {
|
|
|
|
if (ref->type & R_ANAL_REF_TYPE_WRITE) {
|
|
|
|
return 'w';
|
|
|
|
}
|
|
|
|
if (ref->type & R_ANAL_REF_TYPE_READ) {
|
|
|
|
return 'r';
|
|
|
|
}
|
|
|
|
if (ref->type & R_ANAL_REF_TYPE_EXEC) {
|
|
|
|
return 'x';
|
|
|
|
}
|
|
|
|
switch (R_ANAL_REF_TYPE_MASK (ref->type)) {
|
|
|
|
case R_ANAL_REF_TYPE_CODE:
|
|
|
|
case R_ANAL_REF_TYPE_CALL:
|
|
|
|
case R_ANAL_REF_TYPE_JUMP:
|
|
|
|
return 'x';
|
|
|
|
}
|
|
|
|
return '-';
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API const char *r_anal_ref_perm_tostring(RAnalRef *ref) {
|
|
|
|
int perm = R_ANAL_REF_TYPE_PERM (ref->type);
|
|
|
|
if (!perm) {
|
|
|
|
switch (R_ANAL_REF_TYPE_MASK (ref->type)) {
|
|
|
|
case R_ANAL_REF_TYPE_CODE:
|
|
|
|
case R_ANAL_REF_TYPE_CALL:
|
|
|
|
case R_ANAL_REF_TYPE_JUMP:
|
|
|
|
perm = R_ANAL_REF_TYPE_EXEC;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return r_str_rwx_i (perm);
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API const char *r_anal_ref_type_tostring(RAnalRefType type) {
|
|
|
|
switch (R_ANAL_REF_TYPE_MASK (type)) {
|
2022-05-18 08:29:11 +00:00
|
|
|
case ' ':
|
2022-04-25 20:19:23 +00:00
|
|
|
case R_ANAL_REF_TYPE_NULL:
|
|
|
|
return "NULL";
|
2023-01-16 12:20:27 +00:00
|
|
|
case R_ANAL_REF_TYPE_CODE | R_ANAL_REF_TYPE_DATA:
|
|
|
|
return "ICOD"; // indirect code reference
|
2014-09-23 08:15:19 +00:00
|
|
|
case R_ANAL_REF_TYPE_CODE:
|
2018-05-08 06:41:53 +00:00
|
|
|
return "CODE";
|
2014-09-23 08:15:19 +00:00
|
|
|
case R_ANAL_REF_TYPE_CALL:
|
|
|
|
return "CALL";
|
2022-12-13 22:49:38 +00:00
|
|
|
case R_ANAL_REF_TYPE_JUMP:
|
|
|
|
return "JUMP";
|
2014-09-23 08:15:19 +00:00
|
|
|
case R_ANAL_REF_TYPE_DATA:
|
|
|
|
return "DATA";
|
|
|
|
case R_ANAL_REF_TYPE_STRING:
|
2022-04-25 20:19:23 +00:00
|
|
|
return "STRN";
|
2014-09-24 11:03:03 +00:00
|
|
|
default:
|
2022-04-25 20:19:23 +00:00
|
|
|
return "UNKN";
|
2014-09-23 08:15:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-25 20:19:23 +00:00
|
|
|
R_API RAnalRefType r_anal_xrefs_type_from_string(const char *s) {
|
|
|
|
RAnalRefType rt = R_ANAL_REF_TYPE_NULL;
|
|
|
|
if (strchr (s, 'r')) {
|
|
|
|
rt |= R_ANAL_REF_TYPE_READ | R_ANAL_REF_TYPE_DATA;
|
|
|
|
}
|
|
|
|
if (strchr (s, 'w')) {
|
|
|
|
rt |= R_ANAL_REF_TYPE_WRITE | R_ANAL_REF_TYPE_DATA;
|
|
|
|
}
|
|
|
|
if (strchr (s, 'x')) {
|
|
|
|
rt |= R_ANAL_REF_TYPE_EXEC;
|
|
|
|
}
|
|
|
|
if (strchr (s, 'c')) {
|
|
|
|
rt |= R_ANAL_REF_TYPE_CODE;
|
|
|
|
}
|
|
|
|
if (strchr (s, 'C')) {
|
|
|
|
rt |= R_ANAL_REF_TYPE_CALL;
|
|
|
|
}
|
|
|
|
if (strchr (s, 'j')) {
|
|
|
|
rt |= R_ANAL_REF_TYPE_JUMP;
|
|
|
|
}
|
|
|
|
if (strchr (s, 'd')) {
|
|
|
|
rt |= R_ANAL_REF_TYPE_DATA;
|
|
|
|
}
|
|
|
|
if (strchr (s, 's')) {
|
|
|
|
rt |= R_ANAL_REF_TYPE_STRING;
|
|
|
|
}
|
|
|
|
return rt;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: deprecate
|
2018-02-09 21:25:30 +00:00
|
|
|
R_API RAnalRefType r_anal_xrefs_type(char ch) {
|
|
|
|
switch (ch) {
|
|
|
|
case R_ANAL_REF_TYPE_CODE:
|
|
|
|
case R_ANAL_REF_TYPE_CALL:
|
|
|
|
case R_ANAL_REF_TYPE_DATA:
|
|
|
|
case R_ANAL_REF_TYPE_STRING:
|
|
|
|
case R_ANAL_REF_TYPE_NULL:
|
|
|
|
return (RAnalRefType)ch;
|
|
|
|
default:
|
|
|
|
return R_ANAL_REF_TYPE_NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API bool r_anal_xrefs_init(RAnal *anal) {
|
2021-07-30 10:34:13 +00:00
|
|
|
r_return_val_if_fail (anal, false);
|
2018-11-14 09:47:28 +00:00
|
|
|
ht_up_free (anal->dict_refs);
|
2018-02-09 21:25:30 +00:00
|
|
|
anal->dict_refs = NULL;
|
2018-11-14 09:47:28 +00:00
|
|
|
ht_up_free (anal->dict_xrefs);
|
2018-02-09 21:25:30 +00:00
|
|
|
anal->dict_xrefs = NULL;
|
|
|
|
|
2018-11-14 09:47:28 +00:00
|
|
|
HtUP *tmp = ht_up_new (NULL, xrefs_ht_free, NULL);
|
2018-02-09 21:25:30 +00:00
|
|
|
if (!tmp) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
anal->dict_refs = tmp;
|
|
|
|
|
2018-11-14 09:47:28 +00:00
|
|
|
tmp = ht_up_new (NULL, xrefs_ht_free, NULL);
|
2018-02-09 21:25:30 +00:00
|
|
|
if (!tmp) {
|
2018-11-14 09:47:28 +00:00
|
|
|
ht_up_free (anal->dict_refs);
|
2018-02-09 21:25:30 +00:00
|
|
|
anal->dict_refs = NULL;
|
|
|
|
return false;
|
2017-12-11 17:00:14 +00:00
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
anal->dict_xrefs = tmp;
|
|
|
|
return true;
|
2016-03-28 23:13:00 +00:00
|
|
|
}
|
|
|
|
|
2020-04-12 14:42:19 +00:00
|
|
|
static bool count_cb(void *user, const ut64 k, const void *v) {
|
|
|
|
(*(ut64 *)user) += ((HtUP *)v)->count;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API ut64 r_anal_xrefs_count(RAnal *anal) {
|
|
|
|
ut64 ret = 0;
|
|
|
|
ht_up_foreach (anal->dict_xrefs, count_cb, &ret);
|
|
|
|
return ret;
|
2018-02-09 21:25:30 +00:00
|
|
|
}
|
|
|
|
|
2023-02-13 12:36:07 +00:00
|
|
|
static RList *fcn_get_all_refs(RAnalFunction *fcn, HtUP *ht) {
|
2018-02-09 21:25:30 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RAnalBlock *bb;
|
|
|
|
RList *list = r_anal_ref_list_new ();
|
2023-02-13 12:36:07 +00:00
|
|
|
if (R_LIKELY (list)) {
|
|
|
|
r_list_foreach (fcn->bbs, iter, bb) {
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < bb->ninstr; i++) {
|
|
|
|
ut64 at = bb->addr + r_anal_bb_offset_inst (bb, i);
|
|
|
|
listxrefs (ht, at, list);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sortxrefs (list);
|
2018-02-09 21:25:30 +00:00
|
|
|
}
|
2023-02-13 12:36:07 +00:00
|
|
|
return list;
|
|
|
|
}
|
2018-02-09 21:25:30 +00:00
|
|
|
|
2023-02-13 12:36:07 +00:00
|
|
|
static RList *fcn_get_refs(RAnalFunction *fcn, HtUP *ht) {
|
|
|
|
RList *list = r_anal_ref_list_new ();
|
|
|
|
if (R_LIKELY (list)) {
|
|
|
|
// XXX assume first basic block is the entrypoint
|
|
|
|
listxrefs (ht, fcn->addr, list);
|
2018-02-09 21:25:30 +00:00
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2020-03-17 11:58:39 +00:00
|
|
|
R_API RList *r_anal_function_get_refs(RAnalFunction *fcn) {
|
|
|
|
r_return_val_if_fail (fcn, NULL);
|
2023-02-13 12:36:07 +00:00
|
|
|
return fcn_get_all_refs (fcn, fcn->anal->dict_refs);
|
2018-02-09 21:25:30 +00:00
|
|
|
}
|
|
|
|
|
2020-03-17 11:58:39 +00:00
|
|
|
R_API RList *r_anal_function_get_xrefs(RAnalFunction *fcn) {
|
|
|
|
r_return_val_if_fail (fcn, NULL);
|
|
|
|
return fcn_get_refs (fcn, fcn->anal->dict_xrefs);
|
2018-02-09 21:25:30 +00:00
|
|
|
}
|
2023-02-13 12:36:07 +00:00
|
|
|
|
|
|
|
#if R2_590
|
|
|
|
R_API RList *r_anal_function_get_all_xrefs(RAnalFunction *fcn) {
|
|
|
|
r_return_val_if_fail (fcn, NULL);
|
|
|
|
return fcn_get_all_refs (fcn, fcn->anal->dict_xrefs);
|
|
|
|
}
|
|
|
|
#endif
|