2013-09-11 23:55:45 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2013 - pancake */
|
2012-02-27 01:40:27 +00:00
|
|
|
|
2013-12-02 13:34:32 +00:00
|
|
|
// XXX DUP
|
|
|
|
#define OPDELTA 32
|
|
|
|
static int prevopsz (RCore *core, ut64 addr) {
|
|
|
|
ut64 target = addr;
|
|
|
|
ut64 base = target-OPDELTA;
|
|
|
|
int len, ret, i;
|
|
|
|
ut8 buf[OPDELTA*2];
|
|
|
|
RAnalOp op;
|
|
|
|
|
|
|
|
r_core_read_at (core, base, buf, sizeof (buf));
|
|
|
|
for (i=0; i<sizeof (buf); i++) {
|
|
|
|
ret = r_anal_op (core->anal, &op, base+i,
|
|
|
|
buf+i, sizeof (buf)-i);
|
|
|
|
if (!ret) continue;
|
2013-12-06 04:04:17 +00:00
|
|
|
len = op.size;
|
2013-12-02 13:34:32 +00:00
|
|
|
r_anal_op_fini (&op); // XXX
|
|
|
|
if (len<1) continue;
|
|
|
|
i += len-1;
|
|
|
|
if (target == base+i+1)
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
return 4;
|
|
|
|
}
|
2014-03-12 01:44:49 +00:00
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
static int cmd_seek(void *data, const char *input) {
|
|
|
|
RCore *core = (RCore *)data;
|
|
|
|
char *cmd, *p;
|
|
|
|
ut64 off;
|
|
|
|
|
|
|
|
if (*input=='r') {
|
|
|
|
if (input[1] && input[2]) {
|
|
|
|
if (core->io->debug) {
|
|
|
|
off = r_debug_reg_get (core->dbg, input+2);
|
|
|
|
r_io_sundo_push (core->io, core->offset);
|
|
|
|
r_core_seek (core, off, 1);
|
|
|
|
}// else eprintf ("cfg.debug is false\n");
|
2014-01-23 08:44:47 +00:00
|
|
|
} else eprintf ("|Usage| 'sr pc' seek to program counter register\n");
|
2012-02-27 01:40:27 +00:00
|
|
|
} else
|
|
|
|
if (*input) {
|
2013-01-02 23:47:58 +00:00
|
|
|
const char *inputnum = strchr (input+1, ' ');
|
2012-02-27 01:40:27 +00:00
|
|
|
int sign = 1;
|
2013-01-02 23:47:58 +00:00
|
|
|
inputnum = inputnum? inputnum+1: input+1;
|
2012-12-30 00:05:12 +00:00
|
|
|
off = r_num_math (core->num, inputnum);
|
2013-09-30 00:19:19 +00:00
|
|
|
if (*inputnum== '-') off = -off;
|
2014-03-12 01:44:49 +00:00
|
|
|
#if 0
|
2012-12-30 00:05:12 +00:00
|
|
|
if (input[0]!='/' && inputnum && isalpha (inputnum[0]) && off == 0) {
|
|
|
|
if (!r_flag_get (core->flags, inputnum)) {
|
|
|
|
eprintf ("Cannot find address for '%s'\n", inputnum);
|
2012-02-27 01:40:27 +00:00
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
}
|
2014-03-12 01:44:49 +00:00
|
|
|
#endif
|
2012-02-27 01:40:27 +00:00
|
|
|
if (input[0]==' ') {
|
|
|
|
switch (input[1]) {
|
|
|
|
case '-': sign=-1;
|
|
|
|
case '+': input++; break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (*input) {
|
|
|
|
case 'C':
|
2012-07-12 02:21:56 +00:00
|
|
|
if (input[1]=='*') {
|
2014-03-12 01:44:49 +00:00
|
|
|
r_core_cmd0 (core, "C*~^\"CC");
|
2012-07-12 02:21:56 +00:00
|
|
|
} else
|
2012-02-27 01:40:27 +00:00
|
|
|
if (input[1]==' ') {
|
2014-03-12 01:44:49 +00:00
|
|
|
typedef struct {
|
|
|
|
ut64 addr;
|
|
|
|
char *str;
|
|
|
|
} MetaCallback;
|
|
|
|
int count = 0;
|
|
|
|
MetaCallback cb = { 0, NULL };
|
|
|
|
ut64 addr;
|
|
|
|
char key[128];
|
|
|
|
const char *val, *comma;
|
|
|
|
char *list = sdb_get (core->anal->sdb_meta, "meta.C", 0);
|
|
|
|
char *str, *next, *cur = list;
|
|
|
|
if (list) {
|
|
|
|
for (;;) {
|
2014-03-26 03:16:03 +00:00
|
|
|
cur = sdb_anext (cur, &next);
|
2014-03-12 01:44:49 +00:00
|
|
|
addr = sdb_atoi (cur);
|
2014-04-02 16:07:47 +00:00
|
|
|
snprintf (key, sizeof (key)-1, "meta.C.0x%"PFMT64x, addr);
|
2014-03-12 01:44:49 +00:00
|
|
|
val = sdb_const_get (core->anal->sdb_meta, key, 0);
|
2014-04-02 16:07:47 +00:00
|
|
|
if (val) {
|
|
|
|
comma = strchr (val, ',');
|
|
|
|
if (comma) {
|
|
|
|
str = (char *)sdb_decode (comma+1, 0);
|
|
|
|
if (strstr (str, input+2)) {
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" %s\n", addr, str);
|
|
|
|
count++;
|
|
|
|
cb.addr = addr;
|
|
|
|
free (cb.str);
|
|
|
|
cb.str = str;
|
|
|
|
} else free (str);
|
|
|
|
}
|
|
|
|
} else eprintf ("sdb_const_get key not found '%s'\n", key);
|
2014-03-12 01:44:49 +00:00
|
|
|
if (!next)
|
|
|
|
break;
|
|
|
|
cur = next;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
}
|
2014-03-12 01:44:49 +00:00
|
|
|
|
|
|
|
switch (count) {
|
2012-02-27 01:40:27 +00:00
|
|
|
case 0:
|
|
|
|
eprintf ("No matching comments\n");
|
|
|
|
break;
|
|
|
|
case 1:
|
2014-03-12 01:44:49 +00:00
|
|
|
off = cb.addr;
|
2012-02-27 01:40:27 +00:00
|
|
|
r_io_sundo_push (core->io, core->offset);
|
|
|
|
r_core_seek (core, off, 1);
|
|
|
|
r_core_block_read (core, 0);
|
|
|
|
break;
|
2014-03-12 01:44:49 +00:00
|
|
|
default:
|
|
|
|
eprintf ("Too many results\n");
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
2014-03-12 01:44:49 +00:00
|
|
|
free (cb.str);
|
2012-07-12 02:21:56 +00:00
|
|
|
} else eprintf ("Usage: sC[?*] comment-grep\n"
|
|
|
|
"sC* list all comments\n"
|
|
|
|
"sC const seek to comment matching 'const'\n");
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
r_io_sundo_push (core->io, core->offset);
|
|
|
|
r_core_seek (core, off*sign, 1);
|
|
|
|
r_core_block_read (core, 0);
|
|
|
|
break;
|
|
|
|
case '/':
|
|
|
|
{
|
|
|
|
const char *pfx = r_config_get (core->config, "search.prefix");
|
2012-12-30 00:05:12 +00:00
|
|
|
//kwidx cfg var is ignored
|
|
|
|
int kwidx = core->search->n_kws; //(int)r_config_get_i (core->config, "search.kwidx")-1;
|
2012-02-27 01:40:27 +00:00
|
|
|
if (kwidx<0) kwidx = 0;
|
2012-06-10 21:58:34 +00:00
|
|
|
switch (input[1]) {
|
2012-12-30 00:05:12 +00:00
|
|
|
case ' ':
|
2012-06-10 21:58:34 +00:00
|
|
|
case 'x':
|
2012-12-30 00:05:12 +00:00
|
|
|
r_config_set_i (core->config, "search.count", 1);
|
|
|
|
r_core_cmdf (core, "s+1; p8 ; .%s;s-1;s %s%d_0;f-%s%d_0",
|
|
|
|
input, pfx, kwidx, pfx, kwidx, pfx, kwidx);
|
|
|
|
r_config_set_i (core->config, "search.count", 0);
|
2012-06-10 21:58:34 +00:00
|
|
|
break;
|
2012-12-30 00:05:12 +00:00
|
|
|
default:
|
|
|
|
eprintf ("unknown search method\n");
|
2012-06-10 21:58:34 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
break;
|
2013-09-11 23:55:45 +00:00
|
|
|
case '.':
|
|
|
|
for (input++;*input=='.';input++);
|
|
|
|
r_core_seek_base (core, input);
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
case '*':
|
|
|
|
r_io_sundo_list (core->io);
|
|
|
|
break;
|
|
|
|
case '+':
|
|
|
|
if (input[1]!='\0') {
|
2012-12-30 00:05:12 +00:00
|
|
|
int delta = (input[1]=='+')? core->blocksize: off;
|
2012-02-27 01:40:27 +00:00
|
|
|
r_io_sundo_push (core->io, core->offset);
|
|
|
|
r_core_seek_delta (core, delta);
|
|
|
|
} else {
|
|
|
|
off = r_io_sundo_redo (core->io);
|
|
|
|
if (off != UT64_MAX)
|
|
|
|
r_core_seek (core, off, 0);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '-':
|
|
|
|
if (input[1]!='\0') {
|
2012-12-30 00:05:12 +00:00
|
|
|
int delta = (input[1]=='-') ? -core->blocksize: -off;
|
2012-02-27 01:40:27 +00:00
|
|
|
r_io_sundo_push (core->io, core->offset);
|
|
|
|
r_core_seek_delta (core, delta);
|
|
|
|
} else {
|
|
|
|
off = r_io_sundo (core->io, core->offset);
|
|
|
|
if (off != UT64_MAX)
|
|
|
|
r_core_seek (core, off, 0);
|
|
|
|
}
|
|
|
|
break;
|
2012-09-28 00:20:52 +00:00
|
|
|
case 'n':
|
2012-02-27 01:40:27 +00:00
|
|
|
r_io_sundo_push (core->io, core->offset);
|
2012-09-28 00:20:52 +00:00
|
|
|
r_core_seek_next (core, r_config_get (core->config, "scr.nkey"));
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
2013-10-08 22:29:49 +00:00
|
|
|
case 'p':
|
2012-02-27 01:40:27 +00:00
|
|
|
r_io_sundo_push (core->io, core->offset);
|
2012-09-28 00:20:52 +00:00
|
|
|
r_core_seek_previous (core, r_config_get (core->config, "scr.nkey"));
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
off = core->blocksize;
|
|
|
|
if (input[1]&&input[2]) {
|
|
|
|
cmd = strdup (input);
|
|
|
|
p = strchr (cmd+2, ' ');
|
|
|
|
if (p) {
|
|
|
|
off = r_num_math (core->num, p+1);;
|
|
|
|
*p = '\0';
|
|
|
|
}
|
|
|
|
cmd[0] = 's';
|
|
|
|
// perform real seek if provided
|
2012-09-19 12:08:44 +00:00
|
|
|
r_cmd_call (core->rcmd, cmd);
|
2012-02-27 01:40:27 +00:00
|
|
|
free (cmd);
|
|
|
|
}
|
|
|
|
r_io_sundo_push (core->io, core->offset);
|
|
|
|
r_core_seek_align (core, off, 0);
|
|
|
|
break;
|
|
|
|
case 'b':
|
2012-08-03 00:05:50 +00:00
|
|
|
if (off == 0)
|
|
|
|
off = core->offset;
|
2012-02-27 01:40:27 +00:00
|
|
|
r_io_sundo_push (core->io, core->offset);
|
|
|
|
r_core_anal_bb_seek (core, off);
|
|
|
|
break;
|
2013-10-19 22:25:37 +00:00
|
|
|
case 'f':
|
|
|
|
{
|
|
|
|
RAnalFunction *fcn = r_anal_fcn_find (core->anal, core->offset, 0);
|
|
|
|
if (fcn)
|
|
|
|
r_core_seek (core, fcn->addr+fcn->size, 1);
|
|
|
|
}
|
|
|
|
break;
|
2012-09-28 00:20:52 +00:00
|
|
|
case 'o':
|
2012-02-27 01:40:27 +00:00
|
|
|
{
|
|
|
|
RAnalOp op;
|
2013-12-03 02:36:56 +00:00
|
|
|
int val=0, ret, i, n = r_num_math (core->num, input+1);
|
2013-12-10 00:58:06 +00:00
|
|
|
if (n==0) n = 1;
|
2013-12-02 13:34:32 +00:00
|
|
|
if (n<0) {
|
|
|
|
int ret = prevopsz (core, n);
|
|
|
|
ret = r_anal_op (core->anal, &op,
|
|
|
|
core->offset, core->block, core->blocksize);
|
|
|
|
val += ret;
|
|
|
|
} else
|
2013-11-25 01:03:54 +00:00
|
|
|
for (val=i=0; i<n; i++) {
|
|
|
|
ret = r_anal_op (core->anal, &op,
|
|
|
|
core->offset, core->block, core->blocksize);
|
|
|
|
if (ret<1)
|
|
|
|
break;
|
|
|
|
r_core_seek_delta (core, ret);
|
|
|
|
val += ret;
|
|
|
|
}
|
|
|
|
core->num->value = val;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
break;
|
2013-12-10 00:58:06 +00:00
|
|
|
case 'g':
|
|
|
|
{
|
|
|
|
RIOSection *s = r_io_section_get (core->io,
|
|
|
|
r_io_section_vaddr_to_offset (core->io,
|
|
|
|
core->offset));
|
|
|
|
if (s) r_core_seek (core, s->vaddr, 1);
|
|
|
|
else r_core_seek (core, 0, 1);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'G':
|
|
|
|
{
|
|
|
|
RIOSection *s = r_io_section_get (core->io,
|
|
|
|
r_io_section_vaddr_to_offset (core->io,
|
|
|
|
core->offset));
|
|
|
|
// XXX: this +2 is a hack. must fix gap between sections
|
|
|
|
if (s) r_core_seek (core, s->vaddr+s->size+2, 1);
|
|
|
|
else r_core_seek (core, core->file->size, 1);
|
|
|
|
}
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
case '?':
|
|
|
|
r_cons_printf (
|
2014-01-23 08:44:47 +00:00
|
|
|
"|Usage: s[+-] [addr]\n"
|
|
|
|
"| s print current address\n"
|
|
|
|
"| s 0x320 seek to this address\n"
|
|
|
|
"| s- undo seek\n"
|
|
|
|
"| s+ redo seek\n"
|
|
|
|
"| s* list undo seek history\n"
|
|
|
|
"| s++ seek blocksize bytes forward\n"
|
|
|
|
"| s-- seek blocksize bytes backward\n"
|
|
|
|
"| s+ 512 seek 512 bytes forward\n"
|
|
|
|
"| s- 512 seek 512 bytes backward\n"
|
|
|
|
"| sg/sG seek begin (sg) or end (sG) of section or file\n"
|
|
|
|
"| s.hexoff Seek honoring a base from core->offset\n"
|
|
|
|
"| sa [[+-]a] [asz] seek asz (or bsize) aligned to addr\n"
|
|
|
|
"| sn/sp seek next/prev scr.nkey\n"
|
|
|
|
"| s/ DATA search for next occurrence of 'DATA'\n"
|
|
|
|
"| s/x 9091 search for next occurrence of \\x90\\x91\n"
|
|
|
|
"| sb seek aligned to bb start\n"
|
|
|
|
//"| sp [page] seek page N (page = block)\n"
|
|
|
|
"| so [num] seek to N next opcode(s)\n"
|
|
|
|
"| sf seek to next function (f->addr+f->size)\n"
|
|
|
|
"| sC str seek to comment matching given string\n"
|
|
|
|
"| sr pc seek to register\n");
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else r_cons_printf ("0x%"PFMT64x"\n", core->offset);
|
|
|
|
return 0;
|
|
|
|
}
|