Implement /g to find all possible paths from A to B inside a function

This commit is contained in:
pancake 2018-04-04 00:42:24 +02:00
parent dfcf6f745d
commit 51958b62c3
3 changed files with 87 additions and 1 deletions

View File

@ -3987,3 +3987,80 @@ R_API void r_core_anal_esil(RCore *core, const char *str, const char *target) {
// restore register
r_reg_arena_pop (core->anal->reg);
}
typedef struct {
dict visited;
RList *path;
RCore *core;
ut64 from;
RAnalBlock *fromBB;
ut64 to;
RAnalBlock *toBB;
RAnalBlock *cur;
} RCoreAnalPaths;
static void printAnalPaths(RCoreAnalPaths *p) {
RListIter *iter;
RAnalBlock *path;
r_cons_printf ("pdb @@= ");
r_list_foreach (p->path, iter, path) {
// eprintf ("-> 0x%08"PFMT64x" ", path->addr);
r_cons_printf ("0x%08"PFMT64x" ", path->addr);
}
//eprintf ("-> 0x%08"PFMT64x"\n", p->to);
r_cons_printf ("0x%08"PFMT64x"\n", p->to);
}
static void analPaths (RCoreAnalPaths *p) {
RAnalBlock *cur = p->cur;
if (!cur) {
//eprintf ("eof\n");
return;
}
dict_set (&p->visited, cur->addr, 1, NULL);
r_list_append (p->path, cur);
if (cur->addr == p->toBB->addr) {
printAnalPaths (p);
} else {
if (cur->jump != UT64_MAX) {
if (!dict_get (&p->visited, cur->jump)) {
p->cur = r_anal_bb_from_offset (p->core->anal, cur->jump);
analPaths (p);
}
}
if (cur->fail != UT64_MAX) {
if (!dict_get (&p->visited, cur->fail)) {
p->cur = r_anal_bb_from_offset (p->core->anal, cur->fail);
analPaths (p);
}
}
// TODO: follow calls in this basic block
}
p->cur = r_list_pop (p->path);
dict_del (&p->visited, cur->addr);
}
R_API void r_core_anal_paths(RCore *core, ut64 from, ut64 to) {
RAnalBlock *b0 = r_anal_bb_from_offset (core->anal, from);
RAnalBlock *b1 = r_anal_bb_from_offset (core->anal, to);
if (!b0) {
eprintf ("Cannot find basic block for 0x%08"PFMT64x"\n", from);
}
if (!b1) {
eprintf ("Cannot find basic block for 0x%08"PFMT64x"\n", to);
}
RCoreAnalPaths rcap = {0};
dict_init (&rcap.visited, 32, free);
rcap.path = r_list_new ();
rcap.core = core;
rcap.from = from;
rcap.fromBB = b0;
rcap.to = to;
rcap.toBB = b1;
rcap.cur = b0;
analPaths (&rcap);
dict_fini (&rcap.visited);
r_list_free (rcap.path);
}

View File

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2010-2017 - pancake */
/* radare - LGPL - Copyright 2010-2018 - pancake */
#include <stddef.h>
@ -29,6 +29,8 @@ static const char *help_msg_slash[] = {
"/E", " esil-expr", "offset matching given esil expressions %%= here",
"/f", "", "search forwards, command modifier, followed by other command",
"/F", " file [off] [sz]", "search contents of file with offset and size",
// TODO: add subcommands to find paths between functions and filter only function names instead of offsets, etc
"/g", " [from]", "find all graph paths from A to current offset (inside current function)",
"/h", "[t] [hash] [len]", "find block matching this hash. See /#?",
"/i", " foo", "search for string 'foo' ignoring case",
"/m", " magicfile", "search for matching magic file (use blocksize)",
@ -3088,6 +3090,12 @@ reread:
}
}
break;
case 'g': // "/g" graph search
{
ut64 addr = r_num_math (core->num, input + 1);
r_core_anal_paths (core, addr, core->offset);
}
break;
case 'F': // "/F" search file /F [file] ([offset] ([sz]))
if (input[param_offset - 1] == ' ') {
int n_args;

View File

@ -291,6 +291,7 @@ R_API char* r_core_add_asmqjmp(RCore *core, ut64 addr);
R_API void r_core_anal_type_init(RCore *core);
R_API void r_core_anal_cc_init(RCore *core);
R_API void r_core_anal_paths(RCore *core, ut64 from, ut64 to);
R_API void r_core_list_io(RCore *core);
/* visual marks */