From 32816c46699449b54388032dc952e82dfd6424b6 Mon Sep 17 00:00:00 2001 From: pancake Date: Tue, 8 Oct 2013 04:58:51 +0200 Subject: [PATCH] Rewrite the code flow analysis logic --- binr/radare2/radare2.c | 2 +- libr/anal/fcn.c | 112 ++++++++++++++++++++++++++++++------ libr/anal/p/anal_x86_udis.c | 5 +- libr/cons/pal.c | 2 +- libr/core/anal.c | 12 ++-- libr/core/cmd_anal.c | 9 +++ libr/core/cmd_print.c | 4 +- libr/io/cache.c | 3 +- 8 files changed, 118 insertions(+), 31 deletions(-) diff --git a/binr/radare2/radare2.c b/binr/radare2/radare2.c index df389fcead..f2450a5abe 100644 --- a/binr/radare2/radare2.c +++ b/binr/radare2/radare2.c @@ -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; } diff --git a/libr/anal/fcn.c b/libr/anal/fcn.c index 22e292d2e5..cd612fa3f2 100644 --- a/libr/anal/fcn.c +++ b/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+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; diff --git a/libr/anal/p/anal_x86_udis.c b/libr/anal/p/anal_x86_udis.c index 0eb76a9f46..7d9627be87 100644 --- a/libr/anal/p/anal_x86_udis.c +++ b/libr/anal/p/anal_x86_udis.c @@ -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: diff --git a/libr/cons/pal.c b/libr/cons/pal.c index 74a33cfd04..0802740c35 100644 --- a/libr/cons/pal.c +++ b/libr/cons/pal.c @@ -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; diff --git a/libr/core/anal.c b/libr/core/anal.c index 95049c01ec..515b387b9f 100644 --- a/libr/core/anal.c +++ b/libr/core/anal.c @@ -5,6 +5,8 @@ #include #include +#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); diff --git a/libr/core/cmd_anal.c b/libr/core/cmd_anal.c index 22ae101f65..23602f1284 100644 --- a/libr/core/cmd_anal.c +++ b/libr/core/cmd_anal.c @@ -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; diff --git a/libr/core/cmd_print.c b/libr/core/cmd_print.c index ac65439930..ec63d491b3 100644 --- a/libr/core/cmd_print.c +++ b/libr/core/cmd_print.c @@ -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); diff --git a/libr/io/cache.c b/libr/io/cache.c index 4b5acadaaa..2c98052938 100644 --- a/libr/io/cache.c +++ b/libr/io/cache.c @@ -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; }