2013-02-12 02:42:34 +01:00
|
|
|
/* radare - LGPL - Copyright 2010-2013 - nibble, pancake */
|
2010-03-12 03:05:20 +01:00
|
|
|
|
|
|
|
#include <r_anal.h>
|
|
|
|
#include <r_util.h>
|
|
|
|
#include <r_list.h>
|
|
|
|
|
2010-09-28 13:58:03 +02:00
|
|
|
R_API RAnalRef *r_anal_ref_new() {
|
2010-06-14 00:57:40 +02:00
|
|
|
RAnalRef *ref = R_NEW (RAnalRef);
|
|
|
|
if (ref) {
|
|
|
|
ref->addr = -1;
|
2010-08-02 12:42:59 +02:00
|
|
|
ref->at = -1;
|
2010-09-28 13:58:03 +02:00
|
|
|
ref->type = R_ANAL_REF_TYPE_CODE;
|
2010-06-14 00:57:40 +02:00
|
|
|
}
|
2010-05-20 17:40:58 +02:00
|
|
|
return ref;
|
2010-03-12 03:05:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API RList *r_anal_ref_list_new() {
|
|
|
|
RList *list = r_list_new ();
|
|
|
|
list->free = &r_anal_ref_free;
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_anal_ref_free(void *ref) {
|
|
|
|
free (ref);
|
|
|
|
}
|
2010-09-28 13:58:03 +02:00
|
|
|
|
|
|
|
R_API int r_anal_ref_add(RAnal *anal, ut64 addr, ut64 at, int type) {
|
|
|
|
RAnalRef *ref = NULL, *refi;
|
|
|
|
RListIter *iter;
|
|
|
|
int append = 0;
|
|
|
|
r_list_foreach (anal->refs, iter, refi)
|
|
|
|
if (at == refi->at) {
|
|
|
|
ref = refi;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ref == NULL) {
|
|
|
|
if (!(ref = r_anal_ref_new ()))
|
|
|
|
return R_FALSE;
|
|
|
|
append = 1;
|
|
|
|
}
|
|
|
|
ref->addr = addr;
|
|
|
|
ref->at = at;
|
|
|
|
ref->type = type;
|
|
|
|
if (append) r_list_append (anal->refs, ref);
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_anal_ref_del(RAnal *anal, ut64 at) {
|
|
|
|
RAnalRef *refi;
|
2012-02-14 18:10:52 +01:00
|
|
|
RListIter *iter, *iter_tmp;
|
2010-09-28 13:58:03 +02:00
|
|
|
if (at == 0) {
|
|
|
|
r_list_free (anal->refs);
|
|
|
|
if (!(anal->refs = r_anal_ref_list_new ()))
|
|
|
|
return R_FALSE;
|
2011-04-29 13:55:27 +02:00
|
|
|
} else {
|
2012-02-14 18:10:52 +01:00
|
|
|
r_list_foreach_safe (anal->refs, iter, iter_tmp, refi) {
|
2013-04-16 19:48:59 +02:00
|
|
|
if (at == refi->at)
|
2012-02-14 18:10:52 +01:00
|
|
|
r_list_delete (anal->refs, iter);
|
2011-04-29 13:55:27 +02:00
|
|
|
}
|
|
|
|
}
|
2010-09-28 13:58:03 +02:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
2010-09-28 18:05:31 +02:00
|
|
|
|
2013-04-16 19:48:59 +02:00
|
|
|
// XXX: MAJOR SLOWDOWN PLZ FIX
|
2010-09-28 18:05:31 +02:00
|
|
|
R_API RList *r_anal_xref_get(RAnal *anal, ut64 addr) {
|
2012-07-19 06:54:22 +04:00
|
|
|
RAnalFunction *fcni;
|
2013-02-13 17:54:20 +01:00
|
|
|
RAnalRef *refi, *ref, *refr;
|
|
|
|
RListIter *iter, *iter2, *iter3;
|
2010-09-28 18:05:31 +02:00
|
|
|
RList *ret;
|
|
|
|
|
2013-04-18 03:58:44 +02:00
|
|
|
return r_anal_xrefs_get (anal, addr);
|
|
|
|
return NULL; // fuck yeah optimization!
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
for (list = sdb_list_begin (DB); list; list = sdb_list_next (list)) {
|
|
|
|
char *str = astring();
|
|
|
|
eprintf ("--> %s\n", str);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *list = sdb_list_begin(DB)
|
|
|
|
while (list) {
|
|
|
|
|
|
|
|
list = sdb_list_next (list);
|
|
|
|
}
|
|
|
|
$ sdb xrefs
|
|
|
|
()types=code,data
|
|
|
|
()data.0x1200=0x1000,0x1030,0x1090
|
|
|
|
()code.0x3020=0x2010,0x2042
|
|
|
|
|
|
|
|
int clen, dlen;
|
|
|
|
const char **coderefs, **datarefs;
|
|
|
|
|
|
|
|
coderefs = r_anal_xrefs_get (anal, "code", &clen);
|
|
|
|
datarefs = r_anal_xrefs_get (anal, "data", &dlen);
|
|
|
|
if (!coderefs && !datarefs)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
xrefs[0x80480] = { type: "data", from: "
|
|
|
|
RAnalFudr_anal_fcn_get_at (anal, addr);
|
|
|
|
#endif
|
2010-09-28 18:05:31 +02:00
|
|
|
if (!(ret = r_anal_ref_list_new ()))
|
|
|
|
return NULL;
|
2013-02-13 17:54:20 +01:00
|
|
|
// XXX: this is just a hack that makes analysis/disasm much slower but
|
|
|
|
// work as expected. We need to redesign the whole analysis engine :)
|
|
|
|
// - find real reverse xrefs by deep walk
|
|
|
|
// - addr = our target destination
|
2011-07-03 01:51:20 +02:00
|
|
|
r_list_foreach (anal->fcns, iter, fcni) {
|
2013-02-13 17:54:20 +01:00
|
|
|
r_list_foreach (fcni->refs, iter2, refi) {
|
|
|
|
if (refi->addr == addr) {
|
|
|
|
int gonext = 0;
|
|
|
|
r_list_foreach (ret, iter3, refr) {
|
|
|
|
if (refr->addr == refi->at) // same sauce, so we can skip
|
|
|
|
gonext = 1;
|
|
|
|
}
|
|
|
|
if (gonext) continue;
|
|
|
|
// wtf copying xrefs for new lists .. tahts insanely slow
|
2011-07-03 01:51:20 +02:00
|
|
|
if (!(ref = r_anal_ref_new ())) {
|
|
|
|
r_list_destroy (ret);
|
|
|
|
return NULL;
|
2010-09-28 18:05:31 +02:00
|
|
|
}
|
2013-02-13 17:54:20 +01:00
|
|
|
// NOTE: swapped hacky valuez
|
|
|
|
ref->addr = refi->at;
|
|
|
|
ref->at = refi->addr;
|
|
|
|
ref->type = refi->type;
|
2011-07-03 01:51:20 +02:00
|
|
|
r_list_append (ret, ref);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-02-13 17:54:20 +01:00
|
|
|
if (r_list_length (ret)>0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
r_list_foreach (anal->fcns, iter, fcni) {
|
|
|
|
if (addr >= fcni->addr && addr < fcni->addr+fcni->size) {
|
|
|
|
r_list_foreach (fcni->xrefs, iter2, refi) {
|
|
|
|
if (refi->at == addr) {
|
|
|
|
if (!(ref = r_anal_ref_new ())) {
|
|
|
|
r_list_destroy (ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ref->addr = refi->addr;
|
|
|
|
ref->at = refi->at;
|
|
|
|
ref->type= refi->type;
|
|
|
|
r_list_append (ret, ref);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break; // may break on corner cases
|
|
|
|
}
|
|
|
|
}
|
2010-09-28 18:05:31 +02:00
|
|
|
r_list_foreach (anal->refs, iter2, refi)
|
|
|
|
if (refi->addr == addr) {
|
|
|
|
if (!(ref = r_anal_ref_new ())) {
|
|
|
|
r_list_destroy (ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ref->addr = refi->at;
|
|
|
|
ref->at = refi->addr;
|
|
|
|
ref->type= refi->type;
|
|
|
|
r_list_append (ret, ref);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|