diff --git a/libr/anal/Makefile b/libr/anal/Makefile index 0826e029f0..5692859b8e 100644 --- a/libr/anal/Makefile +++ b/libr/anal/Makefile @@ -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 diff --git a/libr/anal/anal.c b/libr/anal/anal.c index fd141dbaf2..cc9ef9af02 100644 --- a/libr/anal/anal.c +++ b/libr/anal/anal.c @@ -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); diff --git a/libr/anal/bb.c b/libr/anal/bb.c index 00379fc346..ce3aa4f467 100644 --- a/libr/anal/bb.c +++ b/libr/anal/bb.c @@ -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); } } } diff --git a/libr/anal/fcn.c b/libr/anal/fcn.c index 5118ad0ac8..1943411841 100644 --- a/libr/anal/fcn.c +++ b/libr/anal/fcn.c @@ -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; -} diff --git a/libr/anal/flirt.c b/libr/anal/flirt.c index 9f50907087..5343f49696 100644 --- a/libr/anal/flirt.c +++ b/libr/anal/flirt.c @@ -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); } diff --git a/libr/anal/meson.build b/libr/anal/meson.build index 11b8c17469..30cb49fb80 100644 --- a/libr/anal/meson.build +++ b/libr/anal/meson.build @@ -66,7 +66,6 @@ files = [ 'p/anal_xtensa.c', 'p/anal_z80.c', 'pin.c', - 'ref.c', 'reflines.c', 'rtti.c', 'rtti_msvc.c', diff --git a/libr/anal/p/anal_java.c b/libr/anal/p/anal_java.c index 6489461fb1..6bffb867c0 100644 --- a/libr/anal/p/anal_java.c +++ b/libr/anal/p/anal_java.c @@ -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: diff --git a/libr/anal/ref.c b/libr/anal/ref.c deleted file mode 100644 index 976601e9b2..0000000000 --- a/libr/anal/ref.c +++ /dev/null @@ -1,72 +0,0 @@ -/* radare - LGPL - Copyright 2010-2018 - nibble, pancake */ - -#include -#include -#include - -// 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); -} diff --git a/libr/anal/vtable.c b/libr/anal/vtable.c index 47be11ecac..d154efa5e0 100644 --- a/libr/anal/vtable.c +++ b/libr/anal/vtable.c @@ -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); diff --git a/libr/anal/xrefs.c b/libr/anal/xrefs.c index 201847f808..9f476281d0 100644 --- a/libr/anal/xrefs.c +++ b/libr/anal/xrefs.c @@ -1,10 +1,7 @@ -/* radare - LGPL - Copyright 2009-2017 - pancake, nibble */ +/* radare - LGPL - Copyright 2009-2018 - pancake, nibble, defragger, ret2libc */ #include #include -#include - -#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; } diff --git a/libr/core/canal.c b/libr/core/canal.c index 9fb2ecbfe8..24c81b2ced 100644 --- a/libr/core/canal.c +++ b/libr/core/canal.c @@ -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); } } } diff --git a/libr/core/cmd_anal.c b/libr/core/cmd_anal.c index 6756fb1d1b..c4ab59460d 100644 --- a/libr/core/cmd_anal.c +++ b/libr/core/cmd_anal.c @@ -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); diff --git a/libr/core/cmd_search.c b/libr/core/cmd_search.c index 6059be7ce6..b81eaab06b 100644 --- a/libr/core/cmd_search.c +++ b/libr/core/cmd_search.c @@ -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); diff --git a/libr/core/core.c b/libr/core/core.c index f37b4e5309..b8ee6179ca 100644 --- a/libr/core/core.c +++ b/libr/core/core.c @@ -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++; diff --git a/libr/core/disasm.c b/libr/core/disasm.c index 9fa8bc9fbd..474a68d8db 100644 --- a/libr/core/disasm.c +++ b/libr/core/disasm.c @@ -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) { diff --git a/libr/core/project.c b/libr/core/project.c index 28b2495c45..cb50296d66 100644 --- a/libr/core/project.c +++ b/libr/core/project.c @@ -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); diff --git a/libr/core/visual.c b/libr/core/visual.c index 4e3fddefaa..92da6a6ea3 100644 --- a/libr/core/visual.c +++ b/libr/core/visual.c @@ -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) { diff --git a/libr/include/r_anal.h b/libr/include/r_anal.h index 43d0837778..5eb44fd8e3 100644 --- a/libr/include/r_anal.h +++ b/libr/include/r_anal.h @@ -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);