mirror of
https://github.com/radareorg/radare2.git
synced 2025-01-21 21:27:06 +00:00
Rewrite the code flow analysis logic
This commit is contained in:
parent
9210656589
commit
32816c4669
@ -61,7 +61,7 @@ static int verify_version(int show) {
|
||||
ret = 1;
|
||||
if (show) printf ("%s %s\n", name, v->name);
|
||||
}
|
||||
if (ret) eprintf ("Warning: r2 library versions mismatch!\n");
|
||||
//if (ret) eprintf ("Warning: r2 library versions mismatch!\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
112
libr/anal/fcn.c
112
libr/anal/fcn.c
@ -127,34 +127,77 @@ R_API int r_anal_fcn_local_del_addr (RAnal *anal, RAnalFunction *fcn, ut64 addr)
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
// TODO: limit recursivity
|
||||
|
||||
R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64 len, int reftype) {
|
||||
RAnalOp op = {0};
|
||||
static RAnalBlock *bbget(RAnalFunction *fcn, ut64 addr) {
|
||||
RListIter *iter;
|
||||
RAnalBlock *bb;
|
||||
r_list_foreach (fcn->bbs, iter, bb) {
|
||||
if (bb->addr == addr)
|
||||
return bb;
|
||||
if (addr >= bb->addr && (addr < bb->addr+bb->size))
|
||||
return bb;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int bbsum(RAnalFunction *fcn) {
|
||||
RListIter *iter;
|
||||
RAnalBlock *bb;
|
||||
ut32 size = 0;
|
||||
r_list_foreach (fcn->bbs, iter, bb) {
|
||||
size += bb->size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64 len, int reftype) {
|
||||
int ret = 0;
|
||||
ut8 bbuf[8096];
|
||||
int overlapped = 0;
|
||||
char *varname;
|
||||
RAnalOp op = {0};
|
||||
int oplen, idx = 0;
|
||||
if (fcn->addr == -1)
|
||||
fcn->addr = addr;
|
||||
fcn->type = (reftype==R_ANAL_REF_TYPE_CODE)?
|
||||
R_ANAL_FCN_TYPE_LOC: R_ANAL_FCN_TYPE_FCN;
|
||||
//if (len>16)
|
||||
// len -= 16; // XXX: hack to avoid buffer overflow by reading >64 bytes..
|
||||
// add basic block
|
||||
RAnalBlock *bb = NULL;
|
||||
RAnalBlock *bbg = NULL;
|
||||
if (bbget (fcn, addr))
|
||||
return R_ANAL_RET_ERROR; // MUST BE DUP
|
||||
bb = R_NEW0 (RAnalBlock);
|
||||
bb->addr = addr;
|
||||
bb->size = 0;
|
||||
bb->jump = UT64_MAX;
|
||||
bb->fail = UT64_MAX;
|
||||
bb->type = 0; // TODO
|
||||
r_list_append (fcn->bbs, bb);
|
||||
|
||||
while (idx < len) {
|
||||
r_anal_op_fini (&op);
|
||||
if (buf[idx]==buf[idx+1] && buf[idx]==0xff && buf[idx+2]==0xff) {
|
||||
r_anal_op_fini (&op);
|
||||
if (buf[idx]==buf[idx+1] && buf[idx]==0xff && buf[idx+2]==0xff)
|
||||
return R_ANAL_RET_ERROR;
|
||||
}
|
||||
// check if opcode is in another basic block
|
||||
// in that case we break
|
||||
if ((oplen = r_anal_op (anal, &op, addr+idx, buf+idx, len-idx)) < 1) {
|
||||
if (idx == 0) {
|
||||
VERBOSE_ANAL eprintf ("Unknown opcode at 0x%08"PFMT64x"\n", addr+idx);
|
||||
r_anal_op_fini (&op);
|
||||
return R_ANAL_RET_END;
|
||||
} else break;
|
||||
} else break; // unspecified behaviour
|
||||
}
|
||||
if (idx>0 && !overlapped) {
|
||||
bbg = bbget (fcn, addr+idx);
|
||||
if (bbg && bbg != bb) {
|
||||
bb->jump = addr+idx;
|
||||
overlapped = 1;
|
||||
//return R_ANAL_RET_END;
|
||||
}
|
||||
}
|
||||
fcn->ninstr++;
|
||||
idx += oplen;
|
||||
fcn->size += oplen;
|
||||
if (!overlapped) {
|
||||
bb->size += oplen;
|
||||
fcn->ninstr++;
|
||||
fcn->size += oplen; /// XXX. must be the sum of all the bblocks
|
||||
}
|
||||
/* TODO: Parse fastargs (R_ANAL_VAR_ARGREG) */
|
||||
switch (op.stackop) {
|
||||
case R_ANAL_STACK_INC:
|
||||
@ -195,14 +238,34 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64
|
||||
}
|
||||
switch (op.type) {
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
#if 0
|
||||
if (!r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump,
|
||||
R_ANAL_REF_TYPE_CODE)) {
|
||||
r_anal_op_fini (&op);
|
||||
return R_ANAL_RET_ERROR;
|
||||
}
|
||||
break;
|
||||
//return R_ANAL_RET_END;
|
||||
#endif
|
||||
if (!overlapped) {
|
||||
bb->jump = op.jump;
|
||||
bb->fail = UT64_MAX;
|
||||
}
|
||||
// hardcoded jmp size // must be checked at the end wtf?
|
||||
if (op.jump < addr-512 && op.jump<addr)
|
||||
return R_ANAL_RET_END;
|
||||
if (op.jump > addr+512)
|
||||
return R_ANAL_RET_END;
|
||||
//
|
||||
anal->iob.read_at (anal->iob.io, op.jump, bbuf, sizeof(bbuf));
|
||||
return fcn_recurse (anal, fcn, op.jump, bbuf, 8096, reftype);
|
||||
case R_ANAL_OP_TYPE_CJMP:
|
||||
if (!overlapped) {
|
||||
bb->jump = op.jump;
|
||||
bb->fail = op.fail;
|
||||
}
|
||||
anal->iob.read_at (anal->iob.io, op.jump, bbuf, sizeof (bbuf));
|
||||
fcn_recurse (anal, fcn, op.jump, bbuf, sizeof (bbuf), reftype);
|
||||
anal->iob.read_at (anal->iob.io, op.fail, bbuf, sizeof (bbuf));
|
||||
return fcn_recurse (anal, fcn, op.fail, bbuf, sizeof (bbuf), reftype);
|
||||
#if 0
|
||||
// do not add xrefs for cjmps?
|
||||
r_anal_op_fini (&op);
|
||||
@ -213,6 +276,7 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64
|
||||
op.type == R_ANAL_OP_TYPE_CALL?
|
||||
R_ANAL_REF_TYPE_CALL : R_ANAL_REF_TYPE_CODE)) {
|
||||
r_anal_op_fini (&op);
|
||||
//fcn->size = bbsum (fcn);
|
||||
return R_ANAL_RET_ERROR;
|
||||
}
|
||||
break;
|
||||
@ -220,11 +284,24 @@ R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64
|
||||
case R_ANAL_OP_TYPE_UJMP:
|
||||
case R_ANAL_OP_TYPE_RET:
|
||||
r_anal_op_fini (&op);
|
||||
//fcn->size = bbsum (fcn);
|
||||
return R_ANAL_RET_END;
|
||||
}
|
||||
}
|
||||
r_anal_op_fini (&op);
|
||||
return fcn->size;
|
||||
return ret;
|
||||
}
|
||||
|
||||
R_API int r_anal_fcn(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64 len, int reftype) {
|
||||
//int oplen, idx = 0;
|
||||
if (fcn->addr == -1)
|
||||
fcn->addr = addr;
|
||||
fcn->type = (reftype==R_ANAL_REF_TYPE_CODE)?
|
||||
R_ANAL_FCN_TYPE_LOC: R_ANAL_FCN_TYPE_FCN;
|
||||
//if (len>16)
|
||||
// len -= 16; // XXX: hack to avoid buffer overflow by reading >64 bytes..
|
||||
|
||||
return fcn_recurse (anal, fcn, addr, buf, len, reftype);
|
||||
}
|
||||
|
||||
// TODO: need to implement r_anal_fcn_remove(RAnal *anal, RAnalFunction *fcn);
|
||||
@ -343,7 +420,6 @@ R_API RAnalFunction *r_anal_fcn_find_name(RAnal *anal, const char *name) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* rename RAnalFunctionBB.add() */
|
||||
R_API int r_anal_fcn_add_bb(RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump, ut64 fail, int type, RAnalDiff *diff) {
|
||||
RAnalBlock *bb = NULL, *bbi;
|
||||
|
@ -352,8 +352,9 @@ default:
|
||||
#endif
|
||||
if (u.operand[0].type==UD_OP_PTR) {
|
||||
op->jump = getval (&u.operand[0]);
|
||||
} else
|
||||
op->jump = addr + oplen + getval (&u.operand[0]);
|
||||
} else {
|
||||
op->jump = addr + oplen + (int)getval (&u.operand[0]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UD_Ijz:
|
||||
|
@ -17,7 +17,7 @@ R_API void r_cons_pal_init(const char *foo) {
|
||||
cons->pal.label = Color_CYAN;
|
||||
cons->pal.flow = Color_CYAN;
|
||||
cons->pal.math = Color_YELLOW;
|
||||
cons->pal.bin = Color_RED;
|
||||
cons->pal.bin = Color_YELLOW;
|
||||
cons->pal.b0x00 = Color_GREEN;
|
||||
cons->pal.b0x7f = Color_CYAN;
|
||||
cons->pal.b0xff = Color_RED;
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <r_flags.h>
|
||||
#include <r_core.h>
|
||||
|
||||
#define ANALBS 1024
|
||||
|
||||
R_API void r_core_anal_hint_list (RAnal *a, int mode) {
|
||||
int count = 0;
|
||||
RAnalHint *hint;
|
||||
@ -294,7 +296,6 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
|
||||
ut64 *next = NULL;
|
||||
int i, nexti = 0;
|
||||
ut8 *buf;
|
||||
#define ANALBS 256
|
||||
|
||||
if (from != UT64_MAX && at == 0)
|
||||
return R_FALSE;
|
||||
@ -386,7 +387,7 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
|
||||
r_list_sort (fcn->bbs, &cmpaddr);
|
||||
|
||||
/* New function: Add initial xref */
|
||||
if (from != -1) {
|
||||
if (from != UT64_MAX) {
|
||||
if (!(ref = r_anal_ref_new ())) {
|
||||
eprintf ("Error: new (xref)\n");
|
||||
goto error;
|
||||
@ -415,7 +416,7 @@ R_API int r_core_anal_fcn(RCore *core, ut64 at, ut64 from, int reftype, int dept
|
||||
#endif
|
||||
//r_list_append (core->anal->fcns, fcn);
|
||||
r_list_foreach (fcn->refs, iter, refi)
|
||||
if (refi->addr != -1)
|
||||
if (refi->addr != UT64_MAX)
|
||||
// TODO: fix memleak here, fcn not freed even though it is
|
||||
// added in core->anal->fcns which is freed in r_anal_free()
|
||||
r_core_anal_fcn (core, refi->addr, refi->at, refi->type, depth-1);
|
||||
@ -645,9 +646,10 @@ R_API int r_core_anal_fcn_list(RCore *core, const char *input, int rad) {
|
||||
}
|
||||
return R_TRUE;
|
||||
}
|
||||
#define infun(x,y) (y>=x->addr&&y<(x->addr+x->size))
|
||||
r_list_foreach (core->anal->fcns, iter, fcn)
|
||||
if (((input == NULL || *input == '\0') && fcn->type!=R_ANAL_FCN_TYPE_LOC)
|
||||
|| fcn->addr == addr || !strcmp (fcn->name, input+1)) {
|
||||
|| infun(fcn, addr) || !strcmp (fcn->name, input+1)) {
|
||||
if (!rad) {
|
||||
r_cons_printf ("#\n offset: 0x%08"PFMT64x"\n name: %s\n size: %"PFMT64d,
|
||||
fcn->addr, fcn->name, fcn->size);
|
||||
@ -684,7 +686,7 @@ R_API int r_core_anal_fcn_list(RCore *core, const char *input, int rad) {
|
||||
r_cons_printf ("0x%08"PFMT64x" ", refi->addr);
|
||||
|
||||
if (fcn->type==R_ANAL_FCN_TYPE_FCN || fcn->type==R_ANAL_FCN_TYPE_SYM) {
|
||||
r_cons_printf ("\n vars: %d");
|
||||
r_cons_printf ("\n vars: %d", r_list_length (fcn->vars));
|
||||
r_list_foreach (fcn->vars, iter2, vari) {
|
||||
char *s = r_anal_type_to_str (core->anal, vari->type);
|
||||
r_cons_printf ("\n %s %s @ 0x%02x", s, vari->name, vari->delta);
|
||||
|
@ -475,6 +475,15 @@ eprintf ("XXX: This command conflicts with 'ar'\n");
|
||||
free (ptr);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
{
|
||||
ut64 addr = core->offset;
|
||||
if (input[2]==' ')
|
||||
addr = r_num_math (core->num, input+2);
|
||||
RAnalFunction *fcn = r_anal_fcn_find (core->anal, addr, R_ANAL_FCN_TYPE_NULL);
|
||||
if (fcn) r_cons_printf ("0x%08"PFMT64x"\n", fcn->addr);
|
||||
}
|
||||
break;
|
||||
case 'i':
|
||||
r_core_anal_fcn_list (core, input+2, 0);
|
||||
break;
|
||||
|
@ -452,9 +452,9 @@ static int cmd_print(void *data, const char *input) {
|
||||
r_list_foreach (f->bbs, iter, b) {
|
||||
r_core_cmdf (core, "pD %"PFMT64d" @0x%"PFMT64x, b->size, b->addr);
|
||||
if (b->jump != UT64_MAX)
|
||||
r_cons_printf ("--> 0x%08"PFMT64x"\n", b->jump);
|
||||
r_cons_printf ("-[true]-> 0x%08"PFMT64x"\n", b->jump);
|
||||
if (b->fail != UT64_MAX)
|
||||
r_cons_printf ("--> 0x%08"PFMT64x"\n", b->fail);
|
||||
r_cons_printf ("-[false]-> 0x%08"PFMT64x"\n", b->fail);
|
||||
r_cons_printf ("--\n");
|
||||
}
|
||||
} else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", core->offset);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* radare - LGPL - Copyright 2008-2012 pancake */
|
||||
/* radare - LGPL - Copyright 2008-2013 - pancake */
|
||||
|
||||
// TODO: implement a more inteligent way to store cached memory
|
||||
// TODO: define limit of max mem to cache
|
||||
@ -89,7 +89,6 @@ R_API int r_io_cache_write(RIO *io, ut64 addr, const ut8 *buf, int len) {
|
||||
ch->size = len;
|
||||
ch->data = (ut8*)malloc (len);
|
||||
memcpy (ch->data, buf, len);
|
||||
|
||||
r_list_append (io->cache, ch);
|
||||
return len;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user