anal/xrefs: single, global xrefs API

* several bugfixes
* Fix xrefs/refs confusion with asm.cmt.refs
* Also check if xref source is valid offset
* Fix ax* to show type of ref
* anal/xrefs: pass the right hashtable to mylistrefs
* r_anal_refs_get should use anal->refs, not anal->xrefs
* anal/fcn: add xref also when there's a CALL to a noreturn function
* projects: use radare2 output of ax command to save/restore xrefs
* core/cmd_anal: when analyzing calls, we should use REF_TYPE_CALL
* core/canal: use xrefs API, because the list is a just a copy
* core/canal: rename "loc." entries to "fcn." when a CALL is found
* sort xrefs to make results consistent
* core/canal: avoid recomputing function every time during `aan`
* anal: move fcn_refs/xrefs functions to the xrefs.c file
* core/canal.c: avoid iterating fcn xrefs list
* anal/xrefs: compute fcn xrefs by analyzing fcn addresses
* remove other unused functions
* anal/xrefs: remove fcn_xrefs_add and fcn_xrefs_deln
* anal/xrefs: remove old fcn->refs/xrefs
* anal/xrefs: directly store RAnalRef objects in the hash table
* libr: prevent memory leaks when using refs/xrefs
* anal/xrefs: merge anal/ref and anal/xref and clean API

Big xrefs/refs refactoring that provides a more uniform and simple API.
It avoids changes to refs/xrefs except through the API and it keeps all
xrefs/refs info in one single place, to improve consistency.

Thanks to:
Riccardo Schirone <sirmy15@gmail.com>
pancake <pancake@nopcode.org>
rene <rlaemmert@gmail.com>
This commit is contained in:
Riccardo Schirone 2018-02-09 22:25:30 +01:00
parent cbe9a12be2
commit b703dfbf17
18 changed files with 513 additions and 932 deletions

View File

@ -27,7 +27,7 @@ plugins: ${LIBSO} ${LIBAR}
include ${STATIC_ANAL_PLUGINS}
STATIC_OBJS=$(addprefix $(LTOP)/anal/p/,$(STATIC_OBJ))
OBJLIBS=meta.o reflines.o ref.o op.o fcn.o bb.o var.o
OBJLIBS=meta.o reflines.o op.o fcn.o bb.o var.o
OBJLIBS+=cond.o value.o cc.o diff.o types.o
OBJLIBS+=hint.o anal.o data.o xrefs.o esil.o sign.o
OBJLIBS+=anal_ex.o switch.o state.o cycles.o

View File

