mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-03 10:51:01 +00:00
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:
parent
173761085d
commit
b1ade9c1c6
@ -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++);
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user