2014-02-21 00:59:32 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2014 - pancake, nibble */
|
2009-02-06 17:22:27 +00:00
|
|
|
|
2009-02-15 23:57:03 +00:00
|
|
|
#include <r_anal.h>
|
|
|
|
#include <r_util.h>
|
2010-02-26 12:08:42 +00:00
|
|
|
#include <r_list.h>
|
2011-12-16 15:33:06 +00:00
|
|
|
#include <r_io.h>
|
2010-02-28 19:07:36 +00:00
|
|
|
#include "../config.h"
|
|
|
|
|
2013-06-14 00:51:33 +00:00
|
|
|
R_LIB_VERSION(r_anal);
|
|
|
|
|
2012-07-19 02:54:22 +00:00
|
|
|
static RAnalPlugin *anal_static_plugins[] =
|
2010-02-28 19:07:36 +00:00
|
|
|
{ R_ANAL_STATIC_PLUGINS };
|
2009-02-15 23:57:03 +00:00
|
|
|
|
2012-07-22 08:00:35 +00:00
|
|
|
/*
|
2010-03-19 11:00:04 +00:00
|
|
|
static RAnalVarType anal_default_vartypes[] =
|
2011-09-14 01:47:30 +00:00
|
|
|
{{ "char", "c", 1 },
|
2010-03-11 18:52:05 +00:00
|
|
|
{ "byte", "b", 1 },
|
2011-09-14 01:47:30 +00:00
|
|
|
{ "int", "i", 4 },
|
2010-03-11 18:52:05 +00:00
|
|
|
{ "int32", "d", 4 },
|
2011-09-14 01:47:30 +00:00
|
|
|
{ "int64", "q", 8 },
|
2010-03-11 18:52:05 +00:00
|
|
|
{ "dword", "x", 4 },
|
|
|
|
{ "float", "f", 4 },
|
|
|
|
{ NULL, NULL, 0 }};
|
2012-07-22 08:00:35 +00:00
|
|
|
*/
|
2010-03-11 18:52:05 +00:00
|
|
|
|
2013-08-13 01:23:39 +00:00
|
|
|
static void r_anal_type_init(RAnal *anal) {
|
|
|
|
Sdb *D = anal->sdb_types;
|
2013-09-01 23:20:12 +00:00
|
|
|
sdb_set (D, "unsigned int", "type", 0);
|
|
|
|
sdb_set (D, "int", "type", 0);
|
|
|
|
sdb_set (D, "long", "type", 0);
|
|
|
|
sdb_set (D, "void *", "type", 0);
|
|
|
|
sdb_set (D, "char", "type", 0);
|
|
|
|
sdb_set (D, "char*", "type", 0);
|
|
|
|
sdb_set (D, "const char*", "type", 0);
|
2013-08-13 01:23:39 +00:00
|
|
|
sdb_set (D, "type.unsigned int", "i", 0);
|
|
|
|
sdb_set (D, "type.int", "d", 0);
|
|
|
|
sdb_set (D, "type.long", "x", 0);
|
|
|
|
sdb_set (D, "type.void *", "p", 0);
|
|
|
|
sdb_set (D, "type.char", "x", 0);
|
|
|
|
sdb_set (D, "type.char*", "*z", 0);
|
|
|
|
sdb_set (D, "type.const char*", "*z", 0);
|
|
|
|
}
|
|
|
|
|
2010-03-19 11:00:04 +00:00
|
|
|
R_API RAnal *r_anal_new() {
|
2010-02-28 19:07:36 +00:00
|
|
|
int i;
|
2010-06-04 21:47:35 +00:00
|
|
|
RAnalPlugin *static_plugin;
|
2013-04-18 01:58:44 +00:00
|
|
|
RAnal *anal = R_NEW0 (RAnal);
|
2013-02-12 01:42:34 +00:00
|
|
|
if (!anal) return NULL;
|
2014-02-21 00:59:32 +00:00
|
|
|
anal->cpu = NULL;
|
|
|
|
anal->decode = R_TRUE; // slow slow if not used
|
2014-03-05 02:52:42 +00:00
|
|
|
anal->sdb = sdb_new (NULL, NULL, 0);
|
2014-03-31 01:05:48 +00:00
|
|
|
anal->sdb_fcns = sdb_ns (anal->sdb, "fcns");
|
2014-03-05 02:52:42 +00:00
|
|
|
anal->sdb_meta = sdb_ns (anal->sdb, "meta");
|
2014-03-12 01:44:49 +00:00
|
|
|
anal->sdb_hints = sdb_ns (anal->sdb, "hints");
|
2014-03-12 02:23:50 +00:00
|
|
|
anal->sdb_xrefs = sdb_ns (anal->sdb, "xrefs");
|
2014-03-31 01:05:48 +00:00
|
|
|
//anal->sdb_vars = sdb_ns (anal->sdb, "vars");
|
|
|
|
//anal->sdb_args = sdb_ns (anal->sdb, "args");
|
|
|
|
//anal->sdb_ret = sdb_ns (anal->sdb, "ret");
|
|
|
|
//anal->sdb_locals = sdb_ns (anal->sdb, "locals");
|
2014-03-12 01:44:49 +00:00
|
|
|
anal->sdb_types = sdb_ns (anal->sdb, "types");
|
2014-01-23 02:28:25 +00:00
|
|
|
anal->printf = (PrintfCallback) printf;
|
2013-08-13 01:23:39 +00:00
|
|
|
r_anal_type_init (anal);
|
2013-04-18 01:58:44 +00:00
|
|
|
r_anal_xrefs_init (anal);
|
2011-10-14 08:09:53 +00:00
|
|
|
anal->diff_ops = 0;
|
|
|
|
anal->diff_thbb = R_ANAL_THRESHOLDBB;
|
|
|
|
anal->diff_thfcn = R_ANAL_THRESHOLDFCN;
|
2011-10-19 11:05:41 +00:00
|
|
|
anal->split = R_TRUE; // used from core
|
2011-03-28 08:24:01 +00:00
|
|
|
anal->queued = NULL;
|
2011-02-03 08:31:50 +00:00
|
|
|
anal->syscall = r_syscall_new ();
|
|
|
|
r_io_bind_init (anal->iob);
|
2011-02-18 12:08:09 +00:00
|
|
|
anal->reg = r_reg_new ();
|
2011-02-03 08:31:50 +00:00
|
|
|
anal->lineswidth = 0;
|
|
|
|
anal->fcns = r_anal_fcn_list_new ();
|
2013-02-12 01:42:34 +00:00
|
|
|
#if USE_NEW_FCN_STORE
|
2011-09-14 00:07:06 +00:00
|
|
|
anal->fcnstore = r_listrange_new ();
|
2013-02-12 01:42:34 +00:00
|
|
|
#endif
|
2011-02-03 08:31:50 +00:00
|
|
|
anal->refs = r_anal_ref_list_new ();
|
2012-07-19 02:54:22 +00:00
|
|
|
anal->types = r_anal_type_list_new ();
|
2011-02-03 08:31:50 +00:00
|
|
|
r_anal_set_bits (anal, 32);
|
|
|
|
r_anal_set_big_endian (anal, R_FALSE);
|
2014-03-25 11:05:34 +00:00
|
|
|
anal->plugins = r_list_new ();
|
2014-04-18 15:18:48 +00:00
|
|
|
anal->plugins->free = (RListFree) r_anal_plugin_free;
|
2011-02-03 08:31:50 +00:00
|
|
|
for (i=0; anal_static_plugins[i]; i++) {
|
|
|
|
static_plugin = R_NEW (RAnalPlugin);
|
2014-03-26 16:23:46 +00:00
|
|
|
*static_plugin = *anal_static_plugins[i];
|
2011-02-03 08:31:50 +00:00
|
|
|
r_anal_add (anal, static_plugin);
|
2010-01-31 01:30:59 +00:00
|
|
|
}
|
2012-07-22 08:00:35 +00:00
|
|
|
/*
|
2011-02-03 08:31:50 +00:00
|
|
|
for (i=0; anal_default_vartypes[i].name; i++)
|
|
|
|
r_anal_var_type_add (anal, anal_default_vartypes[i].name,
|
|
|
|
anal_default_vartypes[i].size, anal_default_vartypes[i].fmt);
|
2012-07-22 08:00:35 +00:00
|
|
|
*/
|
2010-01-31 01:30:59 +00:00
|
|
|
return anal;
|
2009-02-06 17:22:27 +00:00
|
|
|
}
|
|
|
|
|
2014-03-25 11:05:34 +00:00
|
|
|
R_API void r_anal_plugin_free (RAnalPlugin *p) {
|
|
|
|
if (p && p->fini) {
|
|
|
|
p->fini (p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-02-20 01:11:04 +00:00
|
|
|
R_API void r_anal_free(RAnal *a) {
|
|
|
|
if (!a) return;
|
2011-11-13 23:21:25 +00:00
|
|
|
/* TODO: Free anals here */
|
2014-02-20 01:11:04 +00:00
|
|
|
free (a->cpu);
|
2014-03-02 21:16:54 +00:00
|
|
|
a->cpu = NULL;
|
2014-03-25 11:05:34 +00:00
|
|
|
r_list_free (a->plugins);
|
2014-02-20 01:11:04 +00:00
|
|
|
a->fcns->free = r_anal_fcn_free;
|
|
|
|
r_list_free (a->fcns);
|
2011-12-16 15:33:06 +00:00
|
|
|
// r_listrange_free (anal->fcnstore); // might provoke double frees since this is used in r_anal_fcn_insert()
|
2014-02-20 01:11:04 +00:00
|
|
|
r_list_free (a->refs);
|
|
|
|
r_list_free (a->types);
|
2014-04-01 23:32:18 +00:00
|
|
|
r_reg_free (a->reg);
|
2014-02-20 01:11:04 +00:00
|
|
|
r_anal_op_free (a->queued);
|
2014-04-01 02:03:48 +00:00
|
|
|
a->sdb = NULL;
|
2014-04-01 23:32:18 +00:00
|
|
|
r_syscall_free (a->syscall);
|
|
|
|
sdb_ns_free (a->sdb);
|
2011-12-16 15:33:06 +00:00
|
|
|
// r_io_free(anal->iob.io); // need r_core (but recursive problem to fix)
|
2014-02-20 01:11:04 +00:00
|
|
|
free (a);
|
2010-05-20 15:40:58 +00:00
|
|
|
}
|
|
|
|
|
2010-03-19 11:00:04 +00:00
|
|
|
R_API void r_anal_set_user_ptr(RAnal *anal, void *user) {
|
2009-02-15 23:57:03 +00:00
|
|
|
anal->user = user;
|
2009-02-06 17:22:27 +00:00
|
|
|
}
|
|
|
|
|
2010-05-25 23:42:22 +00:00
|
|
|
R_API int r_anal_add(RAnal *anal, RAnalPlugin *foo) {
|
2009-02-15 23:57:03 +00:00
|
|
|
if (foo->init)
|
2010-06-16 07:42:46 +00:00
|
|
|
foo->init (anal->user);
|
2014-03-25 11:05:34 +00:00
|
|
|
r_list_append (anal->plugins, foo);
|
2009-02-06 17:22:27 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
2009-02-08 23:19:06 +00:00
|
|
|
|
2009-10-12 15:41:52 +00:00
|
|
|
// TODO: Must be deprecated
|
2010-03-19 11:00:04 +00:00
|
|
|
R_API int r_anal_list(RAnal *anal) {
|
2014-03-25 11:05:34 +00:00
|
|
|
RAnalPlugin *h;
|
|
|
|
RListIter *it;
|
|
|
|
r_list_foreach (anal->plugins, it, h) {
|
2013-10-24 11:59:19 +00:00
|
|
|
anal->printf ("anal %-10s %s\n", h->name, h->desc);
|
2009-02-15 23:57:03 +00:00
|
|
|
}
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2010-03-19 11:00:04 +00:00
|
|
|
R_API int r_anal_use(RAnal *anal, const char *name) {
|
2014-03-25 11:05:34 +00:00
|
|
|
RListIter *it;
|
|
|
|
RAnalPlugin *h;
|
|
|
|
r_list_foreach (anal->plugins, it, h) {
|
2010-02-02 10:09:52 +00:00
|
|
|
if (!strcmp (h->name, name)) {
|
2009-02-15 23:57:03 +00:00
|
|
|
anal->cur = h;
|
2011-02-18 12:08:09 +00:00
|
|
|
r_anal_set_reg_profile (anal);
|
2009-02-15 23:57:03 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2011-02-18 12:08:09 +00:00
|
|
|
R_API int r_anal_set_reg_profile(RAnal *anal) {
|
2011-09-14 00:07:06 +00:00
|
|
|
if (anal && anal->cur && anal->cur->set_reg_profile)
|
2011-02-18 12:08:09 +00:00
|
|
|
return anal->cur->set_reg_profile (anal);
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
2010-03-19 11:00:04 +00:00
|
|
|
R_API int r_anal_set_bits(RAnal *anal, int bits) {
|
2009-02-15 23:57:03 +00:00
|
|
|
switch (bits) {
|
2009-08-14 00:37:18 +00:00
|
|
|
case 8:
|
2009-02-15 23:57:03 +00:00
|
|
|
case 16:
|
|
|
|
case 32:
|
|
|
|
case 64:
|
|
|
|
anal->bits = bits;
|
2011-02-18 12:08:09 +00:00
|
|
|
r_anal_set_reg_profile (anal);
|
2009-02-15 23:57:03 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
2009-09-25 02:04:51 +00:00
|
|
|
return R_FALSE;
|
2009-02-15 23:57:03 +00:00
|
|
|
}
|
|
|
|
|
2014-02-05 20:08:46 +00:00
|
|
|
R_API void r_anal_set_cpu(RAnal *anal, const char *cpu) {
|
2014-02-21 00:59:32 +00:00
|
|
|
free (anal->cpu);
|
|
|
|
anal->cpu = cpu ? strdup (cpu) : NULL;
|
2014-02-05 20:08:46 +00:00
|
|
|
}
|
|
|
|
|
2010-03-19 11:00:04 +00:00
|
|
|
R_API int r_anal_set_big_endian(RAnal *anal, int bigend) {
|
2009-09-09 00:35:00 +00:00
|
|
|
anal->big_endian = bigend;
|
2009-02-15 23:57:03 +00:00
|
|
|
return R_TRUE;
|
|
|
|
}
|
2010-05-16 12:04:08 +00:00
|
|
|
|
|
|
|
R_API char *r_anal_strmask (RAnal *anal, const char *data) {
|
2011-02-24 13:06:49 +00:00
|
|
|
RAnalOp *op;
|
2010-05-16 12:04:08 +00:00
|
|
|
ut8 *buf;
|
|
|
|
char *ret = NULL;
|
|
|
|
int oplen, len, idx = 0;
|
|
|
|
|
|
|
|
ret = strdup (data);
|
2011-05-11 17:19:53 +00:00
|
|
|
buf = malloc (1+strlen (data));
|
2011-02-24 13:06:49 +00:00
|
|
|
op = r_anal_op_new ();
|
|
|
|
if (op == NULL || ret == NULL || buf == NULL) {
|
|
|
|
free (op);
|
2010-05-16 12:04:08 +00:00
|
|
|
free (buf);
|
|
|
|
free (ret);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
len = r_hex_str2bin (data, buf);
|
|
|
|
while (idx < len) {
|
2011-02-24 13:06:49 +00:00
|
|
|
if ((oplen = r_anal_op (anal, op, 0, buf+idx, len-idx)) == 0)
|
2010-05-16 12:04:08 +00:00
|
|
|
break;
|
2011-02-24 13:06:49 +00:00
|
|
|
switch (op->type) {
|
2010-05-16 12:04:08 +00:00
|
|
|
case R_ANAL_OP_TYPE_CALL:
|
2010-11-21 18:01:41 +00:00
|
|
|
case R_ANAL_OP_TYPE_UCALL:
|
2010-05-16 12:04:08 +00:00
|
|
|
case R_ANAL_OP_TYPE_CJMP:
|
|
|
|
case R_ANAL_OP_TYPE_JMP:
|
2010-11-21 18:01:41 +00:00
|
|
|
case R_ANAL_OP_TYPE_UJMP:
|
2011-02-24 13:06:49 +00:00
|
|
|
if (op->nopcode != 0)
|
|
|
|
memset (ret+(idx+op->nopcode)*2, '.', (oplen-op->nopcode)*2);
|
2010-05-16 12:04:08 +00:00
|
|
|
}
|
|
|
|
idx += oplen;
|
|
|
|
}
|
2011-02-24 13:06:49 +00:00
|
|
|
free (op);
|
2010-05-16 12:04:08 +00:00
|
|
|
free (buf);
|
|
|
|
return ret;
|
|
|
|
}
|
2010-12-06 15:26:21 +00:00
|
|
|
|
2011-02-11 10:22:43 +00:00
|
|
|
R_API void r_anal_trace_bb(RAnal *anal, ut64 addr) {
|
|
|
|
RAnalBlock *bbi;
|
2012-07-22 08:00:35 +00:00
|
|
|
RAnalFunction *fcni;
|
2011-02-11 10:22:43 +00:00
|
|
|
RListIter *iter, *iter2;
|
2011-09-03 03:09:31 +00:00
|
|
|
VERBOSE_ANAL eprintf ("bbtraced\n"); // XXX Debug msg
|
|
|
|
r_list_foreach (anal->fcns, iter, fcni) {
|
2011-02-11 10:22:43 +00:00
|
|
|
r_list_foreach (fcni->bbs, iter2, bbi) {
|
|
|
|
if (addr>=bbi->addr && addr<(bbi->addr+bbi->size)) {
|
|
|
|
bbi->traced = R_TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2011-09-03 03:09:31 +00:00
|
|
|
}
|
2011-02-11 10:22:43 +00:00
|
|
|
}
|
2012-06-05 15:50:12 +00:00
|
|
|
|
|
|
|
R_API RList* r_anal_get_fcns (RAnal *anal) { return anal->fcns; }
|
2013-04-18 01:58:44 +00:00
|
|
|
|
|
|
|
R_API int r_anal_project_load(RAnal *anal, const char *prjfile) {
|
|
|
|
if (!prjfile || !*prjfile)
|
|
|
|
return R_FALSE;
|
|
|
|
r_anal_xrefs_load (anal, prjfile);
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API int r_anal_project_save(RAnal *anal, const char *prjfile) {
|
|
|
|
if (!prjfile || !*prjfile)
|
|
|
|
return R_FALSE;
|
|
|
|
r_anal_xrefs_save (anal, prjfile);
|
|
|
|
return R_TRUE;
|
|
|
|
}
|
2013-07-19 09:51:51 +00:00
|
|
|
|
|
|
|
R_API RAnalOp *r_anal_op_hexstr(RAnal *anal, ut64 addr, const char *str) {
|
|
|
|
int len;
|
2013-10-24 11:59:19 +00:00
|
|
|
ut8 *buf;
|
2013-07-19 09:51:51 +00:00
|
|
|
RAnalOp *op = R_NEW0 (RAnalOp);
|
2014-05-12 00:15:57 +00:00
|
|
|
if (!op) return NULL;
|
2013-12-02 23:14:59 +00:00
|
|
|
buf = malloc (strlen (str)+1);
|
2014-05-16 23:04:52 +00:00
|
|
|
if (!buf) {
|
|
|
|
free (op);
|
|
|
|
return NULL;
|
|
|
|
}
|
2013-07-19 09:51:51 +00:00
|
|
|
len = r_hex_str2bin (str, buf);
|
|
|
|
r_anal_op (anal, op, addr, buf, len);
|
|
|
|
return op;
|
|
|
|
}
|