Rewrite the code flow analysis logic

This commit is contained in:
pancake 2013-10-08 04:58:51 +02:00
parent 9210656589
commit 32816c4669
8 changed files with 118 additions and 31 deletions

View File

@ -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;
}

View File

@ -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;

View File

@ -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:

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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;
}