Implement dsuf and cmd.times to run a command when using times repetition prefix

dsuf: step until program counter on a flag that matches the given string or any
cmd.times: command to run when prefixing a command with a number

for example:

	"e cmd.times=ps@rbx"
	10dsuf strlen
or
	e cmd.times=?v rbx
	10dsuf malloc
or
	10dsuf sym
This commit is contained in:
pancake 2015-01-17 04:23:07 +01:00
parent 173761085d
commit b1ade9c1c6
4 changed files with 86 additions and 3 deletions

View File

@ -944,8 +944,9 @@ R_API int r_core_cmd_pipe(RCore *core, char *radare_cmd, char *shell_cmd) {
static int r_core_cmd_subst_i(RCore *core, char *cmd, char* colon);
static int r_core_cmd_subst(RCore *core, char *cmd) {
int ret = 0, rep = atoi (cmd);
int ret = 0, rep = atoi (cmd), orep;
char *cmt, *colon = NULL, *icmd = strdup (cmd);
const char *cmdrep = NULL;
cmd = r_str_trim_head_tail (icmd);
if (!icmd || !strncmp (cmd, "# ", 2))
goto beach;
@ -973,10 +974,22 @@ static int r_core_cmd_subst(RCore *core, char *cmd) {
goto beach;
}
}
// TODO: store in core->cmdtimes to speedup ?
cmdrep = r_config_get (core->config, "cmd.times");
orep = rep;
while (rep-- && *cmd) {
ret = r_core_cmd_subst_i (core, cmd, colon);
if (ret && *cmd=='q')
goto beach;
if (cmdrep && *cmdrep) {
if (orep>1) {
// XXX: do not flush here, we need r_cons_push () and r_cons_pop()
r_cons_flush ();
// XXX: we must inport register flags in C
r_core_cmd0 (core, ".dr*");
r_core_cmd0 (core, cmdrep);
}
}
}
if (colon && colon[1]) {
for (++colon; *colon==';'; colon++);

View File

@ -61,6 +61,10 @@ static void dot_r_graph_traverse(RCore *core, RGraph *t) {
r_cons_printf ("}\n");
}
/* TODO: refactor all those step_until* function into a single one
* TODO: handle when the process is dead
* TODO: handle ^C */
static int checkbpcallback(RCore *core) ;
static int step_until(RCore *core, ut64 addr) {
ut64 off = r_debug_reg_get (core->dbg, "pc");
@ -72,7 +76,12 @@ static int step_until(RCore *core, ut64 addr) {
eprintf ("Cannot continue until address 0\n");
return R_FALSE;
}
r_cons_break (NULL, NULL);
do {
if (r_cons_singleton ()->breaked)
break;
if (r_debug_is_dead (core->dbg))
break;
r_debug_step (core->dbg, 1);
if (checkbpcallback (core)) {
eprintf ("Interrupted by a breakpoint\n");
@ -81,6 +90,7 @@ static int step_until(RCore *core, ut64 addr) {
off = r_debug_reg_get (core->dbg, "pc");
// check breakpoint here
} while (off != addr);
r_cons_break_end();
return R_TRUE;
}
@ -90,7 +100,12 @@ static int step_until_esil(RCore *core, const char *esilstr) {
eprintf ("Not initialized %p. Run 'aei' first.\n", core->anal->esil);
return R_FALSE;
}
r_cons_break (NULL, NULL);
for (;;) {
if (r_cons_singleton ()->breaked)
break;
if (r_debug_is_dead (core->dbg))
break;
r_debug_step (core->dbg, 1);
r_debug_reg_sync (core->dbg, -1, 0);
if (checkbpcallback (core)) {
@ -102,6 +117,7 @@ static int step_until_esil(RCore *core, const char *esilstr) {
break;
}
}
r_cons_break_end();
return R_TRUE;
}
@ -116,7 +132,12 @@ static int step_until_inst(RCore *core, const char *instr) {
eprintf ("Wrong state\n");
return R_FALSE;
}
r_cons_break (NULL, NULL);
for (;;) {
if (r_cons_singleton ()->breaked)
break;
if (r_debug_is_dead (core->dbg))
break;
r_debug_step (core->dbg, 1);
r_debug_reg_sync (core->dbg, -1, 0);
if (checkbpcallback (core)) {
@ -137,13 +158,55 @@ static int step_until_inst(RCore *core, const char *instr) {
}
}
}
r_cons_break_end();
return R_TRUE;
}
static int step_until_flag(RCore *core, const char *instr) {
const RList *list;
RListIter *iter;
RFlagItem *f;
ut64 pc;
instr = r_str_chop_ro (instr);
if (!core || !instr|| !core->dbg) {
eprintf ("Wrong state\n");
return R_FALSE;
}
r_cons_break (NULL, NULL);
for (;;) {
if (r_cons_singleton ()->breaked)
break;
if (r_debug_is_dead (core->dbg))
break;
r_debug_step (core->dbg, 1);
r_debug_reg_sync (core->dbg, -1, 0);
if (checkbpcallback (core)) {
eprintf ("Interrupted by a breakpoint\n");
break;
}
pc = r_debug_reg_get (core->dbg, "pc");
list = r_flag_get_list (core->flags, pc);
r_list_foreach (list, iter, f) {
if (!instr|| !*instr || strstr(f->realname, instr)) {
r_cons_printf ("[ 0x%08"PFMT64x" ] %s\n",
f->offset, f->realname);
goto beach;
}
}
}
beach:
r_cons_break_end();
return R_TRUE;
}
/* until end of frame */
static int step_until_eof(RCore *core) {
ut64 off, now = r_debug_reg_get (core->dbg, "sp");
r_cons_break (NULL, NULL);
do {
if (r_cons_singleton ()->breaked)
break;
if (!r_debug_step (core->dbg, 1))
break;
if (checkbpcallback (core)) {
@ -153,6 +216,7 @@ static int step_until_eof(RCore *core) {
off = r_debug_reg_get (core->dbg, "sp");
// check breakpoint here
} while (off <= now);
r_cons_break_end();
return R_TRUE;
}
@ -1454,6 +1518,7 @@ static int cmd_debug(void *data, const char *input) {
"dsu", " <address>", "Step until address",
"dsui", " <instr>", "Step until an instruction that matches `instr`",
"dsue", " <esil>", "Step until esil expression matches",
"dsuf", " <flag>", "Step until pc == flag matching name",
NULL
};
@ -1487,6 +1552,9 @@ static int cmd_debug(void *data, const char *input) {
break;
case 'u':
switch (input[2]) {
case 'f':
step_until_flag (core, input+3);
break;
case 'i':
step_until_inst (core, input+3);
break;
@ -1498,8 +1566,8 @@ static int cmd_debug(void *data, const char *input) {
step_until (core, r_num_math (core->num, input+2)); // XXX dupped by times
break;
default:
eprintf ("Usage: dsu[ei] [arg] . step until address ' ',"
" 'e'sil or 'i'nstruction matching\n");
eprintf ("Usage: dsu[fei] [arg] . step until address ' ',"
" 'f'lag, 'e'sil or 'i'nstruction matching\n");
break;
}
break;

View File

@ -291,6 +291,7 @@ static int cmd_help(void *data, const char *input) {
break;
case 'e': // echo
for (input++; *input==' '; input++);
// TODO: replace all ${flagname} by its value in hexa
r_cons_printf ("%s\n", input);
break;
case 's': // sequence from to step

View File

@ -1041,6 +1041,7 @@ R_API int r_core_config_init(RCore *core) {
SETPREF("cmd.xterm", "xterm -bg black -fg gray -e", "xterm command to spawn with V@");
SETICB("cmd.depth", 10, &cb_cmddepth, "Maximum command depth");
SETPREF("cmd.bp", "", "Command to executed every breakpoint hit");
SETPREF("cmd.times", "", "Command to run on every repeated command (number prefix)");
SETPREF("cmd.stack", "", "Command to display the stack in visual debug mode");
SETPREF("cmd.cprompt", "", "Column visual prompt commands");
SETPREF("cmd.gprompt", "", "Graph visual prompt commands");