@ -78,14 +78,9 @@ R_API RAnal *r_anal_new() {
anal->sdb_fcns = sdb_ns (anal->sdb, "fcns", 1);
anal->sdb_meta = sdb_ns (anal->sdb, "meta", 1);
anal->sdb_hints = sdb_ns (anal->sdb, "hints", 1);
anal->sdb_xrefs = sdb_ns (anal->sdb, "xrefs", 1);
anal->sdb_types = sdb_ns (anal->sdb, "types", 1);
anal->sdb_cc = sdb_ns (anal->sdb, "cc", 1);
anal->sdb_zigns = sdb_ns (anal->sdb, "zigns", 1);
#if USE_DICT
anal->dict_refs = dict_new (100, dict_free);
anal->dict_xrefs = dict_new (100, dict_free);
#endif
anal->zign_path = strdup ("");
anal->cb_printf = (PrintfCallback) printf;
(void)r_anal_pin_init (anal);
@ -141,6 +136,8 @@ R_API RAnal *r_anal_free(RAnal *a) {
r_reg_free (a->reg);
r_anal_op_free (a->queued);
r_list_free (a->bits_ranges);
ht_free (a->dict_refs);
ht_free (a->dict_xrefs);
a->sdb = NULL;
sdb_ns_free (a->sdb);
if (a->esil) {
@ -364,13 +361,6 @@ R_API RList* r_anal_get_fcns (RAnal *anal) {
return anal->fcns;
}
R_API bool r_anal_project_save(RAnal *anal, const char *prjfile) {
if (prjfile && *prjfile) {
return r_anal_xrefs_save (anal, prjfile);
}
return false;
}
R_API RAnalOp *r_anal_op_hexstr(RAnal *anal, ut64 addr, const char *str) {
int len;
ut8 *buf;
@ -412,7 +402,6 @@ R_API int r_anal_purge (RAnal *anal) {
sdb_reset (anal->sdb_fcns);
sdb_reset (anal->sdb_meta);
sdb_reset (anal->sdb_hints);
sdb_reset (anal->sdb_xrefs);
sdb_reset (anal->sdb_types);
sdb_reset (anal->sdb_zigns);
r_list_free (anal->fcns);

View File

@ -144,7 +144,7 @@ R_API int r_anal_bb(RAnal *anal, RAnalBlock *bb, ut64 addr, ut8 *buf, ut64 len,
ut8 b[8];
ut64 ptr = idx+addr+src->delta;
anal->iob.read_at (anal->iob.io, ptr, b, memref);
r_anal_ref_add (anal, ptr, addr+idx-op->size, 'd');
r_anal_xrefs_set (anal, addr+idx-op->size, ptr, R_ANAL_REF_TYPE_DATA);
}
}
}

View File

@ -293,10 +293,6 @@ R_API RAnalFunction *r_anal_fcn_new() {
fcn->cc = NULL;
/* Function attributes: weak/noreturn/format/etc */
fcn->addr = UT64_MAX;
#if FCN_OLD
fcn->refs = r_anal_ref_list_new ();
fcn->xrefs = r_anal_ref_list_new ();
#endif
fcn->fcn_locs = NULL;
fcn->bbs = r_anal_bb_list_new ();
fcn->fingerprint = NULL;
@ -323,10 +319,6 @@ R_API void r_anal_fcn_free(void *_fcn) {
free (fcn->name);
free (fcn->attr);
r_tinyrange_fini (&fcn->bbr);
#if FCN_OLD
r_list_free (fcn->refs);
r_list_free (fcn->xrefs);
#endif
// all functions are freed in anal->fcns
fcn->fcn_locs = NULL;
if (fcn->bbs) {
@ -352,64 +344,6 @@ static bool refExists(RList *refs, RAnalRef *ref) {
return false;
}
R_API int r_anal_fcn_xref_add(RAnal *a, RAnalFunction *fcn, ut64 at, ut64 addr, int type) {
RAnalRef *ref;
if (!fcn || !a) {
return false;
}
if (!a->iob.is_valid_offset (a->iob.io, addr, 0)) {
return false;
}
ref = r_anal_ref_new ();
if (!ref) {
return false;
}
// set global reference
// r_cons_printf ("C 0x%llx 0x%llx\n", at, addr);
r_anal_xrefs_set (a, type, at, addr);
// set per-function reference
#if FCN_OLD
// TOO OLD we shouldnt be storing this.. or we do?
ref->at = at; // from
ref->addr = addr; // to
ref->type = type;
// TODO: ensure we are not dupping xrefs
if (refExists (fcn->refs, ref)) {
r_anal_ref_free (ref);
} else {
r_list_append (fcn->refs, ref);
}
#endif
#if FCN_SDB
sdb_add (DB, sdb_fmt ("fcn.0x%08"PFMT64x ".name", fcn->addr), fcn->name, 0);
// encode the name in base64 ?
sdb_num_add (DB, sdb_fmt ("fcn.name.%s", fcn->name), fcn->addr, 0);
sdb_array_add_num (DB, sdb_fmt ("fcn.0x%08"PFMT64x ".xrefs", fcn->addr), at, 0);
#endif
return true;
}
R_API int r_anal_fcn_xref_del(RAnal *a, RAnalFunction *fcn, ut64 at, ut64 addr, int type) {
#if FCN_OLD
RAnalRef *ref;
RListIter *iter;
/* No need for _safe loop coz we return immediately after the delete. */
r_list_foreach (fcn->xrefs, iter, ref) {
if ((type != -1 || type == ref->type) &&
(at == 0LL || at == ref->at) &&
(addr == 0LL || addr == ref->addr)) {
r_list_delete (fcn->xrefs, iter);
return true;
}
}
#endif
#if FCN_SDB
// TODO
// sdb_array_delete_num (DB, key, at, 0);
#endif
return false;
}
static RAnalBlock *bbget(RAnalFunction *fcn, ut64 addr) {
RListIter *iter;
RAnalBlock *bb;
@ -1150,7 +1084,7 @@ repeat:
if (op.ptr && op.ptr != UT64_MAX && op.ptr != UT32_MAX) {
// swapped parameters wtf
r_anal_fcn_xref_add (anal, fcn, op.addr, op.ptr, R_ANAL_REF_TYPE_DATA);
r_anal_xrefs_set (anal, op.addr, op.ptr, R_ANAL_REF_TYPE_DATA);
}
switch (op.type & R_ANAL_OP_TYPE_MASK) {
@ -1289,7 +1223,7 @@ repeat:
return R_ANAL_RET_END;
}
if (anal->opt.jmpref) {
(void) r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump, R_ANAL_REF_TYPE_CODE);
(void) r_anal_xrefs_set (anal, op.addr, op.jump, R_ANAL_REF_TYPE_CODE);
}
if (!anal->opt.jmpabove && (op.jump < fcn->addr)) {
FITFCNSZ ();
@ -1384,8 +1318,7 @@ repeat:
break;
case R_ANAL_OP_TYPE_CJMP:
if (anal->opt.cjmpref) {
(void) r_anal_fcn_xref_add (anal, fcn,
op.addr, op.jump, R_ANAL_REF_TYPE_CODE);
(void) r_anal_xrefs_set (anal, op.addr, op.jump, R_ANAL_REF_TYPE_CODE);
}
if (!overlapped) {
bb->jump = op.jump;
@ -1455,23 +1388,25 @@ repeat:
case R_ANAL_OP_TYPE_ICALL:
case R_ANAL_OP_TYPE_IRCALL:
/* call [dst] */
// XXX: this is TYPE_MCALL or indirect-call
(void) r_anal_xrefs_set (anal, op.addr, op.ptr, R_ANAL_REF_TYPE_CALL);
if (op.ptr != UT64_MAX && r_anal_noreturn_at (anal, op.ptr)) {
FITFCNSZ ();
r_anal_op_fini (&op);
return R_ANAL_RET_END;
}
// XXX: this is TYPE_MCALL or indirect-call
(void) r_anal_fcn_xref_add (anal, fcn, op.addr, op.ptr, R_ANAL_REF_TYPE_CALL);
break;
case R_ANAL_OP_TYPE_CCALL:
case R_ANAL_OP_TYPE_CALL:
/* call dst */
(void) r_anal_xrefs_set (anal, op.addr, op.jump, R_ANAL_REF_TYPE_CALL);
if (r_anal_noreturn_at (anal, op.jump)) {
FITFCNSZ ();
r_anal_op_fini (&op);
return R_ANAL_RET_END;
}
(void) r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump, R_ANAL_REF_TYPE_CALL);
#if CALL_IS_EOB
recurseAt (op.jump);
recurseAt (op.fail);
@ -1491,13 +1426,6 @@ repeat:
}
// switch statement
if (anal->opt.jmptbl) {
if (fcn->refs->tail) {
RAnalRef *last_ref = fcn->refs->tail->data;
last_ref->type = R_ANAL_REF_TYPE_NULL;
// TODO: walk switch? try_walkthrough_jmptbl?
// Why is this a jmp table and what does it look like
// walk_switch (anal, fcn, op.addr, op.addr + op.size);
}
// op.ireg since rip relative addressing produces way too many false positives otherwise
// op.ireg is 0 for rip relative, "rax", etc otherwise
if (op.ptr != UT64_MAX && op.ireg) { // direct jump
@ -1554,7 +1482,7 @@ analopfinish:
last_is_push = true;
last_push_addr = op.val;
if (anal->iob.is_valid_offset (anal->iob.io, op.val, 1)) {
(void) r_anal_fcn_xref_add (anal, fcn, op.addr, op.val, R_ANAL_REF_TYPE_DATA);
(void) r_anal_xrefs_set (anal, op.addr, op.val, R_ANAL_REF_TYPE_DATA);
}
break;
case R_ANAL_OP_TYPE_RET:
@ -1666,15 +1594,18 @@ R_API void r_anal_fcn_fit_overlaps(RAnal *anal, RAnalFunction *fcn) {
}
}
R_API void r_anal_trim_jmprefs(RAnalFunction *fcn) {
R_API void r_anal_trim_jmprefs(RAnal *anal, RAnalFunction *fcn) {
RAnalRef *ref;
RList *refs = r_anal_fcn_get_refs (anal, fcn);
RListIter *iter;
RListIter *tmp;
r_list_foreach_safe (fcn->refs, iter, tmp, ref) {
r_list_foreach (refs, iter, ref) {
if (ref->type == R_ANAL_REF_TYPE_CODE && r_anal_fcn_is_in_offset (fcn, ref->addr)) {
r_list_delete (fcn->refs, iter);
r_anal_xrefs_deln (anal, ref->at, ref->addr, ref->type);
}
}
r_list_free (refs);
}
R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64 len, int reftype) {
@ -1718,7 +1649,7 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64
// fcn is not yet in anal => pass NULL
r_anal_fcn_resize (NULL, fcn, endaddr - fcn->addr);
#endif
r_anal_trim_jmprefs (fcn);
r_anal_trim_jmprefs (anal, fcn);
}
return ret;
}
@ -2319,13 +2250,3 @@ R_API int r_anal_fcn_count_edges(RAnalFunction *fcn, int *ebbs) {
}
return edges;
}
R_API RList *r_anal_fcn_get_refs(RAnal *anal, RAnalFunction *fcn) {
RList *ret = (fcn) ? r_list_clone (fcn->refs) : NULL;
return ret;
}
R_API RList *r_anal_fcn_get_xrefs(RAnal *anal, RAnalFunction *fcn) {
RList *ret = (fcn) ? r_list_clone (fcn->xrefs) : NULL;
return ret;
}

View File

@ -593,7 +593,7 @@ static int module_match_buffer(const RAnal *anal, const RFlirtModule *module,
}
r_anal_fcn_resize (anal, next_module_function, flirt_fcn_size);
next_module_function_size = r_anal_fcn_size (next_module_function);
r_anal_trim_jmprefs (next_module_function);
r_anal_trim_jmprefs ((RAnal *)anal, next_module_function);
}

View File

@ -66,7 +66,6 @@ files = [
'p/anal_xtensa.c',
'p/anal_z80.c',
'pin.c',
'ref.c',
'reflines.c',
'rtti.c',
'rtti_msvc.c',

View File

@ -223,7 +223,7 @@ static int handle_bb_cf_recursive_descent (RAnal *anal, RAnalState *state) {
switch (control_type) {
case R_ANAL_OP_TYPE_CALL:
IFDBG eprintf (" - Handling a call @ 0x%04"PFMT64x".\n", addr);
r_anal_fcn_xref_add (anal, state->current_fcn, bb->addr, bb->jump, R_ANAL_REF_TYPE_CALL);
r_anal_xrefs_set (anal, bb->addr, bb->jump, R_ANAL_REF_TYPE_CALL);
result = R_ANAL_RET_ERROR;
break;
case R_ANAL_OP_TYPE_JMP:
@ -406,7 +406,7 @@ static int handle_bb_cf_linear_sweep (RAnal *anal, RAnalState *state) {
switch (control_type) {
case R_ANAL_OP_TYPE_CALL:
IFDBG eprintf (" - Handling a call @ 0x%04"PFMT64x"\n", addr);
r_anal_fcn_xref_add (anal, state->current_fcn, bb->addr, bb->jump, R_ANAL_REF_TYPE_CALL);
r_anal_xrefs_set (anal, bb->addr, bb->jump, R_ANAL_REF_TYPE_CALL);
result = R_ANAL_RET_ERROR;
break;
case R_ANAL_OP_TYPE_JMP:

View File

@ -1,72 +0,0 @@
/* radare - LGPL - Copyright 2010-2018 - nibble, pancake */
#include <r_anal.h>
#include <r_util.h>
#include <r_list.h>
// This file contains the reversed api for querying xrefs.c which
// is implemented on top of sdb. Anyway, the sdbization is not
// complete because there's still r_anal_ref_new() which doesnt
// serializes with sdb_native
R_API RAnalRef *r_anal_ref_new() {
RAnalRef *ref = R_NEW0 (RAnalRef);
if (ref) {
ref->addr = -1;
ref->at = -1;
ref->type = R_ANAL_REF_TYPE_CODE;
}
return ref;
}
R_API RList *r_anal_ref_list_new() {
RList *list = r_list_new ();
if (!list) return NULL;
list->free = &r_anal_ref_free;
return list;
}
R_API void r_anal_ref_free(void *ref) {
free (ref);
}
R_API int r_anal_ref_add(RAnal *anal, ut64 addr, ut64 at, int type) {
r_anal_xrefs_set (anal, type, at, addr);
return true;
}
R_API const char *r_anal_ref_to_string(int type) {
switch (type) {
case R_ANAL_REF_TYPE_NULL: return "null";
case R_ANAL_REF_TYPE_CODE: return "code";
case R_ANAL_REF_TYPE_CALL: return "call";
case R_ANAL_REF_TYPE_DATA: return "data";
case R_ANAL_REF_TYPE_STRING: return "strg";
}
return "unk";
}
R_API int r_anal_ref_del(RAnal *anal, ut64 from, ut64 to) {
#if USE_MHT
// TODO Must delete from mht_refs too
mht *m = anal->mht_xrefs;
mhtkv *kv = mht_getr (m, from);
if (kv) {
mht *ht = kv->u;
if (ht) {
mht_del (ht, to);
}
}
#else
r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_NULL, from, to);
r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_CODE, from, to);
r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_CALL, from, to);
r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_DATA, from, to);
r_anal_xrefs_deln (anal, R_ANAL_REF_TYPE_STRING, from, to);
#endif
return true;
}
R_API RList *r_anal_xref_get(RAnal *anal, ut64 addr) {
return r_anal_xrefs_get (anal, addr);
}

View File

@ -146,6 +146,7 @@ static int vtable_is_addr_vtable_start(RVTableContext *context, ut64 curAddress)
r_anal_op_fini (&analop);
}
}
r_list_free (xrefs);
return false;
}
@ -198,9 +199,12 @@ R_API RList *r_anal_vtable_search(RVTableContext *context) {
startAddress += context->word_size;
// a ref means the vtable has ended
if (!r_list_empty (r_anal_xrefs_get (context->anal, startAddress))) {
RList *ll = r_anal_xrefs_get (context->anal, startAddress);
if (!r_list_empty (ll)) {
r_list_free (ll);
break;
}
r_list_free (ll);
}
vtable->method_count = noOfMethods;
r_list_append (vtables, vtable);

View File

@ -1,10 +1,7 @@
/* radare - LGPL - Copyright 2009-2017 - pancake, nibble */
/* radare - LGPL - Copyright 2009-2018 - pancake, nibble, defragger, ret2libc */
#include <r_anal.h>
#include <r_cons.h>
#include <sdb.h>
#define DB anal->sdb_xrefs
#if 0
DICT
@ -24,284 +21,160 @@ xrefs
20: call 10
#endif
// XXX: is it possible to have multiple type for the same (from, to) pair?
// if it is, things need to be adjusted
#define u64_to_key(x) (sdb_fmt ("%"PFMT64x, (x)))
#define ht_find_u64(_ht,_key,_found) (ht_find ((_ht), u64_to_key (_key), (_found)))
#define ht_insert_u64(_ht,_key,_value) (ht_insert ((_ht), u64_to_key (_key), _value))
#define ht_update_u64(_ht,_key,_value) (ht_update ((_ht), u64_to_key (_key), _value))
#define ht_delete_u64(_ht,_key) (ht_delete ((_ht), u64_to_key (_key)))
R_API RAnalRef *r_anal_ref_new() {
RAnalRef *ref = R_NEW0 (RAnalRef);
if (ref) {
ref->addr = -1;
ref->at = -1;
ref->type = R_ANAL_REF_TYPE_CODE;
}
return ref;
}
R_API RList *r_anal_ref_list_new() {
return r_list_newf (r_anal_ref_free);
}
R_API void r_anal_ref_free(void *ref) {
free (ref);
}
void xrefs_ht_free(HtKv *kv) {
free (kv->key);
ht_free (kv->value);
free (kv);
}
void xrefs_ref_free(HtKv *kv) {
free (kv->key);
r_anal_ref_free (kv->value);
free (kv);
}
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";
return "code jmp";
case R_ANAL_REF_TYPE_CALL:
return "code.call";
return "code call";
case R_ANAL_REF_TYPE_DATA:
return "data.mem";
return "data mem";
case R_ANAL_REF_TYPE_STRING:
return "data.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);
static bool appendRef(RList *list, const char *k, RAnalRef *ref) {
RAnalRef *cloned = r_anal_ref_new ();
if (!cloned) {
return false;
}
cloned->addr = ref->addr;
cloned->at = ref->at;
cloned->type = ref->type;
r_list_append (list, cloned);
return true;
}
R_API bool r_anal_xrefs_save(RAnal *anal, const char *prjDir) {
#if USE_DICT
anal->sdb_xrefs = sdb_new0 ();
#endif
char *xrefs_path = r_str_newf ("%s" R_SYS_DIR "xrefs.sdb", prjDir);
sdb_file (anal->sdb_xrefs, xrefs_path);
free (xrefs_path);
return sdb_sync (anal->sdb_xrefs);
static bool mylistrefs_cb(RList *list, const char *k, SdbHash *ht) {
ht_foreach (ht, (HtForeachCallback)appendRef, list);
return true;
}
#if USE_DICT
static void appendRef(RList *list, dicti k, dicti v, void *u) {
static void listxrefs(SdbHash *m, ut64 addr, RList *list) {
if (addr == UT64_MAX) {
ht_foreach (m, (HtForeachCallback)mylistrefs_cb, list);
} else {
bool found;
SdbHash *d = ht_find_u64 (m, addr, &found);
if (!found) {
return;
}
ht_foreach (d, (HtForeachCallback)appendRef, list);
}
}
static void setxref(SdbHash *m, ut64 from, ut64 to, int type) {
bool found;
SdbHash *ht = ht_find_u64 (m, from, &found);
if (!found) {
ht = ht_new (NULL, xrefs_ref_free, NULL);
if (!ht) {
return;
}
ht_insert_u64 (m, from, ht);
}
RAnalRef *ref = r_anal_ref_new ();
if (ref) {
#if 0
eprintf ("%s 0x%08llx -> 0x%08llx (0x%llx)\n",
kv->u, kv->k, kv->v, addr);
#endif
ref->at = k;
ref->addr = v;
ref->type = u;
r_list_append (list, ref);
}
ref->at = from;
ref->addr = to;
ref->type = type;
ht_update_u64 (ht, to, ref);
}
static void mylistrefs(dict *m, ut64 addr, RList *list) {
int i, j;
for (i = 0; i < m->size; i++) {
dictkv *kv = m->table[i];
if (!kv) {
continue;
}
while (kv->k != MHTNO) {
if (addr == UT64_MAX || addr == kv->k) {
appendRef (list, kv->k, kv->v, kv->u);
}
kv++;
}
// set a reference from FROM to TO and a cross-reference(xref) from TO to FROM.
R_API int r_anal_xrefs_set(RAnal *anal, ut64 from, ut64 to, const RAnalRefType type) {
if (!anal) {
return false;
}
}
static void listrefs(dict *m, ut64 addr, RList *list) {
int i;
if (addr == UT64_MAX) {
for (i = 0; i < m->size; i++) {
dictkv *kv = m->table[i];
if (kv) {
dict *ht = kv->u;
while (kv->k != MHTNO) {
mylistrefs (ht, UT64_MAX, list);
kv++;
}
}
}
} else {
dict *d = dict_getu (m, addr);
if (!d) {
return;
}
mylistrefs (d, addr, list);
for (i = 0; i < m->size; i++) {
dictkv *kv = m->table[i];
if (kv) {
while (kv->k != MHTNO) {
if (kv->k == addr) {
appendRef (list, kv->k, kv->v, kv->u);
}
// mylistrefs (ht, UT64_MAX, list);
kv++;
}
}
}
}
}
static void listxrefs(dict *m, ut64 addr, RList *list) {
int i;
if (addr == UT64_MAX) {
for (i = 0; i < m->size; i++) {
dictkv *kv = m->table[i];
if (kv) {
dict *ht = kv->u;
while (kv->k != MHTNO) {
mylistrefs (ht, UT64_MAX, list);
kv++;
}
}
}
} else {
dict *d = dict_getu (m, addr);
if (!d) {
return;
}
mylistrefs (d, addr, list);
}
}
// [from=[from:to,],]
// 10->20
static void setref(dict *m, ut64 from, ut64 to, int type) {
dict_set (m, from, to, r_anal_xrefs_type_tostring (type));
}
static void setxref(dict *m, ut64 from, ut64 to, int type) {
dictkv *kv = dict_getr (m, from);
dict *d = NULL;
if (kv) {
d = kv->u;
} else {
d = R_NEW0 (dict);
if (d) {
dict_init (d, 9, dict_free);
dict_set (m, from, to, d);
}
}
if (d) {
dict_set (d, from, to, r_anal_xrefs_type_tostring (type));
}
}
static void delref(dict *m, ut64 from, ut64 to, int type) {
dict_del (m, to);
#if 0
dictkv *kv = dict_getr (m, from);
if (kv) {
dict *ht = kv->u;
if (ht) {
dict_del (ht, to);
}
}
#endif
}
#endif
R_API int r_anal_xrefs_set (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to) {
char key[33];
if (!anal || !DB) {
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;
}
// unknown refs should not be stored. seems wrong
#if 0
if (type == R_ANAL_REF_TYPE_NULL) {
return false;
}
#endif
#if USE_DICT
setxref (anal->dict_xrefs, to, from, type);
setref (anal->dict_refs, from, to, type);
// setref (anal->dict_refs, from, to, type);
// setref (anal->dict_xrefs, from, to, type);
// setref (anal->dict_refs, to, from, type);
// eprintf ("set %llx %llx %p\n", from , to, dict_getr(anal->dict_refs, from));
// dict_getu(m, from, checkType, "ref");
#else
XREFKEY (key, sizeof (key), "ref", type, from);
sdb_array_add_num (DB, key, to, 0);
XREFKEY (key, sizeof (key), "xref", type, to);
sdb_array_add_num (DB, key, from, 0);
#endif
setxref (anal->dict_refs, from, to, type);
return true;
}
R_API int r_anal_xrefs_deln (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to) {
char key[33];
if (!anal || !DB) {
R_API int r_anal_xrefs_deln(RAnal *anal, ut64 from, ut64 to, const RAnalRefType type) {
if (!anal) {
return false;
}
#if USE_DICT
delref (anal->dict_refs, from, to, type);
delref (anal->dict_xrefs, to, from, type);
#else
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);
#endif
ht_delete_u64 (anal->dict_refs, from);
ht_delete_u64 (anal->dict_xrefs, to);
return true;
}
static int _type = -1;
static RList *_list = NULL;
static char *_kpfx = NULL;
R_API int r_anal_xref_del(RAnal *anal, ut64 from, ut64 to) {
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);
return res;
}
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);
}
}
R_API int r_anal_xrefs_from(RAnal *anal, RList *list, const char *kind, const RAnalRefType type, ut64 addr) {
listxrefs (anal->dict_refs, addr, list);
return true;
}
#if USE_DICT
R_API int r_anal_xrefs_from (RAnal *anal, RList *list, const char *kind, const RAnalRefType type, ut64 addr) {
listrefs (anal->dict_refs, addr, list);
return true;
}
#else
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) {
s = sdb_anext (ptr, &next);
if (!(ref = r_anal_ref_new ())) {
return false;
}
ref->addr = r_num_get (NULL, s);
ref->at = addr;
ref->type = type;
r_list_append (list, ref);
}
free (str);
return true;
}
#endif
R_API RList *r_anal_xrefs_get (RAnal *anal, ut64 to) {
RList *list = r_list_newf (r_anal_ref_free);
R_API RList *r_anal_xrefs_get(RAnal *anal, ut64 to) {
RList *list = r_anal_ref_list_new ();
if (!list) {
return NULL;
}
#if USE_DICT
// listrefs (anal->dict_refs, to, list);
// XXX, one or the other?
listxrefs (anal->dict_xrefs, to, list);
// listrefs (anal->dict_xrefs, to, list);
#else
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);
#endif
if (r_list_empty (list)) {
r_list_free (list);
list = NULL;
@ -309,22 +182,12 @@ R_API RList *r_anal_xrefs_get (RAnal *anal, ut64 to) {
return list;
}
R_API RList *r_anal_refs_get (RAnal *anal, ut64 from) {
RList *list = r_list_newf (r_anal_ref_free);
R_API RList *r_anal_refs_get(RAnal *anal, ut64 from) {
RList *list = r_anal_ref_list_new ();
if (!list) {
return NULL;
}
#if USE_DICT
// listrefs (anal->dict_refs, from, list);
listxrefs (anal->dict_xrefs, from, list);
// eprintf ("refs_get from %llx %d\n", from, r_list_length (list));
#else
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_NULL, from);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CODE, from);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_CALL, from);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_DATA, from);
r_anal_xrefs_from (anal, list, "ref", R_ANAL_REF_TYPE_STRING, from);
#endif
listxrefs (anal->dict_refs, from, list);
if (r_list_empty (list)) {
r_list_free (list);
list = NULL;
@ -332,21 +195,12 @@ R_API RList *r_anal_refs_get (RAnal *anal, ut64 from) {
return list;
}
R_API RList *r_anal_xrefs_get_from (RAnal *anal, ut64 to) {
RList *list = r_list_newf (NULL);
R_API RList *r_anal_xrefs_get_from(RAnal *anal, ut64 to) {
RList *list = r_anal_ref_list_new ();
if (!list) {
return NULL;
}
#if USE_DICT
listxrefs (anal->dict_xrefs, to, list);
//listrefs (anal->dict_refs, to, list);
#else
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);
#endif
listxrefs (anal->dict_refs, to, list);
if (r_list_empty (list)) {
r_list_free (list);
list = NULL;
@ -354,174 +208,63 @@ R_API RList *r_anal_xrefs_get_from (RAnal *anal, ut64 to) {
return list;
}
R_API bool r_anal_xrefs_init(RAnal *anal) {
sdb_reset (DB);
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_quiet(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);
char * type = strchr (k, '.');
if (type) {
type = strdup (type + 1);
char *t = strchr (type, '.');
if (t) {
*t = ' ';
}
char *T = (char *)r_str_rchr (type, NULL, '.');
if (T) {
T = (char *)r_str_rchr (T, NULL, '.');
if (T) {
*T = 0;
anal->cb_printf ("0x%08"PFMT64x" -> 0x%08"PFMT64x" %s\n", src, dst, type);
}
} else {
if (t) {
*t = 0;
}
}
anal->cb_printf ("0x%08"PFMT64x" -> 0x%08"PFMT64x" %s\n", src, dst, type);
free (type);
}
}
}
return 1;
}
static int xrefs_list_cb_normal(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);
char * type = strchr (k, '.');
if (type) {
type = strdup (type + 1);
char *ot = strchr (type, '.');
if (ot) {
*ot = ' ';
}
char *t = (char *)r_str_rchr (type, NULL, '.');
if (t) {
t = (char *)r_str_rchr (t, NULL, '.');
if (t) {
*t = 0;
}
} else {
if (ot) {
*ot = 0;
}
}
{
char *name = anal->coreb.getNameDelta (anal->coreb.core, src);
r_str_replace_char (name, ' ', 0);
anal->cb_printf ("%40s", name? name: "");
free (name);
anal->cb_printf (" 0x%"PFMT64x" -> %9s -> 0x%"PFMT64x, src, type, dst);
name = anal->coreb.getNameDelta (anal->coreb.core, dst);
r_str_replace_char (name, ' ', 0);
if (name && *name) {
anal->cb_printf (" %s\n", name);
} else {
anal->cb_printf ("\n");
}
free (name);
}
free (type);
}
}
}
return 1;
}
static bool xrefs_list_cb_json(RAnal *anal, bool is_first, const char *k, const char *v) {
ut64 dst, src = r_num_get (NULL, v);
if (strlen (k) > 8) {
const char *p = r_str_rchr (k, NULL, '.');
if (p) {
if (is_first) {
is_first = false;
} else {
anal->cb_printf (",");
}
dst = r_num_get (NULL, p + 1);
sscanf (p + 1, "0x%"PFMT64x, &dst);
anal->cb_printf ("\"%"PFMT64d"\":%"PFMT64d, src, dst);
}
}
return is_first;
}
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) {
#if USE_DICT
bool is_first = true;
RListIter *iter;
RAnalRef *ref;
RList *list = r_list_new();
RList *list = r_anal_ref_list_new();
listxrefs (anal->dict_xrefs, UT64_MAX, list);
if (rad == 'j') {
anal->cb_printf ("{");
}
r_list_foreach (list, iter, ref) {
int type = ref->type? ref->type: ' ';
r_cons_printf ("%c 0x%08llx -> 0x%08llx\n", type, ref->at, ref->addr);
int t = ref->type ? ref->type: ' ';
switch (rad) {
case '*':
anal->cb_printf ("ax%c 0x%"PFMT64x" 0x%"PFMT64x"\n",
t, ref->at, ref->addr);
break;
case '\0':
{
char *name = anal->coreb.getNameDelta (anal->coreb.core, ref->at);
r_str_replace_char (name, ' ', 0);
anal->cb_printf ("%40s", name? name: "");
free (name);
anal->cb_printf (" 0x%"PFMT64x" -> %9s -> 0x%"PFMT64x, ref->at, analref_toString (t), ref->addr);
name = anal->coreb.getNameDelta (anal->coreb.core, ref->addr);
r_str_replace_char (name, ' ', 0);
if (name && *name) {
anal->cb_printf (" %s\n", name);
} else {
anal->cb_printf ("\n");
}
free (name);
}
break;
case 'q':
anal->cb_printf ("0x%08"PFMT64x" -> 0x%08"PFMT64x" %s\n", ref->at, ref->addr, analref_toString (t));
break;
case 'j':
{
if (is_first) {
is_first = false;
} else {
anal->cb_printf (",");
}
anal->cb_printf ("\"%"PFMT64d"\":%"PFMT64d, ref->at, ref->addr);
}
break;
default:
break;
}
}
if (rad == 'j') {
anal->cb_printf ("}\n");
}
r_list_free (list);
#else
switch (rad) {
case 1:
case '*':
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_rad, anal);
break;
case '\0':
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_normal, anal);
break;
case 'q':
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_quiet, anal);
break;
case 'j':
{
anal->cb_printf ("{");
bool is_first = true;
SdbListIter *sdb_iter;
SdbKv *kv;
SdbList *sdb_list = sdb_foreach_match (DB, "^ref.", false);
ls_foreach (sdb_list, sdb_iter, kv) {
is_first = xrefs_list_cb_json (anal, is_first, kv->key, kv->value);
}
ls_free (sdb_list);
anal->cb_printf ("}\n");
}
break;
default:
sdb_foreach (DB, (SdbForeachCallback)xrefs_list_cb_plain, anal);
break;
}
#endif
}
R_API const char *r_anal_xrefs_type_tostring (char type) {
R_API const char *r_anal_xrefs_type_tostring(RAnalRefType type) {
switch (type) {
case R_ANAL_REF_TYPE_CODE:
return "JMP";
@ -537,20 +280,98 @@ R_API const char *r_anal_xrefs_type_tostring (char type) {
}
}
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 ++;
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;
}
return 1;
}
R_API bool r_anal_xrefs_init(RAnal *anal) {
SdbHash *tmp;
ht_free (anal->dict_refs);
anal->dict_refs = NULL;
ht_free (anal->dict_xrefs);
anal->dict_xrefs = NULL;
tmp = ht_new (NULL, xrefs_ht_free, NULL);
if (!tmp) {
return false;
}
anal->dict_refs = tmp;
tmp = ht_new (NULL, xrefs_ht_free, NULL);
if (!tmp) {
ht_free (anal->dict_refs);
anal->dict_refs = NULL;
return false;
}
anal->dict_xrefs = tmp;
return true;
}
R_API int r_anal_xrefs_count(RAnal *anal) {
CountState cs = { anal, 0 };
sdb_foreach (DB, (SdbForeachCallback)countcb, &cs);
return cs.count;
return anal->dict_xrefs->count;
}
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;
}
static RList *fcn_get_refs(RAnalFunction *fcn, SdbHash *ht) {
RListIter *iter;
RAnalBlock *bb;
RList *list = r_anal_ref_list_new ();
if (!list) {
return NULL;
}
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);
}
}
return list;
}
R_API RList *r_anal_fcn_get_refs(RAnal *anal, RAnalFunction *fcn) {
return fcn_get_refs (fcn, anal->dict_refs);
}
R_API RList *r_anal_fcn_get_xrefs(RAnal *anal, RAnalFunction *fcn) {
return fcn_get_refs (fcn, anal->dict_xrefs);
}
R_API RList *r_anal_fcn_get_refs_sorted(RAnal *anal, RAnalFunction *fcn) {
RList *l = r_anal_fcn_get_refs (anal, fcn);
r_list_sort (l, (RListComparator)ref_cmp);
return l;
}
R_API RList *r_anal_fcn_get_xrefs_sorted(RAnal *anal, RAnalFunction *fcn) {
RList *l = r_anal_fcn_get_xrefs (anal, fcn);
r_list_sort (l, (RListComparator)ref_cmp);
return l;
}

