mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-11 23:16:05 +00:00
Initial support for analyzing and graphing generic switch tables
This commit is contained in:
parent
96dbf57b30
commit
dc0e8ff820
@ -111,16 +111,15 @@ R_API void r_anal_ex_clone_op_switch_to_bb (RAnalBlock *bb, RAnalOp *op) {
|
||||
RListIter *iter;
|
||||
RAnalCaseOp *caseop = NULL;
|
||||
|
||||
if (op->switch_op) {
|
||||
|
||||
if (!op->switch_op) {
|
||||
bb->switch_op = r_anal_switch_op_new (op->switch_op->addr,
|
||||
op->switch_op->min_val,
|
||||
op->switch_op->max_val);
|
||||
if (bb->switch_op){
|
||||
r_list_foreach (op->switch_op->cases, iter, caseop) {
|
||||
r_anal_switch_op_add_case (bb->switch_op, caseop->addr,
|
||||
caseop->value, caseop->jump);
|
||||
}
|
||||
op->switch_op->min_val,
|
||||
op->switch_op->max_val);
|
||||
}
|
||||
if (bb->switch_op) {
|
||||
r_list_foreach (op->switch_op->cases, iter, caseop) {
|
||||
r_anal_switch_op_add_case (bb->switch_op, caseop->addr,
|
||||
caseop->value, caseop->jump);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -473,6 +473,48 @@ static int skip_hp(RAnal *anal, RAnalFunction *fcn, RAnalOp *op, RAnalBlock *bb,
|
||||
return 0;
|
||||
}
|
||||
|
||||
R_API int r_anal_case(RAnal *anal, RAnalFunction *fcn, ut64 addr_bbsw, ut64 addr, ut8 *buf, ut64 len, int reftype) {
|
||||
RAnalOp op = {0};
|
||||
int oplen, idx = 0;
|
||||
while (idx < len) {
|
||||
if ((len - idx) < 5) {
|
||||
break;
|
||||
}
|
||||
r_anal_op_fini (&op);
|
||||
if ((oplen = r_anal_op (anal, &op, addr + idx, buf + idx, len - idx)) < 1) {
|
||||
return 0;
|
||||
}
|
||||
switch (op.type) {
|
||||
case R_ANAL_OP_TYPE_TRAP:
|
||||
case R_ANAL_OP_TYPE_RET:
|
||||
case R_ANAL_OP_TYPE_JMP:
|
||||
// eprintf ("CASE AT 0x%llx size %d\n", addr, idx + oplen);
|
||||
anal->cb_printf ("afb+ 0x%"PFMT64x" 0x%"PFMT64x" %d\n",
|
||||
fcn->addr, addr, idx + oplen);
|
||||
anal->cb_printf ("afbe 0x%"PFMT64x" 0x%"PFMT64x"\n",
|
||||
addr_bbsw, addr);
|
||||
return idx + oplen;
|
||||
}
|
||||
idx += oplen;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
static int walk_switch(RAnal *anal, RAnalFunction *fcn, ut64 from, ut64 at) {
|
||||
ut8 buf[1024];
|
||||
int i;
|
||||
eprintf ("WALK SWITCH TABLE INTO (0x%llx) %llx\n", from, at);
|
||||
for (i = 0; i < 10; i++) {
|
||||
anal->iob.read_at (anal->iob.io, at, buf, sizeof (buf));
|
||||
int sz = r_anal_case (anal, fcn, from, at, buf, sizeof (buf), 0);
|
||||
if (sz < 1) {
|
||||
break;
|
||||
}
|
||||
at += sz;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fcn_recurse(RAnal *anal, RAnalFunction *fcn, ut64 addr, ut8 *buf, ut64 len, int depth) {
|
||||
int continue_after_jump = anal->opt.afterjmp;
|
||||
int noncode = anal->opt.noncode;
|
||||
@ -882,10 +924,10 @@ repeat:
|
||||
return R_ANAL_RET_END;
|
||||
#if JMP_IS_EOB_RANGE > 0
|
||||
} else {
|
||||
if (op.jump < addr-JMP_IS_EOB_RANGE && op.jump<addr) {
|
||||
if (op.jump < addr - JMP_IS_EOB_RANGE && op.jump<addr) {
|
||||
gotoBeach (R_ANAL_RET_END);
|
||||
}
|
||||
if (op.jump > addr+JMP_IS_EOB_RANGE) {
|
||||
if (op.jump > addr + JMP_IS_EOB_RANGE) {
|
||||
gotoBeach (R_ANAL_RET_END);
|
||||
}
|
||||
#endif
|
||||
@ -966,8 +1008,9 @@ repeat:
|
||||
}
|
||||
}
|
||||
}
|
||||
walk_switch (anal, fcn, op.addr, op.addr + op.size);
|
||||
}
|
||||
if (anal->cur) {
|
||||
if (anal->cur) {
|
||||
/* if UJMP is in .plt section just skip it */
|
||||
RIOSection *s = anal->iob.section_vget (anal->iob.io, addr);
|
||||
if (s && s->name) {
|
||||
@ -977,7 +1020,9 @@ repeat:
|
||||
if (!in_plt) goto river;
|
||||
}
|
||||
} else {
|
||||
if (in_plt) goto river;
|
||||
if (in_plt) {
|
||||
goto river;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -833,6 +833,35 @@ static int anal_fcn_list_bb(RCore *core, const char *input) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool anal_bb_edge (RCore *core, const char *input) {
|
||||
// "afbe" switch-bb-addr case-bb-addr
|
||||
char *arg = strdup (r_str_chop_ro(input));
|
||||
char *sp = strchr (arg, ' ');
|
||||
if (sp) {
|
||||
*sp++ = 0;
|
||||
ut64 sw_at = r_num_math (core->num, arg);
|
||||
ut64 cs_at = r_num_math (core->num, sp);
|
||||
RAnalFunction *fcn = r_anal_get_fcn_in (core->anal, sw_at, 0);
|
||||
if (fcn) {
|
||||
RAnalBlock *bb;
|
||||
RListIter *iter;
|
||||
r_list_foreach (fcn->bbs, iter, bb) {
|
||||
if (sw_at >= bb->addr && sw_at < (bb->addr + bb->size)) {
|
||||
if (!bb->switch_op) {
|
||||
bb->switch_op = r_anal_switch_op_new (
|
||||
sw_at, 0, 0);
|
||||
}
|
||||
r_anal_switch_op_add_case (bb->switch_op, cs_at, 0, cs_at);
|
||||
}
|
||||
}
|
||||
free (arg);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
free (arg);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool anal_fcn_del_bb(RCore *core, const char *input) {
|
||||
ut64 addr = r_num_math (core->num, input);
|
||||
if (!addr) {
|
||||
@ -1057,10 +1086,12 @@ static void r_core_anal_fmap (RCore *core, const char *input) {
|
||||
}
|
||||
|
||||
static bool fcnNeedsPrefix(const char *name) {
|
||||
if (!strncmp (name, "entry", 5))
|
||||
if (!strncmp (name, "entry", 5)) {
|
||||
return false;
|
||||
if (!strncmp (name, "main", 4))
|
||||
}
|
||||
if (!strncmp (name, "main", 4)) {
|
||||
return false;
|
||||
}
|
||||
return (!strchr (name, '.'));
|
||||
}
|
||||
|
||||
@ -1373,7 +1404,10 @@ static int cmd_anal_fcn(RCore *core, const char *input) {
|
||||
case 'b': // "afb"
|
||||
switch (input[2]) {
|
||||
case '-':
|
||||
anal_fcn_del_bb (core, input +3);
|
||||
anal_fcn_del_bb (core, input + 3);
|
||||
break;
|
||||
case 'e':
|
||||
anal_bb_edge (core, input + 3);
|
||||
break;
|
||||
case 0:
|
||||
case ' ':
|
||||
|
@ -1800,6 +1800,16 @@ static int get_bbnodes(RAGraph *g, RCore *core, RAnalFunction *fcn) {
|
||||
free (title);
|
||||
r_agraph_add_edge (g, u, v);
|
||||
}
|
||||
if (bb->switch_op) {
|
||||
RListIter *it;
|
||||
RAnalCaseOp *cop;
|
||||
r_list_foreach (bb->switch_op->cases, it, cop) {
|
||||
title = get_title (cop->addr);
|
||||
v = r_agraph_get_node (g, title);
|
||||
free (title);
|
||||
r_agraph_add_edge (g, u, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = true;
|
||||
|
Loading…
Reference in New Issue
Block a user