Add anal.bbsplit (=true) fixing basic block split analysis

- Thanks @earada for reporting!

	$ cat /tmp/analbug.r2
	wx 5589e583ec04837d08027507b802000000eb0b8b4508890424e8d7ffffffc9c3
	e anal.bbsplit=true
	af
	afb
	# pdr

	$ r2 -qni /tmp/analbug.r2 -
	0x00000000 0x0000000c 12 j 0x00000013 f 0x0000000c
	0x00000013 0x0000001e 11 j 0x0000001e
	0x0000000c 0x00000013 7 j 0x0000001e
	0x0000001e 0x00000020 2
This commit is contained in:
pancake 2015-01-29 23:27:18 +01:00
parent e55ef93b0d
commit a4cd6db606
3 changed files with 34 additions and 7 deletions

View File

@ -229,10 +229,15 @@ static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut6
if (depth<1) {
return R_ANAL_RET_ERROR; // MUST BE TOO DEEP
}
#if 1
if (r_anal_get_fcn_at (anal, addr, 0)) {
return R_ANAL_RET_ERROR; // MUST BE NOT FOUND
}
if (bbget (fcn, addr)) {
#endif
bb = bbget (fcn, addr);
if (bb) {
r_anal_fcn_split_bb (fcn, bb, addr);
return R_ANAL_RET_ERROR; // MUST BE NOT DUP
}
@ -375,9 +380,9 @@ repeat:
#endif
}
}
#define recurseAt(x) \
anal->iob.read_at (anal->iob.io, x, bbuf, sizeof (bbuf));\
ret = fcn_recurse (anal, fcn, x, bbuf, sizeof (bbuf), depth-1);
#define recurseAt(x) \
anal->iob.read_at (anal->iob.io, x, bbuf, sizeof (bbuf));\
ret = fcn_recurse (anal, fcn, x, bbuf, sizeof (bbuf), depth-1);
switch (op.type) {
case R_ANAL_OP_TYPE_ILL:
if (anal->nopskip && !memcmp (buf, "\x00\x00\x00\x00", 4)) {
@ -423,6 +428,15 @@ repeat:
}
break;
case R_ANAL_OP_TYPE_JMP:
if (anal->bbsplit) {
(void) r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump, R_ANAL_REF_TYPE_CODE);
if (!overlapped) {
bb->jump = op.jump;
bb->fail = UT64_MAX;
}
recurseAt (op.jump);
gotoBeach (ret);
} else {
if (!r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump,
R_ANAL_REF_TYPE_CODE)) {
}
@ -469,6 +483,7 @@ repeat:
}
}
}
}
break;
case R_ANAL_OP_TYPE_CJMP:
(void) r_anal_fcn_xref_add (anal, fcn, op.addr, op.jump, R_ANAL_REF_TYPE_CODE);
@ -732,20 +747,23 @@ R_API int r_anal_fcn_add_bb(RAnalFunction *fcn, ut64 addr, ut64 size, ut64 jump,
}
// TODO: rename fcn_bb_split()
// bb seems to be ignored
R_API int r_anal_fcn_split_bb(RAnalFunction *fcn, RAnalBlock *bb, ut64 addr) {
RAnalBlock *bbi;
#if R_ANAL_BB_HAS_OPS
RAnalOp *opi;
#endif
RListIter *iter;
if (addr == UT64_MAX)
return 0;
r_list_foreach (fcn->bbs, iter, bbi) {
if (addr == bbi->addr)
return R_ANAL_RET_DUP;
if (addr > bbi->addr && addr < bbi->addr + bbi->size) {
r_list_append (fcn->bbs, bb);
bb->addr = addr+bbi->size;
eprintf ("\nADD BB %llx\n\n", bb->addr);
bb = appendBasicBlock (fcn, addr);
//r_list_append (fcn->bbs, bb);
//bb->addr = addr+bbi->size;
bb->size = bbi->addr + bbi->size - addr;
bb->jump = bbi->jump;
bb->fail = bbi->fail;

View File

@ -101,6 +101,13 @@ static int cb_analnopskip (void *user, void *data) {
return R_TRUE;
}
static int cb_analbbsplit (void *user, void *data) {
RCore *core = (RCore*) user;
RConfigNode *node = (RConfigNode*) data;
core->anal->bbsplit = node->i_value;
return R_TRUE;
}
static int cb_analarch(void *user, void *data) {
RCore *core = (RCore*) user;
RConfigNode *node = (RConfigNode*) data;
@ -881,6 +888,7 @@ R_API int r_core_config_init(RCore *core) {
SETPREF("anal.hasnext", "true", "Continue analysis after each function");
SETPREF("anal.esil", "false", "Use the new ESIL code analysis");
SETCB("anal.nopskip", "true", &cb_analnopskip, "Skip nops at the beginning of functions");
SETCB("anal.bbsplit", "true", &cb_analbbsplit, "Use the experimental basic block split for JMPs");
SETCB("anal.arch", R_SYS_ARCH, &cb_analarch, "Specify the anal.arch to use");
SETCB("anal.cpu", R_SYS_ARCH, &cb_analcpu, "Specify the anal.cpu to use");
SETPREF("anal.prelude", "", "Specify an hexpair to find preludes in code");

View File

@ -550,6 +550,7 @@ typedef struct r_anal_t {
RBinBind binb; // Set only from core when an analysis plugin is called.
int decode;
int eobjmp; // option
int bbsplit;
int afterjmp; // continue analysis after jmp eax or forward jmp // option
int maxreflines;
RList *types;