View File

@ -318,12 +318,92 @@ R_API ut64 r_core_anal_address(RCore *core, ut64 addr) {
return types;
}
static bool blacklisted_word(char* name) {
const char * list[] = {
"__stack_chk_guard", "__stderrp", "__stdinp", "__stdoutp", "_DefaultRuneLocale"
};
int i;
for (i = 0; i < sizeof (list) / sizeof (list[0]); i++) {
if (strstr (name, list[i])) { return true; }
}
return false;
}
static char *anal_fcn_autoname(RCore *core, RAnalFunction *fcn, int dump) {
int use_getopt = 0;
int use_isatty = 0;
char *do_call = NULL;
RAnalRef *ref;
RListIter *iter;
RList *refs = r_anal_fcn_get_refs_sorted (core->anal, fcn);
r_list_foreach (refs, iter, ref) {
RFlagItem *f = r_flag_get_i (core->flags, ref->addr);
if (f) {
if (dump) {
r_cons_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" %s\n", ref->at, ref->addr, f->name);
}
if (blacklisted_word (f->name)) {
break;
}
if (strstr (f->name, ".isatty")) {
use_isatty = 1;
}
if (strstr (f->name, ".getopt")) {
use_getopt = 1;
}
if (!strncmp (f->name, "method.", 7)) {
free (do_call);
do_call = strdup (f->name + 7);
break;
}
if (!strncmp (f->name, "str.", 4)) {
free (do_call);
do_call = strdup (f->name + 4);
break;
}
if (!strncmp (f->name, "sym.imp.", 8)) {
free (do_call);
do_call = strdup (f->name + 8);
break;
}
if (!strncmp (f->name, "reloc.", 6)) {
free (do_call);
do_call = strdup (f->name + 6);
break;
}
}
}
r_list_free (refs);
// TODO: append counter if name already exists
if (use_getopt) {
RFlagItem *item = r_flag_get (core->flags, "main");
free (do_call);
// if referenced from entrypoint. this should be main
if (item && item->offset == fcn->addr) {
return strdup ("main"); // main?
}
return strdup ("parse_args"); // main?
}
if (use_isatty) {
char *ret = r_str_newf ("sub.setup_tty_%s_%x", do_call, fcn->addr & 0xfff);
free (do_call);
return ret;
}
if (do_call) {
char *ret = r_str_newf ("sub.%s_%x", do_call, fcn->addr & 0xfff);
free (do_call);
return ret;
}
return NULL;
}
/*this only autoname those function that start with fcn.* or sym.func.* */
R_API void r_core_anal_autoname_all_fcns(RCore *core) {
RListIter *it;
RAnalFunction *fcn;
r_list_foreach (core->anal->fcns, it, fcn) {
char *name = r_core_anal_fcn_autoname (core, fcn->addr, 0);
char *name = anal_fcn_autoname (core, fcn, 0);
if (name && (!strncmp (fcn->name, "fcn.", 4) || \
!strncmp (fcn->name, "sym.func.", 9))) {
r_flag_rename (core->flags, r_flag_get (core->flags, fcn->name), name);
@ -335,86 +415,12 @@ R_API void r_core_anal_autoname_all_fcns(RCore *core) {
}
}
static bool blacklisted_word(char* name) {
const char * list[] = {
"__stack_chk_guard", "__stderrp", "__stdinp", "__stdoutp", "_DefaultRuneLocale"
};
int i;
for (i = 0; i < sizeof (list) / sizeof (list[0]); i++) {
if (strstr (name, list[i])) { return true; }
}
return false;
}
/* suggest a name for the function at the address 'addr'.
* If dump is true, every strings associated with the function is printed */
R_API char *r_core_anal_fcn_autoname(RCore *core, ut64 addr, int dump) {
int use_getopt = 0;
int use_isatty = 0;
char *do_call = NULL;
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, addr, 0);
if (fcn) {
RAnalRef *ref;
RListIter *iter;
RList *refs = r_anal_fcn_get_refs (core->anal, fcn);
r_list_foreach (refs, iter, ref) {
RFlagItem *f = r_flag_get_i (core->flags, ref->addr);
if (f) {
if (dump) {
r_cons_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" %s\n", ref->at, ref->addr, f->name);
}
if (blacklisted_word (f->name)) {
break;
}
if (strstr (f->name, ".isatty")) {
use_isatty = 1;
}
if (strstr (f->name, ".getopt")) {
use_getopt = 1;
}
if (!strncmp (f->name, "method.", 7)) {
free (do_call);
do_call = strdup (f->name + 7);
break;
}
if (!strncmp (f->name, "str.", 4)) {
free (do_call);
do_call = strdup (f->name + 4);
break;
}
if (!strncmp (f->name, "sym.imp.", 8)) {
free (do_call);
do_call = strdup (f->name + 8);
break;
}
if (!strncmp (f->name, "reloc.", 6)) {
free (do_call);
do_call = strdup (f->name + 6);
break;
}
}
}
r_list_free (refs);
// TODO: append counter if name already exists
if (use_getopt) {
RFlagItem *item = r_flag_get (core->flags, "main");
free (do_call);
// if referenced from entrypoint. this should be main
if (item && item->offset == addr) {
return strdup ("main"); // main?
}
return strdup ("parse_args"); // main?
}
if (use_isatty) {
char *ret = r_str_newf ("sub.setup_tty_%s_%x", do_call, addr & 0xfff);
free (do_call);
return ret;
}
if (do_call) {
char *ret = r_str_newf ("sub.%s_%x", do_call, addr & 0xfff);
free (do_call);
return ret;
}
return anal_fcn_autoname (core, fcn, dump);
}
return NULL;
}
@ -437,7 +443,7 @@ static void r_anal_set_stringrefs(RCore *core, RAnalFunction *fcn) {
r_list_foreach (refs, iter, ref) {
if (ref->type == R_ANAL_REF_TYPE_DATA &&
r_bin_is_string (core->bin, ref->addr)) {
ref->type = R_ANAL_REF_TYPE_STRING;
r_anal_xrefs_set (core->anal, ref->at, ref->addr, R_ANAL_REF_TYPE_STRING);
}
}
r_list_free (refs);
@ -509,34 +515,55 @@ static int r_anal_try_get_fcn(RCore *core, RAnalRef *ref, int fcndepth, int refd
}
static int r_anal_analyze_fcn_refs(RCore *core, RAnalFunction *fcn, int depth) {
RListIter *iter, *tmp;
RListIter *iter;
RAnalRef *ref;
RList *refs = r_anal_fcn_get_refs (core->anal, fcn);
r_list_foreach_safe (refs, iter, tmp, ref) {
if (ref->addr != UT64_MAX) {
switch (ref->type) {
case 'd':
if (core->anal->opt.followdatarefs) {
r_anal_try_get_fcn (core, ref, depth, 2);
}
break;
case R_ANAL_REF_TYPE_CODE:
case R_ANAL_REF_TYPE_CALL:
r_core_anal_fcn (core, ref->addr, ref->at, ref->type, depth-1);
break;
default:
break;
}
// TODO: fix memleak here, fcn not freed even though it is
// added in core->anal->fcns which is freed in r_anal_free()
r_list_foreach (refs, iter, ref) {
if (ref->addr == UT64_MAX) {
continue;
}
switch (ref->type) {
case 'd':
if (core->anal->opt.followdatarefs) {
r_anal_try_get_fcn (core, ref, depth, 2);
}
break;
case R_ANAL_REF_TYPE_CODE:
case R_ANAL_REF_TYPE_CALL:
r_core_anal_fcn (core, ref->addr, ref->at, ref->type, depth-1);
break;
default:
break;
}
// TODO: fix memleak here, fcn not freed even though it is
// added in core->anal->fcns which is freed in r_anal_free()
}
r_list_free (refs);
return 1;
}
static void function_rename(RFlag *flags, RAnalFunction *fcn) {
const char *locname = "loc.";
const size_t locsize = strlen (locname);
char *fcnname = fcn->name;
if (strncmp (fcn->name, locname, locsize) == 0) {
const char *fcnpfx, *restofname;
RFlagItem *f;
fcn->type = R_ANAL_FCN_TYPE_FCN;
fcnpfx = r_anal_fcn_type_tostring (fcn->type);
restofname = fcn->name + locsize;
fcn->name = r_str_newf ("%s.%s", fcnpfx, restofname);
f = r_flag_get_i (flags, fcn->addr);
r_flag_rename (flags, f, fcn->name);
free (fcnname);
}
}
static int core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int depth) {
if (depth < 0) {
// printf ("Too deep for 0x%08"PFMT64x"\n", at);
@ -581,7 +608,6 @@ static int core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int depth
}
do {
RFlagItem *f;
RAnalRef *ref;
int delta = r_anal_fcn_size (fcn);
// XXX hack slow check io error
if (core->io->va) {
@ -690,13 +716,6 @@ static int core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int depth
/* New function: Add initial xref */
if (from != UT64_MAX) {
// We shuold not use fcn->xrefs .. because that should be only via api (on top of sdb)
// the concepts of refs and xrefs are a bit twisted in the old implementation
ref = r_anal_ref_new ();
if (!ref) {
eprintf ("Error: new (xref)\n");
goto error;
}
if (fcn->type == R_ANAL_FCN_TYPE_LOC) {
RAnalFunction *f = r_anal_get_fcn_in (core->anal, from, -1);
if (f) {
@ -707,11 +726,7 @@ static int core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int depth
r_list_sort (f->fcn_locs, &cmpfcn);
}
}
ref->addr = from;
ref->at = fcn->addr;
ref->type = reftype;
// XXX this is creating dupped entries in the refs list with invalid reftypes, wtf?
r_anal_xrefs_set (core->anal, reftype, from, fcn->addr);
r_anal_xrefs_set (core->anal, from, fcn->addr, reftype);
}
// XXX: this is wrong. See CID 1134565
r_anal_fcn_insert (core->anal, fcn);
@ -1468,7 +1483,6 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
bool use_esil = r_config_get_i (core->config, "anal.esil");
RAnalFunction *fcn;
RListIter *iter;
RList *xrefs = NULL;
//update bits based on the core->offset otherwise we could have the
//last value set and blow everything up
@ -1514,36 +1528,26 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
fcn = r_anal_get_fcn_in (core->anal, at, 0);
if (fcn) {
if (fcn->addr == at) {
// if the function was already analyzed as a "loc.",
// convert it to function and rename it to "fcn.",
// because we found a call to this address
if (reftype == R_ANAL_REF_TYPE_CALL && fcn->type == R_ANAL_FCN_TYPE_LOC) {
function_rename (core->flags, fcn);
}
return 0; // already analyzed function
}
if (r_anal_fcn_is_in_offset (fcn, from)) { // inner function
RAnalRef *ref;
// XXX: use r_anal-xrefs api and sdb
// If the xref is new, add it
// avoid dupes
xrefs = r_anal_fcn_get_xrefs (core->anal, fcn);
r_list_foreach (xrefs, iter, ref) {
if (from == ref->addr) {
r_list_free (xrefs);
return true;
}
RList *l = r_anal_xrefs_get (core->anal, from);
if (l && !r_list_empty (l)) {
r_list_free (l);
return true;
}
r_list_free (xrefs);
r_list_free (l);
// we should analyze and add code ref otherwise aaa != aac
if (from != UT64_MAX) {
// We shuold not use fcn->xrefs .. because that should be only via api (on top of sdb)
// the concepts of refs and xrefs are a bit twisted in the old implementation
ref = r_anal_ref_new ();
if (ref) {
ref->addr = from;
ref->at = fcn->addr;
ref->type = reftype;
// XXX this is creating dupped entries in the refs list with invalid reftypes, wtf?
r_anal_xrefs_set (core->anal, reftype, from, fcn->addr);
} else {
eprintf ("Error: new (xref)\n");
}
r_anal_xrefs_set (core->anal, from, fcn->addr, reftype);
}
return true;
}
@ -1581,7 +1585,7 @@ R_API void r_core_anal_codexrefs(RCore *core, ut64 addr, int fmt) {
const char *me = fcn->name;
RListIter *iter;
RAnalRef *ref;
RList *refs = r_anal_fcn_get_refs (core->anal, fcn);
RList *refs = r_anal_fcn_get_refs_sorted (core->anal, fcn);
r_cons_printf ("e graph.layout=1\n");
r_cons_printf ("ag-\n");
r_cons_printf ("agn %s\n", me);
@ -1599,6 +1603,7 @@ R_API void r_core_anal_codexrefs(RCore *core, ut64 addr, int fmt) {
r_cons_printf ("agn %s\n", src);
r_cons_printf ("age %s %s\n", src, me);
}
r_list_free (list);
}
}
@ -1653,7 +1658,7 @@ repeat:
if (addr != UT64_MAX && addr != fcni->addr) {
continue;
}
RList *refs = r_anal_fcn_get_refs (core->anal, fcni);
RList *refs = r_anal_fcn_get_refs_sorted (core->anal, fcni);
if (!fmt) {
r_cons_printf ("0x%08"PFMT64x"\n", fcni->addr);
} else if (fmt == 1 && isGML) {
@ -1783,7 +1788,7 @@ repeat:
}
} else if (fmt == 2) {
if (fr) {
RList *refs1 = r_anal_fcn_get_refs (core->anal, fr);
RList *refs1 = r_anal_fcn_get_refs_sorted (core->anal, fr);
if (!hideempty || (hideempty && r_list_length (refs1) > 0)) {
if (usenames) {
r_cons_printf ("%s\"%s\"", first2?",":"", fr->name);
@ -1896,10 +1901,10 @@ static int fcnlist_gather_metadata(RAnal *anal, RList *fcns) {
numcallrefs++;
}
}
r_list_free (refs);
fcn->meta.numcallrefs = numcallrefs;
xrefs = r_anal_xrefs_get (anal, fcn->addr);
fcn->meta.numrefs = xrefs? xrefs->length: 0;
r_list_free (refs);
r_list_free (xrefs);
// Determine the bounds of the functions address space
@ -2070,7 +2075,7 @@ static int fcn_print_json(RCore *core, RAnalFunction *fcn) {
fcn->diff->type == R_ANAL_DIFF_TYPE_UNMATCH?"UNMATCH":"NEW");
}
int outdegree = 0;
refs = r_anal_fcn_get_refs (core->anal, fcn);
refs = r_anal_fcn_get_refs_sorted (core->anal, fcn);
if (!r_list_empty (refs)) {
r_cons_printf (",\"callrefs\":[");
r_list_foreach (refs, iter, refi) {
@ -2102,7 +2107,7 @@ static int fcn_print_json(RCore *core, RAnalFunction *fcn) {
r_list_free (refs);
int indegree = 0;
xrefs = r_anal_fcn_get_xrefs (core->anal, fcn);
xrefs = r_anal_fcn_get_xrefs_sorted (core->anal, fcn);
if (!r_list_empty (xrefs)) {
first = true;
r_cons_printf (",\"codexrefs\":[");
@ -2206,7 +2211,7 @@ static int fcn_print_detail(RCore *core, RAnalFunction *fcn) {
/* Show references */
RListIter *refiter;
RAnalRef *refi;
RList *refs = r_anal_fcn_get_refs (core->anal, fcn);
RList *refs = r_anal_fcn_get_refs_sorted (core->anal, fcn);
r_list_foreach (refs, refiter, refi) {
switch (refi->type) {
case R_ANAL_REF_TYPE_CALL:
@ -2220,9 +2225,9 @@ static int fcn_print_detail(RCore *core, RAnalFunction *fcn) {
break;
}
}
r_list_free (refs);
/*Saving Function stack frame*/
r_cons_printf ("afS %"PFMT64d" @ 0x%"PFMT64x"\n", fcn->maxstack, fcn->addr);
r_list_free (refs);
free (name);
return 0;
}
@ -2253,7 +2258,7 @@ static int fcn_print_legacy(RCore *core, RAnalFunction *fcn) {
r_cons_printf ("\nend-bbs: %d", ebbs);
r_cons_printf ("\ncall-refs: ");
int outdegree = 0;
refs = r_anal_fcn_get_refs (core->anal, fcn);
refs = r_anal_fcn_get_refs_sorted (core->anal, fcn);
r_list_foreach (refs, iter, refi) {
if (refi->type == R_ANAL_REF_TYPE_CALL) {
outdegree++;
@ -2273,7 +2278,7 @@ static int fcn_print_legacy(RCore *core, RAnalFunction *fcn) {
int indegree = 0;
r_cons_printf ("\ncode-xrefs: ");
xrefs = r_anal_fcn_get_xrefs (core->anal, fcn);
xrefs = r_anal_fcn_get_xrefs_sorted (core->anal, fcn);
r_list_foreach (xrefs, iter, refi) {
if (refi->type == R_ANAL_REF_TYPE_CODE || refi->type == R_ANAL_REF_TYPE_CALL) {
indegree++;
@ -2289,6 +2294,7 @@ static int fcn_print_legacy(RCore *core, RAnalFunction *fcn) {
r_cons_printf ("0x%08"PFMT64x" ", refi->addr);
}
}
r_list_free (xrefs);
if (fcn->type == R_ANAL_FCN_TYPE_FCN || fcn->type == R_ANAL_FCN_TYPE_SYM) {
int args_count = r_anal_var_count (core->anal, fcn, 'b', 1);
@ -2312,7 +2318,6 @@ static int fcn_print_legacy(RCore *core, RAnalFunction *fcn) {
r_cons_printf ("function: %s", fcn->diff->name);
}
}
r_list_free (xrefs);
free (name);
return 0;
}
@ -2618,8 +2623,8 @@ static int core_anal_followptr(RCore *core, int type, ut64 at, ut64 ptr, ut64 re
return false;
}
if (ref == UT64_MAX || ptr == ref) {
const int t = code? type? type: 'c': 'd';
r_anal_ref_add (core->anal, ptr, at, t);
const RAnalRefType t = code? type? type: R_ANAL_REF_TYPE_CODE: R_ANAL_REF_TYPE_DATA;
r_anal_xrefs_set (core->anal, at, ptr, t);
return true;
}
if (depth < 1) {
@ -2961,7 +2966,7 @@ R_API int r_core_anal_search_xrefs(RCore *core, ut64 from, ut64 to, int rad) {
}
// Add to SDB
if (xref_to) {
r_anal_xrefs_set (core->anal, type, at, xref_to);
r_anal_xrefs_set (core->anal, at, xref_to, type);
}
} else if (rad == 'j') {
// Output JSON
@ -3575,7 +3580,7 @@ static int esilbreak_mem_read(RAnalEsil *esil, ut64 addr, ut8 *buf, int len) {
bool validRef = false;
if (trace && myvalid (mycore->io, refptr)) {
if (ntarget == UT64_MAX || ntarget == refptr) {
r_anal_ref_add (mycore->anal, refptr, esil->address, 'd');
r_anal_xrefs_set (mycore->anal, esil->address, refptr, R_ANAL_REF_TYPE_DATA);
str[0] = 0;
if (r_io_read_at (mycore->io, refptr, str, sizeof (str)) < 1) {
eprintf ("Invalid read\n");
@ -3590,7 +3595,7 @@ static int esilbreak_mem_read(RAnalEsil *esil, ut64 addr, ut8 *buf, int len) {
/** resolve ptr */
if (ntarget == UT64_MAX || ntarget == addr || (ntarget == UT64_MAX && !validRef)) {
r_anal_ref_add (mycore->anal, addr, esil->address, 'd');
r_anal_xrefs_set (mycore->anal, esil->address, addr, R_ANAL_REF_TYPE_DATA);
}
}
return 0; // fallback
@ -3929,15 +3934,15 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
// arm64
if (core->anal->cur && arch == R2_ARCH_ARM64) {
if (CHECKREF (ESIL->cur)) {
r_anal_ref_add (core->anal, ESIL->cur, cur, 's');
r_anal_xrefs_set (core->anal, cur, ESIL->cur, R_ANAL_REF_TYPE_STRING);
}
} else if ((target && op.ptr == ntarget) || !target) {
// if (core->anal->cur && strcmp (core->anal->cur->arch, "arm")) {
if (CHECKREF (ESIL->cur)) {
if (op.ptr && r_io_is_valid_offset (core->io, op.ptr, !core->anal->opt.noncode)) {
r_anal_ref_add (core->anal, op.ptr, cur,'s');
r_anal_xrefs_set (core->anal, cur, op.ptr, R_ANAL_REF_TYPE_STRING);
} else {
r_anal_ref_add (core->anal, ESIL->cur, cur, 's');
r_anal_xrefs_set (core->anal, cur, ESIL->cur, R_ANAL_REF_TYPE_STRING);
}
}
}
@ -3952,7 +3957,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
ut64 dst = ESIL->cur;
if ((target && dst == ntarget) || !target) {
if (CHECKREF (dst)) {
r_anal_ref_add (core->anal, dst, cur, 'd');
r_anal_xrefs_set (core->anal, cur, dst, R_ANAL_REF_TYPE_DATA);
}
}
// if (cfg_anal_strings) {
@ -3974,7 +3979,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
RFlagItem *f;
char *str;
if (CHECKREF (dst) || CHECKREF (cur)) {
r_anal_ref_add (core->anal, dst, cur, 'd');
r_anal_xrefs_set (core->anal, cur, dst, R_ANAL_REF_TYPE_DATA);
if (cfg_anal_strings) {
add_string_ref (core, dst);
}
@ -3999,7 +4004,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
ut64 dst = esilbreak_last_read;
if (dst != UT64_MAX && CHECKREF (dst)) {
if (myvalid (mycore->io, dst)) {
r_anal_ref_add (core->anal, dst, cur, 'd');
r_anal_xrefs_set (core->anal, cur, dst, R_ANAL_REF_TYPE_DATA);
if (cfg_anal_strings) {
add_string_ref (core, dst);
}
@ -4008,7 +4013,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
dst = esilbreak_last_data;
if (dst != UT64_MAX && CHECKREF (dst)) {
if (myvalid (mycore->io, dst)) {
r_anal_ref_add (core->anal, dst, cur, 'd');
r_anal_xrefs_set (core->anal, cur, dst, R_ANAL_REF_TYPE_DATA);
if (cfg_anal_strings) {
add_string_ref (core, dst);
}
@ -4021,7 +4026,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
ut64 dst = op.jump;
if (CHECKREF (dst)) {
if (myvalid (core->io, dst)) {
r_anal_ref_add (core->anal, dst, cur, 'c');
r_anal_xrefs_set (core->anal, cur, dst, R_ANAL_REF_TYPE_CODE);
}
}
}
@ -4031,7 +4036,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
ut64 dst = op.jump;
if (CHECKREF (dst)) {
if (myvalid (core->io, dst)) {
r_anal_ref_add (core->anal, dst, cur, 'C');
r_anal_xrefs_set (core->anal, cur, dst, R_ANAL_REF_TYPE_CALL);
}
ESIL->old = cur + op.size;
getpcfromstack (core, ESIL);
@ -4055,7 +4060,7 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
(op.type & R_ANAL_OP_TYPE_MASK) == R_ANAL_OP_TYPE_UCALL
? R_ANAL_REF_TYPE_CALL
: R_ANAL_REF_TYPE_CODE;
r_anal_ref_add (core->anal, dst, cur, ref);
r_anal_xrefs_set (core->anal, cur, dst, ref);
}
}
}

View File

@ -560,7 +560,8 @@ static const char *help_msg_ax[] = {
"Usage:", "ax[?d-l*]", " # see also 'afx?'",
"ax", "", "list refs",
"ax", " addr [at]", "add code ref pointing to addr (from curseek)",
"ax-", " [at]", "clean all refs (or refs from addr)",
"ax-", " [at]", "clean all refs/refs from addr",
"ax-*", "", "clean all refs/refs",
"axc", " addr [at]", "add code jmp ref // unused?",
"axC", " addr [at]", "add code call ref",
"axg", " [addr]", "show xrefs graph to reach current function",
@ -571,7 +572,6 @@ static const char *help_msg_ax[] = {
"axF", " [flg-glob]", "find data/code references of flags",
"axt", " [addr]", "find data/code references to this address",
"axf", " [addr]", "find data/code references from this address",
"axk", " [query]", "perform sdb query",
"ax*", "", "output radare commands",
NULL
};
@ -2571,7 +2571,7 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
if (fcn) {
RAnalRef *ref;
RListIter *iter;
RList *refs = r_anal_fcn_get_refs (core->anal, fcn);
RList *refs = r_anal_fcn_get_refs_sorted (core->anal, fcn);
r_list_foreach (refs, iter, ref) {
if (input[2] == 'j') {
r_cons_printf ("{\"type\":\"%c\",\"from\":%"PFMT64d",\"to\":%"PFMT64d"}%s",
@ -2602,10 +2602,11 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
ut64 a, b;
char *mi = strdup (input);
if (mi && mi[3] == ' ' && (p = strchr (mi + 4, ' '))) {
RAnalRefType reftype = r_anal_xrefs_type (input[2]);
*p = 0;
a = r_num_math (core->num, mi + 3);
b = r_num_math (core->num, p + 1);
r_anal_xrefs_set (core->anal, input[2], a, b);
r_anal_xrefs_set (core->anal, a, b, reftype);
} else {
r_core_cmd_help (core, help_msg_afx);
}
@ -2621,7 +2622,7 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
*p = 0;
a = r_num_math (core->num, mi);
b = r_num_math (core->num, p + 1);
r_anal_xrefs_deln (core->anal, -1, a, b);
r_anal_xrefs_deln (core->anal, a, b, -1);
} else {
eprintf ("Usage: afx- [src] [dst]\n");
}
@ -2687,7 +2688,7 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
if (fcn) {
RAnalRef *ref;
RListIter *iter;
RList *refs = r_anal_fcn_get_refs (core->anal, fcn);
RList *refs = r_anal_fcn_get_refs_sorted (core->anal, fcn);
r_list_foreach (refs, iter, ref) {
if (ref->addr == UT64_MAX) {
//eprintf ("Warning: ignore 0x%08"PFMT64x" call 0x%08"PFMT64x"\n", ref->at, ref->addr);
@ -2707,7 +2708,7 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
if (f) {
RListIter *iter;
RAnalRef *ref;
RList *refs1 = r_anal_fcn_get_refs (core->anal, f);
RList *refs1 = r_anal_fcn_get_refs_sorted (core->anal, f);
r_list_foreach (refs1, iter, ref) {
if (!r_io_is_valid_offset (core->io, ref->addr, !core->anal->opt.noncode)) {
continue;
@ -4748,14 +4749,14 @@ static void _anal_calls(RCore *core, ut64 addr, ut64 addr_end) {
if (!anal_is_bad_call (core, from, to, addr, buf, bufi)) {
fcn = r_anal_get_fcn_in (core->anal, op.jump, R_ANAL_FCN_TYPE_ROOT);
if (!fcn) {
r_core_anal_fcn (core, op.jump, addr, R_ANAL_REF_TYPE_NULL, depth);
r_core_anal_fcn (core, op.jump, addr, R_ANAL_REF_TYPE_CALL, depth);
}
}
#else
// add xref here
r_anal_xrefs_set (core->anal, R_ANAL_REF_TYPE_CALL, addr, op.jump);
r_anal_xrefs_set (core->anal, addr, op.jump, R_ANAL_REF_TYPE_CALL);
if (r_io_is_valid_offset (core->io, op.jump, 1)) {
r_core_anal_fcn (core, op.jump, addr, R_ANAL_REF_TYPE_NULL, depth);
r_core_anal_fcn (core, op.jump, addr, R_ANAL_REF_TYPE_CALL, depth);
}
#endif
}
@ -5086,7 +5087,7 @@ static bool cmd_anal_refs(RCore *core, const char *input) {
RAnalRef *ref;
char *cp_inp = strdup (input + 1);
char *ptr = r_str_trim_head (cp_inp);
if (!strcmp (ptr, "*")) {
if (!strcmp (ptr, "*")) { // "ax-*"
r_anal_xrefs_init (core->anal);
} else {
int n = r_str_word_set0 (ptr);
@ -5106,14 +5107,14 @@ static bool cmd_anal_refs(RCore *core, const char *input) {
if (list) {
r_list_foreach (list, iter, ref) {
if (from != UT64_MAX && from == ref->addr) {
r_anal_ref_del (core->anal, ref->addr, ref->at);
r_anal_xref_del (core->anal, ref->addr, ref->at);
}
if (from == UT64_MAX) {
r_anal_ref_del (core->anal, ref->addr, ref->at);
r_anal_xref_del (core->anal, ref->addr, ref->at);
}
}
r_list_free (list);
}
r_list_free (list);
}
free (cp_inp);
} break;
@ -5128,15 +5129,6 @@ static bool cmd_anal_refs(RCore *core, const char *input) {
sdb_free (db);
}
break;
case 'k': // "axk"
if (input[1] == '?') {
eprintf ("Usage: axk [query]\n");
} else if (input[1] == ' ') {
sdb_query (core->anal->sdb_xrefs, input + 2);
} else {
r_core_anal_ref_list (core, 'k');
}
break;
case '\0': // "ax"
case 'j': // "axj"
case 'q': // "axq"
@ -5183,7 +5175,7 @@ static bool cmd_anal_refs(RCore *core, const char *input) {
r_parse_filter (core->parser, core->flags,
asmop.buf_asm, str, sizeof (str), core->print->big_endian);
r_cons_printf ("{\"from\":%" PFMT64u ",\"type\":\"%s\",\"opcode\":\"%s\"", ref->addr, r_anal_ref_to_string (ref->type), str);
r_cons_printf ("{\"from\":%" PFMT64u ",\"type\":\"%s\",\"opcode\":\"%s\"", ref->addr, r_anal_xrefs_type_tostring (ref->type), str);
if (fcn) {
r_cons_printf (",\"fcn_addr\":%"PFMT64d",\"fcn_name\":\"%s\"", fcn->addr, fcn->name);
}
@ -5256,17 +5248,17 @@ static bool cmd_anal_refs(RCore *core, const char *input) {
? r_str_newf ("%s; %s", fcn ? fcn->name : "(nofunc)", strtok (comment, "\n"))
: r_str_newf ("%s", fcn ? fcn->name : "(nofunc)");
r_cons_printf ("%s 0x%" PFMT64x " [%s] %s\n",
buf_fcn, ref->addr, r_anal_ref_to_string (ref->type), buf_asm);
buf_fcn, ref->addr, r_anal_xrefs_type_tostring (ref->type), buf_asm);
free (buf_asm);
free (buf_fcn);
}
}
r_list_free (list);
} else {
if (input[1] == 'j') { // "axtj"
r_cons_print ("[]\n");
}
}
r_list_free (list);
} break;
case 'f': { // "axf"
ut8 buf[12];
@ -5286,7 +5278,7 @@ static bool cmd_anal_refs(RCore *core, const char *input) {
list = list_ = r_anal_xrefs_get_from (core->anal, addr);
if (!list) {
RAnalFunction * fcn = r_anal_get_fcn_in (core->anal, addr, 0);
list = r_anal_fcn_get_refs (core->anal, fcn);
list = r_anal_fcn_get_refs_sorted (core->anal, fcn);
}
} else {
list = r_anal_refs_get (core->anal, addr);
@ -5304,7 +5296,7 @@ static bool cmd_anal_refs(RCore *core, const char *input) {
r_asm_set_pc (core->assembler, ref->at);
r_asm_disassemble (core->assembler, &asmop, buf, 12);
r_cons_printf ("{\"from\":%" PFMT64d ",\"to\":%" PFMT64d ",\"type\":\"%s\",\"opcode\":\"%s\"}%s",
ref->at, ref->addr, r_anal_ref_to_string (ref->type), asmop.buf_asm, iter->n? ",": "");
ref->at, ref->addr, r_anal_xrefs_type_tostring (ref->type), asmop.buf_asm, iter->n? ",": "");
}
r_cons_print ("]\n");
} else if (input[1] == '*') { // axf*
@ -5342,13 +5334,12 @@ static bool cmd_anal_refs(RCore *core, const char *input) {
free (buf_asm);
}
}
r_list_free (list_);
r_list_free (list);
} else {
if (input[1] == 'j') { // axfj
r_cons_print ("[]\n");
}
}
r_list_free (list);
} break;
case 'F':
find_refs (core, input + 1);
@ -5362,6 +5353,7 @@ static bool cmd_anal_refs(RCore *core, const char *input) {
int n = r_str_word_set0 (ptr);
ut64 at = core->offset;
ut64 addr = UT64_MAX;
RAnalRefType reftype = r_anal_xrefs_type (input[0]);
switch (n) {
case 2: // get at
at = r_num_math (core->num, r_str_word_get0 (ptr, 1));
@ -5373,7 +5365,7 @@ static bool cmd_anal_refs(RCore *core, const char *input) {
free (ptr);
return false;
}
r_anal_xrefs_set (core->anal, input[0], at, addr);
r_anal_xrefs_set (core->anal, at, addr, reftype);
free (ptr);
}
break;
@ -6042,9 +6034,9 @@ static int compute_calls(RCore *core) {
xrefs = r_anal_fcn_get_xrefs (core->anal, fcn);
if (xrefs) {
cov += r_list_length (xrefs);
r_list_free (xrefs);
xrefs = NULL;
}
r_list_free (xrefs);
}
return cov;
}
@ -6143,7 +6135,7 @@ void _CbInRangeAav(RCore *core, ut64 from, ut64 to, int vsize, bool asterisk, in
r_cons_printf ("f+ aav.0x%08"PFMT64x "= 0x%08"PFMT64x, to, to);
} else {
#if 1
r_anal_ref_add (core->anal, to, from, ' ');
r_anal_xrefs_set (core->anal, from, to, R_ANAL_REF_TYPE_NULL);
r_meta_add (core->anal, 'd', from, from + vsize, NULL);
if (!r_flag_get_at (core->flags, to, false)) {
char *name = r_str_newf ("aav.0x%08"PFMT64x, to);

View File

@ -1834,7 +1834,7 @@ static void do_ref_search(RCore *core, ut64 addr,ut64 from, ut64 to, struct sear
: r_str_newf ("%s", fcn ? fcn->name : "(nofunc)");
if (from <= ref->addr && to >= ref->addr) {
r_cons_printf ("%s 0x%" PFMT64x " [%s] %s\n",
buf_fcn, ref->addr, r_anal_ref_to_string (ref->type), str);
buf_fcn, ref->addr, r_anal_xrefs_type_tostring (ref->type), str);
if (*param->cmd_hit) {
ut64 here = core->offset;
r_core_seek (core, ref->addr, true);

View File

@ -327,15 +327,14 @@ static ut64 getref (RCore *core, int n, char t, int type) {
}
#if FCN_OLD
if (t == 'r') {
list = r_anal_fcn_get_refs (core->anal, fcn);
list = r_anal_fcn_get_refs_sorted (core->anal, fcn);
} else {
list = r_anal_fcn_get_xrefs (core->anal, fcn);
list = r_anal_fcn_get_xrefs_sorted (core->anal, fcn);
}
r_list_foreach (list, iter, r) {
if (r->type == type) {
if (i == n) {
ut64 addr = r->addr;
r_list_free (list);
return addr;
}
i++;

View File

@ -1084,7 +1084,6 @@ static void ds_pre_xrefs(RDisasmState *ds, bool no_fcnlines) {
}
static void ds_show_refs(RDisasmState *ds) {
RList *list;
RAnalRef *ref;
RListIter *iter;
RFlagItem *flagi, *flagat;
@ -1092,7 +1091,8 @@ static void ds_show_refs(RDisasmState *ds) {
if (!ds->show_cmtrefs) {
return;
}
list = r_anal_xrefs_get_from (ds->core->anal, ds->at);
RList *list = r_anal_xrefs_get_from (ds->core->anal, ds->at);
r_list_foreach (list, iter, ref) {
char *cmt = r_meta_get_string (ds->core->anal, R_META_TYPE_COMMENT, ref->addr);
flagi = r_flag_get_i (ds->core->flags, ref->addr);
@ -1127,6 +1127,7 @@ static void ds_show_refs(RDisasmState *ds) {
}
ds_print_color_reset (ds);
}
r_list_free (list);
}
static void ds_show_xrefs(RDisasmState *ds) {
@ -1141,7 +1142,7 @@ static void ds_show_xrefs(RDisasmState *ds) {
return;
}
/* show xrefs */
RList *xrefs = r_anal_xref_get (core->anal, ds->at);
RList *xrefs = r_anal_xrefs_get (core->anal, ds->at);
if (!xrefs) {
return;
}
@ -2636,7 +2637,7 @@ static void ds_instruction_mov_lea(RDisasmState *ds, int idx) {
dst->reg->name, ptr, off, item?item->name: "");
if (ds->asm_anal) {
if (r_io_is_valid_offset (core->io, off, 0)) {
r_anal_ref_add (core->anal, ds->addr, off, 'd');
r_anal_xrefs_set (core->anal, off, ds->addr, R_ANAL_REF_TYPE_DATA);
}
}
}
@ -2668,7 +2669,7 @@ static void ds_instruction_mov_lea(RDisasmState *ds, int idx) {
dst->reg->name, ptr, off, item?item->name: s);
if (ds->asm_anal) {
if (r_io_is_valid_offset (core->io, off, 0)) {
r_anal_ref_add (core->anal, ds->addr, ptr, 'd');
r_anal_xrefs_set (core->anal, ptr, ds->addr, R_ANAL_REF_TYPE_DATA);
}
}
}
@ -5246,7 +5247,7 @@ R_API int r_core_print_disasm_json(RCore *core, ut64 addr, ut8 *buf, int nb_byte
{
RAnalRef *ref;
RListIter *iter;
RList *xrefs = r_anal_xref_get (core->anal, at);
RList *xrefs = r_anal_xrefs_get (core->anal, at);
if (xrefs && !r_list_empty (xrefs)) {
r_cons_printf (",\"xrefs\":[");
r_list_foreach (xrefs, iter, ref) {

View File

@ -186,14 +186,6 @@ R_API int r_core_project_delete(RCore *core, const char *prjfile) {
eprintf ("rm %s\n", path);
}
//rm xrefs.sdb file
char *xrefs_sdb = r_str_newf ("%s%s%s", prjDir, R_SYS_DIR, "xrefs.sdb");
if (r_file_exists (xrefs_sdb)) {
r_file_rm (xrefs_sdb);
eprintf ("rm %s\n", xrefs_sdb);
}
free (xrefs_sdb);
//rm notes.txt file
char *notes_txt = r_str_newf ("%s%s%s", prjDir, R_SYS_DIR, "notes.txt");
if (r_file_exists (notes_txt)) {
@ -810,8 +802,6 @@ R_API bool r_core_project_save(RCore *core, const char *prjName) {
}
projectInit (core);
r_anal_project_save (core->anal, prjDir);
Sdb *rop_db = sdb_ns (core->sdb, "rop", false);
if (rop_db) {
/* set filepath for all the rop sub-dbs */
@ -829,12 +819,12 @@ R_API bool r_core_project_save(RCore *core, const char *prjName) {
}
r_config_set (core->config, "prj.name", prjName);
if (r_config_get_i (core->config, "prj.simple")) {
if (!simpleProjectSaveScript (core, scriptPath, R_CORE_PRJ_ALL ^ R_CORE_PRJ_XREFS)) {
if (!simpleProjectSaveScript (core, scriptPath, R_CORE_PRJ_ALL)) {
eprintf ("Cannot open '%s' for writing\n", prjName);
ret = false;
}
} else {
if (!projectSaveScript (core, scriptPath, R_CORE_PRJ_ALL ^ R_CORE_PRJ_XREFS)) {
if (!projectSaveScript (core, scriptPath, R_CORE_PRJ_ALL)) {
eprintf ("Cannot open '%s' for writing\n", prjName);
ret = false;
}
@ -909,62 +899,11 @@ R_API char *r_core_project_notes_file(RCore *core, const char *prjName) {
return notes_txt;
}
#define DB core->anal->sdb_xrefs
static bool projectLoadXrefs(RCore *core, const char *prjName) {
char *path, *db;
if (!prjName || !*prjName) {
return false;
}
const char *prjdir = r_config_get (core->config, "dir.projects");
if (prjName[0] == R_SYS_DIR[0]) {
db = r_str_newf ("%s", prjName);
if (!db) {
return false;
}
path = strdup (db);
} else {
db = r_str_newf ("%s" R_SYS_DIR "%s", prjdir, prjName);
if (!db) {
return false;
}
path = r_file_abspath (db);
}
if (!path) {
free (db);
return false;
}
if (!r_file_is_directory (db)) {
db = r_str_append (db, ".d");
}
if (!sdb_ns_unset (core->anal->sdb, NULL, DB)) {
sdb_free (DB);
}
const char *xrefs_path = r_file_fexists ("%s" R_SYS_DIR "xrefs.sdb", path)
? "xrefs.sdb": "xrefs";
DB = sdb_new (path, xrefs_path, 0);
if (!DB) {
free (db);
free (path);
return false;
}
sdb_ns_set (core->anal->sdb, "xrefs", DB);
free (path);
free (db);
return true;
}
R_API bool r_core_project_load(RCore *core, const char *prjName, const char *rcpath) {
const bool cfg_fortunes = r_config_get_i (core->config, "cfg.fortunes");
const bool scr_interactive = r_config_get_i (core->config, "scr.interactive");
const bool scr_prompt = r_config_get_i (core->config, "scr.prompt");
(void) projectLoadRop (core, prjName);
(void) projectLoadXrefs (core, prjName);
bool ret = r_core_cmd_file (core, rcpath);
r_config_set_i (core->config, "cfg.fortunes", cfg_fortunes);
r_config_set_i (core->config, "scr.interactive", scr_interactive);

View File

@ -1013,7 +1013,7 @@ repeat:
}
r_cons_printf (" %d [%s] 0x%08"PFMT64x " %s %cREF (%s)\n",
idx, cstr, refi->addr,
r_anal_ref_to_string (refi->type),
r_anal_xrefs_type_tostring (refi->type),
xref ? 'X':' ', name);
free (name);
if (idx == skip) {

View File

@ -3,7 +3,7 @@
#ifndef R2_ANAL_H
#define R2_ANAL_H
#define USE_DICT 0
#define USE_DICT 1
/* use sdb function storage */
#define FCN_SDB 1
@ -296,10 +296,6 @@ typedef struct r_anal_type_function_t {
RList *fcn_locs; //sorted list of a function *.loc refs
//RList *locals; // list of local labels -> moved to anal->sdb_fcns
RList *bbs;
#if FCN_OLD
RList *refs;
RList *xrefs;
#endif
RAnalFcnMeta meta;
RRangeTiny bbr;
RBNode rb;
@ -654,14 +650,13 @@ typedef struct r_anal_t {
struct r_anal_plugin_t *cur;
RAnalRange *limit;
RList *plugins;
Sdb *sdb_xrefs;
Sdb *sdb_types;
Sdb *sdb_meta; // TODO: Future r_meta api
Sdb *sdb_zigns;
#if USE_DICT
dict *dict_refs;
dict *dict_xrefs;
SdbHash *dict_refs;
SdbHash *dict_xrefs;
#endif
bool recursive_noreturn;
RSpaces meta_spaces;
@ -867,7 +862,7 @@ typedef enum {
} RAnalRefType;
typedef struct r_anal_ref_t {
int type;
RAnalRefType type;
ut64 addr;
ut64 at;
} RAnalRef;
@ -1381,6 +1376,7 @@ R_API int r_anal_fcn_add_bb(RAnal *anal, RAnalFunction *fcn,
R_API bool r_anal_check_fcn(RAnal *anal, ut8 *buf, ut16 bufsz, ut64 addr, ut64 low, ut64 high);
R_API void r_anal_fcn_update_tinyrange_bbs(RAnalFunction *fcn);
/* locals */
#if 0
R_API int r_anal_fcn_local_add(RAnal *anal, RAnalFunction *fcn, int index, const char *name, const char *type);
@ -1415,7 +1411,7 @@ R_API int r_anal_fcn_split_bb(RAnal *anal, RAnalFunction *fcn, RAnalBlock *bb, u
R_API int r_anal_fcn_bb_overlaps(RAnalFunction *fcn, RAnalBlock *bb);
R_API RAnalVar *r_anal_fcn_get_var(RAnalFunction *fs, int num, int dir);
R_API void r_anal_fcn_fit_overlaps (RAnal *anal, RAnalFunction *fcn);
R_API void r_anal_trim_jmprefs(RAnalFunction *fcn);
R_API void r_anal_trim_jmprefs(RAnal *anal, RAnalFunction *fcn);
R_API RAnalFunction *r_anal_fcn_next(RAnal *anal, ut64 addr);
R_API char *r_anal_fcn_to_string(RAnal *a, RAnalFunction* fs);
R_API int r_anal_str_to_fcn(RAnal *a, RAnalFunction *f, const char *_str);
@ -1424,38 +1420,29 @@ R_API RAnalBlock *r_anal_fcn_bbget(RAnalFunction *fcn, ut64 addr);
R_API bool r_anal_fcn_bbadd(RAnalFunction *fcn, RAnalBlock *bb);
R_API int r_anal_fcn_resize (const RAnal *anal, RAnalFunction *fcn, int newsize);
#if 0
#define r_anal_fcn_get_refs(x) x->refs
#define r_anal_fcn_get_xrefs(x) x->xrefs
#define r_anal_fcn_get_vars(x) x->vars
#define r_anal_fcn_get_bbs(x) x->bbs
#else
R_API int r_anal_xrefs_count(RAnal *anal);
R_API const char *r_anal_xrefs_type_tostring (char type);
R_API RList *r_anal_xrefs_get (RAnal *anal, ut64 to);
R_API RList *r_anal_refs_get (RAnal *anal, ut64 to);
R_API RList *r_anal_xrefs_get_from (RAnal *anal, ut64 from);
R_API void r_anal_xrefs_list(RAnal *anal, int rad);
R_API RList *r_anal_fcn_get_refs(RAnal *anal, RAnalFunction *fcn);
R_API RList *r_anal_fcn_get_xrefs(RAnal *anal, RAnalFunction *fcn);
R_API int r_anal_xrefs_from (RAnal *anal, RList *list, const char *kind, const RAnalRefType type, ut64 addr);
R_API int r_anal_xrefs_set (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to);
R_API int r_anal_xrefs_deln (RAnal *anal, const RAnalRefType type, ut64 from, ut64 to);
R_API bool r_anal_xrefs_save(RAnal *anal, const char *prjfile);
R_API RList* r_anal_fcn_get_vars (RAnalFunction *anal);
R_API RList* r_anal_fcn_get_bbs (RAnalFunction *anal);
R_API RList* r_anal_get_fcns (RAnal *anal);
#endif
/* ref.c */
typedef bool (* RAnalRefCmp)(RAnalRef *ref, void *data);
R_API RAnalRef *r_anal_ref_new(void);
R_API RList *r_anal_ref_list_new(void);
R_API void r_anal_ref_free(void *ref);
R_API const char *r_anal_ref_to_string(int type);
R_API int r_anal_ref_add(RAnal *anal, ut64 addr, ut64 at, int type);
R_API int r_anal_ref_del(RAnal *anal, ut64 at, ut64 addr);
R_API RList *r_anal_xref_get(RAnal *anal, ut64 addr);
R_API RList *r_anal_ref_get(RAnal *anal, ut64 addr);
R_API int r_anal_xrefs_count(RAnal *anal);
R_API const char *r_anal_xrefs_type_tostring(RAnalRefType type);
R_API RAnalRefType r_anal_xrefs_type(char ch);
R_API RList *r_anal_xrefs_get(RAnal *anal, ut64 to);
R_API RList *r_anal_refs_get(RAnal *anal, ut64 to);
R_API RList *r_anal_xrefs_get_from(RAnal *anal, ut64 from);
R_API void r_anal_xrefs_list(RAnal *anal, int rad);
R_API RList *r_anal_fcn_get_refs(RAnal *anal, RAnalFunction *fcn);
R_API RList *r_anal_fcn_get_xrefs(RAnal *anal, RAnalFunction *fcn);
R_API RList *r_anal_fcn_get_refs_sorted(RAnal *anal, RAnalFunction *fcn);
R_API RList *r_anal_fcn_get_xrefs_sorted(RAnal *anal, RAnalFunction *fcn);
R_API int r_anal_xrefs_from(RAnal *anal, RList *list, const char *kind, const RAnalRefType type, ut64 addr);
R_API int r_anal_xrefs_set(RAnal *anal, ut64 from, ut64 to, const RAnalRefType type);
R_API int r_anal_xrefs_deln(RAnal *anal, ut64 from, ut64 to, const RAnalRefType type);
R_API int r_anal_xref_del(RAnal *anal, ut64 at, ut64 addr);
R_API RList* r_anal_fcn_get_vars (RAnalFunction *anal);
R_API RList* r_anal_fcn_get_bbs (RAnalFunction *anal);
R_API RList* r_anal_get_fcns (RAnal *anal);
/* var.c */
R_API void r_anal_var_access_clear (RAnal *a, ut64 var_addr, int scope, int index);
@ -1484,7 +1471,6 @@ R_API RAnalVarAccess *r_anal_var_access_get(RAnal *anal, RAnalVar *var, ut64 fro
R_API RAnalVar *r_anal_var_get_byname (RAnal *anal, RAnalFunction *fcn, const char* name);
/* project */
R_API bool r_anal_project_save(RAnal *anal, const char *prjfile);
R_API bool r_anal_xrefs_init (RAnal *anal);
#define R_ANAL_THRESHOLDFCN 0.7F
@ -1584,9 +1570,6 @@ R_API RAnalMetaItem *r_meta_item_new(int type);
R_API bool r_meta_deserialize_val(RAnalMetaItem *it, int type, ut64 from, const char *v);
R_API void r_meta_print(RAnal *a, RAnalMetaItem *d, int rad, bool show_full);
R_API int r_anal_fcn_xref_add (RAnal *anal, RAnalFunction *fcn, ut64 at, ut64 addr, int type);
R_API int r_anal_fcn_xref_del (RAnal *anal, RAnalFunction *fcn, ut64 at, ut64 addr, int type);
/* hints */
R_API void r_anal_build_range_on_hints (RAnal *a);