2011-01-26 20:54:39 +00:00
|
|
|
|
/* radare - LGPL - Copyright 2009-2011 // nibble<.ds@gmail.com>, pancake<nopcode.org> */
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
|
|
|
|
#include "r_core.h"
|
|
|
|
|
#include "r_hash.h"
|
2009-02-26 14:15:19 +00:00
|
|
|
|
|
2009-12-31 00:27:03 +00:00
|
|
|
|
#include <sys/types.h>
|
2011-05-21 12:27:46 +00:00
|
|
|
|
#include <ctype.h>
|
2009-02-18 00:43:57 +00:00
|
|
|
|
#include <stdarg.h>
|
2011-02-23 18:11:39 +00:00
|
|
|
|
#if HAVE_LIB_MAGIC
|
|
|
|
|
#include <magic.h>
|
|
|
|
|
#endif
|
2010-07-03 01:35:26 +00:00
|
|
|
|
|
2011-02-17 00:22:15 +00:00
|
|
|
|
static int printzoomcallback(void *user, int mode, ut64 addr, ut8 *bufz, ut64 size) {
|
2011-02-16 23:58:54 +00:00
|
|
|
|
RCore *core = (RCore *) user;
|
|
|
|
|
int j, ret = 0;
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
RFlagItem *flag;
|
|
|
|
|
|
2011-02-17 00:22:15 +00:00
|
|
|
|
switch (mode) {
|
|
|
|
|
case 'p':
|
|
|
|
|
for (j=0; j<size; j++)
|
2011-02-24 08:40:19 +00:00
|
|
|
|
if (IS_PRINTABLE (bufz[j]))
|
2011-02-17 00:22:15 +00:00
|
|
|
|
ret++;
|
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
|
|
|
|
r_list_foreach (core->flags->flags, iter, flag)
|
|
|
|
|
if (flag->offset <= addr && addr < flag->offset+flag->size)
|
|
|
|
|
ret++;
|
|
|
|
|
break;
|
|
|
|
|
case 's':
|
|
|
|
|
j = r_flag_space_get (core->flags, "strings");
|
|
|
|
|
r_list_foreach (core->flags->flags, iter, flag) {
|
|
|
|
|
if (flag->space == j && ((addr <= flag->offset
|
|
|
|
|
&& flag->offset < addr+size)
|
|
|
|
|
|| (addr <= flag->offset+flag->size
|
|
|
|
|
&& flag->offset+flag->size < addr+size)))
|
|
|
|
|
ret++;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2011-03-08 12:02:02 +00:00
|
|
|
|
case '0': // 0xFF
|
|
|
|
|
for (j=0; j<size; j++)
|
|
|
|
|
if (bufz[j] == 0)
|
|
|
|
|
ret++;
|
|
|
|
|
break;
|
2011-02-17 00:22:15 +00:00
|
|
|
|
case 'F': // 0xFF
|
|
|
|
|
for (j=0; j<size; j++)
|
|
|
|
|
if (bufz[j] == 0xff)
|
|
|
|
|
ret++;
|
|
|
|
|
break;
|
|
|
|
|
case 'e': // entropy
|
2011-03-08 12:02:02 +00:00
|
|
|
|
ret = (ut8) (r_hash_entropy_fraction (bufz, size)*255);
|
2011-02-17 00:22:15 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'h': //head
|
|
|
|
|
default:
|
|
|
|
|
ret = *bufz;
|
2011-02-16 23:58:54 +00:00
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2010-07-12 23:20:57 +00:00
|
|
|
|
static int checkbpcallback(RCore *core) {
|
2010-07-12 23:22:44 +00:00
|
|
|
|
ut64 pc = r_debug_reg_get (core->dbg, "pc");
|
|
|
|
|
RBreakpointItem *bpi = r_bp_get (core->dbg->bp, pc);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
if (bpi) {
|
|
|
|
|
if (bpi->data)
|
|
|
|
|
r_core_cmd (core, bpi->data, 0);
|
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-28 18:47:21 +00:00
|
|
|
|
static int bypassbp(RCore *core) {
|
|
|
|
|
ut64 addr;
|
|
|
|
|
r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE);
|
|
|
|
|
addr = r_debug_reg_get (core->dbg, "pc");
|
|
|
|
|
RBreakpointItem *bpi = r_bp_get (core->dbg->bp, addr);
|
2011-05-13 08:22:28 +00:00
|
|
|
|
if (!bpi) return R_FALSE;
|
2010-10-28 19:20:44 +00:00
|
|
|
|
/* XXX 2 if libr/debug/debug.c:226 is enabled */
|
|
|
|
|
r_debug_step (core->dbg, 1);
|
2010-10-28 18:47:21 +00:00
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-24 08:40:19 +00:00
|
|
|
|
// TODO: move somewhere else
|
2011-02-24 15:50:29 +00:00
|
|
|
|
R_API RAsmOp *r_core_disassemble (RCore *core, ut64 addr) {
|
2011-02-24 08:40:19 +00:00
|
|
|
|
ut8 buf[4096];
|
|
|
|
|
static RBuffer *b = NULL; // XXX: never freed and non-thread safe. move to RCore
|
2011-02-24 15:50:29 +00:00
|
|
|
|
RAsmOp *op = R_NEW (RAsmOp);
|
2011-02-24 08:40:19 +00:00
|
|
|
|
if (b == NULL) {
|
|
|
|
|
b = r_buf_new ();
|
|
|
|
|
if (r_core_read_at (core, addr, buf, sizeof (buf))) {
|
|
|
|
|
b->base = addr;
|
|
|
|
|
r_buf_set_bytes (b, buf, 4096);
|
|
|
|
|
} else return NULL;
|
|
|
|
|
} else {
|
|
|
|
|
if (addr < b->base || addr > b->base+b->length-32) {
|
|
|
|
|
if (r_core_read_at (core, addr, buf, sizeof (buf))) {
|
|
|
|
|
b->base = addr;
|
|
|
|
|
r_buf_set_bytes (b, buf, 4096);
|
|
|
|
|
} else return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-02-24 15:50:29 +00:00
|
|
|
|
if (r_asm_disassemble (core->assembler, op, b->buf, b->length)<1) {
|
|
|
|
|
free (op);
|
2011-02-24 08:40:19 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2011-02-24 15:50:29 +00:00
|
|
|
|
return op;
|
2011-02-24 08:40:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-05-24 16:51:01 +00:00
|
|
|
|
static int cmd_project(void *data, const char *input) {
|
|
|
|
|
RCore *core = (RCore *)data;
|
|
|
|
|
const char *arg = input+1;
|
|
|
|
|
char *str = strdup (r_config_get (core->config, "file.project"));
|
|
|
|
|
if (*arg==' ') arg++;
|
|
|
|
|
switch (input[0]) {
|
|
|
|
|
case 'o': r_core_project_open (core, input[1]?arg:str); break;
|
|
|
|
|
case 's': r_core_project_save (core, input[1]?arg:str); break;
|
|
|
|
|
case 'i': free (r_core_project_info (core, input[1]?arg:str)); break;
|
|
|
|
|
default:
|
|
|
|
|
r_cons_printf (
|
2011-07-01 11:22:13 +00:00
|
|
|
|
"Usage: P[?osi] [file]\n"
|
2010-05-24 16:51:01 +00:00
|
|
|
|
" Po [file] open project\n"
|
|
|
|
|
" Ps [file] save project\n"
|
|
|
|
|
" Pi [file] info\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
free (str);
|
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-04-08 10:29:47 +00:00
|
|
|
|
static int cmd_zign(void *data, const char *input) {
|
2010-05-24 16:51:01 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2010-04-08 14:20:41 +00:00
|
|
|
|
RAnalFcn *fcni;
|
|
|
|
|
RListIter *iter;
|
2010-04-08 13:48:53 +00:00
|
|
|
|
RSignItem *item;
|
2011-04-06 10:26:19 +00:00
|
|
|
|
int i, fd = -1, len;
|
2010-05-24 16:51:01 +00:00
|
|
|
|
char *ptr, *name;
|
2010-04-08 10:29:47 +00:00
|
|
|
|
|
|
|
|
|
switch (input[0]) {
|
2010-04-08 14:20:41 +00:00
|
|
|
|
case 'g':
|
|
|
|
|
if (input[1]==' ' && input[2]) {
|
|
|
|
|
ptr = strchr (input+2, ' ');
|
|
|
|
|
if (ptr) {
|
|
|
|
|
*ptr = '\0';
|
2010-11-21 18:01:41 +00:00
|
|
|
|
fd = open (ptr+1, O_RDWR|O_CREAT|O_TRUNC, 0644);
|
2010-04-08 14:20:41 +00:00
|
|
|
|
if (fd == -1) {
|
|
|
|
|
eprintf ("Cannot open %s in read-write\n", ptr+1);
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
r_cons_singleton ()->fdout = fd;
|
|
|
|
|
r_cons_strcat ("# Signatures\n");
|
|
|
|
|
}
|
|
|
|
|
r_cons_printf ("zp %s\n", input+2);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_list_foreach (core->anal->fcns, iter, fcni) {
|
2010-04-08 14:20:41 +00:00
|
|
|
|
ut8 buf[128];
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if (r_io_read_at (core->io, fcni->addr, buf, sizeof (buf)) == sizeof (buf)) {
|
|
|
|
|
RFlagItem *flag = r_flag_get_i (core->flags, fcni->addr);
|
2010-04-08 14:20:41 +00:00
|
|
|
|
if (flag) {
|
|
|
|
|
name = flag->name;
|
|
|
|
|
r_cons_printf ("zb %s ", name);
|
|
|
|
|
len = (fcni->size>sizeof (buf))?sizeof (buf):fcni->size;
|
|
|
|
|
for (i=0; i<len; i++) {
|
|
|
|
|
r_cons_printf ("%02x", buf[i]);
|
|
|
|
|
}
|
|
|
|
|
r_cons_newline ();
|
2010-04-14 11:02:23 +00:00
|
|
|
|
} else eprintf ("Unnamed function at 0x%08"PFMT64x"\n", fcni->addr);
|
|
|
|
|
} else eprintf ("Cannot read at 0x%08"PFMT64x"\n", fcni->addr);
|
2010-04-08 14:20:41 +00:00
|
|
|
|
}
|
2010-07-20 21:25:15 +00:00
|
|
|
|
r_cons_strcat ("zp-\n");
|
2010-04-08 14:20:41 +00:00
|
|
|
|
if (ptr) {
|
|
|
|
|
r_cons_flush ();
|
|
|
|
|
r_cons_singleton ()->fdout = 1;
|
|
|
|
|
close (fd);
|
|
|
|
|
}
|
|
|
|
|
} else eprintf ("Usage: zg libc [libc.sig]\n");
|
|
|
|
|
break;
|
2010-04-08 13:48:53 +00:00
|
|
|
|
case 'p':
|
|
|
|
|
if (!input[1])
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_cons_printf ("%s", core->sign->prefix);
|
2010-04-08 13:48:53 +00:00
|
|
|
|
else if (!strcmp ("-", input+1))
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_sign_prefix (core->sign, "");
|
|
|
|
|
else r_sign_prefix (core->sign, input+2);
|
2010-04-08 10:29:47 +00:00
|
|
|
|
break;
|
2010-04-08 13:48:53 +00:00
|
|
|
|
case 'a':
|
2010-04-08 10:29:47 +00:00
|
|
|
|
case 'b':
|
2010-06-17 15:55:39 +00:00
|
|
|
|
case 'h':
|
2010-04-08 16:48:39 +00:00
|
|
|
|
case 'f':
|
2010-04-08 13:48:53 +00:00
|
|
|
|
ptr = strchr (input+3, ' ');
|
2010-04-08 10:29:47 +00:00
|
|
|
|
if (ptr) {
|
|
|
|
|
*ptr = 0;
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_sign_add (core->sign, core->anal, (int)*input, input+2, ptr+1);
|
2010-06-17 15:55:39 +00:00
|
|
|
|
} else eprintf ("Usage: z%c [name] [arg]\n", *input);
|
2010-04-08 10:29:47 +00:00
|
|
|
|
break;
|
2010-04-08 13:48:53 +00:00
|
|
|
|
case 'c':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
item = r_sign_check (core->sign, core->block, core->blocksize);
|
2010-04-08 13:48:53 +00:00
|
|
|
|
if (item)
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("f sign.%s @ 0x%08"PFMT64x"\n", item->name, core->offset);
|
2010-04-08 10:29:47 +00:00
|
|
|
|
break;
|
|
|
|
|
case '-':
|
2010-06-20 23:58:45 +00:00
|
|
|
|
if (input[1] == '*')
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_sign_reset (core->sign);
|
2010-06-20 23:58:45 +00:00
|
|
|
|
else eprintf ("TODO\n");
|
2010-04-08 10:29:47 +00:00
|
|
|
|
break;
|
|
|
|
|
case '/':
|
|
|
|
|
{
|
|
|
|
|
// TODO: parse arg0 and arg1
|
2010-04-08 13:48:53 +00:00
|
|
|
|
ut8 *buf;
|
|
|
|
|
int len, idx;
|
|
|
|
|
ut64 ini, fin;
|
|
|
|
|
RSignItem *si;
|
|
|
|
|
RIOSection *s;
|
|
|
|
|
if (input[1]) {
|
2010-07-21 09:12:24 +00:00
|
|
|
|
char *ptr = strchr (input+2, ' ');
|
2010-04-08 13:48:53 +00:00
|
|
|
|
if (ptr) {
|
|
|
|
|
*ptr = '\0';
|
2010-05-19 22:59:42 +00:00
|
|
|
|
ini = r_num_math (core->num, input+2);
|
|
|
|
|
fin = r_num_math (core->num, ptr+1);
|
2010-04-08 13:48:53 +00:00
|
|
|
|
} else {
|
|
|
|
|
ini = core->offset;
|
2010-05-19 22:59:42 +00:00
|
|
|
|
fin = ini+r_num_math (core->num, input+2);
|
2010-04-08 13:48:53 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
2010-07-21 10:59:11 +00:00
|
|
|
|
s = r_io_section_get (core->io, core->io->off);
|
2010-04-08 13:48:53 +00:00
|
|
|
|
if (s) {
|
2010-07-21 10:59:11 +00:00
|
|
|
|
ini = core->io->va?s->vaddr:s->offset;
|
|
|
|
|
fin = ini + (core->io->va?s->vsize:s->size);
|
2010-04-08 13:48:53 +00:00
|
|
|
|
} else {
|
|
|
|
|
eprintf ("No section identified, please provide range.\n");
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (ini>=fin) {
|
2010-07-21 09:12:24 +00:00
|
|
|
|
eprintf ("Invalid range (0x%"PFMT64x"-0x%"PFMT64x").\n", ini, fin);
|
2010-04-08 13:48:53 +00:00
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
len = fin-ini;
|
|
|
|
|
buf = malloc (len);
|
|
|
|
|
if (buf != NULL) {
|
2010-04-14 11:02:23 +00:00
|
|
|
|
eprintf ("Ranges are: 0x%08"PFMT64x" 0x%08"PFMT64x"\n", ini, fin);
|
2010-04-08 16:48:39 +00:00
|
|
|
|
r_cons_printf ("f-sign*\n");
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if (r_io_read_at (core->io, ini, buf, len) == len) {
|
2010-04-08 13:48:53 +00:00
|
|
|
|
for (idx=0; idx<len; idx++) {
|
2010-07-21 15:11:06 +00:00
|
|
|
|
si = r_sign_check (core->sign, buf+idx, len-idx);
|
2010-04-08 16:48:39 +00:00
|
|
|
|
if (si) {
|
2011-01-02 13:39:25 +00:00
|
|
|
|
if (si->type == 'f')
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("f sign.fun_%s_%d @ 0x%08"PFMT64x"\n",
|
2010-07-21 09:12:24 +00:00
|
|
|
|
si->name, idx, ini+idx); //core->offset);
|
2010-04-14 11:02:23 +00:00
|
|
|
|
else r_cons_printf ("f sign.%s @ 0x%08"PFMT64x"\n",
|
2010-07-21 09:12:24 +00:00
|
|
|
|
si->name, ini+idx); //core->offset+idx);
|
2010-04-08 16:48:39 +00:00
|
|
|
|
}
|
2010-04-08 13:48:53 +00:00
|
|
|
|
}
|
2010-04-14 11:02:23 +00:00
|
|
|
|
} else eprintf ("Cannot read %d bytes at 0x%08"PFMT64x"\n", len, ini);
|
2010-04-08 13:48:53 +00:00
|
|
|
|
free (buf);
|
|
|
|
|
} else eprintf ("Cannot alloc %d bytes\n", len);
|
2010-04-08 10:29:47 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2010-04-08 13:48:53 +00:00
|
|
|
|
case '\0':
|
2010-07-20 22:05:33 +00:00
|
|
|
|
case '*':
|
|
|
|
|
r_sign_list (core->sign, (input[0]=='*'));
|
2010-04-08 13:48:53 +00:00
|
|
|
|
break;
|
2010-04-08 10:29:47 +00:00
|
|
|
|
default:
|
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
2010-04-08 13:48:53 +00:00
|
|
|
|
"Usage: z[abcp/*-] [arg]\n"
|
|
|
|
|
" z show status of zignatures\n"
|
|
|
|
|
" z* display all zignatures\n"
|
|
|
|
|
" zp display current prefix\n"
|
|
|
|
|
" zp prefix define prefix for following zignatures\n"
|
|
|
|
|
" zp- unset prefix\n"
|
2010-04-08 10:29:47 +00:00
|
|
|
|
" z-prefix unload zignatures prefixed as\n"
|
|
|
|
|
" z-* unload all zignatures\n"
|
|
|
|
|
" za ... define new zignature for analysis\n"
|
2010-06-17 15:55:39 +00:00
|
|
|
|
" zf name fmt define function zignature (fast/slow, args, types)\n"
|
|
|
|
|
" zb name bytes define zignature for bytes\n"
|
|
|
|
|
" zh name bytes define function header zignature\n"
|
2010-07-12 19:37:40 +00:00
|
|
|
|
" zg pfx [file] generate signature for current file\n"
|
2010-04-08 13:48:53 +00:00
|
|
|
|
" .zc @ fcn.foo flag signature if matching (.zc@@fcn)\n"
|
2010-04-08 16:48:39 +00:00
|
|
|
|
" z/ [ini] [end] search zignatures between these regions\n"
|
|
|
|
|
"NOTE: bytes can contain '.' (dots) to specify a binary mask\n");
|
2010-04-08 10:29:47 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-23 04:39:23 +00:00
|
|
|
|
static int cmd_rap(void *data, const char *input) {
|
2010-02-05 11:21:37 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2011-06-04 01:51:33 +00:00
|
|
|
|
switch (*input) {
|
2010-08-24 09:58:09 +00:00
|
|
|
|
case '\0':
|
2011-06-04 01:51:33 +00:00
|
|
|
|
r_core_rtr_list (core);
|
2010-08-24 09:58:09 +00:00
|
|
|
|
break;
|
|
|
|
|
case '?':
|
2011-06-04 01:51:33 +00:00
|
|
|
|
r_core_rtr_help (core);
|
2010-08-24 09:58:09 +00:00
|
|
|
|
break;
|
|
|
|
|
case '+':
|
2011-06-04 01:51:33 +00:00
|
|
|
|
r_core_rtr_add (core, input+1);
|
2010-08-24 09:58:09 +00:00
|
|
|
|
break;
|
|
|
|
|
case '-':
|
2011-06-04 01:51:33 +00:00
|
|
|
|
r_core_rtr_remove (core, input+1);
|
2010-08-24 09:58:09 +00:00
|
|
|
|
break;
|
|
|
|
|
case '=':
|
2011-06-04 01:51:33 +00:00
|
|
|
|
r_core_rtr_session (core, input+1);
|
2010-08-24 09:58:09 +00:00
|
|
|
|
break;
|
|
|
|
|
case '<':
|
|
|
|
|
r_core_rtr_pushout (core, input+1);
|
|
|
|
|
break;
|
|
|
|
|
case '!':
|
|
|
|
|
r_io_system (core->io, input+1);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
r_core_rtr_cmd (core, input);
|
|
|
|
|
}
|
|
|
|
|
#if 0
|
2010-02-05 11:21:37 +00:00
|
|
|
|
switch (input[0]) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '\0':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_lib_list (core->lib);
|
2010-05-26 16:25:35 +00:00
|
|
|
|
r_io_plugin_list (core->io);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2010-08-23 04:39:23 +00:00
|
|
|
|
case '?':
|
|
|
|
|
eprintf ("usage: =[fd] [cmd]\n"
|
|
|
|
|
"TODO: import the rest of functionality from r1\n");
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
default:
|
2010-08-23 04:39:23 +00:00
|
|
|
|
r_io_set_fd (core->io, core->file->fd);
|
|
|
|
|
if (input[0]==' ')
|
|
|
|
|
input++;
|
|
|
|
|
r_io_system (core->io, input);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2010-08-24 09:58:09 +00:00
|
|
|
|
#endif
|
2009-02-05 21:08:46 +00:00
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-30 21:12:19 +00:00
|
|
|
|
static void cmd_reg(RCore *core, const char *str) {
|
2010-01-19 10:25:17 +00:00
|
|
|
|
struct r_reg_item_t *r;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
const char *name;
|
2010-01-19 10:25:17 +00:00
|
|
|
|
char *arg;
|
|
|
|
|
int size, i, type = R_REG_TYPE_GPR;
|
|
|
|
|
switch (str[0]) {
|
|
|
|
|
case '?':
|
2010-02-28 21:58:21 +00:00
|
|
|
|
if (str[1]) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE);
|
|
|
|
|
r = r_reg_get (core->dbg->reg, str+1, R_REG_TYPE_GPR);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
if (r == NULL) eprintf ("Unknown register (%s)\n", str+1);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
else r_cons_printf ("0x%08"PFMT64x"\n", r_reg_get_value (core->dbg->reg, r));
|
2010-02-28 21:58:21 +00:00
|
|
|
|
} else
|
2010-01-21 01:38:52 +00:00
|
|
|
|
eprintf ("Usage: dr[*] [type] [size] - get/set registers\n"
|
2010-01-19 10:25:17 +00:00
|
|
|
|
" dr? display this help message\n"
|
2010-03-04 01:11:54 +00:00
|
|
|
|
" dr show registers in rows\n"
|
|
|
|
|
" dr= show registers in columns\n"
|
2010-02-28 21:58:21 +00:00
|
|
|
|
" dr?eax show value of eax register\n"
|
2010-01-19 10:25:17 +00:00
|
|
|
|
" .dr* include common register values in flags\n"
|
|
|
|
|
" .dr- unflag all registers\n"
|
|
|
|
|
" drp [file] load register metadata file\n"
|
|
|
|
|
" drp display current register profile\n"
|
2010-10-19 20:17:58 +00:00
|
|
|
|
" drb [type] display hexdump of gpr arena (WIP)\n"
|
2010-01-19 10:25:17 +00:00
|
|
|
|
" dr show 'gpr' registers\n"
|
|
|
|
|
" drt show all register types\n"
|
2010-02-03 17:15:31 +00:00
|
|
|
|
" drn [pc] get register name for pc,sp,bp,a0-3\n"
|
2010-09-23 18:42:35 +00:00
|
|
|
|
" dro show previous (old) values of registers\n"
|
2010-01-19 10:25:17 +00:00
|
|
|
|
" dr all show all registers\n"
|
|
|
|
|
" dr flg 1 show flag registers ('flg' is type, see drt)\n"
|
|
|
|
|
" dr 16 show 16 bit registers\n"
|
|
|
|
|
" dr 32 show 32 bit registers\n"
|
|
|
|
|
" dr eax=33 set register value. eax = 33\n");
|
2010-09-23 18:42:35 +00:00
|
|
|
|
// TODO: 'drs' to swap register arenas and display old register valuez
|
2010-01-31 01:30:59 +00:00
|
|
|
|
break;
|
2010-10-19 20:17:58 +00:00
|
|
|
|
case 'b':
|
|
|
|
|
{ // WORK IN PROGRESS // DEBUG COMMAND
|
|
|
|
|
int len;
|
|
|
|
|
const ut8 *buf = r_reg_get_bytes (core->dbg->reg, R_REG_TYPE_GPR, &len);
|
|
|
|
|
r_print_hexdump (core->print, 0LL, buf, len, 16, 16);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-01-19 10:25:17 +00:00
|
|
|
|
case 'p':
|
2010-10-14 17:01:14 +00:00
|
|
|
|
if (!str[1]) {
|
2011-04-02 18:03:00 +00:00
|
|
|
|
if (core->dbg->reg->reg_profile_str) {
|
2011-03-23 23:54:09 +00:00
|
|
|
|
//core->anal->reg = core->dbg->reg;
|
2011-04-02 18:03:00 +00:00
|
|
|
|
r_cons_printf ("%s\n", core->dbg->reg->reg_profile_str);
|
2011-03-23 23:54:09 +00:00
|
|
|
|
//r_cons_printf ("%s\n", core->anal->reg->reg_profile);
|
|
|
|
|
} else eprintf ("No register profile defined. Try 'dr.'\n");
|
2010-05-19 22:59:42 +00:00
|
|
|
|
} else r_reg_set_profile (core->dbg->reg, str+2);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 't':
|
2011-03-24 21:47:06 +00:00
|
|
|
|
for (i=0; (name=r_reg_get_type (i)); i++)
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_cons_printf ("%s\n", name);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
2010-02-03 17:15:31 +00:00
|
|
|
|
case 'n':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
name = r_reg_get_name (core->dbg->reg, r_reg_get_name_idx (str+2));
|
2010-02-28 21:58:21 +00:00
|
|
|
|
if (name && *name)
|
|
|
|
|
r_cons_printf ("%s\n", name);
|
|
|
|
|
else eprintf ("Oops. try dn [pc|sp|bp|a0|a1|a2|a3]\n");
|
2010-02-03 17:15:31 +00:00
|
|
|
|
break;
|
2010-09-24 14:45:56 +00:00
|
|
|
|
case 'd':
|
|
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 32, 3); // XXX detect which one is current usage
|
|
|
|
|
break;
|
2010-09-23 18:42:35 +00:00
|
|
|
|
case 'o':
|
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_FALSE);
|
|
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 32, 0); // XXX detect which one is current usage
|
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_FALSE);
|
|
|
|
|
break;
|
2010-03-04 01:11:54 +00:00
|
|
|
|
case '=':
|
2011-01-21 08:17:14 +00:00
|
|
|
|
if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE)) {
|
|
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 32, 2); // XXX detect which one is current usage
|
|
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 64, 2);
|
|
|
|
|
} else eprintf ("Cannot retrieve registers from pid %d\n", core->dbg->pid);
|
2010-03-04 01:11:54 +00:00
|
|
|
|
break;
|
2010-01-19 10:25:17 +00:00
|
|
|
|
case '*':
|
2011-01-21 08:17:14 +00:00
|
|
|
|
if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE)) {
|
|
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 32, 1); // XXX detect which one is current usage
|
|
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 64, 1);
|
2011-05-20 18:42:25 +00:00
|
|
|
|
} //else eprintf ("Cannot retrieve registers from pid %d\n", core->dbg->pid);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case '\0':
|
2011-01-21 08:17:14 +00:00
|
|
|
|
if (r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE)) {
|
|
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 32, 0);
|
|
|
|
|
r_debug_reg_list (core->dbg, R_REG_TYPE_GPR, 64, 0);
|
2011-05-20 18:42:25 +00:00
|
|
|
|
} //else eprintf ("Cannot retrieve registers from pid %d\n", core->dbg->pid);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
2010-03-04 01:11:54 +00:00
|
|
|
|
arg = strchr (str+1, '=');
|
2010-01-19 10:25:17 +00:00
|
|
|
|
if (arg) {
|
|
|
|
|
*arg = 0;
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r = r_reg_get (core->dbg->reg, str+1, R_REG_TYPE_GPR);
|
2010-02-02 10:09:52 +00:00
|
|
|
|
if (r) {
|
|
|
|
|
//eprintf ("SET(%s)(%s)\n", str, arg+1);
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" ->", str,
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_reg_get_value (core->dbg->reg, r));
|
|
|
|
|
r_reg_set_value (core->dbg->reg, r,
|
|
|
|
|
r_num_math (core->num, arg+1));
|
|
|
|
|
r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_TRUE);
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"\n",
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_reg_get_value (core->dbg->reg, r));
|
2010-02-02 10:09:52 +00:00
|
|
|
|
} else eprintf ("Unknown register '%s'\n", str+1);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
size = atoi (str+1);
|
|
|
|
|
if (size==0) {
|
|
|
|
|
arg = strchr (str+1, ' ');
|
|
|
|
|
if (arg && size==0) {
|
|
|
|
|
*arg='\0';
|
|
|
|
|
size = atoi (arg);
|
|
|
|
|
} else size = 32;
|
2010-09-24 03:41:54 +00:00
|
|
|
|
//eprintf ("ARG(%s)\n", str+1);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
type = r_reg_type_by_name (str+1);
|
|
|
|
|
}
|
|
|
|
|
//printf("type = %d\nsize = %d\n", type, size);
|
|
|
|
|
if (type != R_REG_TYPE_LAST) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_reg_sync (core->dbg, type, R_FALSE);
|
|
|
|
|
r_debug_reg_list (core->dbg, type, size, str[0]=='*');
|
2010-02-05 11:21:37 +00:00
|
|
|
|
} else eprintf ("cmd_reg: Unknown type\n");
|
2010-01-19 10:25:17 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-30 21:12:19 +00:00
|
|
|
|
static void r_core_cmd_bp(RCore *core, const char *input) {
|
2010-10-27 17:00:45 +00:00
|
|
|
|
RBreakpointItem *bp;
|
2010-09-24 03:41:54 +00:00
|
|
|
|
int hwbp = r_config_get_i (core->config, "dbg.hwbp");
|
2010-01-19 10:25:17 +00:00
|
|
|
|
switch (input[1]) {
|
2010-03-12 17:46:11 +00:00
|
|
|
|
case 't':
|
|
|
|
|
{
|
|
|
|
|
int i = 0;
|
2010-05-19 22:59:42 +00:00
|
|
|
|
RList *list = r_debug_frames (core->dbg);
|
2010-03-12 17:46:11 +00:00
|
|
|
|
RListIter *iter = r_list_iterator (list);
|
|
|
|
|
while (r_list_iter_next (iter)) {
|
|
|
|
|
RDebugFrame *frame = r_list_iter_get (iter);
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("%d 0x%08"PFMT64x" %d\n", i++, frame->addr, frame->size);
|
2010-03-12 17:46:11 +00:00
|
|
|
|
}
|
|
|
|
|
r_list_destroy (list);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-01-19 10:25:17 +00:00
|
|
|
|
case '\0':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_bp_list (core->dbg->bp, input[1]=='*');
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case '-':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_bp_del (core->dbg->bp, r_num_math (core->num, input+2));
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
2010-07-12 23:22:44 +00:00
|
|
|
|
case 'c': {
|
2010-07-12 23:20:57 +00:00
|
|
|
|
ut64 off = r_num_math (core->num, input+2);
|
|
|
|
|
RBreakpointItem *bpi = r_bp_get (core->dbg->bp, off);
|
|
|
|
|
if (bpi) {
|
2010-07-12 23:22:44 +00:00
|
|
|
|
char *arg = strchr (input+2, ' ');
|
|
|
|
|
if (arg) {
|
|
|
|
|
free (bpi->data);
|
|
|
|
|
bpi->data = strdup (arg+1);
|
|
|
|
|
} else {
|
|
|
|
|
free (bpi->data);
|
|
|
|
|
bpi->data = NULL;
|
|
|
|
|
}
|
2010-07-12 23:20:57 +00:00
|
|
|
|
} else eprintf ("No breakpoint defined at 0x%08"PFMT64x"\n", off);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-01-19 10:25:17 +00:00
|
|
|
|
case 'e':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_bp_enable (core->dbg->bp, r_num_math (core->num, input+2), 1);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_bp_enable (core->dbg->bp, r_num_math (core->num, input+2), 0);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'h':
|
|
|
|
|
if (input[2]==' ') {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if (!r_bp_use (core->dbg->bp, input+3))
|
2010-02-01 10:55:56 +00:00
|
|
|
|
eprintf ("Invalid name: '%s'.\n", input+3);
|
2010-05-26 16:25:35 +00:00
|
|
|
|
} else r_bp_plugin_list (core->dbg->bp);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
|
|
|
|
case '?':
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_cons_printf (
|
2010-07-12 23:20:57 +00:00
|
|
|
|
"Usage: db[ecdht] [[-]addr] [len] [rwx] [condstring]\n"
|
|
|
|
|
"db ; list breakpoints\n"
|
|
|
|
|
"db sym.main ; add breakpoint into sym.main\n"
|
|
|
|
|
"db 0x804800 ; add breakpoint\n"
|
|
|
|
|
"db -0x804800 ; remove breakpoint\n"
|
|
|
|
|
"dbe 0x8048000 ; enable breakpoint\n"
|
|
|
|
|
"dbc 0x8048000 cmd ; run command when breakpoint is hit\n"
|
|
|
|
|
"dbd 0x8048000 ; disable breakpoint\n"
|
|
|
|
|
"dbh x86 ; set/list breakpoint plugin handlers\n"
|
2010-03-12 17:46:11 +00:00
|
|
|
|
"Unrelated:\n"
|
2010-07-12 23:20:57 +00:00
|
|
|
|
"dbt ; debug backtrace\n");
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-10-27 17:00:45 +00:00
|
|
|
|
{
|
|
|
|
|
ut64 addr = r_num_math (core->num, input+2);
|
|
|
|
|
if (hwbp) bp = r_bp_add_hw (core->dbg->bp, addr, 1, R_BP_PROT_EXEC);
|
|
|
|
|
else bp = r_bp_add_sw (core->dbg->bp, addr, 1, R_BP_PROT_EXEC);
|
|
|
|
|
if (!bp) eprintf ("Cannot set breakpoint (%s)\n", input+2);
|
|
|
|
|
}
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-15 18:24:19 +00:00
|
|
|
|
/* TODO: this should be moved to the core->yank api */
|
2011-01-11 23:01:06 +00:00
|
|
|
|
// TODO: arg must be const !!! use strdup here
|
2010-03-30 21:12:19 +00:00
|
|
|
|
static int cmd_yank_to(RCore *core, char *arg) {
|
2010-01-12 01:12:18 +00:00
|
|
|
|
ut64 src = core->offset;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
ut64 len = 0;
|
2009-07-08 11:49:55 +00:00
|
|
|
|
ut64 pos = -1;
|
2009-04-15 18:24:19 +00:00
|
|
|
|
char *str;
|
2009-07-08 11:49:55 +00:00
|
|
|
|
ut8 *buf;
|
2009-04-15 18:24:19 +00:00
|
|
|
|
|
2010-02-28 21:58:21 +00:00
|
|
|
|
while (*arg==' ')
|
|
|
|
|
arg = arg+1;
|
|
|
|
|
str = strchr (arg, ' ');
|
2009-04-15 18:24:19 +00:00
|
|
|
|
if (str) {
|
|
|
|
|
str[0]='\0';
|
2010-05-19 22:59:42 +00:00
|
|
|
|
len = r_num_math (core->num, arg);
|
|
|
|
|
pos = r_num_math (core->num, str+1);
|
2009-04-15 18:24:19 +00:00
|
|
|
|
str[0]=' ';
|
|
|
|
|
}
|
2010-02-28 21:58:21 +00:00
|
|
|
|
if ((str == NULL) || (pos == -1) || (len == 0)) {
|
2010-03-26 16:01:25 +00:00
|
|
|
|
eprintf ("Usage: yt [len] [dst-addr]\n");
|
2009-04-15 18:24:19 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
#if 0
|
|
|
|
|
if (!config_get("file.write")) {
|
|
|
|
|
eprintf("You are not in read-write mode.\n");
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2010-02-22 23:26:13 +00:00
|
|
|
|
buf = (ut8*)malloc (len);
|
2009-04-15 18:24:19 +00:00
|
|
|
|
r_core_read_at (core, src, buf, len);
|
|
|
|
|
r_core_write_at (core, pos, buf, len);
|
2011-01-11 23:01:06 +00:00
|
|
|
|
free (buf);
|
2009-04-15 18:24:19 +00:00
|
|
|
|
|
2010-01-12 01:12:18 +00:00
|
|
|
|
core->offset = src;
|
2010-02-22 23:26:13 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2009-04-15 18:24:19 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-01-11 23:01:06 +00:00
|
|
|
|
static int cmd_mount(void *data, const char *_input) {
|
2011-01-14 13:41:56 +00:00
|
|
|
|
ut64 off = 0;
|
2011-01-14 00:02:20 +00:00
|
|
|
|
char *input, *oinput, *ptr, *ptr2;
|
2011-01-11 23:01:06 +00:00
|
|
|
|
RList *list;
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
RFSFile *file;
|
|
|
|
|
RFSRoot *root;
|
|
|
|
|
RFSPlugin *plug;
|
2011-01-14 13:41:56 +00:00
|
|
|
|
RFSPartition *part;
|
2011-01-11 23:01:06 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
|
|
|
|
input = oinput = strdup (_input);
|
|
|
|
|
|
2011-02-22 23:54:40 +00:00
|
|
|
|
switch (*input) {
|
2011-01-11 23:01:06 +00:00
|
|
|
|
case ' ':
|
|
|
|
|
input++;
|
|
|
|
|
if (input[0]==' ')
|
|
|
|
|
input++;
|
|
|
|
|
ptr = strchr (input, ' ');
|
|
|
|
|
if (ptr) {
|
|
|
|
|
*ptr = 0;
|
2011-01-14 00:02:20 +00:00
|
|
|
|
ptr++;
|
|
|
|
|
ptr2 = strchr (ptr, ' ');
|
|
|
|
|
if (ptr2) {
|
|
|
|
|
*ptr2 = 0;
|
2011-01-14 13:41:56 +00:00
|
|
|
|
off = r_num_math (core->num, ptr2+1);
|
2011-01-14 00:02:20 +00:00
|
|
|
|
}
|
|
|
|
|
//r_io_bind (core->io, &(core->fs->iob));
|
2011-04-19 08:04:06 +00:00
|
|
|
|
if (!r_fs_mount (core->fs, input, ptr, off))
|
|
|
|
|
eprintf ("Cannot mount %s\n", input);
|
2011-01-11 23:01:06 +00:00
|
|
|
|
} else eprintf ("Usage: m ext2 /mnt");
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
|
|
|
|
r_fs_umount (core->fs, input+1);
|
|
|
|
|
break;
|
|
|
|
|
case '*':
|
|
|
|
|
eprintf ("List commands in radare format\n");
|
|
|
|
|
r_list_foreach (core->fs->roots, iter, root) {
|
2011-01-14 00:02:20 +00:00
|
|
|
|
r_cons_printf ("m %s 0x%"PFMT64x" %s\n", root->p->name, root->delta, root->path);
|
2011-01-11 23:01:06 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '\0':
|
|
|
|
|
r_list_foreach (core->fs->roots, iter, root) {
|
2011-01-14 00:02:20 +00:00
|
|
|
|
r_cons_printf ("%s\t0x%"PFMT64x"\t%s\n", root->p->name, root->delta, root->path);
|
2011-01-11 23:01:06 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'l': // list of plugins
|
|
|
|
|
r_list_foreach (core->fs->plugins, iter, plug) {
|
|
|
|
|
r_cons_printf ("%s\t%s\n", plug->name, plug->desc);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
input++;
|
|
|
|
|
if (input[0]==' ')
|
|
|
|
|
input++;
|
|
|
|
|
list = r_fs_dir (core->fs, input);
|
|
|
|
|
if (list) {
|
|
|
|
|
r_list_foreach (list, iter, file) {
|
|
|
|
|
r_cons_printf ("%c %s\n", file->type, file->name);
|
|
|
|
|
}
|
|
|
|
|
r_list_free (list);
|
|
|
|
|
} else eprintf ("Cannot open '%s' directory\n", input);
|
|
|
|
|
break;
|
2011-01-14 13:41:56 +00:00
|
|
|
|
case 'p':
|
|
|
|
|
input++;
|
2011-02-22 23:54:40 +00:00
|
|
|
|
if (*input == ' ')
|
2011-01-14 13:41:56 +00:00
|
|
|
|
input++;
|
2011-02-22 23:54:40 +00:00
|
|
|
|
ptr = strchr (input, ' ');
|
|
|
|
|
if (ptr) {
|
|
|
|
|
*ptr = 0;
|
|
|
|
|
off = r_num_math (core->num, ptr+1);
|
2011-01-14 13:41:56 +00:00
|
|
|
|
}
|
2011-02-22 23:54:40 +00:00
|
|
|
|
list = r_fs_partitions (core->fs, input, off);
|
|
|
|
|
if (list) {
|
|
|
|
|
r_list_foreach (list, iter, part) {
|
2011-04-20 11:04:24 +00:00
|
|
|
|
r_cons_printf ("%d %02x 0x%010"PFMT64x" 0x%010"PFMT64x"\n",
|
|
|
|
|
part->number, part->type,
|
|
|
|
|
part->start, part->start+part->length);
|
2011-02-22 23:54:40 +00:00
|
|
|
|
}
|
|
|
|
|
r_list_free (list);
|
|
|
|
|
} else eprintf ("Cannot read partition\n");
|
|
|
|
|
break;
|
|
|
|
|
case 'o':
|
|
|
|
|
input++;
|
|
|
|
|
if (input[0]==' ')
|
|
|
|
|
input++;
|
|
|
|
|
file = r_fs_open (core->fs, input);
|
|
|
|
|
if (file) {
|
|
|
|
|
// XXX: dump to file or just pipe?
|
|
|
|
|
r_fs_read (core->fs, file, 0, file->size);
|
2011-02-24 08:40:19 +00:00
|
|
|
|
r_cons_printf ("f file %d 0x%08"PFMT64x"\n", file->size, file->off);
|
2011-02-22 23:54:40 +00:00
|
|
|
|
r_fs_close (core->fs, file);
|
|
|
|
|
} else eprintf ("Cannot open file\n");
|
2011-01-14 13:41:56 +00:00
|
|
|
|
break;
|
2011-01-11 23:01:06 +00:00
|
|
|
|
case 'g':
|
2011-05-11 23:17:35 +00:00
|
|
|
|
input++;
|
|
|
|
|
if (*input == ' ')
|
|
|
|
|
input++;
|
|
|
|
|
ptr = strchr (input, ' ');
|
|
|
|
|
if (ptr)
|
|
|
|
|
*ptr++ = 0;
|
|
|
|
|
else
|
|
|
|
|
ptr = "./";
|
2011-05-12 13:01:29 +00:00
|
|
|
|
file = r_fs_open (core->fs, input);
|
|
|
|
|
if (file) {
|
|
|
|
|
r_fs_read (core->fs, file, 0, file->size);
|
|
|
|
|
write (1, file->data, file->size);
|
|
|
|
|
r_fs_close (core->fs, file);
|
|
|
|
|
write (1, "\n", 1);
|
|
|
|
|
} else if (!r_fs_dir_dump (core->fs, input, ptr))
|
|
|
|
|
eprintf ("Cannot open file\n");
|
2011-05-11 23:17:35 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
|
|
|
|
input++;
|
2011-05-21 22:23:39 +00:00
|
|
|
|
switch (*input) {
|
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: mf[no] [...]\n"
|
|
|
|
|
" mfn /foo *.c ; search files by name in /foo path\n"
|
|
|
|
|
" mfo /foo 0x5e91 ; search files by offset in /foo path\n"
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
case 'n':
|
|
|
|
|
input++;
|
|
|
|
|
if (*input == ' ')
|
|
|
|
|
input++;
|
|
|
|
|
ptr = strchr (input, ' ');
|
|
|
|
|
if (ptr) {
|
|
|
|
|
*ptr++ = 0;
|
|
|
|
|
list = r_fs_find_name (core->fs, input, ptr);
|
|
|
|
|
r_list_foreach (list, iter, ptr) {
|
|
|
|
|
r_str_chop_path (ptr);
|
|
|
|
|
printf ("%s\n", ptr);
|
|
|
|
|
}
|
|
|
|
|
//XXX: r_list_destroy (list);
|
|
|
|
|
} else eprintf ("Unknown store path\n");
|
|
|
|
|
break;
|
|
|
|
|
case 'o':
|
|
|
|
|
input++;
|
|
|
|
|
if (*input == ' ')
|
|
|
|
|
input++;
|
|
|
|
|
ptr = strchr (input, ' ');
|
|
|
|
|
if (ptr) {
|
|
|
|
|
*ptr++ = 0;
|
|
|
|
|
ut64 off = r_num_math (core->num, ptr);
|
|
|
|
|
list = r_fs_find_off (core->fs, input, off);
|
|
|
|
|
r_list_foreach (list, iter, ptr) {
|
|
|
|
|
r_str_chop_path (ptr);
|
|
|
|
|
printf ("%s\n", ptr);
|
|
|
|
|
}
|
|
|
|
|
//XXX: r_list_destroy (list);
|
|
|
|
|
} else eprintf ("Unknown store path\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-05-11 23:17:35 +00:00
|
|
|
|
break;
|
2011-02-18 17:22:51 +00:00
|
|
|
|
case 's':
|
|
|
|
|
input++;
|
|
|
|
|
if (input[0]==' ')
|
|
|
|
|
input++;
|
|
|
|
|
r_fs_prompt (core->fs, input);
|
|
|
|
|
break;
|
2011-01-11 23:01:06 +00:00
|
|
|
|
case 'y':
|
|
|
|
|
eprintf ("TODO\n");
|
|
|
|
|
break;
|
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: m[-?*dgy] [...]\n"
|
2011-01-14 13:41:56 +00:00
|
|
|
|
" m ; list all mountpoints in human readable format\n"
|
|
|
|
|
" m* ; same as above, but in r2 commands\n"
|
|
|
|
|
" ml ; list filesystem plugins\n"
|
2011-02-18 00:43:31 +00:00
|
|
|
|
" m ext2 /mnt 0 ; mount ext2 fs at /mnt with delta 0 on IO\n"
|
2011-01-14 13:41:56 +00:00
|
|
|
|
" m-/ ; umount given path (/)\n"
|
|
|
|
|
" my ; yank contents of file into clipboard\n"
|
2011-02-22 23:54:40 +00:00
|
|
|
|
" mo /foo ; get offset and size of given file\n"
|
2011-05-12 13:01:29 +00:00
|
|
|
|
" mg /foo ; get contents of file/dir dumped to disk (XXX?)\n"
|
2011-05-21 23:16:12 +00:00
|
|
|
|
" mf[o|n] ; search files for given filename or for offset\n"
|
2011-01-14 13:41:56 +00:00
|
|
|
|
" md / ; list directory contents for path\n"
|
|
|
|
|
" mp ; list all supported partition types\n"
|
|
|
|
|
" mp msdos 0 ; show partitions in msdos format at offset 0\n"
|
2011-02-18 17:22:51 +00:00
|
|
|
|
" ms /mnt ; open filesystem prompt at /mnt\n"
|
2011-01-14 13:41:56 +00:00
|
|
|
|
" m? ; show this help\n"
|
2011-01-11 23:01:06 +00:00
|
|
|
|
"TODO: support multiple mountpoints and RFile IO's (need io+core refactor)\n"
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
free (oinput);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-25 02:04:51 +00:00
|
|
|
|
static int cmd_yank(void *data, const char *input) {
|
2011-02-23 01:10:28 +00:00
|
|
|
|
int i;
|
2010-03-30 21:12:19 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
switch (input[0]) {
|
2009-02-18 12:10:59 +00:00
|
|
|
|
case ' ':
|
2010-03-26 16:01:25 +00:00
|
|
|
|
r_core_yank (core, core->offset, atoi(input+1));
|
2009-02-18 12:10:59 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'y':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_core_yank_paste (core, r_num_math(core->num, input+2), 0);
|
2009-02-18 12:10:59 +00:00
|
|
|
|
break;
|
2011-02-23 01:10:28 +00:00
|
|
|
|
case 'p':
|
2011-02-23 18:11:39 +00:00
|
|
|
|
r_cons_memcat ((const char*)core->yank, core->yank_len);
|
2011-02-23 01:10:28 +00:00
|
|
|
|
r_cons_newline ();
|
|
|
|
|
break;
|
2009-04-15 18:24:19 +00:00
|
|
|
|
case 't':
|
|
|
|
|
{ /* hacky implementation */
|
|
|
|
|
char *arg = strdup(input+1);
|
|
|
|
|
cmd_yank_to(core, arg);
|
|
|
|
|
free(arg);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-18 12:10:59 +00:00
|
|
|
|
case '\0':
|
2009-09-25 02:04:51 +00:00
|
|
|
|
if (core->yank) {
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" %d ",
|
2009-02-18 12:10:59 +00:00
|
|
|
|
core->yank_off, core->yank_len);
|
2011-02-23 01:10:28 +00:00
|
|
|
|
for (i=0; i<core->yank_len; i++)
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf ("%02x", core->yank[i]);
|
|
|
|
|
r_cons_newline ();
|
|
|
|
|
} else eprintf ("No buffer yanked already\n");
|
2009-02-18 12:10:59 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_cons_printf (
|
2009-02-18 12:10:59 +00:00
|
|
|
|
"Usage: y[y] [len] [[@]addr]\n"
|
|
|
|
|
" y ; show yank buffer information (srcoff len bytes)\n"
|
|
|
|
|
" y 16 ; copy 16 bytes into clipboard\n"
|
|
|
|
|
" y 16 0x200 ; copy 16 bytes into clipboard from 0x200\n"
|
|
|
|
|
" y 16 @ 0x200 ; copy 16 bytes into clipboard from 0x200\n"
|
2011-02-23 01:10:28 +00:00
|
|
|
|
" yp ; print contents of clipboard\n"
|
|
|
|
|
" yt 0x200 ; paste clipboard to 0x200\n"
|
2009-02-18 12:10:59 +00:00
|
|
|
|
" yy 0x3344 ; paste clipboard\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_quit(void *data, const char *input) {
|
2010-03-30 21:12:19 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2011-05-24 13:25:52 +00:00
|
|
|
|
if (input)
|
|
|
|
|
switch (*input) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '?':
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf (
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Usage: q[!] [retvalue]\n"
|
|
|
|
|
" q ; quit program\n"
|
|
|
|
|
" q! ; force quit (no questions)\n"
|
|
|
|
|
" q 1 ; quit with return value 1\n"
|
|
|
|
|
" q a-b ; quit with return value a-b\n");
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
|
|
|
|
case '!':
|
2010-02-28 22:57:55 +00:00
|
|
|
|
input++;
|
|
|
|
|
case '\0':
|
2009-12-30 09:56:41 +00:00
|
|
|
|
// TODO
|
2009-02-05 21:08:46 +00:00
|
|
|
|
default:
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_line_hist_save (".radare2_history");
|
2010-02-28 22:57:55 +00:00
|
|
|
|
if (*input)
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_num_math (core->num, input);
|
|
|
|
|
else core->num->value = 0LL;
|
|
|
|
|
//exit (*input?r_num_math (core->num, input+1):0);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
return -2;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
2010-02-28 21:58:21 +00:00
|
|
|
|
return R_FALSE;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-25 02:04:51 +00:00
|
|
|
|
static int cmd_interpret(void *data, const char *input) {
|
|
|
|
|
char *str, *ptr, *eol;
|
2010-02-22 23:26:13 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
|
|
|
|
switch (input[0]) {
|
2010-03-19 03:02:23 +00:00
|
|
|
|
case '\0':
|
|
|
|
|
/* repeat last command */
|
2010-05-25 23:42:22 +00:00
|
|
|
|
/* NOTE: Plugind in r_core_cmd with ugly strcmp */
|
2010-03-19 03:02:23 +00:00
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case ' ':
|
2010-03-30 22:03:59 +00:00
|
|
|
|
if (!r_core_cmd_file (core, input+1))
|
|
|
|
|
eprintf ("Cannot interpret file.\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '!':
|
|
|
|
|
/* from command */
|
2010-02-22 23:26:13 +00:00
|
|
|
|
r_core_cmd_command (core, input+1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '(':
|
2010-02-28 21:58:21 +00:00
|
|
|
|
//eprintf ("macro call (%s)\n", input+1);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_cmd_macro_call (&core->cmd->macro, input+1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '?':
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf (
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Usage: . [file] | [!command] | [(macro)]\n"
|
|
|
|
|
" . foo.rs ; interpret r script\n"
|
|
|
|
|
" .!rabin -ri $FILE ; interpret output of command\n"
|
2009-02-16 23:09:40 +00:00
|
|
|
|
" .(foo 1 2 3) ; run macro 'foo' with args 1, 2, 3\n"
|
2011-02-25 10:45:05 +00:00
|
|
|
|
" ./ ELF ; interpret output of command /m ELF as r. commands\n");
|
2009-02-16 23:09:40 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-02-22 23:26:13 +00:00
|
|
|
|
ptr = str = r_core_cmd_str (core, input);
|
2010-02-01 10:55:56 +00:00
|
|
|
|
for (;;) {
|
2010-02-22 23:26:13 +00:00
|
|
|
|
eol = strchr (ptr, '\n');
|
2009-02-16 23:09:40 +00:00
|
|
|
|
if (eol) eol[0]='\0';
|
2010-02-22 23:26:13 +00:00
|
|
|
|
r_core_cmd (core, ptr, 0);
|
2009-02-16 23:09:40 +00:00
|
|
|
|
if (!eol) break;
|
|
|
|
|
ptr = eol+1;
|
|
|
|
|
}
|
2010-02-22 23:26:13 +00:00
|
|
|
|
free (str);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-31 13:22:27 +00:00
|
|
|
|
static int cmd_section(void *data, const char *input) {
|
2010-03-30 21:12:19 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2010-02-01 10:55:56 +00:00
|
|
|
|
switch (input[0]) {
|
2010-01-31 13:22:27 +00:00
|
|
|
|
case '?':
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf (
|
|
|
|
|
" S ; list sections\n"
|
2011-06-26 21:49:11 +00:00
|
|
|
|
" S. ; show current section name\n"
|
|
|
|
|
" S? ; show this help message\n"
|
2010-08-26 02:19:12 +00:00
|
|
|
|
" S* ; list sections (in radare commands)\n"
|
2010-02-01 10:55:56 +00:00
|
|
|
|
" S= ; list sections (in nice ascii-art bars)\n"
|
2011-06-26 21:49:11 +00:00
|
|
|
|
" S [off] [vaddr] [sz] [vsz] [name] [rwx] ; add new section\n"
|
2011-04-18 22:59:16 +00:00
|
|
|
|
" S-[id|0xoff|*] ; remove this section definition\n");
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
|
|
|
|
if (input[1] == '*') {
|
|
|
|
|
// remove all sections
|
|
|
|
|
r_io_section_init (core->io);
|
|
|
|
|
} else
|
|
|
|
|
if (input[1] == '0' && input[2]=='x') {
|
|
|
|
|
RIOSection *s = r_io_section_get (core->io, r_num_get (NULL, input+1));
|
|
|
|
|
// use offset
|
|
|
|
|
r_io_section_rm (core->io, s->id);
|
|
|
|
|
} else {
|
|
|
|
|
r_io_section_rm (core->io, atoi (input+1));
|
|
|
|
|
}
|
2010-01-31 13:22:27 +00:00
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
2010-02-01 10:55:56 +00:00
|
|
|
|
switch (input[1]) {
|
2010-01-31 13:22:27 +00:00
|
|
|
|
case '-': // remove
|
|
|
|
|
if (input[2]=='?' || input[2]=='\0')
|
2010-04-08 13:48:53 +00:00
|
|
|
|
eprintf ("Usage: S -N # where N is the section index\n");
|
2010-05-19 22:59:42 +00:00
|
|
|
|
else r_io_section_rm (core->io, atoi (input+1));
|
2010-01-31 13:22:27 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
2010-04-08 10:29:47 +00:00
|
|
|
|
int i, rwx = 7;
|
2010-01-31 13:22:27 +00:00
|
|
|
|
char *ptr = strdup(input+1);
|
2010-02-18 17:58:28 +00:00
|
|
|
|
const char *name = NULL;
|
|
|
|
|
ut64 vaddr = 0LL;
|
|
|
|
|
ut64 offset = 0LL;
|
|
|
|
|
ut64 size = 0LL;
|
|
|
|
|
ut64 vsize = 0LL;
|
2011-01-02 13:39:25 +00:00
|
|
|
|
|
2010-02-28 21:58:21 +00:00
|
|
|
|
i = r_str_word_set0 (ptr);
|
2010-04-08 10:29:47 +00:00
|
|
|
|
switch (i) {
|
|
|
|
|
case 6: // get rwx
|
|
|
|
|
rwx = r_str_rwx (r_str_word_get0 (ptr, 5));
|
2010-02-18 17:58:28 +00:00
|
|
|
|
case 5: // get name
|
2010-02-28 21:58:21 +00:00
|
|
|
|
name = r_str_word_get0 (ptr, 4);
|
2010-02-18 17:58:28 +00:00
|
|
|
|
case 4: // get vsize
|
2010-05-19 22:59:42 +00:00
|
|
|
|
vsize = r_num_math (core->num, r_str_word_get0 (ptr, 3));
|
2010-02-18 17:58:28 +00:00
|
|
|
|
case 3: // get size
|
2010-05-19 22:59:42 +00:00
|
|
|
|
size = r_num_math (core->num, r_str_word_get0 (ptr, 2));
|
2010-02-18 17:58:28 +00:00
|
|
|
|
case 2: // get vaddr
|
2010-05-19 22:59:42 +00:00
|
|
|
|
vaddr = r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
2010-02-18 17:58:28 +00:00
|
|
|
|
case 1: // get offset
|
2010-05-19 22:59:42 +00:00
|
|
|
|
offset = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
2010-01-31 13:22:27 +00:00
|
|
|
|
}
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_section_add (core->io, offset, vaddr, size, vsize, rwx, name);
|
2010-01-31 13:22:27 +00:00
|
|
|
|
free (ptr);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '=':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_section_list_visual (core->io, core->offset, core->blocksize);
|
2010-01-31 13:22:27 +00:00
|
|
|
|
break;
|
2011-06-26 21:49:11 +00:00
|
|
|
|
case '.':
|
|
|
|
|
{
|
|
|
|
|
ut64 o = core->offset;
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
RIOSection *s;
|
|
|
|
|
if (core->io->va || core->io->debug)
|
|
|
|
|
o = r_io_section_vaddr_to_offset (core->io, o);
|
|
|
|
|
r_list_foreach (core->io->sections, iter, s) {
|
|
|
|
|
if (o>=s->offset && o<s->offset+s->size) {
|
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" 0x%08"PFMT64x" %s\n",
|
|
|
|
|
s->offset + s->vaddr,
|
|
|
|
|
s->offset + s->vaddr + s->size,
|
|
|
|
|
s->name);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-01-31 13:22:27 +00:00
|
|
|
|
case '\0':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_section_list (core->io, core->offset, 0);
|
2010-01-31 13:22:27 +00:00
|
|
|
|
break;
|
|
|
|
|
case '*':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_section_list (core->io, core->offset, 1);
|
2010-01-31 13:22:27 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-25 02:04:51 +00:00
|
|
|
|
static int cmd_seek(void *data, const char *input) {
|
2010-02-28 22:57:55 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2011-01-02 13:39:25 +00:00
|
|
|
|
char *cmd, *p;
|
2010-02-28 22:57:55 +00:00
|
|
|
|
ut64 off;
|
|
|
|
|
|
2011-05-21 23:36:23 +00:00
|
|
|
|
if (*input=='r') {
|
2010-02-28 22:57:55 +00:00
|
|
|
|
if (input[1] && input[2]) {
|
2011-07-04 21:23:06 +00:00
|
|
|
|
if (core->io->debug) {
|
|
|
|
|
off = r_debug_reg_get (core->dbg, input+2);
|
|
|
|
|
r_io_sundo_push (core->io);
|
|
|
|
|
r_core_seek (core, off, 1);
|
|
|
|
|
} else eprintf ("cfg.debug is false\n");
|
2010-02-28 22:57:55 +00:00
|
|
|
|
} else eprintf ("Usage: 'sr pc' ; seek to register\n");
|
|
|
|
|
} else
|
2011-06-28 22:36:52 +00:00
|
|
|
|
if (*input) {
|
2010-02-02 10:09:52 +00:00
|
|
|
|
st32 delta = (input[1]==' ')?2:1;
|
2011-01-02 13:39:25 +00:00
|
|
|
|
off = r_num_math (core->num, input + delta);
|
2009-03-12 22:19:58 +00:00
|
|
|
|
if (input[0]==' ' && (input[1]=='+'||input[1]=='-'))
|
|
|
|
|
input = input+1;
|
2010-02-02 10:09:52 +00:00
|
|
|
|
switch (input[0]) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case ' ':
|
2011-05-21 23:16:12 +00:00
|
|
|
|
r_io_sundo_push (core->io);
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_core_seek (core, off, 1);
|
2011-04-18 22:59:16 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2010-05-19 00:39:01 +00:00
|
|
|
|
break;
|
2011-05-21 12:27:46 +00:00
|
|
|
|
case '/':
|
2011-05-21 23:36:23 +00:00
|
|
|
|
{
|
|
|
|
|
const char *pfx = r_config_get (core->config, "search.prefix");
|
|
|
|
|
int kwidx = (int)r_config_get_i (core->config, "search.kwidx")-1;
|
|
|
|
|
if (kwidx<0) kwidx=0;
|
|
|
|
|
//r_core_seek (core, off+1, 0);
|
|
|
|
|
eprintf ("s+1;.%s ; ? %s%d_0 ; ?! s %s%d_0\n", input, pfx, kwidx, pfx, kwidx);
|
|
|
|
|
r_core_cmdf (core, "s+1;.%s ; ? %s%d_0 ; ?! s %s%d_0", input, pfx, kwidx, pfx, kwidx);
|
|
|
|
|
}
|
2011-05-21 12:27:46 +00:00
|
|
|
|
break;
|
2010-05-19 00:39:01 +00:00
|
|
|
|
case '*':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_sundo_list (core->io);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '+':
|
2010-05-19 00:39:01 +00:00
|
|
|
|
if (input[1]!='\0') {
|
2011-05-21 23:16:12 +00:00
|
|
|
|
delta = (input[1]=='+')? core->blocksize: off;
|
|
|
|
|
r_io_sundo_push (core->io);
|
2010-05-19 00:39:01 +00:00
|
|
|
|
r_core_seek_delta (core, delta);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
} else if (r_io_sundo_redo (core->io))
|
|
|
|
|
r_core_seek (core, core->io->off, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '-':
|
2010-05-19 00:39:01 +00:00
|
|
|
|
if (input[1]!='\0') {
|
|
|
|
|
if (input[1]=='-') delta = -core->blocksize; else delta = -off;
|
2011-05-21 23:16:12 +00:00
|
|
|
|
r_io_sundo_push (core->io);
|
2010-05-19 00:39:01 +00:00
|
|
|
|
r_core_seek_delta (core, delta);
|
2011-05-21 23:16:12 +00:00
|
|
|
|
} else {
|
|
|
|
|
if (r_io_sundo (core->io)) {
|
|
|
|
|
r_core_seek (core, core->io->off, 0);
|
|
|
|
|
} else eprintf ("Cannot undo\n");
|
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2011-05-21 13:45:43 +00:00
|
|
|
|
case 'f':
|
2011-05-21 23:16:12 +00:00
|
|
|
|
r_io_sundo_push (core->io);
|
2011-05-21 13:45:43 +00:00
|
|
|
|
r_core_seek_next (core, r_config_get (core->config, "scr.fkey"));
|
|
|
|
|
break;
|
|
|
|
|
case 'F':
|
2011-05-21 23:16:12 +00:00
|
|
|
|
r_io_sundo_push (core->io);
|
2011-05-21 13:45:43 +00:00
|
|
|
|
r_core_seek_previous (core, r_config_get (core->config, "scr.fkey"));
|
|
|
|
|
break;
|
2009-03-12 22:19:58 +00:00
|
|
|
|
case 'a':
|
2009-09-25 02:04:51 +00:00
|
|
|
|
off = core->blocksize;
|
|
|
|
|
if (input[1]&&input[2]) {
|
2010-02-01 10:55:56 +00:00
|
|
|
|
cmd = strdup (input);
|
|
|
|
|
p = strchr (cmd+2, ' ');
|
2009-09-25 02:04:51 +00:00
|
|
|
|
if (p) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
off = r_num_math (core->num, p+1);;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
*p = '\0';
|
2009-03-12 22:19:58 +00:00
|
|
|
|
}
|
2010-02-28 21:58:21 +00:00
|
|
|
|
cmd[0] = 's';
|
2009-09-25 02:04:51 +00:00
|
|
|
|
// perform real seek if provided
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_cmd_call (core->cmd, cmd);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
free (cmd);
|
2009-03-12 22:19:58 +00:00
|
|
|
|
}
|
2011-05-21 23:16:12 +00:00
|
|
|
|
r_io_sundo_push (core->io);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_core_seek_align (core, off, 0);
|
2009-03-12 22:19:58 +00:00
|
|
|
|
break;
|
2010-03-03 17:05:24 +00:00
|
|
|
|
case 'b':
|
2011-05-21 23:16:12 +00:00
|
|
|
|
r_io_sundo_push (core->io);
|
2010-03-03 17:05:24 +00:00
|
|
|
|
r_core_anal_bb_seek (core, off);
|
|
|
|
|
break;
|
2011-06-26 21:49:11 +00:00
|
|
|
|
case 'n':
|
|
|
|
|
{
|
|
|
|
|
RAnalOp op;
|
|
|
|
|
int ret = r_anal_op (core->anal, &op,
|
|
|
|
|
core->offset, core->block, core->blocksize);
|
|
|
|
|
r_core_seek_delta (core, ret);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '?':
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf (
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Usage: s[+-] [addr]\n"
|
2009-03-12 22:19:58 +00:00
|
|
|
|
" s 0x320 ; seek to this address\n"
|
2010-05-19 00:39:01 +00:00
|
|
|
|
" s- ; undo seek\n"
|
|
|
|
|
" s+ ; redo seek\n"
|
|
|
|
|
" s* ; list undo seek history\n"
|
2009-03-12 22:19:58 +00:00
|
|
|
|
" 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"
|
2010-03-03 17:05:24 +00:00
|
|
|
|
" sa [[+-]a] [asz] ; seek asz (or bsize) aligned to addr\n"
|
2011-05-21 23:36:23 +00:00
|
|
|
|
" sf|sF ; seek next/prev scr.fkey\n"
|
|
|
|
|
" s/ DATA ; search for next occurrence of 'DATA'\n"
|
2010-10-27 15:45:53 +00:00
|
|
|
|
" sb ; seek aligned to bb start\n"
|
2011-06-26 21:49:11 +00:00
|
|
|
|
" sn ; seek to next opcode\n"
|
2010-10-27 15:45:53 +00:00
|
|
|
|
" sr pc ; seek to register\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2010-04-14 11:02:23 +00:00
|
|
|
|
} else r_cons_printf ("0x%"PFMT64x"\n", core->offset);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_help(void *data, const char *input) {
|
2011-02-25 10:45:05 +00:00
|
|
|
|
int i;
|
2010-02-22 23:26:13 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2010-10-26 19:00:54 +00:00
|
|
|
|
char out[65];
|
2009-07-08 11:49:55 +00:00
|
|
|
|
ut64 n;
|
2010-02-02 10:09:52 +00:00
|
|
|
|
switch (input[0]) {
|
2010-10-26 19:00:54 +00:00
|
|
|
|
case 'b':
|
|
|
|
|
{
|
|
|
|
|
n = r_num_get (core->num, input+1);
|
|
|
|
|
r_num_to_bits (out, n);
|
|
|
|
|
r_cons_printf ("%s\n", out);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
|
|
|
|
if (input[1]==' ') {
|
|
|
|
|
char *q, *p = strdup (input+2);
|
|
|
|
|
if (!p) {
|
|
|
|
|
eprintf ("Cannot strdup\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
q = strchr (p, ' ');
|
|
|
|
|
if (q) {
|
|
|
|
|
*q = 0;
|
|
|
|
|
n = r_num_get (core->num, p);
|
|
|
|
|
r_str_bits (out, (const ut8*)&n, sizeof (n), q+1);
|
|
|
|
|
r_cons_printf ("%s\n", out);
|
|
|
|
|
} else eprintf ("Usage: \"?b value bitstring\"\n");
|
|
|
|
|
free (p);
|
|
|
|
|
} else eprintf ("Whitespace expected after '?b'\n");
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case ' ':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
n = r_num_math (core->num, input+1);
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("%"PFMT64d" 0x%"PFMT64x"\n", n,n);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2011-06-05 18:36:22 +00:00
|
|
|
|
case 'v':
|
|
|
|
|
n = r_num_math (core->num, input+2);
|
|
|
|
|
r_cons_printf ("0x%"PFMT64x"\n", n,n);
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '=':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_num_math (core->num, input+1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '+':
|
|
|
|
|
if (input[1]) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if (core->num->value & UT64_GT0)
|
2010-01-31 13:22:27 +00:00
|
|
|
|
r_core_cmd (core, input+1, 0);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
} else r_cons_printf ("0x%"PFMT64x"\n", core->num->value);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '-':
|
|
|
|
|
if (input[1]) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if (core->num->value & UT64_LT0)
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_core_cmd (core, input+1, 0);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
} else r_cons_printf ("0x%"PFMT64x"\n", core->num->value);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '!': // ??
|
|
|
|
|
if (input[1]) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if (core->num->value != UT64_MIN)
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_core_cmd (core, input+1, 0);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
} else r_cons_printf ("0x%"PFMT64x"\n", core->num->value);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2009-04-15 00:29:01 +00:00
|
|
|
|
case '$':
|
2010-02-02 10:09:52 +00:00
|
|
|
|
return cmd_help (data, " $?");
|
2010-07-15 11:34:53 +00:00
|
|
|
|
case 'V':
|
2011-02-24 08:40:19 +00:00
|
|
|
|
r_cons_printf ("r2-%s\n", R2_VERSION);
|
2010-07-15 11:34:53 +00:00
|
|
|
|
break;
|
2009-03-13 11:28:36 +00:00
|
|
|
|
case 'z':
|
2011-02-25 10:45:05 +00:00
|
|
|
|
for (input++; input[0]==' '; input++);
|
2010-07-13 08:56:56 +00:00
|
|
|
|
core->num->value = strlen (input);
|
2009-03-13 11:28:36 +00:00
|
|
|
|
break;
|
2011-02-25 10:45:05 +00:00
|
|
|
|
case 'X':
|
|
|
|
|
{
|
|
|
|
|
for (input++; input[0]==' '; input++);
|
|
|
|
|
ut64 n = r_num_math (core->num, input);
|
|
|
|
|
r_cons_printf ("%"PFMT64x"\n", n);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'x':
|
|
|
|
|
for (input++; input[0]==' '; input++);
|
|
|
|
|
if (!memcmp (input, "0x", 2) || (*input>='0' && *input<='9')) {
|
|
|
|
|
ut64 n = r_num_math (core->num, input);
|
|
|
|
|
int bits = r_num_to_bits (NULL, n) / 8;
|
|
|
|
|
for (i=0; i<bits; i++)
|
|
|
|
|
r_cons_printf ("%02x", (ut8)((n>>(i*8)) &0xff));
|
|
|
|
|
r_cons_newline ();
|
|
|
|
|
} else {
|
|
|
|
|
for (i=0; input[i]; i++)
|
|
|
|
|
r_cons_printf ("%02x", input[i]);
|
|
|
|
|
r_cons_newline ();
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'e': // echo
|
|
|
|
|
for (input++; *input==' '; input++);
|
|
|
|
|
r_cons_printf ("%s\n", input);
|
|
|
|
|
break;
|
|
|
|
|
case 's': // sequence from to step
|
|
|
|
|
{
|
|
|
|
|
ut64 from, to, step;
|
|
|
|
|
char *p, *p2;
|
|
|
|
|
for (input++; *input==' '; input++);
|
|
|
|
|
p = strchr (input, ' ');
|
|
|
|
|
if (p) {
|
|
|
|
|
*p='\0';
|
|
|
|
|
from = r_num_math (core->num, input);
|
|
|
|
|
p2 = strchr (p+1, ' ');
|
|
|
|
|
if (p2) {
|
|
|
|
|
*p2='\0';
|
|
|
|
|
step = r_num_math (core->num, p2+1);
|
|
|
|
|
} else step = 1;
|
|
|
|
|
to = r_num_math (core->num, p+1);
|
|
|
|
|
for (;from<=to;from+=step)
|
|
|
|
|
r_cons_printf ("%"PFMT64d" ", from);
|
|
|
|
|
r_cons_newline();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'i': // input num
|
|
|
|
|
{
|
|
|
|
|
char foo[1024];
|
|
|
|
|
for (input++; *input==' '; input++);
|
|
|
|
|
eprintf ("%s: ", input);
|
|
|
|
|
fgets (foo, sizeof (foo)-1, stdin);
|
|
|
|
|
core->num->value = r_num_math (core->num, foo);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-01-19 10:25:17 +00:00
|
|
|
|
case 't': {
|
|
|
|
|
struct r_prof_t prof;
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_prof_start (&prof);
|
|
|
|
|
r_core_cmd (core, input+1, 0);
|
|
|
|
|
r_prof_end (&prof);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
core->num->value = (ut64)prof.result;
|
2010-02-02 10:09:52 +00:00
|
|
|
|
eprintf ("%lf\n", prof.result);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
} break;
|
2009-03-13 11:28:36 +00:00
|
|
|
|
case '?': // ???
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (input[1]=='?') {
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf (
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Usage: ?[?[?]] expression\n"
|
2011-06-05 18:36:22 +00:00
|
|
|
|
" ? eip-0x804800 ; show hex and dec result for this math expr\n"
|
|
|
|
|
" ?v eip-0x804800 ; show hex value of math expr\n"
|
2009-03-13 11:28:36 +00:00
|
|
|
|
" ?= eip-0x804800 ; same as above without user feedback\n"
|
|
|
|
|
" ?? [cmd] ; ? == 0 run command when math matches\n"
|
2011-02-25 10:45:05 +00:00
|
|
|
|
" ?i prompt ; prompt for number and store in $$?\n"
|
|
|
|
|
" ?e string ; echo string\n"
|
2010-10-26 19:00:54 +00:00
|
|
|
|
" ?b [num] ; show binary value of number\n"
|
|
|
|
|
" ?f [num] [str] ; map each bit of the number as flag string index\n"
|
2011-02-25 10:45:05 +00:00
|
|
|
|
" ?s from to step ; sequence of numbers from to by steps\n"
|
|
|
|
|
" ?x num|0xnum|str; returns the hexpair of number or string\n"
|
|
|
|
|
" ?X num|expr ; returns the hexadecimal value numeric expr\n"
|
2009-03-13 11:28:36 +00:00
|
|
|
|
" ?z str ; returns the length of string (0 if null)\n"
|
|
|
|
|
" ?t cmd ; returns the time to run a command\n"
|
|
|
|
|
" ?! [cmd] ; ? != 0\n"
|
|
|
|
|
" ?+ [cmd] ; ? > 0\n"
|
|
|
|
|
" ?- [cmd] ; ? < 0\n"
|
2009-04-15 18:24:19 +00:00
|
|
|
|
" ??? ; show this help\n"
|
|
|
|
|
"$variables:\n"
|
|
|
|
|
" $$ = here (current seek)\n"
|
2011-03-01 18:16:29 +00:00
|
|
|
|
" $o = here (current io offset)\n"
|
2009-04-15 18:24:19 +00:00
|
|
|
|
" $s = file size\n"
|
|
|
|
|
" $b = block size\n"
|
|
|
|
|
" $j = jump address\n"
|
|
|
|
|
" $f = address of next opcode\n"
|
|
|
|
|
" $r = opcode reference pointer\n"
|
2011-06-26 21:49:11 +00:00
|
|
|
|
" $l = opcode length\n"
|
2009-04-15 18:24:19 +00:00
|
|
|
|
" $e = 1 if end of block, else 0\n"
|
|
|
|
|
" ${eval} = get value of eval variable\n"
|
|
|
|
|
" $? = last comparision value\n");
|
|
|
|
|
return 0;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
} else
|
|
|
|
|
if (input[1]) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if (core->num->value == UT64_MIN)
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_core_cmd (core, input+1, 0);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
} else r_cons_printf ("0x%"PFMT64x"\n", core->num->value);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '\0':
|
|
|
|
|
default:
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_cons_printf (
|
2009-02-18 12:10:59 +00:00
|
|
|
|
" a ; perform analysis of code\n"
|
|
|
|
|
" b [bsz] ; get or change block size\n"
|
2010-08-08 17:03:51 +00:00
|
|
|
|
" c[dqxXfg] [arg] ; compare block with given data\n"
|
|
|
|
|
" C[Cf..] ; Code metadata management\n"
|
2009-03-14 11:39:37 +00:00
|
|
|
|
" d[hrscb] ; debugger commands\n"
|
2009-02-18 12:10:59 +00:00
|
|
|
|
" e [a[=b]] ; list/get/set config evaluable vars\n"
|
|
|
|
|
" f [name][sz][at] ; set flag at current address\n"
|
|
|
|
|
" s [addr] ; seek to address\n"
|
2010-01-31 13:22:27 +00:00
|
|
|
|
" S?[size] [vaddr] ; IO section manipulation information\n"
|
2009-02-18 12:10:59 +00:00
|
|
|
|
" i [file] ; get info about opened file\n"
|
2010-02-01 10:55:56 +00:00
|
|
|
|
" o [file] (addr) ; open file at optional address\n"
|
2009-02-18 12:10:59 +00:00
|
|
|
|
" p?[len] ; print current block with format and length\n"
|
2011-07-01 11:24:51 +00:00
|
|
|
|
" P[osi?] ; project management utilities\n"
|
2009-03-14 11:39:37 +00:00
|
|
|
|
" V[vcmds] ; enter visual mode (vcmds=visualvisual keystrokes)\n"
|
|
|
|
|
" w[mode] [arg] ; multiple write operations\n"
|
2010-05-03 19:24:58 +00:00
|
|
|
|
" x [len] ; alias for 'px' (print hexadecimal)\n"
|
2009-02-18 12:10:59 +00:00
|
|
|
|
" y [len] [off] ; yank/paste bytes from/to memory\n"
|
2011-02-05 11:51:37 +00:00
|
|
|
|
" r[+- ][len] ; resize file\n"
|
2009-02-18 12:10:59 +00:00
|
|
|
|
" ? [expr] ; help or evaluate math expression\n"
|
|
|
|
|
" /[xmp/] ; search for bytes, regexps, patterns, ..\n"
|
2010-08-23 04:39:23 +00:00
|
|
|
|
" ![cmd] ; run given command as in system(3)\n"
|
|
|
|
|
" = [cmd] ; run this command via rap://\n"
|
2009-02-18 12:10:59 +00:00
|
|
|
|
" #[algo] [len] ; calculate hash checksum of current block\n"
|
|
|
|
|
" .[ file|!cmd|cmd|(macro)] ; interpret as radare cmds\n"
|
2010-06-03 09:53:42 +00:00
|
|
|
|
" :command ; list or execute a plugin command\n"
|
2009-02-18 12:10:59 +00:00
|
|
|
|
" (macro arg0 arg1) ; define scripting macros\n"
|
|
|
|
|
" q [ret] ; quit program with a return value\n"
|
2011-02-05 01:21:40 +00:00
|
|
|
|
"Use '?""?""?' evaluation, special vars and scripting facilities\n"
|
|
|
|
|
"Append '?' to any char command to get detailed help\n"
|
|
|
|
|
"Suffix '@ addr[:bsize]' for a temporary seek and/or bsize\n"
|
2011-06-07 15:53:15 +00:00
|
|
|
|
"Suffix '@@ glob1 glob2i ..' space separated glob greps for flags to seek\n"
|
2011-02-05 01:21:40 +00:00
|
|
|
|
"Suffix '~string:linenumber[column]' to filter output\n"
|
|
|
|
|
);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_bsize(void *data, const char *input) {
|
2010-09-24 02:09:39 +00:00
|
|
|
|
RFlagItem *flag;
|
2010-03-30 21:12:19 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2010-02-02 10:09:52 +00:00
|
|
|
|
switch (input[0]) {
|
2010-09-24 02:09:39 +00:00
|
|
|
|
case 'f':
|
|
|
|
|
if (input[1]==' ') {
|
|
|
|
|
flag = r_flag_get (core->flags, input+2);
|
|
|
|
|
if (flag)
|
|
|
|
|
r_core_block_size (core, flag->size);
|
|
|
|
|
else eprintf ("bf: Cannot find flag named '%s'\n", input+2);
|
|
|
|
|
} else eprintf ("Usage: bf [flagname]\n");
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '\0':
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_cons_printf ("0x%x\n", core->blocksize);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2010-09-24 02:09:39 +00:00
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf ("Usage: b[f] [arg]\n"
|
|
|
|
|
" b # display current block size\n"
|
|
|
|
|
" b 33 # set block size to 33\n"
|
|
|
|
|
" b eip+4 # numeric argument can be an expression\n"
|
|
|
|
|
" bf foo # set block size to flag size\n");
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
default:
|
|
|
|
|
//input = r_str_clean(input);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_core_block_size (core, r_num_math (core->num, input));
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2010-05-19 00:39:01 +00:00
|
|
|
|
|
2010-03-26 10:59:28 +00:00
|
|
|
|
// move it out // r_diff maybe?
|
|
|
|
|
static int radare_compare(RCore *core, const ut8 *f, const ut8 *d, int len) {
|
|
|
|
|
int i, eq = 0;
|
|
|
|
|
for (i=0;i<len;i++) {
|
|
|
|
|
if (f[i]==d[i]) {
|
|
|
|
|
eq++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" (byte=%.2d) %02x '%c' -> %02x '%c'\n",
|
2010-03-26 10:59:28 +00:00
|
|
|
|
core->offset+i, i+1,
|
|
|
|
|
f[i], (IS_PRINTABLE(f[i]))?f[i]:' ',
|
|
|
|
|
d[i], (IS_PRINTABLE(d[i]))?d[i]:' ');
|
|
|
|
|
}
|
|
|
|
|
eprintf ("Compare %d/%d equal bytes\n", eq, len);
|
|
|
|
|
return len-eq;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-05 11:21:37 +00:00
|
|
|
|
static int cmd_cmp(void *data, const char *input) {
|
|
|
|
|
RCore *core = data;
|
2010-03-26 10:59:28 +00:00
|
|
|
|
FILE *fd;
|
|
|
|
|
ut8 *buf;
|
|
|
|
|
int ret;
|
|
|
|
|
ut32 v32;
|
|
|
|
|
ut64 v64;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
|
|
|
|
|
switch (*input) {
|
2010-03-26 10:59:28 +00:00
|
|
|
|
case ' ':
|
|
|
|
|
radare_compare (core, core->block, (ut8*)input+1, strlen (input+1)+1);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
break;
|
2010-03-26 10:59:28 +00:00
|
|
|
|
case 'x':
|
|
|
|
|
if (input[1]!=' ') {
|
|
|
|
|
eprintf ("Usage: cx 001122'\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
buf = (ut8*)malloc (strlen (input+2));
|
|
|
|
|
ret = r_hex_str2bin (input+2, buf);
|
2010-07-13 08:56:56 +00:00
|
|
|
|
if (ret<1) eprintf ("Cannot parse hexpair\n");
|
|
|
|
|
else radare_compare (core, core->block, buf, ret);
|
2010-03-26 10:59:28 +00:00
|
|
|
|
free (buf);
|
|
|
|
|
break;
|
|
|
|
|
case 'X':
|
|
|
|
|
buf = malloc (core->blocksize);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
ret = r_io_read_at (core->io, r_num_math (core->num, input+1), buf, core->blocksize);
|
2010-03-26 10:59:28 +00:00
|
|
|
|
radare_compare (core, core->block, buf, ret);
|
2010-07-13 08:56:56 +00:00
|
|
|
|
free (buf);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
|
|
|
|
if (input[1]!=' ') {
|
2010-03-26 10:59:28 +00:00
|
|
|
|
eprintf ("Please. use 'cf [file]'\n");
|
2010-02-05 11:21:37 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2010-03-26 10:59:28 +00:00
|
|
|
|
fd = fopen (input+2, "rb");
|
2010-02-05 11:21:37 +00:00
|
|
|
|
if (fd == NULL) {
|
2010-03-26 10:59:28 +00:00
|
|
|
|
eprintf ("Cannot open file '%s'\n", input+2);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2010-03-26 10:59:28 +00:00
|
|
|
|
buf = (ut8 *)malloc (core->blocksize);
|
|
|
|
|
fread (buf, 1, core->blocksize, fd);
|
|
|
|
|
fclose (fd);
|
|
|
|
|
radare_compare (core, core->block, buf, core->blocksize);
|
|
|
|
|
free (buf);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
break;
|
2010-03-26 10:59:28 +00:00
|
|
|
|
case 'q':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
v64 = (ut64) r_num_math (core->num, input+1);
|
2010-03-26 16:01:25 +00:00
|
|
|
|
radare_compare (core, core->block, (ut8*)&v64, sizeof (v64));
|
2010-02-05 11:21:37 +00:00
|
|
|
|
break;
|
2010-03-26 10:59:28 +00:00
|
|
|
|
case 'd':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
v32 = (ut32) r_num_math (core->num, input+1);
|
2010-03-26 16:01:25 +00:00
|
|
|
|
radare_compare (core, core->block, (ut8*)&v32, sizeof (v32));
|
2010-02-05 11:21:37 +00:00
|
|
|
|
break;
|
2010-03-26 10:59:28 +00:00
|
|
|
|
#if 0
|
|
|
|
|
case 'c':
|
|
|
|
|
radare_compare_code (
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_num_math (core->num, input+1),
|
2010-03-26 10:59:28 +00:00
|
|
|
|
core->block, core->blocksize);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'D':
|
2010-03-26 10:59:28 +00:00
|
|
|
|
{ // XXX ugly hack
|
2010-02-05 11:21:37 +00:00
|
|
|
|
char cmd[1024];
|
2010-03-26 10:59:28 +00:00
|
|
|
|
sprintf (cmd, "radiff -b %s %s", ".curblock", input+2);
|
|
|
|
|
r_file_dump (".curblock", config.block, config.block_size);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
radare_system(cmd);
|
|
|
|
|
unlink(".curblock");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
2010-05-24 16:35:08 +00:00
|
|
|
|
case 'g':
|
2010-12-06 02:34:44 +00:00
|
|
|
|
{
|
|
|
|
|
RCore *core2;
|
|
|
|
|
char *file2 = (char*)r_str_chop_ro (input+1);
|
|
|
|
|
|
|
|
|
|
if (!(core2 = r_core_new ())) {
|
|
|
|
|
eprintf ("Cannot init diff core\n");
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
core2->io->va = core->io->va;
|
|
|
|
|
core2->anal->split = core->anal->split;
|
2011-02-12 00:52:41 +00:00
|
|
|
|
if (!r_core_file_open (core2, file2, 0, 0LL)) {
|
2010-12-06 02:34:44 +00:00
|
|
|
|
eprintf ("Cannot open diff file '%s'\n", file2);
|
|
|
|
|
r_core_free (core2);
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
2011-02-11 14:42:38 +00:00
|
|
|
|
r_core_bin_load (core2, file2);
|
2010-12-06 02:34:44 +00:00
|
|
|
|
r_core_gdiff (core, core2);
|
|
|
|
|
r_core_free (core2);
|
|
|
|
|
}
|
2010-05-24 16:35:08 +00:00
|
|
|
|
break;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
case '?':
|
|
|
|
|
r_cons_strcat (
|
|
|
|
|
"Usage: c[?cdfx] [argument]\n"
|
|
|
|
|
" c [string] Compares a plain with escaped chars string\n"
|
2010-03-26 10:59:28 +00:00
|
|
|
|
//" cc [offset] Code bindiff current block against offset\n"
|
2010-02-05 11:21:37 +00:00
|
|
|
|
" cd [value] Compare a doubleword from a math expression\n"
|
2010-03-26 10:59:28 +00:00
|
|
|
|
//" cD [file] Like above, but using radiff -b\n");
|
|
|
|
|
" cq [value] Compare a quadword from a math expression\n"
|
2010-02-05 11:21:37 +00:00
|
|
|
|
" cx [hexpair] Compare hexpair string\n"
|
|
|
|
|
" cX [addr] Like 'cc' but using hexdiff output\n"
|
2010-05-24 16:35:08 +00:00
|
|
|
|
" cf [file] Compare contents of file at current seek\n"
|
|
|
|
|
" cg [file] Graphdiff current file and [file]\n");
|
2010-02-05 11:21:37 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-03-19 11:00:04 +00:00
|
|
|
|
eprintf ("Usage: c[?Ddxf] [argument]\n");
|
2010-02-05 11:21:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int cmd_info(void *data, const char *input) {
|
2010-02-28 21:58:21 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2009-04-01 10:41:42 +00:00
|
|
|
|
char buf[1024];
|
2010-02-05 11:21:37 +00:00
|
|
|
|
switch (*input) {
|
2009-04-01 10:41:42 +00:00
|
|
|
|
case 's':
|
|
|
|
|
case 'i':
|
|
|
|
|
case 'I':
|
|
|
|
|
case 'e':
|
|
|
|
|
case 'S':
|
|
|
|
|
case 'z':
|
2010-02-21 10:35:49 +00:00
|
|
|
|
snprintf (buf, sizeof (buf), "rabin2 -%c%s%s '%s'", input[0],
|
2010-05-19 22:59:42 +00:00
|
|
|
|
input[1]=='*'?"r":"", core->io->va?"v":"", core->file->filename);
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_sys_cmd (buf);
|
2009-04-01 10:41:42 +00:00
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '?':
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_cons_printf (
|
2009-04-01 10:41:42 +00:00
|
|
|
|
"Usage: i[eiIsSz]* ; get info from opened file (rabin2)\n"
|
|
|
|
|
"; Append a '*' to get the output in radare commands\n"
|
|
|
|
|
" ii ; imports\n"
|
|
|
|
|
" iI ; binary info\n"
|
|
|
|
|
" ie ; entrypoint\n"
|
|
|
|
|
" is ; symbols\n"
|
|
|
|
|
" iS ; sections\n"
|
|
|
|
|
" iz ; strings\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '*':
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2011-02-07 08:46:01 +00:00
|
|
|
|
if (core->file) {
|
2011-06-04 01:40:44 +00:00
|
|
|
|
int dbg = r_config_get_i (core->config, "cfg.debug");
|
|
|
|
|
RBinInfo *info = r_bin_get_info (core->bin);
|
|
|
|
|
if (dbg) dbg = R_IO_WRITE|R_IO_EXEC;
|
|
|
|
|
r_cons_printf ("fd\t%d\n", core->file->fd->fd);
|
|
|
|
|
r_cons_printf ("size\t0x%x\n", core->file->size);
|
|
|
|
|
r_cons_printf ("mode\t%s\n", r_str_rwx_i (core->file->rwx | dbg));
|
|
|
|
|
r_cons_printf ("block\t0x%x\n", core->blocksize);
|
|
|
|
|
r_cons_printf ("uri\t%s\n", core->file->uri);
|
2011-06-04 01:51:33 +00:00
|
|
|
|
if (core->bin->curxtr)
|
|
|
|
|
r_cons_printf ("packet\t%s\n", core->bin->curxtr->name);
|
|
|
|
|
if (core->bin->curxtr)
|
|
|
|
|
r_cons_printf ("format\t%s\n", core->bin->curarch.curplugin->name);
|
2011-06-04 01:40:44 +00:00
|
|
|
|
if (info) {
|
|
|
|
|
r_cons_printf ("file\t%s\n", info->file);
|
|
|
|
|
r_cons_printf ("type\t%s\n", info->type);
|
|
|
|
|
r_cons_printf ("os\t%s\n", info->os);
|
|
|
|
|
r_cons_printf ("arch\t%s\n", info->machine);
|
|
|
|
|
r_cons_printf ("bits\t%d\n", info->bits);
|
|
|
|
|
r_cons_printf ("endian\t%s\n", info->big_endian?"big":"little");
|
|
|
|
|
}
|
2011-02-07 08:46:01 +00:00
|
|
|
|
} else eprintf ("No selected file\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-02 10:45:20 +00:00
|
|
|
|
static void r_core_magic_at(RCore *core, const char *file, ut64 addr, int depth, int v) {
|
2011-02-23 18:11:39 +00:00
|
|
|
|
#if HAVE_LIB_MAGIC
|
2011-03-02 10:45:20 +00:00
|
|
|
|
char *fmt, *q, *p;
|
2011-02-24 23:23:58 +00:00
|
|
|
|
const char *str;
|
2011-02-23 18:11:39 +00:00
|
|
|
|
magic_t ck;
|
2011-02-24 23:23:58 +00:00
|
|
|
|
|
|
|
|
|
if (depth--<0)
|
|
|
|
|
return;
|
|
|
|
|
if (addr != core->offset)
|
|
|
|
|
r_core_seek (core, addr, R_TRUE);
|
2011-02-23 18:11:39 +00:00
|
|
|
|
if (*file == ' ') file++;
|
|
|
|
|
if (!*file) file = NULL;
|
|
|
|
|
ck = magic_open (0);
|
2011-02-24 23:23:58 +00:00
|
|
|
|
if (magic_load (ck, file) == -1) {
|
|
|
|
|
eprintf ("r_core_magic(\"%s\") %s\n", file, magic_error (ck));
|
|
|
|
|
return;
|
|
|
|
|
}
|
2011-03-02 10:45:20 +00:00
|
|
|
|
if (v) r_cons_printf ("# pm %s @ 0x%"PFMT64x"\n", file?file:"", addr);
|
2011-02-24 23:23:58 +00:00
|
|
|
|
str = magic_buffer (ck, core->block, core->blocksize);
|
|
|
|
|
if (str) {
|
2011-03-02 10:45:20 +00:00
|
|
|
|
if (!v && !strcmp (str, "data"))
|
|
|
|
|
return;
|
|
|
|
|
p = strdup (str);
|
2011-04-06 10:26:19 +00:00
|
|
|
|
fmt = p;
|
2011-02-24 23:23:58 +00:00
|
|
|
|
// processing newlinez
|
|
|
|
|
for (q=p; *q; q++)
|
|
|
|
|
if (q[0]=='\\' && q[1]=='n') {
|
|
|
|
|
*q = '\n';
|
|
|
|
|
strcpy (q+1, q+((q[2]==' ')?3:2));
|
|
|
|
|
}
|
|
|
|
|
r_cons_printf ("%s\n", p);
|
|
|
|
|
// walking childs
|
|
|
|
|
for (q=p; *q; q++) {
|
|
|
|
|
switch (*q) {
|
|
|
|
|
case ' ':
|
|
|
|
|
fmt = q+1;
|
|
|
|
|
break;
|
|
|
|
|
case '@':
|
|
|
|
|
*q = 0;
|
|
|
|
|
if (!memcmp (q+1, "0x", 2))
|
|
|
|
|
sscanf (q+3, "%"PFMT64x, &addr);
|
|
|
|
|
else sscanf (q+1, "%"PFMT64d, &addr);
|
2011-03-02 11:33:28 +00:00
|
|
|
|
r_core_magic_at (core, fmt, addr, depth, v);
|
2011-02-24 23:23:58 +00:00
|
|
|
|
*q = '@';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free (p);
|
|
|
|
|
}
|
2011-02-23 18:11:39 +00:00
|
|
|
|
magic_close (ck);
|
|
|
|
|
#else
|
2011-02-24 23:23:58 +00:00
|
|
|
|
eprintf ("r_core_magic: Compiled without magic :(\n");
|
2011-02-23 18:11:39 +00:00
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2011-03-02 10:45:20 +00:00
|
|
|
|
static void r_core_magic(RCore *core, const char *file, int v) {
|
2011-02-24 23:23:58 +00:00
|
|
|
|
int depth = r_config_get_i (core->config, "magic.depth");
|
|
|
|
|
ut64 addr = core->offset;
|
2011-03-02 10:45:20 +00:00
|
|
|
|
r_core_magic_at (core, file, addr, depth, v);
|
2011-02-24 23:23:58 +00:00
|
|
|
|
if (addr != core->offset)
|
|
|
|
|
r_core_seek (core, addr, R_TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_print(void *data, const char *input) {
|
|
|
|
|
RCore *core = (RCore *)data;
|
2011-02-23 12:25:41 +00:00
|
|
|
|
int i, l, len = core->blocksize;
|
2009-07-08 11:49:55 +00:00
|
|
|
|
ut32 tbs = core->blocksize;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
2010-09-08 17:49:34 +00:00
|
|
|
|
/* TODO: Change also blocksize for 'pd'.. */
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (input[0] && input[1]) {
|
2011-05-25 14:08:26 +00:00
|
|
|
|
if (input[2]) {
|
|
|
|
|
l = (int) r_num_math (core->num, input+(input[1]==' '?2:3));
|
|
|
|
|
/* except disasm and memoryfmt (pd, pm) */
|
|
|
|
|
if (input[0] != 'd' && input[0] != 'm') {
|
|
|
|
|
if (l>0) len = l;
|
|
|
|
|
if (l>tbs) r_core_block_size (core, l);
|
|
|
|
|
l = len;
|
|
|
|
|
}
|
|
|
|
|
} else l = 0;
|
2010-04-14 20:28:45 +00:00
|
|
|
|
} else l = len;
|
2010-09-23 10:59:54 +00:00
|
|
|
|
|
2011-03-13 19:27:28 +00:00
|
|
|
|
i = r_config_get_i (core->config, "cfg.maxbsize");
|
|
|
|
|
if (i && l > i) {
|
|
|
|
|
eprintf ("This block size is too big. Did you mean 'p%c @ %s' instead?\n",
|
|
|
|
|
*input, input+2);
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
2011-05-21 12:27:46 +00:00
|
|
|
|
|
2011-06-16 12:12:09 +00:00
|
|
|
|
if (input[1] == 'f') {
|
|
|
|
|
RAnalFcn *f = r_anal_fcn_find (core->anal, core->offset,
|
|
|
|
|
R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
|
|
|
|
if (f) len = f->size;
|
|
|
|
|
else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", core->offset);
|
|
|
|
|
}
|
2011-05-21 12:27:46 +00:00
|
|
|
|
core->num->value = len;
|
|
|
|
|
switch (*input) {
|
2011-02-23 12:25:41 +00:00
|
|
|
|
case '%':
|
2011-02-23 19:53:56 +00:00
|
|
|
|
{
|
2011-03-01 18:16:29 +00:00
|
|
|
|
ut64 off = core->io->off;
|
2011-02-23 19:53:56 +00:00
|
|
|
|
ut64 s = core->file?core->file->size:0;
|
|
|
|
|
ut64 piece = 0;
|
|
|
|
|
int w = core->print->cols * 4;
|
|
|
|
|
piece = s/w;
|
|
|
|
|
r_cons_strcat (" [");
|
|
|
|
|
for (i=0; i<w; i++) {
|
|
|
|
|
ut64 from = (piece*i);
|
|
|
|
|
ut64 to = from+piece;
|
|
|
|
|
if (off>=from && off<to)
|
|
|
|
|
r_cons_memcat ("#", 1);
|
|
|
|
|
else r_cons_memcat (".", 1);
|
|
|
|
|
// TODO: print where flags are.. code, ..
|
|
|
|
|
}
|
|
|
|
|
r_cons_strcat ("]\n");
|
|
|
|
|
}
|
2011-02-23 12:25:41 +00:00
|
|
|
|
break;
|
|
|
|
|
case '=':
|
|
|
|
|
for (i=0; i<core->blocksize; i++) {
|
|
|
|
|
int pc = (core->block[i]*100)/255;
|
|
|
|
|
r_print_addr (core->print, core->offset+i);
|
|
|
|
|
r_cons_printf ("%02x", core->block[i]);
|
|
|
|
|
r_print_progressbar (core->print, pc, 70);
|
|
|
|
|
r_cons_newline ();
|
|
|
|
|
}
|
|
|
|
|
break;
|
2011-02-12 11:54:26 +00:00
|
|
|
|
case 'b':
|
|
|
|
|
{
|
|
|
|
|
char *buf;
|
|
|
|
|
int size = core->blocksize * 8;
|
|
|
|
|
buf = malloc (size);
|
|
|
|
|
if (buf) {
|
|
|
|
|
r_str_bits (buf, core->block, size, NULL);
|
|
|
|
|
r_cons_printf ("%s\n", buf);
|
|
|
|
|
free (buf);
|
|
|
|
|
} else eprintf ("ERROR: Cannot malloc %d bytes\n", size);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2011-06-08 23:20:02 +00:00
|
|
|
|
case 'w':
|
|
|
|
|
r_print_hexdump (core->print, core->offset, core->block, len, 32, 4);
|
|
|
|
|
break;
|
|
|
|
|
case 'q':
|
|
|
|
|
r_print_hexdump (core->print, core->offset, core->block, len, 64, 8);
|
|
|
|
|
break;
|
2011-06-20 16:33:25 +00:00
|
|
|
|
case 'i': {
|
|
|
|
|
RAsmOp asmop;
|
2011-06-26 19:24:22 +00:00
|
|
|
|
int j, ret, err = 0;
|
2011-06-20 16:33:25 +00:00
|
|
|
|
const ut8 *buf = core->block;
|
|
|
|
|
if (l==0) l = len;
|
|
|
|
|
for (i=j=0; i<core->blocksize && i<len; i+=ret,j++ ) {
|
|
|
|
|
ret = r_asm_disassemble (core->assembler, &asmop, buf+i, len-i);
|
|
|
|
|
if (ret<1) {
|
2011-06-26 19:24:22 +00:00
|
|
|
|
err = 1;
|
|
|
|
|
r_cons_printf ("???\n");
|
|
|
|
|
} else r_cons_printf ("%s\n", asmop.buf_asm);
|
2011-06-20 16:33:25 +00:00
|
|
|
|
}
|
2011-06-26 19:24:22 +00:00
|
|
|
|
return err;
|
2011-06-20 16:33:25 +00:00
|
|
|
|
}
|
2010-02-12 02:17:32 +00:00
|
|
|
|
case 'D':
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case 'd':
|
2011-06-04 01:14:04 +00:00
|
|
|
|
switch (input[1]) {
|
2011-06-20 16:33:25 +00:00
|
|
|
|
case 'f': {
|
2011-02-07 16:43:50 +00:00
|
|
|
|
RAnalFcn *f = r_anal_fcn_find (core->anal, core->offset,
|
|
|
|
|
R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
2010-07-03 01:35:26 +00:00
|
|
|
|
if (f) {
|
|
|
|
|
ut8 *block = malloc (f->size+1);
|
2010-06-30 09:59:52 +00:00
|
|
|
|
if (block) {
|
2010-07-03 01:35:26 +00:00
|
|
|
|
r_core_read_at (core, f->addr, block, f->size);
|
2011-06-04 01:14:04 +00:00
|
|
|
|
core->num->value = r_core_print_disasm (core->print, core, f->addr, block, f->size, 9999);
|
2010-06-30 09:59:52 +00:00
|
|
|
|
free (block);
|
|
|
|
|
}
|
|
|
|
|
} else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", core->offset);
|
2011-06-20 16:33:25 +00:00
|
|
|
|
} break;
|
2011-06-04 01:14:04 +00:00
|
|
|
|
case 'l':
|
|
|
|
|
{
|
|
|
|
|
RAsmOp asmop;
|
|
|
|
|
int j, ret;
|
|
|
|
|
const ut8 *buf = core->block;
|
|
|
|
|
if (l==0) l= len;
|
|
|
|
|
for (i=j=0; i<core->blocksize && j<l; i+=ret,j++ ) {
|
|
|
|
|
ret = r_asm_disassemble (core->assembler, &asmop, buf+i, len-i);
|
|
|
|
|
printf ("%d\n", ret);
|
|
|
|
|
if (ret<1) ret = 1;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '?':
|
|
|
|
|
eprintf ("Usage: pd[f|i|l] [len] @ [addr]\n");
|
|
|
|
|
eprintf (" pdf : disassemble function\n");
|
|
|
|
|
eprintf (" pdi : disassemble only instruction\n");
|
|
|
|
|
eprintf (" pdl : show instruction sizes\n");
|
|
|
|
|
break;
|
2011-05-21 12:27:46 +00:00
|
|
|
|
}
|
|
|
|
|
//if (core->visual)
|
|
|
|
|
// l = core->cons->rows-core->cons->lines;
|
|
|
|
|
if (l<0) {
|
2011-02-15 11:31:32 +00:00
|
|
|
|
RList *bwdhits;
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
RCoreAsmHit *hit;
|
|
|
|
|
ut8 *block = malloc (core->blocksize);
|
|
|
|
|
if (block) {
|
|
|
|
|
l = -l;
|
|
|
|
|
bwdhits = r_core_asm_bwdisassemble (core, core->offset, l, core->blocksize);
|
|
|
|
|
if (bwdhits) {
|
|
|
|
|
r_list_foreach (bwdhits, iter, hit) {
|
|
|
|
|
r_core_read_at (core, hit->addr, block, core->blocksize);
|
2011-06-04 01:14:04 +00:00
|
|
|
|
core->num->value = r_core_print_disasm (core->print, core, hit->addr, block, core->blocksize, l);
|
2011-02-15 11:31:32 +00:00
|
|
|
|
r_cons_printf ("------\n");
|
|
|
|
|
}
|
|
|
|
|
r_list_free (bwdhits);
|
|
|
|
|
}
|
|
|
|
|
free (block);
|
|
|
|
|
}
|
2011-05-21 12:27:46 +00:00
|
|
|
|
} else {
|
2011-06-04 01:14:04 +00:00
|
|
|
|
core->num->value = r_core_print_disasm (core->print, core, core->offset, core->block, len, l);
|
2011-05-21 12:27:46 +00:00
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2009-02-09 00:54:09 +00:00
|
|
|
|
case 's':
|
2011-02-23 18:11:39 +00:00
|
|
|
|
if (input[1]=='p') {
|
|
|
|
|
int mylen = core->block[0];
|
|
|
|
|
// TODO: add support for 2-4 byte length pascal strings
|
|
|
|
|
r_print_string (core->print, core->offset, core->block+1, mylen, 0, 1, 0); //, 78, 1);
|
2011-05-21 12:27:46 +00:00
|
|
|
|
core->num->value = mylen;
|
2011-02-23 18:11:39 +00:00
|
|
|
|
} else r_print_string (core->print, core->offset, core->block, len, 0, 1, 0); //, 78, 1);
|
2009-03-12 01:42:35 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'S':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_print_string (core->print, core->offset, core->block, len, 1, 1, 0); //, 78, 1);
|
2009-03-12 01:42:35 +00:00
|
|
|
|
break;
|
2011-02-23 18:11:39 +00:00
|
|
|
|
case 'm':
|
2011-03-02 10:45:20 +00:00
|
|
|
|
r_core_magic (core, input+1, R_TRUE);
|
2011-02-23 18:11:39 +00:00
|
|
|
|
break;
|
2009-03-12 01:42:35 +00:00
|
|
|
|
case 'u':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_print_string (core->print, core->offset, core->block, len, 0, 1, 1); //, 78, 1);
|
2009-03-12 01:42:35 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'U':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_print_string (core->print, core->offset, core->block, len, 1, 1, 1); //, 78, 1);
|
2009-02-09 00:54:09 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'c':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_print_code (core->print, core->offset, core->block, len); //, 78, 1);
|
2009-02-09 00:54:09 +00:00
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case 'r':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_print_raw (core->print, core->block, len);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2009-03-12 01:42:35 +00:00
|
|
|
|
case 'o':
|
2010-09-23 10:59:54 +00:00
|
|
|
|
r_print_hexdump (core->print, core->offset, core->block, len, 8, 1); //, 78, !(input[1]=='-'));
|
2009-03-12 01:42:35 +00:00
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case 'x':
|
2010-09-23 10:59:54 +00:00
|
|
|
|
r_print_hexdump (core->print, core->offset, core->block, len, 16, 1); //, 78, !(input[1]=='-'));
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2011-02-23 01:10:28 +00:00
|
|
|
|
case '6':
|
|
|
|
|
{
|
|
|
|
|
int malen = (core->blocksize*4)+1;
|
|
|
|
|
ut8 *buf = malloc (malen);
|
|
|
|
|
memset (buf, 0, malen);
|
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case 'e':
|
|
|
|
|
r_base64_encode (buf, core->block, core->blocksize);
|
|
|
|
|
printf ("%s\n", buf);
|
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
if (r_base64_decode (buf, core->block, core->blocksize))
|
|
|
|
|
printf ("%s\n", buf);
|
|
|
|
|
else eprintf ("r_base64_decode: invalid stream\n");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
eprintf ("Usage: p6[ed] [len] ; base 64 encode/decode\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
free (buf);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '8':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_print_bytes (core->print, core->block, len, "%02x");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2011-02-23 18:11:39 +00:00
|
|
|
|
case 'f':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_print_format (core->print, core->offset, core->block, len, input+1);
|
2010-03-01 09:49:04 +00:00
|
|
|
|
break;
|
2010-03-18 23:51:16 +00:00
|
|
|
|
case 'n': // easter penis
|
|
|
|
|
for (l=0; l<10; l++) {
|
|
|
|
|
printf ("\r8");
|
|
|
|
|
for (len=0;len<l;len++)
|
|
|
|
|
printf ("=");
|
|
|
|
|
printf ("D");
|
|
|
|
|
r_sys_usleep (100000);
|
|
|
|
|
fflush (stdout);
|
|
|
|
|
}
|
|
|
|
|
for (l=0; l<3; l++) {
|
|
|
|
|
printf ("~");
|
|
|
|
|
fflush (stdout);
|
|
|
|
|
r_sys_usleep (100000);
|
|
|
|
|
}
|
|
|
|
|
printf ("\n");
|
|
|
|
|
break;
|
2010-09-23 10:59:54 +00:00
|
|
|
|
case 't':
|
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case ' ':
|
|
|
|
|
case '\0':
|
2011-02-23 01:10:28 +00:00
|
|
|
|
for (l=0; l<len; l+=sizeof (time_t))
|
|
|
|
|
r_print_date_unix (core->print, core->block+l, sizeof (time_t));
|
2010-09-23 10:59:54 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
for (l=0; l<len; l+=4)
|
|
|
|
|
r_print_date_dos (core->print, core->block+l, 4);
|
|
|
|
|
break;
|
|
|
|
|
case 'n':
|
2011-02-23 01:10:28 +00:00
|
|
|
|
for (l=0; l<len; l+=sizeof (ut64))
|
|
|
|
|
r_print_date_w32 (core->print, core->block+l, sizeof (ut64));
|
2010-09-23 10:59:54 +00:00
|
|
|
|
break;
|
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: pt[dn?]\n"
|
|
|
|
|
" pt print unix time\n"
|
|
|
|
|
" ptd print dos time\n"
|
|
|
|
|
" ptn print ntfs time\n"
|
|
|
|
|
" pt? show help message\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2011-02-16 23:58:54 +00:00
|
|
|
|
case 'Z':
|
2011-03-08 12:02:02 +00:00
|
|
|
|
if (input[1]=='?') {
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: pZ [len]\n"
|
|
|
|
|
" print N bytes where each byte represents a block of filesize/N\n"
|
|
|
|
|
"Configuration:\n"
|
2011-03-23 18:19:23 +00:00
|
|
|
|
" zoom.maxsz : max size of block\n"
|
2011-03-08 12:02:02 +00:00
|
|
|
|
" zoom.from : start address\n"
|
|
|
|
|
" zoom.to : end address\n"
|
|
|
|
|
" zoom.byte : specify how to calculate each byte\n"
|
|
|
|
|
" p : number of printable chars\n"
|
|
|
|
|
" f : count of flags in block\n"
|
|
|
|
|
" s : strings in range\n"
|
|
|
|
|
" 0 : number of bytes with value '0'\n"
|
|
|
|
|
" F : number of bytes with value 0xFF\n"
|
|
|
|
|
" e : calculate entropy and expand to 0-255 range\n"
|
|
|
|
|
" h : head (first byte value)\n"
|
2011-03-29 12:29:33 +00:00
|
|
|
|
"WARNING: On big files, use 'zoom.byte=h' or restrict ranges\n");
|
2011-03-08 12:02:02 +00:00
|
|
|
|
} else {
|
2011-03-29 12:29:33 +00:00
|
|
|
|
char *oldzoom = NULL;
|
2011-03-23 18:19:23 +00:00
|
|
|
|
ut64 maxsize = r_config_get_i (core->config, "zoom.maxsz");
|
2011-02-16 23:58:54 +00:00
|
|
|
|
ut64 from = r_config_get_i (core->config, "zoom.from");
|
|
|
|
|
ut64 to = r_config_get_i (core->config, "zoom.to");
|
2011-03-29 12:29:33 +00:00
|
|
|
|
if (input[1] != '\0' && input[1] != ' ') {
|
|
|
|
|
oldzoom = strdup (r_config_get (core->config, "zoom.byte"));
|
|
|
|
|
if (!r_config_set (core->config, "zoom.byte", input+1)) {
|
|
|
|
|
eprintf ("Invalid zoom.byte mode (%s)\n", input+1);
|
|
|
|
|
free (oldzoom);
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-03-24 11:17:13 +00:00
|
|
|
|
r_print_zoom (core->print, core, printzoomcallback,
|
|
|
|
|
from, to, core->blocksize, (int)maxsize);
|
2011-03-29 12:29:33 +00:00
|
|
|
|
if (oldzoom) {
|
|
|
|
|
r_config_set (core->config, "zoom.byte", oldzoom);
|
|
|
|
|
free (oldzoom);
|
|
|
|
|
}
|
2011-02-16 23:58:54 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
default:
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: p[fmt] [len]\n"
|
2011-02-23 12:25:41 +00:00
|
|
|
|
" p= [len] print byte percentage bars\n"
|
2011-02-23 01:10:28 +00:00
|
|
|
|
" p6[de] [len] base64 decode/encode\n"
|
|
|
|
|
" p8 [len] 8bit hexpair list of bytes\n"
|
|
|
|
|
" pb [len] bitstream of N bytes\n"
|
2011-06-20 16:33:25 +00:00
|
|
|
|
" pi[f] [len] show opcodes of N bytes\n"
|
|
|
|
|
" pd[lf] [l] disassemble N opcodes (see pd?)\n"
|
2011-02-23 01:10:28 +00:00
|
|
|
|
" pD [len] disassemble N bytes\n"
|
2011-06-08 23:20:02 +00:00
|
|
|
|
" p[w|q] [len] word (32), qword (64) value dump\n"
|
2011-02-23 01:10:28 +00:00
|
|
|
|
" po [len] octal dump of N bytes\n"
|
|
|
|
|
" pc [len] output C format\n"
|
2011-02-23 18:11:39 +00:00
|
|
|
|
" pf [fmt] print formatted data\n"
|
|
|
|
|
" pm [magic] print libmagic data\n"
|
2011-02-23 01:10:28 +00:00
|
|
|
|
" ps [len] print string\n"
|
2011-02-23 18:11:39 +00:00
|
|
|
|
" psp print pascal string\n"
|
2011-02-23 01:10:28 +00:00
|
|
|
|
" pS [len] print wide string\n"
|
|
|
|
|
" pt [len] print diferent timestamps\n"
|
|
|
|
|
" pr [len] print N raw bytes\n"
|
|
|
|
|
" pu [len] print N url encoded bytes\n"
|
2011-02-28 12:29:04 +00:00
|
|
|
|
" pU [len] print N wide url encoded bytes\n"
|
2011-02-23 01:10:28 +00:00
|
|
|
|
" px [len] hexdump of N bytes\n"
|
2011-03-08 12:02:02 +00:00
|
|
|
|
" pZ [len] print zoom view (see pZ? for help)\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (tbs != core->blocksize)
|
2010-02-03 17:15:31 +00:00
|
|
|
|
r_core_block_size (core, tbs);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-25 02:04:51 +00:00
|
|
|
|
static int cmd_hexdump(void *data, const char *input) {
|
2010-02-28 21:58:21 +00:00
|
|
|
|
return cmd_print (data, input-1);
|
2009-04-15 18:24:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-25 02:04:51 +00:00
|
|
|
|
static int cmd_flag(void *data, const char *input) {
|
2010-02-28 21:58:21 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
|
|
|
|
int len = strlen (input)+1;
|
|
|
|
|
char *str = alloca (len);
|
2010-06-20 23:58:45 +00:00
|
|
|
|
ut64 off = core->offset;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
memcpy (str, input+1, len);
|
2009-03-09 13:08:53 +00:00
|
|
|
|
|
2010-02-28 21:58:21 +00:00
|
|
|
|
switch (input[0]) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '+':
|
2010-06-20 23:58:45 +00:00
|
|
|
|
r_flag_set (core->flags, str, off, core->blocksize, 1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2009-03-09 13:08:53 +00:00
|
|
|
|
case ' ': {
|
|
|
|
|
char *s = NULL, *s2 = NULL;
|
2009-07-08 11:49:55 +00:00
|
|
|
|
ut32 bsze = core->blocksize;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
s = strchr (str, ' ');
|
2009-03-09 13:08:53 +00:00
|
|
|
|
if (s) {
|
|
|
|
|
*s = '\0';
|
2010-03-30 23:06:26 +00:00
|
|
|
|
s2 = strchr (s+1, ' ');
|
2009-03-09 13:08:53 +00:00
|
|
|
|
if (s2) {
|
|
|
|
|
*s2 = '\0';
|
2010-03-30 23:06:26 +00:00
|
|
|
|
if (s2[1]&&s2[2])
|
2010-06-20 23:58:45 +00:00
|
|
|
|
off = r_num_math (core->num, s2+1);
|
2009-03-09 13:08:53 +00:00
|
|
|
|
}
|
2010-05-19 22:59:42 +00:00
|
|
|
|
bsze = r_num_math (core->num, s+1);
|
2009-03-09 13:08:53 +00:00
|
|
|
|
}
|
2010-06-20 23:58:45 +00:00
|
|
|
|
r_flag_set (core->flags, str, off, bsze, 0);
|
2009-03-09 13:08:53 +00:00
|
|
|
|
if (s) *s=' ';
|
|
|
|
|
if (s2) *s2=' ';
|
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '-':
|
2011-05-21 19:05:21 +00:00
|
|
|
|
if (input[1]) {
|
|
|
|
|
if (strchr (input+1, '*'))
|
|
|
|
|
r_flag_unset_glob (core->flags, input+1);
|
|
|
|
|
else r_flag_unset (core->flags, input+1, NULL);
|
|
|
|
|
} else r_flag_unset_i (core->flags, off, NULL);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2010-04-09 09:32:17 +00:00
|
|
|
|
case 'S':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_flag_sort (core->flags, (input[1]=='n'));
|
2010-04-09 09:32:17 +00:00
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case 's':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if (input[1]==' ') r_flag_space_set (core->flags, input+2);
|
|
|
|
|
else r_flag_space_list (core->flags);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2009-03-27 00:16:27 +00:00
|
|
|
|
case 'o':
|
|
|
|
|
{
|
2009-04-02 13:07:26 +00:00
|
|
|
|
char *file = PREFIX"/share/doc/radare2/fortunes";
|
2009-03-27 00:16:27 +00:00
|
|
|
|
char *line = r_file_slurp_random_line (file);
|
2010-06-15 11:10:46 +00:00
|
|
|
|
if (line) {
|
|
|
|
|
r_cons_printf (" -- %s\n", line);
|
|
|
|
|
free (line);
|
|
|
|
|
}
|
2009-03-27 00:16:27 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2010-07-12 12:46:43 +00:00
|
|
|
|
case 'r':
|
|
|
|
|
{
|
|
|
|
|
char *old, *new;
|
|
|
|
|
RFlagItem *item;
|
|
|
|
|
old = str+1;
|
|
|
|
|
new = strchr (old, ' ');
|
|
|
|
|
if (new) {
|
|
|
|
|
*new = 0;
|
|
|
|
|
new++;
|
|
|
|
|
item = r_flag_get (core->flags, old);
|
|
|
|
|
} else {
|
|
|
|
|
new = old;
|
|
|
|
|
item = r_flag_get_i (core->flags, core->offset);
|
|
|
|
|
}
|
2011-05-21 19:05:21 +00:00
|
|
|
|
if (item) {
|
|
|
|
|
r_flag_rename (core->flags, item, new);
|
|
|
|
|
} else eprintf ("Cannot find flag\n");
|
2010-07-12 12:46:43 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '*':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_flag_list (core->flags, 1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '\0':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_flag_list (core->flags, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2011-06-03 16:54:12 +00:00
|
|
|
|
case 'd':
|
|
|
|
|
if (input[1]==' ') {
|
|
|
|
|
RFlagItem *f = r_flag_get_i (core->flags, r_num_math (core->num, input+2));
|
|
|
|
|
if (f) r_cons_printf ("%s\n", f->name);
|
|
|
|
|
} else eprintf ("Usage: fd [off]\n");
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '?':
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf (
|
2010-02-28 21:58:21 +00:00
|
|
|
|
"Usage: f[?] [flagname]\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
" f name 12 @ 33 ; set flag 'name' with size 12 at 33\n"
|
|
|
|
|
" f name 12 33 ; same as above\n"
|
|
|
|
|
" f+name 12 @ 33 ; like above but creates new one if doesnt exist\n"
|
|
|
|
|
" f-name ; remove flag 'name'\n"
|
2010-06-20 23:58:45 +00:00
|
|
|
|
" f-@addr ; remove flag at address expression\n"
|
2011-06-03 16:54:12 +00:00
|
|
|
|
" fd addr ; return flag+delta\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
" f ; list flags\n"
|
2010-04-09 09:32:17 +00:00
|
|
|
|
" f* ; list flags in r commands\n"
|
2010-07-12 12:46:43 +00:00
|
|
|
|
" fr [old] [new] ; rename flag\n"
|
2010-04-09 09:32:17 +00:00
|
|
|
|
" fs functions ; set flagspace\n"
|
|
|
|
|
" fs * ; set no flagspace\n"
|
|
|
|
|
" fs ; display flagspaces\n"
|
|
|
|
|
" fS[on] ; sort flags by offset or name\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-04 00:46:25 +00:00
|
|
|
|
static void cmd_syscall_do(RCore *core, int num) {
|
|
|
|
|
int i;
|
2010-05-19 00:39:01 +00:00
|
|
|
|
char str[64];
|
2011-02-02 12:05:48 +00:00
|
|
|
|
RSyscallItem *item = r_syscall_get (core->anal->syscall, num, -1);
|
2010-10-14 15:06:09 +00:00
|
|
|
|
if (item == NULL) {
|
|
|
|
|
r_cons_printf ("%d = unknown ()", num);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2010-03-04 00:46:25 +00:00
|
|
|
|
r_cons_printf ("%d = %s (", item->num, item->name);
|
|
|
|
|
// TODO: move this to r_syscall
|
|
|
|
|
for (i=0; i<item->args; i++) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
ut64 arg = r_debug_arg_get (core->dbg, R_TRUE, i+1);
|
2010-03-04 00:46:25 +00:00
|
|
|
|
if (item->sargs==NULL)
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"", arg);
|
2010-03-04 00:46:25 +00:00
|
|
|
|
else
|
|
|
|
|
switch (item->sargs[i]) {
|
|
|
|
|
case 'p': // pointer
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"", arg);
|
2010-03-04 00:46:25 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'i':
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("%"PFMT64d"", arg);
|
2010-03-04 00:46:25 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'z':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_read_at (core->io, arg, (ut8*)str, sizeof (str));
|
2010-03-04 00:46:25 +00:00
|
|
|
|
// TODO: filter zero terminated string
|
|
|
|
|
str[63] = '\0';
|
|
|
|
|
r_str_filter (str, strlen (str));
|
|
|
|
|
r_cons_printf ("\"%s\"", str);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("0x%08"PFMT64x"", arg);
|
2010-03-04 00:46:25 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (i+1<item->args)
|
|
|
|
|
r_cons_printf (", ");
|
|
|
|
|
}
|
|
|
|
|
r_cons_printf (")\n");
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-22 16:41:57 +00:00
|
|
|
|
|
|
|
|
|
#if 1
|
|
|
|
|
/* TODO: Move into cmd_anal() */
|
|
|
|
|
static void var_help() {
|
2011-07-05 15:14:39 +00:00
|
|
|
|
eprintf("Try afv?\n"
|
|
|
|
|
" afv 12 int buffer[3]\n"
|
|
|
|
|
" afv 12 byte buffer[1024]\n"
|
|
|
|
|
"Try af[aAv][gs] [delta] [[addr]]\n"
|
|
|
|
|
" afag 0 = arg0 get\n"
|
|
|
|
|
" afvs 12 = var12 set\n"
|
|
|
|
|
"a = arg, A = fastarg, v = var\n"
|
|
|
|
|
"TODO: [[addr]] is not yet implemented. use @\n");
|
2010-08-22 16:41:57 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int var_cmd(RCore *core, const char *str) {
|
2011-02-07 16:43:50 +00:00
|
|
|
|
RAnalFcn *fcn = r_anal_fcn_find (core->anal, core->offset,
|
|
|
|
|
R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
2010-08-22 16:41:57 +00:00
|
|
|
|
char *p,*p2,*p3;
|
2010-12-03 12:52:11 +00:00
|
|
|
|
int type, delta, len = strlen(str)+1;
|
2010-08-22 16:41:57 +00:00
|
|
|
|
|
2011-03-10 13:29:54 +00:00
|
|
|
|
p = alloca (len); // XXX: remove this alloca
|
|
|
|
|
memcpy (p, str, len);
|
2010-08-22 16:41:57 +00:00
|
|
|
|
str = p;
|
|
|
|
|
|
2011-03-10 13:29:54 +00:00
|
|
|
|
switch (*str) {
|
2010-08-22 16:41:57 +00:00
|
|
|
|
case 'V': // show vars in human readable format
|
2011-03-10 13:29:54 +00:00
|
|
|
|
r_anal_var_list_show (core->anal, fcn, core->offset);
|
2011-02-18 09:58:17 +00:00
|
|
|
|
return 0;
|
2010-08-22 16:41:57 +00:00
|
|
|
|
case '?':
|
2011-03-10 13:29:54 +00:00
|
|
|
|
var_help ();
|
2010-08-22 16:41:57 +00:00
|
|
|
|
return 0;
|
|
|
|
|
case 'v': // frame variable
|
|
|
|
|
case 'a': // stack arg
|
|
|
|
|
case 'A': // fastcall arg
|
|
|
|
|
// XXX nested dup
|
|
|
|
|
switch (*str) {
|
2010-12-03 12:52:11 +00:00
|
|
|
|
case 'v': type = R_ANAL_VAR_TYPE_LOCAL|R_ANAL_VAR_DIR_NONE; break;
|
|
|
|
|
case 'a': type = R_ANAL_VAR_TYPE_ARG|R_ANAL_VAR_DIR_IN; break;
|
|
|
|
|
case 'A': type = R_ANAL_VAR_TYPE_ARGREG|R_ANAL_VAR_DIR_IN; break;
|
2010-08-22 16:41:57 +00:00
|
|
|
|
default:
|
|
|
|
|
eprintf ("Unknown type\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Variable access CFvs = set fun var */
|
|
|
|
|
switch(str[1]) {
|
2011-02-18 09:58:17 +00:00
|
|
|
|
case '\0': r_anal_var_list (core->anal, fcn, 0, 0); return 0;
|
2010-08-22 16:41:57 +00:00
|
|
|
|
case '?': var_help(); return 0;
|
2011-03-10 13:29:54 +00:00
|
|
|
|
case '.': r_anal_var_list (core->anal, fcn, core->offset, 0); return 0;
|
2011-01-02 13:39:25 +00:00
|
|
|
|
case 's':
|
2010-08-22 16:41:57 +00:00
|
|
|
|
case 'g':
|
|
|
|
|
if (str[2]!='\0') {
|
2011-03-10 13:29:54 +00:00
|
|
|
|
if (fcn != NULL) {
|
|
|
|
|
RAnalVar *var = r_anal_var_get (core->anal, fcn, atoi (str+2), R_ANAL_VAR_TYPE_LOCAL);
|
|
|
|
|
if (var != NULL)
|
|
|
|
|
return r_anal_var_access_add (core->anal, var, atoi (str+2), (str[1]=='g')?0:1);
|
|
|
|
|
eprintf ("Can not find variable in: '%s'\n", str);
|
|
|
|
|
} else eprintf ("Unknown variable in: '%s'\n", str);
|
|
|
|
|
return R_FALSE;
|
2011-03-10 20:38:56 +00:00
|
|
|
|
} else eprintf ("Missing argument\n");
|
2010-08-22 16:41:57 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
str++;
|
|
|
|
|
if (str[0]==' ') str++;
|
|
|
|
|
delta = atoi (str);
|
|
|
|
|
p = strchr (str, ' ');
|
|
|
|
|
if (p==NULL) {
|
|
|
|
|
var_help();
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
p[0]='\0'; p++;
|
|
|
|
|
p2 = strchr (p, ' ');
|
|
|
|
|
if (p2) {
|
|
|
|
|
p2[0]='\0'; p2 = p2+1;
|
|
|
|
|
p3 = strchr (p2,'[');
|
|
|
|
|
if (p3 != NULL) {
|
|
|
|
|
p3[0]='\0';
|
|
|
|
|
p3=p3+1;
|
|
|
|
|
}
|
2010-12-03 12:52:11 +00:00
|
|
|
|
r_anal_var_add (core->anal, fcn, core->offset, delta, type, p, p2, p3?atoi(p3):0);
|
2011-03-10 13:29:54 +00:00
|
|
|
|
} else var_help ();
|
2010-08-22 16:41:57 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2011-03-10 13:29:54 +00:00
|
|
|
|
var_help ();
|
2010-08-22 16:41:57 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_anal(void *data, const char *input) {
|
2010-06-03 22:56:44 +00:00
|
|
|
|
const char *ptr;
|
2010-03-30 21:12:19 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2009-02-15 23:57:03 +00:00
|
|
|
|
int l, len = core->blocksize;
|
2010-06-04 21:47:35 +00:00
|
|
|
|
ut64 addr = core->offset;
|
2009-07-08 11:49:55 +00:00
|
|
|
|
ut32 tbs = core->blocksize;
|
2009-02-15 23:57:03 +00:00
|
|
|
|
|
|
|
|
|
if (input[0] && input[1]) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
l = (int) r_num_get (core->num, input+2);
|
2009-02-15 23:57:03 +00:00
|
|
|
|
if (l>0) len = l;
|
|
|
|
|
if (l>tbs) {
|
2010-03-04 00:46:25 +00:00
|
|
|
|
r_core_block_size (core, l);
|
2009-02-15 23:57:03 +00:00
|
|
|
|
len = l;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-01-02 13:39:25 +00:00
|
|
|
|
|
2010-03-24 00:24:27 +00:00
|
|
|
|
switch (input[0]) {
|
2009-02-15 23:57:03 +00:00
|
|
|
|
case 'o':
|
2011-02-03 08:31:50 +00:00
|
|
|
|
if (input[1] == '?') {
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: ao[e?] [len]\n"
|
|
|
|
|
" aoe ; emulate opcode at current offset\n"
|
|
|
|
|
" aoe 4 ; emulate 4 opcodes starting at current offset\n"
|
|
|
|
|
" ao 5 ; display opcode analysis of 5 opcodes\n");
|
|
|
|
|
} else
|
|
|
|
|
if (input[1] == 'e') {
|
2011-02-24 15:50:29 +00:00
|
|
|
|
eprintf ("TODO: r_anal_op_execute\n");
|
2011-02-03 08:31:50 +00:00
|
|
|
|
} else {
|
2011-01-02 13:39:25 +00:00
|
|
|
|
int ret, idx;
|
2009-07-08 11:49:55 +00:00
|
|
|
|
ut8 *buf = core->block;
|
2011-02-24 15:50:29 +00:00
|
|
|
|
RAnalOp op;
|
2011-01-02 13:39:25 +00:00
|
|
|
|
|
2010-03-26 16:01:25 +00:00
|
|
|
|
for (idx=ret=0; idx<len; idx+=ret) {
|
2011-02-24 15:50:29 +00:00
|
|
|
|
ret = r_anal_op (core->anal, &op,
|
2010-02-22 03:02:13 +00:00
|
|
|
|
core->offset+idx, buf + idx, (len-idx));
|
2010-03-26 16:01:25 +00:00
|
|
|
|
if (ret<1) {
|
2010-04-14 11:02:23 +00:00
|
|
|
|
eprintf ("Oops at 0x%08"PFMT64x"\n", core->offset+idx);
|
2010-03-26 16:01:25 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2010-04-14 11:02:23 +00:00
|
|
|
|
r_cons_printf ("addr: 0x%08"PFMT64x"\n", core->offset+idx);
|
2011-02-24 15:50:29 +00:00
|
|
|
|
r_cons_printf ("size: %d\n", op.length);
|
|
|
|
|
r_cons_printf ("type: %d\n", op.type); // TODO: string
|
|
|
|
|
r_cons_printf ("eob: %d\n", op.eob);
|
|
|
|
|
r_cons_printf ("jump: 0x%08"PFMT64x"\n", op.jump);
|
|
|
|
|
r_cons_printf ("fail: 0x%08"PFMT64x"\n", op.fail);
|
|
|
|
|
r_cons_printf ("stack: %d\n", op.stackop); // TODO: string
|
|
|
|
|
r_cons_printf ("cond: %d\n", op.cond); // TODO: string
|
|
|
|
|
r_cons_printf ("family: %d\n", op.family);
|
2010-03-26 16:01:25 +00:00
|
|
|
|
r_cons_printf ("\n");
|
2010-04-14 11:02:23 +00:00
|
|
|
|
//r_cons_printf ("false: 0x%08"PFMT64x"\n", core->offset+idx);
|
2010-03-26 16:01:25 +00:00
|
|
|
|
}
|
2009-02-16 01:12:02 +00:00
|
|
|
|
}
|
2009-02-15 23:57:03 +00:00
|
|
|
|
break;
|
2010-03-03 02:03:01 +00:00
|
|
|
|
case 'f':
|
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case '-':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_anal_fcn_del (core->anal, r_num_math (core->num, input+2));
|
2010-03-03 02:03:01 +00:00
|
|
|
|
break;
|
|
|
|
|
case '+':
|
2010-03-03 11:08:27 +00:00
|
|
|
|
{
|
2010-05-24 11:57:49 +00:00
|
|
|
|
char *ptr = strdup(input+3), *ptr2;
|
|
|
|
|
int n = r_str_word_set0 (ptr);
|
2010-03-03 11:08:27 +00:00
|
|
|
|
const char *name = NULL;
|
|
|
|
|
ut64 addr = -1LL;
|
|
|
|
|
ut64 size = 0LL;
|
2010-12-05 07:46:56 +00:00
|
|
|
|
RAnalDiff *diff = NULL;
|
2010-11-23 16:15:33 +00:00
|
|
|
|
int type = R_ANAL_FCN_TYPE_FCN;
|
2010-03-03 11:08:27 +00:00
|
|
|
|
|
2010-05-24 11:57:49 +00:00
|
|
|
|
if (n > 2) {
|
2010-11-23 16:15:33 +00:00
|
|
|
|
switch(n) {
|
|
|
|
|
case 5:
|
|
|
|
|
ptr2 = r_str_word_get0 (ptr, 4);
|
2010-12-05 07:46:56 +00:00
|
|
|
|
if (!(diff = r_anal_diff_new ())) {
|
|
|
|
|
eprintf ("error: Cannot init RAnalDiff\n");
|
|
|
|
|
free (ptr);
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
2010-05-24 11:57:49 +00:00
|
|
|
|
if (ptr2[0] == 'm')
|
2010-12-05 07:46:56 +00:00
|
|
|
|
diff->type = R_ANAL_DIFF_TYPE_MATCH;
|
2010-05-24 11:57:49 +00:00
|
|
|
|
else if (ptr2[0] == 'u')
|
2010-12-05 07:46:56 +00:00
|
|
|
|
diff->type = R_ANAL_DIFF_TYPE_UNMATCH;
|
2010-11-23 16:15:33 +00:00
|
|
|
|
case 4:
|
|
|
|
|
ptr2 = r_str_word_get0 (ptr, 3);
|
|
|
|
|
if (strchr (ptr2, 'l'))
|
|
|
|
|
type = R_ANAL_FCN_TYPE_LOC;
|
2011-02-07 16:43:50 +00:00
|
|
|
|
else if (strchr (ptr2, 'i'))
|
|
|
|
|
type = R_ANAL_FCN_TYPE_IMP;
|
|
|
|
|
else if (strchr (ptr2, 's'))
|
|
|
|
|
type = R_ANAL_FCN_TYPE_SYM;
|
2010-11-23 16:15:33 +00:00
|
|
|
|
else type = R_ANAL_FCN_TYPE_FCN;
|
|
|
|
|
case 3:
|
|
|
|
|
name = r_str_word_get0 (ptr, 2);
|
|
|
|
|
case 2:
|
|
|
|
|
size = r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
|
|
|
|
case 1:
|
|
|
|
|
addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
2010-05-24 11:57:49 +00:00
|
|
|
|
}
|
2010-11-23 16:15:33 +00:00
|
|
|
|
if (!r_anal_fcn_add (core->anal, addr, size, name, type, diff))
|
2010-08-01 09:02:55 +00:00
|
|
|
|
eprintf ("Cannot add function (duplicated)\n");
|
2010-03-03 11:08:27 +00:00
|
|
|
|
}
|
2010-12-05 07:46:56 +00:00
|
|
|
|
r_anal_diff_free (diff);
|
2010-03-03 11:08:27 +00:00
|
|
|
|
free (ptr);
|
|
|
|
|
}
|
2010-03-03 02:12:24 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'l':
|
2010-08-02 10:42:59 +00:00
|
|
|
|
r_core_anal_fcn_list (core, input+2, 0);
|
2010-03-03 02:12:24 +00:00
|
|
|
|
break;
|
|
|
|
|
case '*':
|
2010-08-02 10:42:59 +00:00
|
|
|
|
r_core_anal_fcn_list (core, input+2, 1);
|
2010-03-03 02:12:24 +00:00
|
|
|
|
break;
|
2010-08-19 18:28:25 +00:00
|
|
|
|
case 's': {
|
|
|
|
|
ut64 addr;
|
|
|
|
|
RAnalFcn *f;
|
|
|
|
|
const char *arg = input+3;
|
|
|
|
|
if (input[2] && (addr = r_num_math (core->num, arg))) {
|
|
|
|
|
arg = strchr (arg, ' ');
|
|
|
|
|
if (arg) arg++;
|
|
|
|
|
} else addr = core->offset;
|
2010-11-23 18:55:31 +00:00
|
|
|
|
if ((f = r_anal_fcn_find (core->anal, addr, R_ANAL_FCN_TYPE_NULL))) {
|
2010-08-19 18:28:25 +00:00
|
|
|
|
if (arg && *arg) {
|
|
|
|
|
r_anal_fcn_from_string (core->anal, f, arg);
|
|
|
|
|
} else {
|
|
|
|
|
char *str = r_anal_fcn_to_string (core->anal, f);
|
|
|
|
|
r_cons_printf ("%s\n", str);
|
|
|
|
|
free (str);
|
|
|
|
|
}
|
|
|
|
|
} else eprintf("No function defined at 0x%08"PFMT64x"\n", addr);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-08-22 16:41:57 +00:00
|
|
|
|
case 'a':
|
|
|
|
|
case 'A':
|
|
|
|
|
case 'v':
|
|
|
|
|
var_cmd (core, input+1);
|
|
|
|
|
break;
|
2010-11-22 14:14:54 +00:00
|
|
|
|
case 'c':
|
|
|
|
|
{
|
2011-02-11 10:22:43 +00:00
|
|
|
|
RAnalFcn *fcn;
|
|
|
|
|
int cc;
|
|
|
|
|
if ((fcn = r_anal_get_fcn_at (core->anal, core->offset)) != NULL) {
|
|
|
|
|
cc = r_anal_fcn_cc (fcn);
|
|
|
|
|
r_cons_printf ("Cyclomatic Complexity at 0x%08"PFMT64x" = %i\n", core->offset, cc);
|
|
|
|
|
} else r_cons_printf ("Error: function not found\n");
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'b':
|
|
|
|
|
{
|
|
|
|
|
char *ptr = strdup(input+3), *ptr2 = NULL;
|
|
|
|
|
ut64 fcnaddr = -1LL, addr = -1LL;
|
|
|
|
|
ut64 size = 0LL;
|
|
|
|
|
ut64 jump = -1LL;
|
|
|
|
|
ut64 fail = -1LL;
|
|
|
|
|
int type = R_ANAL_BB_TYPE_NULL;
|
|
|
|
|
RAnalFcn *fcn = NULL;
|
|
|
|
|
RAnalDiff *diff = NULL;
|
|
|
|
|
|
|
|
|
|
switch(r_str_word_set0 (ptr)) {
|
|
|
|
|
case 7:
|
|
|
|
|
ptr2 = r_str_word_get0 (ptr, 6);
|
|
|
|
|
if (!(diff = r_anal_diff_new ())) {
|
|
|
|
|
eprintf ("error: Cannot init RAnalDiff\n");
|
|
|
|
|
free (ptr);
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (ptr2[0] == 'm')
|
|
|
|
|
diff->type = R_ANAL_DIFF_TYPE_MATCH;
|
|
|
|
|
else if (ptr2[0] == 'u')
|
|
|
|
|
diff->type = R_ANAL_DIFF_TYPE_UNMATCH;
|
|
|
|
|
case 6:
|
|
|
|
|
ptr2 = r_str_word_get0 (ptr, 5);
|
|
|
|
|
if (strchr (ptr2, 'h'))
|
|
|
|
|
type |= R_ANAL_BB_TYPE_HEAD;
|
|
|
|
|
if (strchr (ptr2, 'b'))
|
|
|
|
|
type |= R_ANAL_BB_TYPE_BODY;
|
|
|
|
|
if (strchr (ptr2, 'l'))
|
|
|
|
|
type |= R_ANAL_BB_TYPE_LAST;
|
|
|
|
|
if (strchr (ptr2, 'f'))
|
|
|
|
|
type |= R_ANAL_BB_TYPE_FOOT;
|
|
|
|
|
case 5: // get fail
|
|
|
|
|
fail = r_num_math (core->num, r_str_word_get0 (ptr, 4));
|
|
|
|
|
case 4: // get jump
|
|
|
|
|
jump = r_num_math (core->num, r_str_word_get0 (ptr, 3));
|
|
|
|
|
case 3: // get size
|
|
|
|
|
size = r_num_math (core->num, r_str_word_get0 (ptr, 2));
|
|
|
|
|
case 2: // get addr
|
|
|
|
|
addr = r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
|
|
|
|
case 1: // get fcnaddr
|
|
|
|
|
fcnaddr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
|
|
|
|
}
|
|
|
|
|
if ((fcn = r_anal_get_fcn_at (core->anal, fcnaddr)) == NULL ||
|
|
|
|
|
!r_anal_fcn_add_bb (fcn, addr, size, jump, fail, type, diff))
|
|
|
|
|
eprintf ("Error: Cannot add bb\n");
|
|
|
|
|
r_anal_diff_free (diff);
|
|
|
|
|
free (ptr);
|
2010-11-22 14:14:54 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2010-03-03 02:12:24 +00:00
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: af[?+-l*]\n"
|
2010-08-19 18:28:25 +00:00
|
|
|
|
" af @ [addr] ; Analyze functions (start at addr)\n"
|
2010-11-23 16:15:33 +00:00
|
|
|
|
" af+ addr size name [type] [diff] ; Add function\n"
|
2011-02-11 10:22:43 +00:00
|
|
|
|
" afb fcnaddr addr size name [type] [diff] ; Add bb to function @ fcnaddr\n"
|
2010-08-19 18:28:25 +00:00
|
|
|
|
" af- [addr] ; Clean all function analysis data (or function at addr)\n"
|
|
|
|
|
" afl [fcn name] ; List functions\n"
|
|
|
|
|
" afs [addr] [fcnsign] ; Get/set function signature at current address\n"
|
2010-08-22 16:41:57 +00:00
|
|
|
|
" af[aAv][?] [arg] ; Manipulate args, fastargs and variables in function\n"
|
2010-11-22 14:14:54 +00:00
|
|
|
|
" afc @ [addr] ; Calculate the Cyclomatic Complexity (starting at addr)\n"
|
2010-08-19 18:28:25 +00:00
|
|
|
|
" af* ; Output radare commands\n");
|
2010-03-03 02:03:01 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-11-23 13:05:23 +00:00
|
|
|
|
r_core_anal_fcn (core, core->offset, -1, R_ANAL_REF_TYPE_NULL,
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_config_get_i (core->config, "anal.depth"));
|
2010-03-03 02:03:01 +00:00
|
|
|
|
}
|
2010-02-26 12:08:42 +00:00
|
|
|
|
break;
|
2010-02-27 10:56:41 +00:00
|
|
|
|
case 'g':
|
2010-03-03 13:35:18 +00:00
|
|
|
|
switch (input[1]) {
|
2010-03-24 00:24:27 +00:00
|
|
|
|
case 'c':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_core_anal_refs (core, r_num_math (core->num, input+2), 1);
|
2010-03-24 00:24:27 +00:00
|
|
|
|
break;
|
2010-03-15 18:47:26 +00:00
|
|
|
|
case 'l':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input+2), R_CORE_ANAL_GRAPHLINES);
|
2010-03-15 18:47:26 +00:00
|
|
|
|
break;
|
2010-03-19 03:32:42 +00:00
|
|
|
|
case 'a':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input+2), 0);
|
2010-03-19 03:32:42 +00:00
|
|
|
|
break;
|
2010-05-24 16:35:08 +00:00
|
|
|
|
case 'd':
|
|
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input+2),
|
|
|
|
|
R_CORE_ANAL_GRAPHBODY|R_CORE_ANAL_GRAPHDIFF);
|
|
|
|
|
break;
|
2010-03-03 13:35:18 +00:00
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: ag[?f]\n"
|
|
|
|
|
" ag [addr] ; Output graphviz code (bb at addr and childs)\n"
|
2010-03-19 03:32:42 +00:00
|
|
|
|
" aga [addr] ; Idem, but only addresses\n"
|
2010-03-24 00:24:27 +00:00
|
|
|
|
" agc [addr] ; Output graphviz call graph of function\n"
|
2010-03-15 18:47:26 +00:00
|
|
|
|
" agl [fcn name] ; Output graphviz code using meta-data\n"
|
2010-05-24 16:35:08 +00:00
|
|
|
|
" agd [fcn name] ; Output graphviz code of diffed function\n"
|
2010-03-15 18:47:26 +00:00
|
|
|
|
" agfl [fcn name] ; Output graphviz code of function using meta-data\n");
|
2010-03-03 13:35:18 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-11-18 23:49:05 +00:00
|
|
|
|
r_core_anal_graph (core, r_num_math (core->num, input+1),
|
|
|
|
|
R_CORE_ANAL_GRAPHBODY);
|
2010-03-03 13:35:18 +00:00
|
|
|
|
}
|
2010-02-27 10:56:41 +00:00
|
|
|
|
break;
|
2010-06-03 22:56:44 +00:00
|
|
|
|
case 't':
|
2010-06-04 21:47:35 +00:00
|
|
|
|
switch (input[1]) {
|
2010-06-03 22:56:44 +00:00
|
|
|
|
case '?':
|
|
|
|
|
r_cons_strcat ("Usage: at[*] [addr]\n"
|
|
|
|
|
" at? ; show help message\n"
|
|
|
|
|
" at ; list all traced opcode ranges\n"
|
|
|
|
|
" at- ; reset the tracing information\n"
|
|
|
|
|
" at* ; list all traced opcode offsets\n"
|
|
|
|
|
" at+ [addr] [times] ; add trace for address N times\n"
|
|
|
|
|
" at [addr] ; show trace info at address\n"
|
|
|
|
|
" att [tag] ; select trace tag (no arg unsets)\n"
|
|
|
|
|
" at% ; TODO\n"
|
2010-06-13 09:59:17 +00:00
|
|
|
|
" ata 0x804020 ... ; only trace given addresses\n"
|
2010-06-03 22:56:44 +00:00
|
|
|
|
" atr ; show traces as range commands (ar+)\n"
|
|
|
|
|
" atd ; show disassembly trace\n"
|
|
|
|
|
" atD ; show dwarf trace (at*|rsc dwarf-traces $FILE)\n");
|
|
|
|
|
eprintf ("Current Tag: %d\n", core->dbg->trace->tag);
|
|
|
|
|
break;
|
2010-06-13 09:59:17 +00:00
|
|
|
|
case 'a':
|
|
|
|
|
eprintf ("NOTE: Ensure given addresses are in 0x%%08llx format\n");
|
|
|
|
|
r_debug_trace_at (core->dbg, input+2);
|
|
|
|
|
break;
|
2010-06-03 22:56:44 +00:00
|
|
|
|
case 't':
|
|
|
|
|
r_debug_trace_tag (core->dbg, atoi (input+2));
|
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
//trace_show (2, trace_tag_get());
|
|
|
|
|
eprintf ("TODO\n");
|
|
|
|
|
break;
|
|
|
|
|
case 'D':
|
|
|
|
|
// XXX: not yet tested..and rsc dwarf-traces comes from r1
|
|
|
|
|
r_core_cmd (core, "at*|rsc dwarf-traces $FILE", 0);
|
|
|
|
|
break;
|
|
|
|
|
case '+':
|
|
|
|
|
ptr = input+3;
|
2010-06-04 21:47:35 +00:00
|
|
|
|
addr = r_num_math (core->num, ptr);
|
2010-06-03 22:56:44 +00:00
|
|
|
|
ptr = strchr (ptr, ' ');
|
|
|
|
|
if (ptr != NULL) {
|
2011-02-24 15:50:29 +00:00
|
|
|
|
RAnalOp *op = r_core_op_anal (core, addr);
|
|
|
|
|
if (op != NULL) {
|
2010-06-04 21:47:35 +00:00
|
|
|
|
//eprintf("at(0x%08llx)=%d (%s)\n", addr, atoi(ptr+1), ptr+1);
|
|
|
|
|
//trace_set_times(addr, atoi(ptr+1));
|
2011-02-24 15:50:29 +00:00
|
|
|
|
RDebugTracepoint *tp = r_debug_trace_add (core->dbg, addr, op->length);
|
2010-06-04 21:47:35 +00:00
|
|
|
|
tp->count = atoi (ptr+1);
|
2011-02-11 10:22:43 +00:00
|
|
|
|
r_anal_trace_bb (core->anal, addr);
|
2011-02-24 15:50:29 +00:00
|
|
|
|
r_anal_op_free (op);
|
2010-06-04 21:47:35 +00:00
|
|
|
|
} else eprintf ("Cannot analyze opcode at 0x%"PFMT64x"\n", addr);
|
2010-06-03 22:56:44 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
|
|
|
|
r_debug_trace_free (core->dbg);
|
|
|
|
|
core->dbg->trace = r_debug_trace_new (core->dbg);
|
|
|
|
|
break;
|
|
|
|
|
case ' ': {
|
|
|
|
|
RDebugTracepoint *t = r_debug_trace_get (core->dbg,
|
2010-06-04 21:47:35 +00:00
|
|
|
|
r_num_math (core->num, input+1));
|
2010-06-03 22:56:44 +00:00
|
|
|
|
if (t != NULL) {
|
2010-07-13 08:56:56 +00:00
|
|
|
|
r_cons_printf ("offset = 0x%"PFMT64x"\n", t->addr);
|
2010-06-03 22:56:44 +00:00
|
|
|
|
r_cons_printf ("opsize = %d\n", t->size);
|
|
|
|
|
r_cons_printf ("times = %d\n", t->times);
|
|
|
|
|
r_cons_printf ("count = %d\n", t->count);
|
|
|
|
|
//TODO cons_printf("time = %d\n", t->tm);
|
|
|
|
|
} }
|
|
|
|
|
break;
|
|
|
|
|
case '*':
|
2010-06-04 21:47:35 +00:00
|
|
|
|
r_debug_trace_list (core->dbg, 1);
|
2010-06-03 22:56:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'r':
|
|
|
|
|
eprintf ("TODO\n");
|
|
|
|
|
//trace_show(-1, trace_tag_get());
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-06-04 21:47:35 +00:00
|
|
|
|
r_debug_trace_list (core->dbg, 0);
|
2010-06-03 22:56:44 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2010-03-04 00:46:25 +00:00
|
|
|
|
case 's':
|
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case 'l':
|
2011-02-02 12:05:48 +00:00
|
|
|
|
r_syscall_list (core->anal->syscall);
|
2010-03-04 00:46:25 +00:00
|
|
|
|
break;
|
|
|
|
|
case '\0': {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
int a0 = (int)r_debug_reg_get (core->dbg, "oeax"); //XXX
|
2010-03-04 00:46:25 +00:00
|
|
|
|
cmd_syscall_do (core, a0);
|
|
|
|
|
} break;
|
|
|
|
|
case ' ':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
cmd_syscall_do (core, (int)r_num_get (core->num, input+2));
|
2010-03-04 00:46:25 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: as[?]\n"
|
|
|
|
|
" as Display syscall and arguments\n"
|
|
|
|
|
" as 4 Show syscall 4 based on asm.os\n"
|
|
|
|
|
" asl List of syscalls by asm.os and asm.arch\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-09-28 11:58:03 +00:00
|
|
|
|
case 'r':
|
|
|
|
|
switch(input[1]) {
|
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: ar[?d-l*]\n"
|
|
|
|
|
" ar addr [at] ; Add code ref\n"
|
|
|
|
|
" ard addr [at] ; Add dara ref\n"
|
|
|
|
|
" ar- [at] ; Clean all refs (or refs from addr)\n"
|
|
|
|
|
" arl ; List refs\n"
|
|
|
|
|
" ar* ; Output radare commands\n");
|
|
|
|
|
break;
|
2010-09-28 16:05:31 +00:00
|
|
|
|
case '-':
|
|
|
|
|
r_anal_ref_del (core->anal, r_num_math (core->num, input+2));
|
|
|
|
|
break;
|
|
|
|
|
case 'l':
|
|
|
|
|
r_core_anal_ref_list (core, R_FALSE);
|
|
|
|
|
break;
|
|
|
|
|
case '*':
|
|
|
|
|
r_core_anal_ref_list (core, R_TRUE);
|
|
|
|
|
break;
|
2010-09-28 11:58:03 +00:00
|
|
|
|
default:
|
2010-09-28 16:05:31 +00:00
|
|
|
|
{
|
|
|
|
|
char *ptr = strdup (r_str_trim_head ((char*)input+2));
|
|
|
|
|
int n = r_str_word_set0 (ptr);
|
|
|
|
|
ut64 at = core->offset;
|
|
|
|
|
ut64 addr = -1LL;
|
|
|
|
|
switch (n) {
|
|
|
|
|
case 2: // get at
|
|
|
|
|
at = r_num_math (core->num, r_str_word_get0 (ptr, 1));
|
|
|
|
|
case 1: // get addr
|
|
|
|
|
addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
r_anal_ref_add (core->anal, addr, at,
|
|
|
|
|
input[1]=='d'?R_ANAL_REF_TYPE_DATA:R_ANAL_REF_TYPE_CODE);
|
|
|
|
|
free (ptr);
|
|
|
|
|
}
|
2010-09-28 11:58:03 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2010-11-27 14:03:00 +00:00
|
|
|
|
case 'a':
|
|
|
|
|
r_core_anal_all (core);
|
|
|
|
|
break;
|
2011-02-12 11:54:26 +00:00
|
|
|
|
case 'p':
|
|
|
|
|
{
|
2011-02-23 19:53:56 +00:00
|
|
|
|
const char *arch = r_config_get (core->config, "asm.arch");
|
|
|
|
|
int bits = r_config_get_i (core->config, "asm.bits");
|
2011-02-12 11:54:26 +00:00
|
|
|
|
// TODO: this is x86 only
|
|
|
|
|
// TODO: allow interruptible search
|
|
|
|
|
char *o = strdup (r_config_get (core->config, "search.prefix"));
|
|
|
|
|
r_config_set (core->config, "search.prefix", "pre.");
|
|
|
|
|
r_core_cmd0 (core, "fs preludes");
|
2011-03-29 15:30:06 +00:00
|
|
|
|
if (strstr (arch, "x86")) {
|
2011-02-23 19:53:56 +00:00
|
|
|
|
switch (bits) {
|
|
|
|
|
case 32:
|
2011-07-05 15:14:39 +00:00
|
|
|
|
r_core_cmd0 (core, "./x 5589e5");
|
|
|
|
|
r_core_cmd0 (core, "af @@ pre.");
|
2011-02-23 19:53:56 +00:00
|
|
|
|
break;
|
|
|
|
|
case 64:
|
2011-07-05 15:24:05 +00:00
|
|
|
|
//r_core_cmd0 (core, "./x 554989e5");
|
|
|
|
|
r_core_cmd0 (core, "./x 554889e5"); // OSX
|
2011-07-05 15:14:39 +00:00
|
|
|
|
r_core_cmd0 (core, "af @@ pre.");
|
2011-02-23 19:53:56 +00:00
|
|
|
|
break;
|
2011-07-05 15:14:39 +00:00
|
|
|
|
default:
|
|
|
|
|
eprintf ("ap: Unsupported bits: %d\n", bits);
|
2011-02-23 19:53:56 +00:00
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
eprintf ("ap: Unsupported asm.arch and asm.bits\n");
|
|
|
|
|
}
|
2011-02-12 11:54:26 +00:00
|
|
|
|
r_config_set (core->config, "search.prefix", o);
|
|
|
|
|
free (o);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2011-06-04 03:27:26 +00:00
|
|
|
|
case 'd':
|
|
|
|
|
{
|
|
|
|
|
int i, bits = r_config_get_i (core->config, "asm.bits");
|
|
|
|
|
char *p, *inp = strdup (input+2);
|
|
|
|
|
p = strchr (inp, ' ');
|
|
|
|
|
if (p) *p=0;
|
|
|
|
|
ut64 a = r_num_math (core->num, inp);
|
|
|
|
|
ut64 b = p?r_num_math (core->num, p+1):0;
|
|
|
|
|
free (inp);
|
|
|
|
|
switch (bits) {
|
|
|
|
|
case 32:
|
|
|
|
|
for (i=0; i<core->blocksize; i+=4) {
|
|
|
|
|
ut32 n;
|
|
|
|
|
memcpy (&n, core->block+i, sizeof(ut32));
|
|
|
|
|
if (n>=a && n<=b) {
|
|
|
|
|
r_cons_printf ("f trampoline.%x @ 0x%"PFMT64x"\n", n, core->offset+i);
|
|
|
|
|
r_cons_printf ("Cd 4 @ 0x%"PFMT64x":4\n", core->offset+i);
|
|
|
|
|
// TODO: add data xrefs
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 64:
|
|
|
|
|
for (i=0; i<core->blocksize; i+=8) {
|
|
|
|
|
ut32 n;
|
|
|
|
|
memcpy (&n, core->block+i, sizeof(ut32));
|
|
|
|
|
if (n>=a && n<=b) {
|
|
|
|
|
r_cons_printf ("f trampoline.%"PFMT64x" @ 0x%"PFMT64x"\n", n, core->offset+i);
|
|
|
|
|
r_cons_printf ("Cd 8 @ 0x%"PFMT64x":8\n", core->offset+i);
|
|
|
|
|
// TODO: add data xrefs
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-11-27 14:03:00 +00:00
|
|
|
|
default:
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf (
|
2011-06-04 03:27:26 +00:00
|
|
|
|
"Usage: a[?obdfrgtv]\n"
|
2010-11-27 14:03:00 +00:00
|
|
|
|
" aa ; Analyze all (fcns + bbs)\n"
|
2011-02-23 19:53:56 +00:00
|
|
|
|
" ap ; Find and analyze function preludes\n"
|
2011-06-04 03:27:26 +00:00
|
|
|
|
" ad [from] [to] ; Analyze data pointers to (from-to)\n"
|
2010-03-04 00:46:25 +00:00
|
|
|
|
" as [num] ; Analyze syscall using dbg.reg\n"
|
2011-02-03 08:31:50 +00:00
|
|
|
|
" ao[e?] [len] ; Analyze Opcodes (or emulate it)\n"
|
2010-06-03 22:56:44 +00:00
|
|
|
|
" ab[?+-l*] ; Analyze Basic blocks\n"
|
|
|
|
|
" af[?+-l*] ; Analyze Functions\n"
|
2010-09-28 11:58:03 +00:00
|
|
|
|
" ar[?d-l*] ; Manage refs/xrefs\n"
|
2010-06-03 22:56:44 +00:00
|
|
|
|
" ag[?f] ; Output Graphviz code\n"
|
2011-06-04 03:27:26 +00:00
|
|
|
|
" at[trd+-*?] [.] ; Analyze execution Traces\n"
|
|
|
|
|
"Examples:\n"
|
|
|
|
|
" f ts @ `S*~text:0[3]`; f t @ section..text\n"
|
|
|
|
|
" f ds @ `S*~data:0[3]`; f d @ section..data\n"
|
|
|
|
|
" .ad t t+ts @ d:ds\n");
|
2009-02-15 23:57:03 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (tbs != core->blocksize)
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_core_block_size (core, tbs);
|
2009-02-15 23:57:03 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-05 21:08:46 +00:00
|
|
|
|
/* TODO: simplify using r_write */
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_write(void *data, const char *input) {
|
2011-03-25 13:54:30 +00:00
|
|
|
|
ut64 off;
|
2010-08-19 18:28:25 +00:00
|
|
|
|
ut8 *buf;
|
2011-03-03 09:42:45 +00:00
|
|
|
|
const char *arg;
|
2011-03-25 13:54:30 +00:00
|
|
|
|
int wseek, i, size, len = strlen (input);
|
2010-03-30 21:12:19 +00:00
|
|
|
|
char *tmp, *str = alloca (len)+1;
|
|
|
|
|
RCore *core = (RCore *)data;
|
2011-03-25 13:54:30 +00:00
|
|
|
|
#define WSEEK(x,y) if(wseek)r_core_seek_delta(x,y)
|
|
|
|
|
wseek = r_config_get_i (core->config, "cfg.wseek");
|
2010-03-30 21:12:19 +00:00
|
|
|
|
memcpy (str, input+1, len);
|
2011-03-03 09:42:45 +00:00
|
|
|
|
switch (*input) {
|
2011-03-25 13:54:30 +00:00
|
|
|
|
case 'r':
|
|
|
|
|
off = r_num_math (core->num, input+1);
|
|
|
|
|
len = (int)off;
|
|
|
|
|
if (len>0) {
|
|
|
|
|
buf = malloc (len);
|
|
|
|
|
if (buf != NULL) {
|
|
|
|
|
r_num_irand ();
|
|
|
|
|
for (i=0; i<len; i++)
|
|
|
|
|
buf[i] = r_num_rand (256);
|
|
|
|
|
r_core_write_at (core, core->offset, buf, len);
|
|
|
|
|
WSEEK (core, len);
|
|
|
|
|
free (buf);
|
|
|
|
|
} else eprintf ("Cannot allocate %d bytes\n", len);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-04-08 22:52:38 +00:00
|
|
|
|
case 'A':
|
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case ' ':
|
2011-03-03 09:42:45 +00:00
|
|
|
|
if (input[2] && input[3]==' ') {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_asm_set_pc (core->assembler, core->offset);
|
2010-04-08 22:52:38 +00:00
|
|
|
|
eprintf ("modify (%c)=%s\n", input[2], input+4);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
len = r_asm_modify (core->assembler, core->block, input[2],
|
|
|
|
|
r_num_math (core->num, input+4));
|
2010-04-08 22:52:38 +00:00
|
|
|
|
eprintf ("len=%d\n", len);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
if (len>0) {
|
2010-04-08 22:52:38 +00:00
|
|
|
|
r_core_write_at (core, core->offset, core->block, len);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, len);
|
|
|
|
|
} else eprintf ("r_asm_modify = %d\n", len);
|
2010-04-08 22:52:38 +00:00
|
|
|
|
} else eprintf ("Usage: wA [type] [value]\n");
|
|
|
|
|
break;
|
|
|
|
|
case '?':
|
|
|
|
|
default:
|
|
|
|
|
r_cons_printf ("Usage: wA [type] [value]\n"
|
|
|
|
|
"Types:\n"
|
|
|
|
|
" r raw write value\n"
|
|
|
|
|
" v set value (taking care of current address)\n"
|
|
|
|
|
" d destination register\n"
|
2011-03-03 09:42:45 +00:00
|
|
|
|
" 0 1st src register\n"
|
2010-04-08 22:52:38 +00:00
|
|
|
|
" 1 2nd src register\n"
|
|
|
|
|
"Example: wA r 0 # e800000000\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-03-30 21:12:19 +00:00
|
|
|
|
case 'c':
|
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case 'i':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_cache_commit (core->io);
|
2011-06-21 22:19:02 +00:00
|
|
|
|
r_core_block_read (core, 1);
|
2010-03-30 21:12:19 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'r':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_cache_reset (core->io, R_TRUE);
|
2011-06-21 22:19:02 +00:00
|
|
|
|
r_core_block_read (core, 1);
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
|
|
|
|
if (input[2]=='*') {
|
|
|
|
|
r_io_cache_reset (core->io, R_TRUE);
|
|
|
|
|
} else
|
|
|
|
|
if (input[2]==' ') {
|
|
|
|
|
char *p = strchr (input+3, ' ');
|
|
|
|
|
ut64 to, from = core->offset;
|
|
|
|
|
if (p) {
|
|
|
|
|
*p = 0;
|
|
|
|
|
from = r_num_math (core->num, input+3);
|
|
|
|
|
to = r_num_math (core->num, input+3);
|
|
|
|
|
if (to<from) {
|
|
|
|
|
eprintf ("Invalid range (from>to)\n");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
from = r_num_math (core->num, input+3);
|
|
|
|
|
to = from + core->blocksize;
|
|
|
|
|
}
|
|
|
|
|
r_io_cache_invalidate (core->io, from, to);
|
|
|
|
|
} else {
|
|
|
|
|
eprintf ("Invalidate write cache at 0x%08"PFMT64x"\n", core->offset);
|
|
|
|
|
r_io_cache_invalidate (core->io, core->offset, core->offset+core->blocksize);
|
|
|
|
|
}
|
|
|
|
|
r_core_block_read (core, 1);
|
2010-03-30 21:12:19 +00:00
|
|
|
|
break;
|
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: wc[ir*?]\n"
|
2011-06-21 22:19:02 +00:00
|
|
|
|
" wc list all write changes\n"
|
|
|
|
|
" wc- [a] [b] remove write op at curseek or given addr\n"
|
|
|
|
|
" wc* \"\" in radare commands\n"
|
|
|
|
|
" wcr reset all write changes in cache\n"
|
|
|
|
|
" wci commit write cache\n"
|
|
|
|
|
"NOTE: Requires 'e io.cache=true'\n");
|
2010-03-30 21:12:19 +00:00
|
|
|
|
break;
|
|
|
|
|
case '*':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_cache_list (core->io, R_TRUE);
|
2010-03-30 21:12:19 +00:00
|
|
|
|
break;
|
|
|
|
|
case '\0':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_cache_list (core->io, R_FALSE);
|
2010-03-30 21:12:19 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case ' ':
|
2009-04-15 18:24:19 +00:00
|
|
|
|
/* write string */
|
2010-02-28 21:58:21 +00:00
|
|
|
|
len = r_str_escape (str);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_set_fd (core->io, core->file->fd);
|
|
|
|
|
r_io_write_at (core->io, core->offset, (const ut8*)str, len);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, len);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2010-08-19 18:28:25 +00:00
|
|
|
|
case 't':
|
|
|
|
|
/* TODO: support userdefined size? */
|
|
|
|
|
arg = (const char *)(input+((input[1]==' ')?2:1));
|
|
|
|
|
r_file_dump (arg, core->block, core->blocksize);
|
|
|
|
|
break;
|
2009-04-15 18:24:19 +00:00
|
|
|
|
case 'T':
|
2010-02-28 21:58:21 +00:00
|
|
|
|
eprintf ("TODO\n");
|
2009-04-15 18:24:19 +00:00
|
|
|
|
break;
|
2010-08-19 18:28:25 +00:00
|
|
|
|
case 'f':
|
|
|
|
|
arg = (const char *)(input+((input[1]==' ')?2:1));
|
2010-08-22 15:56:50 +00:00
|
|
|
|
if ((buf = (ut8*) r_file_slurp (arg, &size))) {
|
2010-08-19 18:28:25 +00:00
|
|
|
|
r_io_set_fd (core->io, core->file->fd);
|
|
|
|
|
r_io_write_at (core->io, core->offset, buf, size);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, size);
|
2010-08-19 18:28:25 +00:00
|
|
|
|
free(buf);
|
2010-08-22 15:56:50 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2010-08-19 18:28:25 +00:00
|
|
|
|
} else eprintf ("Cannot open file '%s'\n", arg);
|
|
|
|
|
break;
|
|
|
|
|
case 'F':
|
|
|
|
|
arg = (const char *)(input+((input[1]==' ')?2:1));
|
2010-08-22 15:56:50 +00:00
|
|
|
|
if ((buf = r_file_slurp_hexpairs (arg, &size))) {
|
2010-08-19 18:28:25 +00:00
|
|
|
|
r_io_set_fd (core->io, core->file->fd);
|
|
|
|
|
r_io_write_at (core->io, core->offset, buf, size);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, size);
|
2010-08-19 18:28:25 +00:00
|
|
|
|
free (buf);
|
2010-08-22 15:56:50 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2010-08-19 18:28:25 +00:00
|
|
|
|
} else eprintf ("Cannot open file '%s'\n", arg);
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case 'w':
|
|
|
|
|
str = str+1;
|
2010-08-19 18:28:25 +00:00
|
|
|
|
len = (len-1)<<1;
|
|
|
|
|
tmp = alloca (len);
|
2010-02-01 10:55:56 +00:00
|
|
|
|
for (i=0;i<len;i++) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (i%2) tmp[i] = 0;
|
|
|
|
|
else tmp[i] = str[i>>1];
|
|
|
|
|
}
|
|
|
|
|
str = tmp;
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_set_fd (core->io, core->file->fd);
|
|
|
|
|
r_io_write_at (core->io, core->offset, (const ut8*)str, len);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, len);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'x':
|
|
|
|
|
{
|
2010-02-28 21:58:21 +00:00
|
|
|
|
int len = strlen (input);
|
|
|
|
|
ut8 *buf = alloca (len);
|
|
|
|
|
len = r_hex_str2bin (input+1, buf);
|
2011-02-26 18:16:08 +00:00
|
|
|
|
if (len != -1) {
|
|
|
|
|
r_core_write_at (core, core->offset, buf, len);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, len);
|
2011-02-26 18:16:08 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
|
|
|
|
} else eprintf ("Error: invalid hexpair string\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2009-04-07 00:26:41 +00:00
|
|
|
|
case 'a':
|
|
|
|
|
{
|
2010-04-14 22:29:42 +00:00
|
|
|
|
RAsmCode *acode;
|
2009-04-08 23:03:49 +00:00
|
|
|
|
/* XXX ULTRAUGLY , needs fallback support in rasm */
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_asm_use (core->assembler, "x86.olly");
|
|
|
|
|
r_asm_set_pc (core->assembler, core->offset);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
if (input[1]==' ') input=input+1;
|
2010-05-19 22:59:42 +00:00
|
|
|
|
acode = r_asm_massemble (core->assembler, input+1);
|
2010-04-14 22:29:42 +00:00
|
|
|
|
if (acode) {
|
2011-06-04 01:14:04 +00:00
|
|
|
|
if (r_config_get_i (core->config, "scr.prompt"))
|
2010-04-14 22:29:42 +00:00
|
|
|
|
eprintf ("Written %d bytes (%s)=wx %s\n", acode->len, input+1, acode->buf_hex);
|
|
|
|
|
r_core_write_at (core, core->offset, acode->buf, acode->len);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, acode->len);
|
2010-04-14 22:29:42 +00:00
|
|
|
|
r_asm_code_free (acode);
|
|
|
|
|
r_core_block_read (core, 0);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_asm_use (core->assembler, "x86"); /* XXX */
|
2010-08-22 15:56:50 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2010-04-14 22:29:42 +00:00
|
|
|
|
}
|
2009-04-07 00:26:41 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case 'b':
|
|
|
|
|
{
|
2010-02-28 21:58:21 +00:00
|
|
|
|
int len = strlen (input);
|
|
|
|
|
ut8 *buf = alloca (len);
|
|
|
|
|
len = r_hex_str2bin (input+1, buf);
|
|
|
|
|
r_mem_copyloop (core->block, buf, core->blocksize, len);
|
|
|
|
|
r_core_write_at (core, core->offset, core->block, core->blocksize);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, core->blocksize);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'm':
|
2010-08-19 18:28:25 +00:00
|
|
|
|
size = r_hex_str2bin (input+1, (ut8*)str);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
switch (input[1]) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '\0':
|
2010-02-28 21:58:21 +00:00
|
|
|
|
eprintf ("Current write mask: TODO\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
// TODO
|
|
|
|
|
break;
|
|
|
|
|
case '?':
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_set_write_mask(core->io, 0, 0);
|
2010-02-22 03:25:35 +00:00
|
|
|
|
eprintf ("Write mask disabled\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
2010-08-19 18:28:25 +00:00
|
|
|
|
if (size>0) {
|
|
|
|
|
r_io_set_fd (core->io, core->file->fd);
|
|
|
|
|
r_io_set_write_mask (core->io, (const ut8*)str, size);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, size);
|
2010-02-01 10:55:56 +00:00
|
|
|
|
eprintf ("Write mask set to '");
|
2011-03-25 13:54:30 +00:00
|
|
|
|
for (i=0; i<size; i++)
|
2010-02-01 10:55:56 +00:00
|
|
|
|
eprintf ("%02x", str[i]);
|
|
|
|
|
eprintf ("'\n");
|
2010-08-19 18:28:25 +00:00
|
|
|
|
} else eprintf ("Invalid string\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'v':
|
2011-03-25 13:54:30 +00:00
|
|
|
|
off = r_num_math (core->num, input+1);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_set_fd (core->io, core->file->fd);
|
|
|
|
|
r_io_seek (core->io, core->offset, R_IO_SEEK_SET);
|
2009-07-16 12:17:32 +00:00
|
|
|
|
if (off&UT64_32U) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
/* 8 byte addr */
|
2009-07-08 11:49:55 +00:00
|
|
|
|
ut64 addr8;
|
|
|
|
|
memcpy((ut8*)&addr8, (ut8*)&off, 8); // XXX needs endian here
|
|
|
|
|
// endian_memcpy((ut8*)&addr8, (ut8*)&off, 8);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_write(core->io, (const ut8 *)&addr8, 8);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, 8);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
} else {
|
|
|
|
|
/* 4 byte addr */
|
2009-07-08 11:49:55 +00:00
|
|
|
|
ut32 addr4, addr4_ = (ut32)off;
|
|
|
|
|
//drop_endian((ut8*)&addr4_, (ut8*)&addr4, 4); /* addr4_ = addr4 */
|
|
|
|
|
//endian_memcpy((ut8*)&addr4, (ut8*)&addr4_, 4); /* addr4 = addr4_ */
|
2010-02-28 21:58:21 +00:00
|
|
|
|
memcpy ((ut8*)&addr4, (ut8*)&addr4_, 4); // XXX needs endian here too
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_write (core->io, (const ut8 *)&addr4, 4);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, 4);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'o':
|
2010-02-28 21:58:21 +00:00
|
|
|
|
switch (input[1]) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case 'a':
|
|
|
|
|
case 's':
|
|
|
|
|
case 'A':
|
|
|
|
|
case 'x':
|
|
|
|
|
case 'r':
|
|
|
|
|
case 'l':
|
|
|
|
|
case 'm':
|
|
|
|
|
case 'd':
|
|
|
|
|
case 'o':
|
|
|
|
|
if (input[2]!=' ') {
|
2011-07-04 21:23:06 +00:00
|
|
|
|
r_cons_printf ("Usage: 'wo%c 00 11 22'\n", input[1]);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
case '2':
|
|
|
|
|
case '4':
|
2010-08-22 15:56:50 +00:00
|
|
|
|
r_core_write_op (core, input+3, input[1]);
|
|
|
|
|
r_core_block_read (core, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2011-05-20 17:49:50 +00:00
|
|
|
|
case 'n':
|
|
|
|
|
r_core_write_op (core, "ff", 'x');
|
|
|
|
|
r_core_block_read (core, 0);
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '\0':
|
|
|
|
|
case '?':
|
|
|
|
|
default:
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf (
|
2011-07-04 21:23:06 +00:00
|
|
|
|
"Usage: wo[asmdxoArl24] [hexpairs] @ addr[:bsize]\n"
|
|
|
|
|
"Example:\n"
|
|
|
|
|
" wox 0x90 ; xor cur block with 0x90\n"
|
|
|
|
|
" wox 90 ; xor cur block with 0x90\n"
|
|
|
|
|
" wox 0x0203 ; xor cur block with 0203\n"
|
|
|
|
|
" woa 02 03 ; add [0203][0203][...] to curblk\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Supported operations:\n"
|
2011-07-04 21:23:06 +00:00
|
|
|
|
" woa += addition\n"
|
|
|
|
|
" wos -= substraction\n"
|
|
|
|
|
" wom *= multiply\n"
|
|
|
|
|
" wod /= divide\n"
|
|
|
|
|
" wox ^= xor\n"
|
|
|
|
|
" woo |= or\n"
|
|
|
|
|
" woA &= and\n"
|
|
|
|
|
" wor >>= shift right\n"
|
|
|
|
|
" wol <<= shift left\n"
|
|
|
|
|
" wo2 2= 2 byte endian swap\n"
|
|
|
|
|
" wo4 4= 4 byte endian swap\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
case '?':
|
|
|
|
|
if (core->oobi) {
|
2010-02-28 21:58:21 +00:00
|
|
|
|
eprintf ("Writing oobi buffer!\n");
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_io_set_fd (core->io, core->file->fd);
|
|
|
|
|
r_io_write (core->io, core->oobi, core->oobi_len);
|
2011-03-25 13:54:30 +00:00
|
|
|
|
WSEEK (core, core->oobi_len);
|
2010-08-22 15:56:50 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
|
|
|
|
} else r_cons_printf (
|
2010-02-01 10:55:56 +00:00
|
|
|
|
"Usage: w[x] [str] [<file] [<<EOF] [@addr]\n"
|
2010-03-30 21:12:19 +00:00
|
|
|
|
" w foobar write string 'foobar'\n"
|
2011-03-25 13:54:30 +00:00
|
|
|
|
" wr 10 Write 10 random bytes\n"
|
2010-03-30 21:12:19 +00:00
|
|
|
|
" ww foobar write wide string 'f\\x00o\\x00o\\x00b\\x00a\\x00r\\x00'\n"
|
|
|
|
|
" wa push ebp write opcode, separated by ';' (use '\"' around the command)\n"
|
2010-04-08 22:52:38 +00:00
|
|
|
|
" wA r 0 alter/modify opcode at current seek (see wA?)\n"
|
2010-03-30 21:12:19 +00:00
|
|
|
|
" wb 010203 fill current block with cyclic hexpairs\n"
|
|
|
|
|
" wc[ir*?] write cache commit/reset/list\n"
|
|
|
|
|
" wx 9090 write two intel nops\n"
|
|
|
|
|
" wv eip+34 write 32-64 bit value\n"
|
|
|
|
|
" wo[] hex write in block with operation. 'wo?' fmi\n"
|
2010-04-08 22:52:38 +00:00
|
|
|
|
" wm f0ff set binary mask hexpair to be used as cyclic write mask\n"
|
2010-03-30 21:12:19 +00:00
|
|
|
|
" wf file write contents of file at current offset\n"
|
|
|
|
|
" wF file write contents of hexpairs file here\n"
|
|
|
|
|
" wt file write current block to file\n");
|
2009-04-15 18:24:19 +00:00
|
|
|
|
//TODO: add support for offset+seek
|
|
|
|
|
// " wf file o s ; write contents of file from optional offset 'o' and size 's'.\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2011-02-05 11:51:37 +00:00
|
|
|
|
static int cmd_resize(void *data, const char *input) {
|
|
|
|
|
RCore *core = (RCore *)data;
|
2011-07-03 10:58:19 +00:00
|
|
|
|
ut64 oldsize, newsize;
|
|
|
|
|
st64 delta = 0;
|
2011-02-05 11:51:37 +00:00
|
|
|
|
int grow;
|
|
|
|
|
|
|
|
|
|
oldsize = core->file->size;
|
2011-07-04 16:54:41 +00:00
|
|
|
|
while (*input==' ')
|
|
|
|
|
input++;
|
2011-07-03 10:58:19 +00:00
|
|
|
|
switch (*input) {
|
2011-07-04 16:54:41 +00:00
|
|
|
|
case '+':
|
|
|
|
|
case '-':
|
|
|
|
|
delta = (st64)r_num_math (NULL, input);
|
|
|
|
|
newsize = oldsize + delta;
|
|
|
|
|
break;
|
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: r[+-][ size]\n"
|
|
|
|
|
" r size expand or truncate file to given size\n"
|
|
|
|
|
" r-num remove num bytes, move following data down\n"
|
|
|
|
|
" r+num insert num bytes, move following data up\n");
|
|
|
|
|
return R_TRUE;
|
|
|
|
|
default:
|
|
|
|
|
newsize = r_num_math (core->num, input+1);
|
2011-02-05 11:51:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
grow = (newsize > oldsize);
|
|
|
|
|
|
|
|
|
|
if (grow) {
|
|
|
|
|
r_io_resize (core->io, newsize);
|
|
|
|
|
core->file->size = newsize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (delta && core->offset < newsize)
|
|
|
|
|
r_io_shift (core->io, core->offset, grow?newsize:oldsize, delta);
|
|
|
|
|
|
|
|
|
|
if (!grow) {
|
|
|
|
|
r_io_resize (core->io, newsize);
|
|
|
|
|
core->file->size = newsize;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (newsize < core->offset+core->blocksize ||
|
|
|
|
|
oldsize < core->offset+core->blocksize)
|
|
|
|
|
r_core_block_read (core, 0);
|
|
|
|
|
|
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2009-09-25 02:04:51 +00:00
|
|
|
|
static const char *cmdhit = NULL;
|
2011-02-05 01:21:40 +00:00
|
|
|
|
static const char *searchprefix = NULL;
|
2011-05-20 20:42:11 +00:00
|
|
|
|
static int searchcount = 0;
|
2011-02-22 23:54:40 +00:00
|
|
|
|
|
2010-04-06 16:21:41 +00:00
|
|
|
|
static int __cb_hit(RSearchKeyword *kw, void *user, ut64 addr) {
|
2010-03-30 21:12:19 +00:00
|
|
|
|
RCore *core = (RCore *)user;
|
2011-05-20 20:42:11 +00:00
|
|
|
|
if (searchcount) {
|
|
|
|
|
if (!--searchcount) {
|
|
|
|
|
eprintf ("search.count reached\n");
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
2011-02-05 01:21:40 +00:00
|
|
|
|
r_cons_printf ("f %s%d_%d %d 0x%08"PFMT64x"\n", searchprefix,
|
2009-04-02 10:23:32 +00:00
|
|
|
|
kw->kwidx, kw->count, kw->keyword_length, addr);
|
2010-02-01 10:55:56 +00:00
|
|
|
|
if (!strnull (cmdhit)) {
|
2010-01-12 01:12:18 +00:00
|
|
|
|
ut64 here = core->offset;
|
2010-02-21 10:35:49 +00:00
|
|
|
|
r_core_seek (core, addr, R_FALSE);
|
2010-03-19 03:02:23 +00:00
|
|
|
|
r_core_cmd (core, cmdhit, 0);
|
2010-02-21 10:35:49 +00:00
|
|
|
|
r_core_seek (core, here, R_TRUE);
|
2009-04-02 10:23:32 +00:00
|
|
|
|
}
|
2009-02-09 00:54:09 +00:00
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_search(void *data, const char *input) {
|
2011-05-12 18:28:44 +00:00
|
|
|
|
char *inp;
|
2010-03-30 21:12:19 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2010-06-24 22:21:22 +00:00
|
|
|
|
ut64 at, from, to;
|
|
|
|
|
//RIOSection *section;
|
2011-05-12 18:28:44 +00:00
|
|
|
|
int i, len, ret, dosearch = R_FALSE;
|
2011-05-21 22:52:46 +00:00
|
|
|
|
int inverse = R_FALSE;
|
2011-02-22 23:54:40 +00:00
|
|
|
|
int aes_search = R_FALSE;
|
2011-05-21 12:27:46 +00:00
|
|
|
|
int ignorecase = R_FALSE;
|
2010-06-24 22:21:22 +00:00
|
|
|
|
ut32 n32;
|
2009-07-08 11:49:55 +00:00
|
|
|
|
ut8 *buf;
|
2010-06-24 22:21:22 +00:00
|
|
|
|
|
|
|
|
|
// TODO: repeat last search doesnt works for /a
|
|
|
|
|
from = r_config_get_i (core->config, "search.from");
|
2011-05-21 23:36:23 +00:00
|
|
|
|
if (from == UT64_MAX)
|
|
|
|
|
from = core->offset;
|
2010-06-24 22:21:22 +00:00
|
|
|
|
to = r_config_get_i (core->config, "search.to");
|
2010-06-30 00:30:07 +00:00
|
|
|
|
core->search->align = r_config_get_i (core->config, "search.align");
|
2010-06-25 09:22:14 +00:00
|
|
|
|
//TODO: handle section ranges if from&&to==0
|
2010-06-24 22:21:22 +00:00
|
|
|
|
/*
|
|
|
|
|
section = r_io_section_get (core->io, core->offset);
|
2010-06-25 09:22:14 +00:00
|
|
|
|
if (section) {
|
|
|
|
|
from += section->vaddr;
|
|
|
|
|
//fin = ini + s->size;
|
2010-06-24 22:21:22 +00:00
|
|
|
|
}
|
|
|
|
|
*/
|
2011-02-05 01:21:40 +00:00
|
|
|
|
searchprefix = r_config_get (core->config, "search.prefix");
|
2011-05-12 18:28:44 +00:00
|
|
|
|
// TODO: get ranges from current IO section
|
2010-06-25 09:22:14 +00:00
|
|
|
|
/* XXX: Think how to get the section ranges here */
|
2011-05-12 18:28:44 +00:00
|
|
|
|
if (from == 0LL) from = core->offset;
|
|
|
|
|
if (to == 0LL) to = UT32_MAX; // XXX?
|
2010-06-24 22:21:22 +00:00
|
|
|
|
|
2011-05-21 22:52:46 +00:00
|
|
|
|
reread:
|
2011-03-02 10:45:20 +00:00
|
|
|
|
switch (*input) {
|
2011-05-21 22:52:46 +00:00
|
|
|
|
case '!':
|
|
|
|
|
input++;
|
|
|
|
|
inverse = R_TRUE;
|
|
|
|
|
goto reread;
|
|
|
|
|
break;
|
2011-02-22 23:54:40 +00:00
|
|
|
|
case 'a':
|
|
|
|
|
if (input[1]==' ')
|
|
|
|
|
r_core_anal_search (core, from, to, r_num_math (core->num, input+2));
|
|
|
|
|
else r_core_anal_search (core, from, to, core->offset);
|
|
|
|
|
break;
|
|
|
|
|
case 'A':
|
|
|
|
|
dosearch = aes_search = R_TRUE;
|
|
|
|
|
break;
|
2009-02-09 00:54:09 +00:00
|
|
|
|
case '/':
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_search_begin (core->search);
|
2011-02-22 23:54:40 +00:00
|
|
|
|
dosearch = R_TRUE;
|
2009-02-09 00:54:09 +00:00
|
|
|
|
break;
|
2011-03-02 10:45:20 +00:00
|
|
|
|
case 'm':
|
|
|
|
|
#if HAVE_LIB_MAGIC
|
|
|
|
|
/* XXX: This is pretty sloow */
|
|
|
|
|
dosearch = R_FALSE;
|
|
|
|
|
if (input[1]==' ') {
|
|
|
|
|
const char *file = input+2;
|
|
|
|
|
ut64 addr = from;
|
|
|
|
|
for (; addr<to; addr++) {
|
|
|
|
|
r_core_seek (core, addr, R_TRUE);
|
|
|
|
|
r_core_magic (core, file, R_FALSE);
|
|
|
|
|
}
|
|
|
|
|
} else eprintf ("Usage: /m [file]\n");
|
|
|
|
|
#else
|
|
|
|
|
eprintf ("r_core_magic: Compiled without magic :(\n");
|
|
|
|
|
#endif
|
|
|
|
|
break;
|
|
|
|
|
case 'p':
|
|
|
|
|
{
|
|
|
|
|
int ps = atoi (input+1);
|
|
|
|
|
if (ps>1) {
|
|
|
|
|
r_search_pattern_size (core->search, ps);
|
|
|
|
|
r_search_pattern (core->search, from, to);
|
|
|
|
|
} else eprintf ("Invalid pattern size (must be >0)\n");
|
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-09 00:54:09 +00:00
|
|
|
|
case 'v':
|
2010-06-30 00:30:07 +00:00
|
|
|
|
r_search_reset (core->search, R_SEARCH_KEYWORD);
|
2010-04-08 22:52:38 +00:00
|
|
|
|
r_search_set_distance (core->search, (int)
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_config_get_i (core->config, "search.distance"));
|
2011-02-03 08:31:50 +00:00
|
|
|
|
n32 = (ut32)r_num_math (core->num, input+1);
|
|
|
|
|
// TODO: Add support for /v4 /v8 /v2
|
2010-04-06 11:02:21 +00:00
|
|
|
|
r_search_kw_add (core->search,
|
|
|
|
|
r_search_keyword_new ((const ut8*)&n32, 4, NULL, 0, NULL));
|
2010-02-21 10:35:49 +00:00
|
|
|
|
r_search_begin (core->search);
|
2011-05-20 20:42:11 +00:00
|
|
|
|
dosearch = R_TRUE;
|
2009-02-09 00:54:09 +00:00
|
|
|
|
break;
|
2011-02-22 23:54:40 +00:00
|
|
|
|
case 'w': /* search wide string */
|
|
|
|
|
if (input[1]==' ') {
|
|
|
|
|
int len = strlen (input+2);
|
|
|
|
|
const char *p2;
|
|
|
|
|
char *p, *str = malloc ((len+1)*2);
|
2011-05-21 12:27:46 +00:00
|
|
|
|
for (p2=input+2, p=str; *p2; p+=2, p2++) {
|
2011-02-22 23:54:40 +00:00
|
|
|
|
p[0] = *p2;
|
|
|
|
|
p[1] = 0;
|
|
|
|
|
}
|
|
|
|
|
r_search_reset (core->search, R_SEARCH_KEYWORD);
|
|
|
|
|
r_search_set_distance (core->search, (int)
|
|
|
|
|
r_config_get_i (core->config, "search.distance"));
|
|
|
|
|
r_search_kw_add (core->search,
|
|
|
|
|
r_search_keyword_new ((const ut8*)str, len*2, NULL, 0, NULL));
|
|
|
|
|
r_search_begin (core->search);
|
2011-05-20 20:42:11 +00:00
|
|
|
|
dosearch = R_TRUE;
|
2011-02-22 23:54:40 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2011-05-21 12:27:46 +00:00
|
|
|
|
case 'i':
|
|
|
|
|
if (input[1]!= ' ') {
|
|
|
|
|
eprintf ("Missing ' ' after /i\n");
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
ignorecase = R_TRUE;
|
2009-02-09 00:54:09 +00:00
|
|
|
|
case ' ': /* search string */
|
2011-05-21 12:27:46 +00:00
|
|
|
|
inp = strdup (input+1+ignorecase);
|
|
|
|
|
if (ignorecase)
|
|
|
|
|
for (i=1; inp[i]; i++)
|
|
|
|
|
inp[i] = tolower (inp[i]);
|
2011-05-12 18:28:44 +00:00
|
|
|
|
len = r_str_escape (inp);
|
|
|
|
|
eprintf ("Searching %d bytes: ", len);
|
|
|
|
|
for (i=0; i<len; i++) eprintf ("%02x ", inp[i]);
|
|
|
|
|
eprintf ("\n");
|
2010-06-30 00:30:07 +00:00
|
|
|
|
r_search_reset (core->search, R_SEARCH_KEYWORD);
|
2010-04-08 22:52:38 +00:00
|
|
|
|
r_search_set_distance (core->search, (int)
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_config_get_i (core->config, "search.distance"));
|
2011-05-21 13:45:43 +00:00
|
|
|
|
{
|
|
|
|
|
RSearchKeyword *skw;
|
|
|
|
|
skw = r_search_keyword_new ((const ut8*)inp, len, NULL, 0, NULL);
|
|
|
|
|
skw->icase = ignorecase;
|
|
|
|
|
r_search_kw_add (core->search, skw);
|
|
|
|
|
}
|
2010-04-06 11:02:21 +00:00
|
|
|
|
r_search_begin (core->search);
|
2011-05-20 20:42:11 +00:00
|
|
|
|
dosearch = R_TRUE;
|
2009-02-09 00:54:09 +00:00
|
|
|
|
break;
|
2011-02-25 10:45:05 +00:00
|
|
|
|
case 'e': /* match regexp */
|
2009-02-16 23:09:40 +00:00
|
|
|
|
{
|
2010-03-30 21:12:19 +00:00
|
|
|
|
char *inp = strdup (input+2);
|
|
|
|
|
char *res = r_str_lchr (inp+1, inp[0]);
|
2009-02-16 23:09:40 +00:00
|
|
|
|
char *opt = NULL;
|
|
|
|
|
if (res > inp) {
|
|
|
|
|
opt = strdup(res+1);
|
|
|
|
|
res[1]='\0';
|
|
|
|
|
}
|
2010-06-30 00:30:07 +00:00
|
|
|
|
r_search_reset (core->search, R_SEARCH_REGEXP);
|
2010-04-08 22:52:38 +00:00
|
|
|
|
r_search_set_distance (core->search, (int)
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_config_get_i (core->config, "search.distance"));
|
2010-04-06 11:02:21 +00:00
|
|
|
|
r_search_kw_add (core->search,
|
2011-05-21 13:45:43 +00:00
|
|
|
|
r_search_keyword_new_str (inp, opt, NULL, 0));
|
2010-03-30 21:12:19 +00:00
|
|
|
|
r_search_begin (core->search);
|
2011-05-20 20:42:11 +00:00
|
|
|
|
dosearch = R_TRUE;
|
|
|
|
|
free (inp);
|
|
|
|
|
free (opt);
|
2009-02-16 23:09:40 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-09 00:54:09 +00:00
|
|
|
|
case 'x': /* search hex */
|
2010-06-30 00:30:07 +00:00
|
|
|
|
r_search_reset (core->search, R_SEARCH_KEYWORD);
|
2010-04-08 22:52:38 +00:00
|
|
|
|
r_search_set_distance (core->search, (int)
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_config_get_i (core->config, "search.distance"));
|
2010-04-06 11:02:21 +00:00
|
|
|
|
r_search_kw_add (core->search,
|
2010-04-08 16:01:45 +00:00
|
|
|
|
r_search_keyword_new_hexmask (input+2, NULL));
|
|
|
|
|
r_search_begin (core->search);
|
2011-05-20 20:42:11 +00:00
|
|
|
|
dosearch = R_TRUE;
|
2009-02-09 00:54:09 +00:00
|
|
|
|
break;
|
2010-08-11 15:48:02 +00:00
|
|
|
|
case 'c': /* search asm */
|
|
|
|
|
{
|
2010-08-11 17:10:47 +00:00
|
|
|
|
/* TODO: Move to a separate function */
|
2010-08-11 15:48:02 +00:00
|
|
|
|
int asmstr = r_config_get_i (core->config, "search.asmstr");
|
|
|
|
|
if (asmstr) {
|
2010-09-30 17:25:47 +00:00
|
|
|
|
RCoreAsmHit *hit;
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
int count = 0;
|
2011-02-05 01:21:40 +00:00
|
|
|
|
RList *hits;
|
2010-09-30 17:25:47 +00:00
|
|
|
|
if ((hits = r_core_asm_strsearch (core, input+2, from, to))) {
|
|
|
|
|
r_list_foreach (hits, iter, hit) {
|
2011-02-05 01:21:40 +00:00
|
|
|
|
r_cons_printf ("f %s_%i @ 0x%08"PFMT64x" # %s (%i)\n",
|
|
|
|
|
searchprefix, count, hit->addr, hit->code, hit->len);
|
2010-09-30 17:25:47 +00:00
|
|
|
|
count++;
|
|
|
|
|
}
|
|
|
|
|
r_list_destroy (hits);
|
|
|
|
|
}
|
2010-08-11 17:10:47 +00:00
|
|
|
|
dosearch = 0;
|
2010-08-11 15:48:02 +00:00
|
|
|
|
} else {
|
2010-08-12 12:54:24 +00:00
|
|
|
|
char *kwd;
|
|
|
|
|
if (!(kwd = r_core_asm_search (core, input+2, from, to)))
|
2010-08-11 15:48:02 +00:00
|
|
|
|
return R_FALSE;
|
|
|
|
|
r_search_reset (core->search, R_SEARCH_KEYWORD);
|
|
|
|
|
r_search_set_distance (core->search, (int)
|
|
|
|
|
r_config_get_i (core->config, "search.distance"));
|
|
|
|
|
r_search_kw_add (core->search,
|
2010-08-12 12:54:24 +00:00
|
|
|
|
r_search_keyword_new_hexmask (kwd, NULL));
|
2010-08-11 15:48:02 +00:00
|
|
|
|
r_search_begin (core->search);
|
2010-08-12 12:54:24 +00:00
|
|
|
|
free (kwd);
|
2011-05-20 20:42:11 +00:00
|
|
|
|
dosearch = R_TRUE;
|
2010-08-11 15:48:02 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-09 00:54:09 +00:00
|
|
|
|
default:
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_printf (
|
2010-06-24 22:21:22 +00:00
|
|
|
|
"Usage: /[amx/] [arg]\n"
|
2011-05-12 18:28:44 +00:00
|
|
|
|
" / foo\\x00 ; search for string 'foo\\0'\n"
|
2011-02-28 12:29:04 +00:00
|
|
|
|
" /w foo ; search for wide string 'f\\0o\\0o\\0'\n"
|
2011-05-21 12:27:46 +00:00
|
|
|
|
" /! ff ; search for first occurrence not matching\n"
|
|
|
|
|
" /i foo ; search for string 'foo' ignoring case\n"
|
2011-02-25 10:45:05 +00:00
|
|
|
|
" /e /E.F/i ; match regular expression\n"
|
2011-02-03 08:31:50 +00:00
|
|
|
|
" /x ff0033 ; search for hex string\n"
|
2011-05-21 22:52:46 +00:00
|
|
|
|
" /!x 00 ; inverse hexa search (find first byte != 0x00)\n"
|
2011-02-05 01:21:40 +00:00
|
|
|
|
" /c jmp [esp] ; search for asm code (see search.asmstr)\n"
|
2011-02-22 23:54:40 +00:00
|
|
|
|
" /A ; search for AES expanded keys\n"
|
2011-02-03 08:31:50 +00:00
|
|
|
|
" /a sym.printf ; analyze code referencing an offset\n"
|
2011-03-02 10:45:20 +00:00
|
|
|
|
" /m magicfile ; search for matching magic file (use blocksize)\n"
|
|
|
|
|
" /p patternsize ; search for pattern of given size\n"
|
2011-02-03 08:31:50 +00:00
|
|
|
|
" /v num ; look for a asm.bigendian 32bit value\n"
|
|
|
|
|
" // ; repeat last search\n"
|
2011-02-22 23:54:40 +00:00
|
|
|
|
" ./ hello ; search 'hello string' and import flags\n"
|
2010-06-24 22:21:22 +00:00
|
|
|
|
"Configuration:\n"
|
2011-05-12 18:28:44 +00:00
|
|
|
|
" e cmd.hit = x ; command to execute on every search hit\n"
|
2011-02-03 08:31:50 +00:00
|
|
|
|
" e search.distance = 0 ; search string distance\n"
|
|
|
|
|
" e search.align = 4 ; only catch aligned search hits\n"
|
|
|
|
|
" e search.from = 0 ; start address\n"
|
|
|
|
|
" e search.to = 0 ; end address\n"
|
|
|
|
|
" e search.asmstr = 0 ; search string instead of assembly\n");
|
2009-02-09 00:54:09 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2011-05-21 12:27:46 +00:00
|
|
|
|
r_config_set_i (core->config, "search.kwidx", core->search->n_kws);
|
2009-02-09 00:54:09 +00:00
|
|
|
|
if (dosearch) {
|
2011-05-21 19:05:21 +00:00
|
|
|
|
r_cons_printf ("fs hits\n");
|
2011-05-21 22:52:46 +00:00
|
|
|
|
core->search->inverse = inverse;
|
2011-05-20 20:42:11 +00:00
|
|
|
|
searchcount = r_config_get_i (core->config, "search.count");
|
|
|
|
|
if (searchcount)
|
|
|
|
|
searchcount++;
|
2011-02-22 23:54:40 +00:00
|
|
|
|
if (core->search->n_kws>0 || aes_search) {
|
|
|
|
|
RSearchKeyword aeskw;
|
|
|
|
|
if (aes_search) {
|
|
|
|
|
memset (&aeskw, 0, sizeof (aeskw));
|
|
|
|
|
aeskw.keyword_length = 31;
|
|
|
|
|
}
|
2010-06-24 22:21:22 +00:00
|
|
|
|
/* set callback */
|
|
|
|
|
/* TODO: handle last block of data */
|
|
|
|
|
/* TODO: handle ^C */
|
|
|
|
|
/* TODO: launch search in background support */
|
|
|
|
|
buf = (ut8 *)malloc (core->blocksize);
|
|
|
|
|
r_search_set_callback (core->search, &__cb_hit, core);
|
|
|
|
|
cmdhit = r_config_get (core->config, "cmd.hit");
|
|
|
|
|
r_cons_break (NULL, NULL);
|
2011-02-22 23:54:40 +00:00
|
|
|
|
// XXX required? imho nor_io_set_fd (core->io, core->file->fd);
|
2010-06-24 22:21:22 +00:00
|
|
|
|
for (at = from; at < to; at += core->blocksize) {
|
|
|
|
|
if (r_cons_singleton ()->breaked)
|
|
|
|
|
break;
|
|
|
|
|
ret = r_io_read_at (core->io, at, buf, core->blocksize);
|
2011-05-21 13:45:43 +00:00
|
|
|
|
/*
|
2011-05-21 12:27:46 +00:00
|
|
|
|
if (ignorecase) {
|
|
|
|
|
int i;
|
|
|
|
|
for (i=0; i<core->blocksize; i++)
|
|
|
|
|
buf[i] = tolower (buf[i]);
|
|
|
|
|
}
|
2011-05-21 13:45:43 +00:00
|
|
|
|
*/
|
2010-06-24 22:21:22 +00:00
|
|
|
|
if (ret != core->blocksize)
|
|
|
|
|
break;
|
2011-02-22 23:54:40 +00:00
|
|
|
|
if (aes_search) {
|
|
|
|
|
int delta = r_search_aes_update (core->search, at, buf, ret);
|
|
|
|
|
if (delta != -1) {
|
2011-05-20 20:42:11 +00:00
|
|
|
|
if (!r_search_hit_new (core->search, &aeskw, at+delta)) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-02-22 23:54:40 +00:00
|
|
|
|
aeskw.count++;
|
|
|
|
|
}
|
|
|
|
|
} else
|
2010-06-24 22:21:22 +00:00
|
|
|
|
if (r_search_update (core->search, &at, buf, ret) == -1) {
|
2011-05-21 22:52:46 +00:00
|
|
|
|
eprintf ("search: update read error at 0x%08"PFMT64x"\n", at);
|
2010-06-24 22:21:22 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2009-02-16 23:09:40 +00:00
|
|
|
|
}
|
2010-06-24 22:21:22 +00:00
|
|
|
|
r_cons_break_end ();
|
2011-02-22 23:54:40 +00:00
|
|
|
|
free (buf);
|
2010-06-24 22:21:22 +00:00
|
|
|
|
} else eprintf ("No keywords defined\n");
|
2009-02-09 00:54:09 +00:00
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_eval(void *data, const char *input) {
|
2010-03-30 21:12:19 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2010-02-01 10:55:56 +00:00
|
|
|
|
switch (input[0]) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '\0':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_config_list (core->config, NULL, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2011-05-21 13:45:43 +00:00
|
|
|
|
case 'e':
|
|
|
|
|
if (input[1]==' ') {
|
|
|
|
|
char *p;
|
|
|
|
|
const char *val = r_config_get (core->config, input+2);
|
|
|
|
|
p = r_core_editor (core, val);
|
|
|
|
|
r_str_subchr (p, '\n', ';');
|
|
|
|
|
r_config_set (core->config, input+2, p);
|
|
|
|
|
} else eprintf ("Usage: ee varname\n");
|
|
|
|
|
break;
|
2009-04-06 22:53:25 +00:00
|
|
|
|
case '!':
|
|
|
|
|
input = r_str_chop_ro(input+1);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if (!r_config_swap (core->config, input))
|
2010-02-01 10:55:56 +00:00
|
|
|
|
eprintf ("r_config: '%s' is not a boolean variable.\n", input);
|
2009-04-06 22:53:25 +00:00
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case '-':
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_core_config_init (core);
|
|
|
|
|
eprintf ("BUG: 'e-' command locks the eval hashtable. patches are welcome :)\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '*':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_config_list (core->config, NULL, 1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '?':
|
2010-02-02 10:09:52 +00:00
|
|
|
|
r_cons_printf (
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Usage: e[?] [var[=value]]\n"
|
|
|
|
|
" e ; list config vars\n"
|
|
|
|
|
" e- ; reset config vars\n"
|
|
|
|
|
" e* ; dump config vars in r commands\n"
|
2009-04-06 22:53:25 +00:00
|
|
|
|
" e!a ; invert the boolean value of 'a' var\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
" e a ; get value of var 'a'\n"
|
|
|
|
|
" e a=b ; set var 'a' the 'b' value\n");
|
2010-05-19 22:59:42 +00:00
|
|
|
|
//r_cmd_help(core->cmd, "e");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2010-06-30 00:30:07 +00:00
|
|
|
|
case ' ':
|
|
|
|
|
r_config_eval (core->config, input+1);
|
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
default:
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_config_eval (core->config, input);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_hash(void *data, const char *input) {
|
2011-02-06 13:10:16 +00:00
|
|
|
|
char *p, algo[32];
|
2010-03-30 21:12:19 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2010-07-15 22:02:33 +00:00
|
|
|
|
ut32 i, len = core->blocksize;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
const char *ptr;
|
|
|
|
|
|
|
|
|
|
if (input[0]=='!') {
|
|
|
|
|
#if 0
|
2011-02-07 08:46:01 +00:00
|
|
|
|
TODO: Honor OOBI
|
2009-02-05 21:08:46 +00:00
|
|
|
|
#!lua < file
|
|
|
|
|
#!lua <<EOF
|
|
|
|
|
#!lua
|
|
|
|
|
#!lua foo bar
|
2011-02-07 08:46:01 +00:00
|
|
|
|
//r_lang_run (core->lang, p+1, strlen (p+1));
|
|
|
|
|
//core->oobi, core->oobi_len);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
#endif
|
2011-02-06 13:10:16 +00:00
|
|
|
|
if (input[1]=='?' || input[1]=='*' || input[1]=='\0') {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_lang_list (core->lang);
|
2009-02-10 23:56:20 +00:00
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
2011-02-06 13:10:16 +00:00
|
|
|
|
p = strchr (input+1, ' ');
|
|
|
|
|
if (p) *p=0;
|
2009-02-10 23:56:20 +00:00
|
|
|
|
// TODO: set argv here
|
2011-02-07 08:46:01 +00:00
|
|
|
|
if (r_lang_use (core->lang, input+1)) {
|
|
|
|
|
r_lang_setup (core->lang);
|
|
|
|
|
if (p) r_lang_run_file (core->lang, p+1);
|
|
|
|
|
else r_lang_prompt (core->lang);
|
|
|
|
|
} else eprintf ("Invalid hashbang plugin name. Try '#!'\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-02 10:09:52 +00:00
|
|
|
|
ptr = strchr (input, ' ');
|
|
|
|
|
sscanf (input, "%31s", algo);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (ptr != NULL)
|
2010-05-19 22:59:42 +00:00
|
|
|
|
len = r_num_math (core->num, ptr+1);
|
2010-07-15 22:02:33 +00:00
|
|
|
|
/* TODO: Simplify this spaguetti monster */
|
|
|
|
|
if (!r_str_ccmp (input, "md4", ' ')) {
|
|
|
|
|
RHash *ctx = r_hash_new (R_TRUE, R_HASH_MD4);
|
|
|
|
|
const ut8 *c = r_hash_do_md4 (ctx, core->block, len);
|
|
|
|
|
for (i=0; i<R_HASH_SIZE_MD4; i++) r_cons_printf ("%02x", c[i]);
|
|
|
|
|
r_cons_newline ();
|
|
|
|
|
r_hash_free (ctx);
|
|
|
|
|
} else
|
|
|
|
|
if (!r_str_ccmp (input, "md5", ' ')) {
|
|
|
|
|
RHash *ctx = r_hash_new (R_TRUE, R_HASH_MD5);
|
|
|
|
|
const ut8 *c = r_hash_do_md5 (ctx, core->block, len);
|
|
|
|
|
for (i=0; i<R_HASH_SIZE_MD5; i++) r_cons_printf ("%02x", c[i]);
|
|
|
|
|
r_cons_newline ();
|
|
|
|
|
r_hash_free (ctx);
|
|
|
|
|
} else
|
|
|
|
|
if (!r_str_ccmp (input, "sha1", ' ')) {
|
|
|
|
|
RHash *ctx = r_hash_new (R_TRUE, R_HASH_SHA1);
|
|
|
|
|
const ut8 *c = r_hash_do_sha1 (ctx, core->block, len);
|
|
|
|
|
for (i=0; i<R_HASH_SIZE_SHA1;i++) r_cons_printf ("%02x", c[i]);
|
|
|
|
|
r_cons_newline ();
|
|
|
|
|
r_hash_free (ctx);
|
|
|
|
|
} else
|
|
|
|
|
if (!r_str_ccmp (input, "sha256", ' ')) {
|
|
|
|
|
RHash *ctx = r_hash_new (R_TRUE, R_HASH_SHA256);
|
|
|
|
|
const ut8 *c = r_hash_do_sha256 (ctx, core->block, len);
|
|
|
|
|
for (i=0; i<R_HASH_SIZE_SHA256;i++) r_cons_printf ("%02x", c[i]);
|
|
|
|
|
r_cons_newline ();
|
|
|
|
|
r_hash_free (ctx);
|
|
|
|
|
} else
|
|
|
|
|
if (!r_str_ccmp (input, "sha512", ' ')) {
|
|
|
|
|
RHash *ctx = r_hash_new (R_TRUE, R_HASH_SHA512);
|
|
|
|
|
const ut8 *c = r_hash_do_sha512 (ctx, core->block, len);
|
|
|
|
|
for (i=0; i<R_HASH_SIZE_SHA512;i++) r_cons_printf ("%02x", c[i]);
|
|
|
|
|
r_cons_newline ();
|
|
|
|
|
r_hash_free (ctx);
|
|
|
|
|
} else
|
|
|
|
|
if (!r_str_ccmp (input, "entropy", ' ')) {
|
2010-07-15 11:34:53 +00:00
|
|
|
|
r_cons_printf ("%lf\n", r_hash_entropy (core->block, len));
|
|
|
|
|
} else
|
2010-07-15 22:02:33 +00:00
|
|
|
|
if (!r_str_ccmp (input, "hamdist", ' ')) {
|
2010-07-15 11:34:53 +00:00
|
|
|
|
r_cons_printf ("%d\n", r_hash_hamdist (core->block, len));
|
|
|
|
|
} else
|
2010-07-15 22:02:33 +00:00
|
|
|
|
if (!r_str_ccmp (input, "pcprint", ' ')) {
|
2010-07-15 11:34:53 +00:00
|
|
|
|
r_cons_printf ("%d\n", r_hash_pcprint (core->block, len));
|
|
|
|
|
} else
|
2010-07-15 22:02:33 +00:00
|
|
|
|
if (!r_str_ccmp (input, "crc32", ' ')) {
|
2010-03-26 16:01:25 +00:00
|
|
|
|
r_cons_printf ("%04x\n", r_hash_crc32 (core->block, len));
|
2009-02-05 21:08:46 +00:00
|
|
|
|
} else
|
2010-07-15 22:02:33 +00:00
|
|
|
|
if (!r_str_ccmp (input, "xor", ' ')) {
|
2010-07-15 11:34:53 +00:00
|
|
|
|
r_cons_printf ("%02x\n", r_hash_xor (core->block, len));
|
|
|
|
|
} else
|
2010-07-15 22:02:33 +00:00
|
|
|
|
if (!r_str_ccmp (input, "crc16", ' ')) {
|
2010-03-26 16:01:25 +00:00
|
|
|
|
r_cons_printf ("%02x\n", r_hash_crc16 (0, core->block, len));
|
|
|
|
|
} else
|
|
|
|
|
if (input[0]=='?') {
|
|
|
|
|
r_cons_printf (
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Usage: #algo <size> @ addr\n"
|
2010-07-15 11:34:53 +00:00
|
|
|
|
" #xor ; calculate xor of all bytes in current block\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
" #crc32 ; calculate crc32 of current block\n"
|
|
|
|
|
" #crc32 < /etc/fstab ; calculate crc32 of this file\n"
|
2010-07-15 11:34:53 +00:00
|
|
|
|
" #pcprint ; count printable chars in current block\n"
|
|
|
|
|
" #hamdist ; calculate hamming distance in current block\n"
|
|
|
|
|
" #entropy ; calculate entropy of current block\n"
|
2010-07-15 22:02:33 +00:00
|
|
|
|
" #md4 ; calculate md4\n"
|
|
|
|
|
" #md5 128K @ edi ; calculate md5 of 128K from 'edi'\n"
|
|
|
|
|
" #sha1 ; calculate SHA-1\n"
|
|
|
|
|
" #sha256 ; calculate SHA-256\n"
|
|
|
|
|
" #sha512 ; calculate SHA-512\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Usage #!interpreter [<args>] [<file] [<<eof]\n"
|
|
|
|
|
" #! ; list all available interpreters\n"
|
|
|
|
|
" #!python ; run python commandline\n"
|
|
|
|
|
" #!python < foo.py ; run foo.py python script\n"
|
|
|
|
|
" #!python <<EOF ; get python code until 'EOF' mark\n"
|
2010-02-02 10:09:52 +00:00
|
|
|
|
" #!python arg0 a1 <<q ; set arg0 and arg1 and read until 'q'\n"
|
|
|
|
|
"Comments:\n"
|
|
|
|
|
" # this is a comment ; note the space after the sharp sign\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_visual(void *data, const char *input) {
|
2010-02-01 10:55:56 +00:00
|
|
|
|
return r_core_visual ((RCore *)data, input);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_system(void *data, const char *input) {
|
2011-02-04 10:30:08 +00:00
|
|
|
|
int ret = 0;
|
|
|
|
|
if (*input!='?') {
|
|
|
|
|
char *cmd = r_core_sysenv_begin ((RCore*)data, input);
|
|
|
|
|
if (cmd) {
|
|
|
|
|
ret = r_sys_cmd (cmd);
|
|
|
|
|
r_core_sysenv_end ((RCore*)data, input);
|
|
|
|
|
free (cmd);
|
|
|
|
|
} else eprintf ("Error setting up system environment\n");
|
|
|
|
|
} else r_core_sysenv_help ();
|
|
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_open(void *data, const char *input) {
|
2010-02-01 10:55:56 +00:00
|
|
|
|
RCore *core = (RCore*)data;
|
|
|
|
|
RCoreFile *file;
|
2011-02-12 11:54:26 +00:00
|
|
|
|
ut64 addr;
|
2011-05-12 07:52:40 +00:00
|
|
|
|
char *ptr, *path;
|
|
|
|
|
int perm, num = -1;
|
2010-02-01 10:55:56 +00:00
|
|
|
|
|
|
|
|
|
switch (*input) {
|
|
|
|
|
case '\0':
|
|
|
|
|
r_core_file_list (core);
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
|
|
|
|
ptr = strchr (input+1, ' ');
|
2011-02-16 08:29:09 +00:00
|
|
|
|
if (ptr) {
|
|
|
|
|
*ptr = '\0';
|
|
|
|
|
addr = r_num_math (core->num, ptr+1);
|
|
|
|
|
} else {
|
|
|
|
|
num = atoi (input+1);
|
|
|
|
|
addr = 0LL;
|
|
|
|
|
}
|
|
|
|
|
if (num<=0) {
|
|
|
|
|
file = r_core_file_open (core, input+1, R_IO_READ, addr);
|
|
|
|
|
if (file) {
|
|
|
|
|
//eprintf ("Map '%s' in 0x%08"PFMT64x" with size 0x%"PFMT64x"\n",
|
|
|
|
|
// input+1, addr, file->size);
|
|
|
|
|
} else eprintf ("Cannot open file '%s'\n", input+1);
|
|
|
|
|
} else r_io_raise (core->io, num);
|
2011-02-12 00:52:41 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2010-02-01 10:55:56 +00:00
|
|
|
|
break;
|
|
|
|
|
case '-':
|
2011-02-07 08:46:01 +00:00
|
|
|
|
if (!r_core_file_close_fd (core, atoi (input+1)))
|
|
|
|
|
eprintf ("Unable to find filedescriptor %d\n", atoi (input+1));
|
2011-02-12 00:52:41 +00:00
|
|
|
|
r_core_block_read (core, 0);
|
2011-02-07 08:46:01 +00:00
|
|
|
|
break;
|
2011-05-12 07:52:40 +00:00
|
|
|
|
case 'o':
|
|
|
|
|
perm = core->file->rwx;
|
|
|
|
|
addr = 0; // XXX ? check file->map ?
|
|
|
|
|
path = strdup (core->file->uri);
|
2011-05-12 18:28:44 +00:00
|
|
|
|
if (r_config_get_i (core->config, "cfg.debug"))
|
|
|
|
|
r_debug_kill (core->dbg, R_FALSE, 9); // KILL
|
2011-05-12 07:52:40 +00:00
|
|
|
|
r_core_file_close (core, core->file);
|
|
|
|
|
file = r_core_file_open (core, path, perm, addr);
|
|
|
|
|
if (file) eprintf ("File %s reopened\n", path);
|
|
|
|
|
else eprintf ("Cannot reopen '%s'\n", path);
|
|
|
|
|
// TODO: in debugger must select new PID
|
|
|
|
|
free (path);
|
|
|
|
|
break;
|
2011-02-07 08:46:01 +00:00
|
|
|
|
case '?':
|
|
|
|
|
default:
|
2011-05-12 07:52:40 +00:00
|
|
|
|
eprintf ("Usage: o[o-] [file] ([offset])\n"
|
2011-02-07 08:46:01 +00:00
|
|
|
|
" o ; list opened files\n"
|
2011-05-12 18:28:44 +00:00
|
|
|
|
" oo ; reopen current file (kill+fork in debugger)\n"
|
2011-02-07 08:46:01 +00:00
|
|
|
|
" o /bin/ls ; open /bin/ls file\n"
|
|
|
|
|
" o /bin/ls 0x8048000 ; map file\n"
|
2011-02-16 08:29:09 +00:00
|
|
|
|
" o 4 ; priorize io on fd 4 (bring to front)\n"
|
2011-02-07 08:46:01 +00:00
|
|
|
|
" o-1 ; close file index 1\n");
|
2010-02-01 10:55:56 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-20 22:48:06 +00:00
|
|
|
|
// XXX this command is broken. output of _list is not compatible with input
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_meta(void *data, const char *input) {
|
2010-07-13 09:48:26 +00:00
|
|
|
|
RAnalVarType *var;
|
2010-07-13 08:56:56 +00:00
|
|
|
|
RListIter *iter;
|
2010-02-22 23:26:13 +00:00
|
|
|
|
RCore *core = (RCore*)data;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
int i, ret, line = 0;
|
2010-06-25 16:00:17 +00:00
|
|
|
|
ut64 addr_end = 0LL;
|
2010-06-20 23:58:45 +00:00
|
|
|
|
ut64 addr = core->offset;
|
2010-02-22 19:10:52 +00:00
|
|
|
|
char file[1024];
|
2010-06-30 00:30:07 +00:00
|
|
|
|
switch (*input) {
|
2009-04-06 22:53:25 +00:00
|
|
|
|
case '*':
|
2011-03-01 23:02:50 +00:00
|
|
|
|
r_meta_list (core->anal->meta, R_META_TYPE_ANY);
|
2009-02-16 10:24:45 +00:00
|
|
|
|
break;
|
2010-07-13 08:56:56 +00:00
|
|
|
|
case 't':
|
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case '-':
|
|
|
|
|
r_anal_var_type_del (core->anal, input+2);
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
|
|
|
|
{
|
|
|
|
|
int size;
|
2010-08-22 22:48:44 +00:00
|
|
|
|
const char *fmt = NULL;
|
2010-07-13 08:56:56 +00:00
|
|
|
|
const char *ptr, *name = input+2;
|
|
|
|
|
ptr = strchr (name, ' ');
|
|
|
|
|
if (ptr) {
|
|
|
|
|
size = atoi (ptr+1);
|
|
|
|
|
ptr = strchr (ptr+2, ' ');
|
|
|
|
|
if (ptr)
|
|
|
|
|
fmt = ptr+1;
|
|
|
|
|
}
|
|
|
|
|
if (fmt==NULL)
|
|
|
|
|
eprintf ("Usage: Ct name size format\n");
|
|
|
|
|
else r_anal_var_type_add (core->anal, name, size, fmt);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '\0':
|
2010-07-13 09:48:26 +00:00
|
|
|
|
r_list_foreach (core->anal->vartypes, iter, var) {
|
2010-07-13 08:56:56 +00:00
|
|
|
|
r_cons_printf ("Ct %s %d %s\n", var->name, var->size, var->fmt);
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
eprintf ("Usage: Ct[..]\n"
|
|
|
|
|
" Ct-int : remove 'int' type\n"
|
|
|
|
|
" Ct int 4 d : define int type\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
break;
|
2011-05-25 13:43:54 +00:00
|
|
|
|
case 'l':
|
|
|
|
|
{
|
|
|
|
|
int num;
|
|
|
|
|
char *f, *p, *line, buf[4096];
|
|
|
|
|
f = strdup (input +2);
|
|
|
|
|
p = strchr (f, ':');
|
|
|
|
|
if (p) {
|
|
|
|
|
*p=0;
|
|
|
|
|
num = atoi (p+1);
|
|
|
|
|
line = r_file_slurp_line (input+2, num, 0);
|
|
|
|
|
if (!line) {
|
|
|
|
|
const char *dirsrc = r_config_get (core->config, "dir.source");
|
|
|
|
|
if (dirsrc && *dirsrc) {
|
|
|
|
|
f = r_str_concat (strdup (dirsrc), f);
|
|
|
|
|
line = r_file_slurp_line (f, num, 0);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if (!line) {
|
|
|
|
|
eprintf ("Cannot slurp file\n");
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
p = strchr (p+1, ' ');
|
|
|
|
|
if (p) {
|
|
|
|
|
snprintf (buf, sizeof (buf), "CC %s:%d %s @ %s",
|
|
|
|
|
f, num, line, p+1);
|
|
|
|
|
} else {
|
|
|
|
|
snprintf (buf, sizeof (buf), "\"CC %s:%d %s\"",
|
|
|
|
|
f, num, line);
|
|
|
|
|
}
|
|
|
|
|
r_core_cmd0 (core, buf);
|
|
|
|
|
free (line);
|
|
|
|
|
free (f);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
2009-03-27 09:47:19 +00:00
|
|
|
|
case 'L': // debug information of current offset
|
2010-05-19 22:59:42 +00:00
|
|
|
|
ret = r_bin_meta_get_line (core->bin, core->offset, file, 1023, &line);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
if (ret) {
|
|
|
|
|
r_cons_printf ("file %s\nline %d\n", file, line);
|
|
|
|
|
ret = (line<5)? 5-line: 5;
|
|
|
|
|
line -= 2;
|
|
|
|
|
for (i = 0; i<ret; i++) {
|
|
|
|
|
char *row = r_file_slurp_line (file, line+i, 0);
|
|
|
|
|
r_cons_printf ("%c %.3x %s\n", (i==2)?'>':' ', line+i, row);
|
2010-06-25 16:00:17 +00:00
|
|
|
|
free (row);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
}
|
2010-04-14 11:02:23 +00:00
|
|
|
|
} else eprintf ("Cannot find meta information at 0x%08"PFMT64x"\n", core->offset);
|
2009-03-27 00:16:27 +00:00
|
|
|
|
break;
|
2011-03-01 18:06:22 +00:00
|
|
|
|
// XXX: use R_META_TYPE_XXX here
|
|
|
|
|
case 'C': /* comment */
|
|
|
|
|
case 's': /* string */
|
2010-06-30 00:44:24 +00:00
|
|
|
|
case 'd': /* data */
|
2011-03-01 18:06:22 +00:00
|
|
|
|
case 'm': /* magic */
|
|
|
|
|
case 'f': /* formatted */
|
2010-06-30 09:59:52 +00:00
|
|
|
|
switch (input[1]) {
|
2011-07-04 22:37:17 +00:00
|
|
|
|
case '?':
|
|
|
|
|
eprintf ("See C?\n");
|
|
|
|
|
break;
|
2010-06-30 09:59:52 +00:00
|
|
|
|
case '-':
|
2011-07-04 22:37:17 +00:00
|
|
|
|
addr = core->offset;
|
2011-05-21 12:27:46 +00:00
|
|
|
|
switch (input[2]) {
|
|
|
|
|
case '*':
|
|
|
|
|
core->num->value = r_meta_del (core->anal->meta, input[0], 0, UT64_MAX, NULL);
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
2010-06-20 23:58:45 +00:00
|
|
|
|
addr = r_num_math (core->num, input+3);
|
2011-05-21 12:27:46 +00:00
|
|
|
|
default:
|
2011-07-04 22:37:17 +00:00
|
|
|
|
core->num->value = r_meta_del (core->anal->meta, input[0], addr, 1, NULL);
|
2011-05-21 12:27:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2010-06-30 09:59:52 +00:00
|
|
|
|
break;
|
|
|
|
|
case '\0':
|
|
|
|
|
case '*':
|
2011-03-01 23:02:50 +00:00
|
|
|
|
r_meta_list (core->anal->meta, input[0]);
|
2010-06-30 09:59:52 +00:00
|
|
|
|
break;
|
2011-05-21 12:27:46 +00:00
|
|
|
|
case '!':
|
|
|
|
|
{
|
|
|
|
|
char *out, *comment = r_meta_get_string (core->anal->meta, R_META_TYPE_COMMENT, addr);
|
|
|
|
|
out = r_core_editor (core, comment);
|
|
|
|
|
//r_meta_add (core->anal->meta, R_META_TYPE_COMMENT, addr, 0, out);
|
|
|
|
|
r_core_cmdf (core, "CC-@0x%08"PFMT64x, addr);
|
|
|
|
|
//r_meta_del (core->anal->meta, input[0], addr, addr+1, NULL);
|
|
|
|
|
r_meta_set_string (core->anal->meta, R_META_TYPE_COMMENT, addr, out);
|
|
|
|
|
free (out);
|
|
|
|
|
free (comment);
|
|
|
|
|
}
|
|
|
|
|
break;
|
2010-06-30 09:59:52 +00:00
|
|
|
|
default: {
|
2011-06-08 16:15:19 +00:00
|
|
|
|
char *t, *p, name[256];
|
|
|
|
|
int n = 0, type = input[0];
|
2010-06-30 09:59:52 +00:00
|
|
|
|
t = strdup (input+2);
|
2011-06-08 16:15:19 +00:00
|
|
|
|
if (atoi (t)>0) {
|
|
|
|
|
p = strchr (t, ' ');
|
|
|
|
|
if (p) {
|
|
|
|
|
*p = '\0';
|
|
|
|
|
strncpy (name, p+1, sizeof (name));
|
|
|
|
|
} else switch (type) {
|
|
|
|
|
case 's':
|
|
|
|
|
// TODO: filter \n and so on :)
|
|
|
|
|
strncpy (name, t, sizeof (name));
|
|
|
|
|
r_core_read_at (core, addr, (ut8*)name, sizeof (name));
|
|
|
|
|
break;
|
|
|
|
|
default: {
|
|
|
|
|
RFlagItem *fi = r_flag_get_i (core->flags, addr);
|
|
|
|
|
if (fi) strncpy (name, fi->name, sizeof (name));
|
|
|
|
|
else sprintf (name, "ptr_%08"PFMT64x"", addr);
|
|
|
|
|
}
|
2010-06-20 22:48:06 +00:00
|
|
|
|
}
|
2011-06-08 16:15:19 +00:00
|
|
|
|
n = atoi (input+1);
|
|
|
|
|
} else {
|
|
|
|
|
p = NULL;
|
|
|
|
|
strncpy (name, t, sizeof (name));
|
2010-06-20 22:48:06 +00:00
|
|
|
|
}
|
2011-06-08 16:15:19 +00:00
|
|
|
|
if (!n) n++;
|
2011-05-21 12:27:46 +00:00
|
|
|
|
addr_end = addr + n;
|
2011-03-01 23:02:50 +00:00
|
|
|
|
r_meta_add (core->anal->meta, type, addr, addr_end, name);
|
2011-05-21 12:27:46 +00:00
|
|
|
|
free (t);
|
2010-06-30 09:59:52 +00:00
|
|
|
|
}
|
2009-04-06 22:53:25 +00:00
|
|
|
|
}
|
2009-02-16 10:24:45 +00:00
|
|
|
|
break;
|
2011-02-23 14:17:06 +00:00
|
|
|
|
case 'v':
|
2011-02-23 14:38:23 +00:00
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case '-':
|
|
|
|
|
{
|
|
|
|
|
RAnalFcn *f;
|
2011-02-26 13:58:54 +00:00
|
|
|
|
RListIter *iter;
|
2011-02-23 14:38:23 +00:00
|
|
|
|
ut64 offset;
|
2011-02-26 13:58:54 +00:00
|
|
|
|
if (input[2]==' ') {
|
2011-02-23 14:38:23 +00:00
|
|
|
|
offset = r_num_math (core->num, input+3);
|
2011-02-26 13:58:54 +00:00
|
|
|
|
if ((f = r_anal_fcn_find (core->anal, offset, R_ANAL_FCN_TYPE_NULL)) != NULL)
|
|
|
|
|
memset (f->varsubs, 0, sizeof(f->varsubs));
|
|
|
|
|
} else if (input[2]=='*') {
|
|
|
|
|
r_list_foreach (core->anal->fcns, iter, f)
|
|
|
|
|
memset (f->varsubs, 0, sizeof(f->varsubs));
|
2011-02-23 14:38:23 +00:00
|
|
|
|
}
|
2011-02-26 13:58:54 +00:00
|
|
|
|
}
|
2011-02-23 14:38:23 +00:00
|
|
|
|
break;
|
|
|
|
|
case '*':
|
|
|
|
|
{
|
|
|
|
|
RAnalFcn *f;
|
|
|
|
|
RListIter *iter;
|
|
|
|
|
r_list_foreach (core->anal->fcns, iter, f) {
|
2011-02-26 18:16:08 +00:00
|
|
|
|
for (i = 0; i < R_ANAL_VARSUBS; i++) {
|
2011-02-26 13:58:54 +00:00
|
|
|
|
if (f->varsubs[i].pat[0] != '\0')
|
|
|
|
|
r_cons_printf ("Cv 0x%08llx %s %s\n", f->addr, f->varsubs[i].pat, f->varsubs[i].sub);
|
2011-02-23 14:38:23 +00:00
|
|
|
|
else break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
2011-02-23 14:17:06 +00:00
|
|
|
|
RAnalFcn *f;
|
2011-04-06 10:26:19 +00:00
|
|
|
|
char *ptr = strdup(input+2), *pattern = NULL, *varsub = NULL;
|
2011-02-23 14:17:06 +00:00
|
|
|
|
ut64 offset = -1LL;
|
2011-04-06 10:26:19 +00:00
|
|
|
|
int i, n = r_str_word_set0 (ptr);
|
2011-02-23 14:17:06 +00:00
|
|
|
|
if (n > 2) {
|
|
|
|
|
switch(n) {
|
2011-04-06 10:26:19 +00:00
|
|
|
|
case 3: varsub = r_str_word_get0 (ptr, 2);
|
|
|
|
|
case 2: pattern = r_str_word_get0 (ptr, 1);
|
|
|
|
|
case 1: offset = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
2011-02-23 14:17:06 +00:00
|
|
|
|
}
|
|
|
|
|
if ((f = r_anal_fcn_find (core->anal, offset, R_ANAL_FCN_TYPE_NULL)) != NULL) {
|
2011-04-06 10:26:19 +00:00
|
|
|
|
if (pattern && varsub)
|
2011-02-26 18:16:08 +00:00
|
|
|
|
for (i = 0; i < R_ANAL_VARSUBS; i++)
|
2011-02-26 13:58:54 +00:00
|
|
|
|
if (f->varsubs[i].pat[0] == '\0' || !strcmp (f->varsubs[i].pat, pattern)) {
|
|
|
|
|
strncpy (f->varsubs[i].pat, pattern, 1024);
|
|
|
|
|
strncpy (f->varsubs[i].sub, varsub, 1024);
|
2011-02-23 14:17:06 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
} else eprintf ("Error: Function not found\n");
|
|
|
|
|
}
|
|
|
|
|
free (ptr);
|
2011-02-23 14:38:23 +00:00
|
|
|
|
}
|
2011-02-23 14:17:06 +00:00
|
|
|
|
break;
|
2011-02-23 14:38:23 +00:00
|
|
|
|
}
|
2010-06-20 23:58:45 +00:00
|
|
|
|
case '-':
|
2010-06-25 16:00:17 +00:00
|
|
|
|
if (input[1]!='*') {
|
2011-07-04 22:37:17 +00:00
|
|
|
|
i = r_num_math (core->num, input+((input[1]==' ')?2:1));
|
2011-06-03 23:36:31 +00:00
|
|
|
|
r_meta_del (core->anal->meta, R_META_TYPE_ANY, core->offset, i, "");
|
2011-03-01 23:02:50 +00:00
|
|
|
|
} else r_meta_cleanup (core->anal->meta, 0LL, UT64_MAX);
|
2010-06-20 23:58:45 +00:00
|
|
|
|
break;
|
2009-04-06 22:53:25 +00:00
|
|
|
|
case '\0':
|
2009-03-27 00:16:27 +00:00
|
|
|
|
case '?':
|
2010-03-01 09:49:04 +00:00
|
|
|
|
eprintf (
|
2011-03-01 18:06:22 +00:00
|
|
|
|
"Usage: C[-LCvsdfm?] [...]\n"
|
2010-09-28 11:58:03 +00:00
|
|
|
|
" C* # List meta info in r2 commands\n"
|
2011-06-03 23:36:31 +00:00
|
|
|
|
" C- [len] [@][ addr] # delete metadata at given address range\n"
|
2010-06-27 22:43:07 +00:00
|
|
|
|
" CL[-] [addr] # show 'code line' information (bininfo)\n"
|
2011-05-25 13:43:54 +00:00
|
|
|
|
" Cl file:line [addr] # add comment with line information\n"
|
2011-05-21 12:27:46 +00:00
|
|
|
|
" CC[-] [size] [string] # add/remove comment. Use CC! to edit with $EDITOR\n"
|
2011-02-23 14:17:06 +00:00
|
|
|
|
" Cv[-] offset reg name # add var substitution\n"
|
2010-06-27 22:43:07 +00:00
|
|
|
|
" Cs[-] [size] [[addr]] # add string\n"
|
2011-03-01 18:06:22 +00:00
|
|
|
|
" Cd[-] [size] # hexdump data\n"
|
|
|
|
|
" Cf[-] [sz] [fmt..] # format memory (see pf?)\n"
|
|
|
|
|
" Cm[-] [sz] [fmt..] # magic parse (see pm?)\n");
|
2010-08-12 10:19:25 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'F':
|
|
|
|
|
{
|
2011-02-07 16:43:50 +00:00
|
|
|
|
RAnalFcn *f = r_anal_fcn_find (core->anal, core->offset,
|
|
|
|
|
R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
2011-03-01 18:06:22 +00:00
|
|
|
|
if (f) r_anal_fcn_from_string (core->anal, f, input+2);
|
|
|
|
|
else eprintf ("Cannot find function here\n");
|
2010-08-12 10:19:25 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2009-02-16 10:24:45 +00:00
|
|
|
|
}
|
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
static int cmd_macro(void *data, const char *input) {
|
2011-01-27 08:31:52 +00:00
|
|
|
|
char *buf = NULL;
|
|
|
|
|
char *p, *ptr = (char *)input;
|
2010-02-22 23:26:13 +00:00
|
|
|
|
RCore *core = (RCore*)data;
|
2011-01-27 08:31:52 +00:00
|
|
|
|
switch (*input) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case ')':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_cmd_macro_break (&core->cmd->macro, input+1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '-':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_cmd_macro_rm (&core->cmd->macro, input+1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '\0':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_cmd_macro_list (&core->cmd->macro);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case '?':
|
2010-02-22 23:26:13 +00:00
|
|
|
|
eprintf (
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Usage: (foo\\n..cmds..\\n)\n"
|
|
|
|
|
" Record macros grouping commands\n"
|
2011-01-27 08:31:52 +00:00
|
|
|
|
" (foo args\\n ..) ; define a macro\n"
|
|
|
|
|
" (-foo) ; remove a macro\n"
|
|
|
|
|
" .(foo) ; to call it\n"
|
|
|
|
|
" () ; break inside macro\n"
|
|
|
|
|
" ( ; list all defined macros\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
"Argument support:\n"
|
2011-01-27 08:31:52 +00:00
|
|
|
|
" (foo x y\\n$1 @ $2) ; define fun with args\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
" .(foo 128 0x804800) ; call it with args\n"
|
|
|
|
|
"Iterations:\n"
|
2011-01-27 08:31:52 +00:00
|
|
|
|
" .(foo\\n() $@) ; define iterator returning iter index\n"
|
2009-02-05 21:08:46 +00:00
|
|
|
|
" x @@ .(foo) ; iterate over them\n"
|
|
|
|
|
);
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2011-01-27 08:31:52 +00:00
|
|
|
|
if (input[strlen (input)-1] != ')') {
|
|
|
|
|
buf = malloc (4096); // XXX: possible heap overflow here
|
|
|
|
|
strcpy (buf, input);
|
|
|
|
|
do {
|
|
|
|
|
ptr = buf + strlen (buf);
|
|
|
|
|
strcpy (ptr, ",");
|
|
|
|
|
ptr++;
|
|
|
|
|
fgets (ptr, 1024, stdin); // XXX: possible overflow // TODO: use r_cons here
|
|
|
|
|
p = strchr (ptr, '#');
|
|
|
|
|
if (p) *p = 0;
|
|
|
|
|
else ptr[strlen (ptr)-1] = 0; // chop \n
|
|
|
|
|
if (feof (stdin))
|
|
|
|
|
break;
|
|
|
|
|
} while (ptr[strlen (ptr)-1] != ')');
|
|
|
|
|
ptr = buf;
|
2011-06-26 19:24:22 +00:00
|
|
|
|
} else {
|
|
|
|
|
buf = strdup (input);
|
|
|
|
|
buf[strlen (input)-1] = 0;
|
2011-01-27 08:31:52 +00:00
|
|
|
|
}
|
2011-06-26 19:24:22 +00:00
|
|
|
|
r_cmd_macro_add (&core->cmd->macro, buf);
|
2011-01-27 08:31:52 +00:00
|
|
|
|
free (buf);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-30 21:12:19 +00:00
|
|
|
|
static int r_core_cmd_pipe(RCore *core, char *radare_cmd, char *shell_cmd) {
|
2010-01-15 16:02:04 +00:00
|
|
|
|
#if __UNIX__
|
2009-12-31 00:27:03 +00:00
|
|
|
|
int fds[2];
|
2010-01-15 16:02:04 +00:00
|
|
|
|
int stdout_fd, status;
|
|
|
|
|
|
2010-03-01 09:49:04 +00:00
|
|
|
|
stdout_fd = dup (1);
|
|
|
|
|
pipe (fds);
|
|
|
|
|
radare_cmd = r_str_trim_head (radare_cmd);
|
|
|
|
|
shell_cmd = r_str_trim_head (shell_cmd);
|
2011-03-01 18:06:22 +00:00
|
|
|
|
if (fork ()) {
|
|
|
|
|
dup2 (fds[1], 1);
|
2010-03-01 09:49:04 +00:00
|
|
|
|
close (fds[1]);
|
|
|
|
|
close (fds[0]);
|
|
|
|
|
r_core_cmd (core, radare_cmd, 0);
|
|
|
|
|
r_cons_flush ();
|
|
|
|
|
close (1);
|
|
|
|
|
wait (&status);
|
|
|
|
|
dup2 (stdout_fd, 1);
|
|
|
|
|
close (stdout_fd);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
} else {
|
2010-03-01 09:49:04 +00:00
|
|
|
|
close (fds[1]);
|
|
|
|
|
dup2 (fds[0], 0);
|
|
|
|
|
dup2 (2, 1);
|
2011-04-03 14:38:24 +00:00
|
|
|
|
execl ("/bin/sh", "sh", "-c", shell_cmd, (char*)NULL);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
}
|
|
|
|
|
return status;
|
2010-01-15 16:02:04 +00:00
|
|
|
|
#else
|
|
|
|
|
#warning r_core_cmd_pipe UNIMPLEMENTED FOR THIS PLATFORM
|
2010-08-22 22:48:44 +00:00
|
|
|
|
eprintf ("r_core_cmd_pipe: unimplemented for this platform\n");
|
2010-01-15 16:02:04 +00:00
|
|
|
|
return -1;
|
|
|
|
|
#endif
|
2009-12-31 00:27:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-30 21:12:19 +00:00
|
|
|
|
static int r_core_cmd_subst(RCore *core, char *cmd) {
|
2009-04-15 18:24:19 +00:00
|
|
|
|
char *ptr, *ptr2, *str;
|
2011-03-01 18:06:22 +00:00
|
|
|
|
int i, len = strlen (cmd), pipefd, ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
|
2009-12-31 00:27:03 +00:00
|
|
|
|
if (!*cmd || cmd[0]=='\0')
|
2009-02-05 21:28:33 +00:00
|
|
|
|
return 0;
|
2010-02-22 23:26:13 +00:00
|
|
|
|
cmd = r_str_trim_head_tail (cmd);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
|
2010-08-17 11:15:18 +00:00
|
|
|
|
/* quoted / raw command */
|
2011-06-26 19:24:22 +00:00
|
|
|
|
switch (*cmd) {
|
|
|
|
|
case '.':
|
|
|
|
|
if (cmd[1] == '"') { /* interpret */
|
|
|
|
|
ret = r_cmd_call (core->cmd, cmd);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '"':
|
2009-12-31 00:27:03 +00:00
|
|
|
|
if (cmd[len-1] != '"') {
|
2010-02-22 23:26:13 +00:00
|
|
|
|
eprintf ("parse: Missing ending '\"'\n");
|
2009-12-31 00:27:03 +00:00
|
|
|
|
return -1;
|
|
|
|
|
}
|
2010-02-22 23:26:13 +00:00
|
|
|
|
cmd[len-1]='\0';
|
2011-06-26 19:24:22 +00:00
|
|
|
|
return r_cmd_call (core->cmd, cmd+1);
|
|
|
|
|
case '(':
|
|
|
|
|
return r_cmd_call (core->cmd, cmd);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-08-16 11:59:48 +00:00
|
|
|
|
/* comments */
|
2010-08-24 02:09:12 +00:00
|
|
|
|
if (*cmd!='#') {
|
|
|
|
|
ptr = strrchr (cmd, '#');
|
|
|
|
|
if (ptr) ptr[0]='\0';
|
|
|
|
|
}
|
2010-08-16 11:59:48 +00:00
|
|
|
|
|
2009-12-31 00:27:03 +00:00
|
|
|
|
/* multiple commands */
|
2010-02-22 23:26:13 +00:00
|
|
|
|
ptr = strrchr (cmd, ';');
|
2009-12-31 00:27:03 +00:00
|
|
|
|
if (ptr) {
|
2009-02-05 21:08:46 +00:00
|
|
|
|
ptr[0]='\0';
|
2010-02-22 23:26:13 +00:00
|
|
|
|
if (r_core_cmd_subst (core, cmd) == -1)
|
2009-12-31 00:27:03 +00:00
|
|
|
|
return -1;
|
|
|
|
|
cmd = ptr+1;
|
2011-05-21 13:45:43 +00:00
|
|
|
|
//r_cons_flush ();
|
2009-12-31 00:27:03 +00:00
|
|
|
|
}
|
2009-02-18 00:43:57 +00:00
|
|
|
|
|
2009-12-31 00:27:03 +00:00
|
|
|
|
/* pipe console to shell process */
|
2010-02-22 23:26:13 +00:00
|
|
|
|
ptr = strchr (cmd, '|');
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (ptr) {
|
|
|
|
|
ptr[0] = '\0';
|
2010-08-23 17:13:19 +00:00
|
|
|
|
cmd = r_str_clean (cmd);
|
|
|
|
|
if (*cmd) r_core_cmd_pipe (core, cmd, ptr+1);
|
|
|
|
|
else r_io_system (core->io, ptr+1);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* bool conditions */
|
2011-06-26 21:49:11 +00:00
|
|
|
|
ptr = strchr (cmd, '&');
|
|
|
|
|
while (ptr && ptr[1]=='&') {
|
|
|
|
|
*ptr = '\0';
|
2010-05-19 22:59:42 +00:00
|
|
|
|
ret = r_cmd_call (core->cmd, cmd);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
if (ret == -1){
|
2010-02-22 23:26:13 +00:00
|
|
|
|
eprintf ("command error(%s)\n", cmd);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
return ret;
|
|
|
|
|
}
|
2010-02-22 23:26:13 +00:00
|
|
|
|
for (cmd=ptr+2;cmd&&cmd[0]==' ';cmd=cmd+1);
|
|
|
|
|
ptr = strchr (cmd, '&');
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Out Of Band Input */
|
2010-02-22 23:26:13 +00:00
|
|
|
|
free (core->oobi);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
core->oobi = NULL;
|
2010-02-22 23:26:13 +00:00
|
|
|
|
ptr = strchr (cmd, '<');
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (ptr) {
|
|
|
|
|
ptr[0] = '\0';
|
|
|
|
|
if (ptr[1]=='<') {
|
|
|
|
|
/* this is a bit mess */
|
2010-02-28 21:58:21 +00:00
|
|
|
|
const char *oprompt = r_line_singleton ()->prompt;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
oprompt = ">";
|
2010-02-28 21:58:21 +00:00
|
|
|
|
for (str=ptr+2; str[0]==' '; str=str+1);
|
|
|
|
|
eprintf ("==> Reading from stdin until '%s'\n", str);
|
|
|
|
|
free (core->oobi);
|
|
|
|
|
core->oobi = malloc (1);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
core->oobi[0] = '\0';
|
|
|
|
|
core->oobi_len = 0;
|
|
|
|
|
for (;;) {
|
|
|
|
|
char buf[1024];
|
|
|
|
|
int ret;
|
2011-03-01 18:06:22 +00:00
|
|
|
|
write (1, "> ", 2);
|
2010-08-10 10:34:10 +00:00
|
|
|
|
fgets (buf, sizeof (buf)-1, stdin); // XXX use r_line ??
|
2010-03-01 09:49:04 +00:00
|
|
|
|
if (feof (stdin))
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2010-03-01 09:49:04 +00:00
|
|
|
|
buf[strlen (buf)-1]='\0';
|
|
|
|
|
ret = strlen (buf);
|
2011-03-06 14:21:13 +00:00
|
|
|
|
core->oobi_len += ret;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
core->oobi = realloc (core->oobi, core->oobi_len+1);
|
|
|
|
|
if (!strcmp (buf, str))
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
strcat ((char *)core->oobi, buf);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
2010-02-18 15:36:55 +00:00
|
|
|
|
r_line_singleton ()->prompt = oprompt;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
} else {
|
2010-02-05 11:21:37 +00:00
|
|
|
|
for (str=ptr+1;str[0]== ' ';str=str+1);
|
|
|
|
|
eprintf ("SLURPING FILE '%s'\n", str);
|
|
|
|
|
core->oobi = (ut8*)r_file_slurp (str, &core->oobi_len);
|
2009-03-14 11:39:37 +00:00
|
|
|
|
if (core->oobi == NULL)
|
2010-02-05 11:21:37 +00:00
|
|
|
|
eprintf ("Cannot open file\n");
|
2009-03-14 11:39:37 +00:00
|
|
|
|
else if (ptr == cmd)
|
2010-02-05 11:21:37 +00:00
|
|
|
|
return r_core_cmd_buffer (core, (const char *)core->oobi);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2009-12-31 00:27:03 +00:00
|
|
|
|
|
|
|
|
|
/* pipe console to file */
|
2010-02-28 21:58:21 +00:00
|
|
|
|
ptr = strchr (cmd, '>');
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (ptr) {
|
2011-06-26 21:49:11 +00:00
|
|
|
|
*ptr = '\0';
|
2010-02-28 21:58:21 +00:00
|
|
|
|
str = r_str_trim_head_tail (ptr+1+(ptr[1]=='>'));
|
|
|
|
|
pipefd = r_cons_pipe_open (str, ptr[1]=='>');
|
|
|
|
|
ret = r_core_cmd_subst (core, cmd);
|
|
|
|
|
r_cons_flush ();
|
|
|
|
|
r_cons_pipe_close (pipefd);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
2009-03-21 22:59:35 +00:00
|
|
|
|
|
2009-12-31 00:27:03 +00:00
|
|
|
|
/* sub commands */
|
2010-02-05 11:21:37 +00:00
|
|
|
|
ptr = strchr (cmd, '`');
|
2009-12-31 00:27:03 +00:00
|
|
|
|
if (ptr) {
|
2010-02-05 11:21:37 +00:00
|
|
|
|
ptr2 = strchr (ptr+1, '`');
|
2009-12-31 00:27:03 +00:00
|
|
|
|
if (!ptr2) {
|
2010-02-05 11:21:37 +00:00
|
|
|
|
eprintf ("parse: Missing '´' in expression.\n");
|
2009-12-31 00:27:03 +00:00
|
|
|
|
return -1;
|
|
|
|
|
} else {
|
2011-06-26 21:49:11 +00:00
|
|
|
|
*ptr = '\0';
|
|
|
|
|
*ptr2 = '\0';
|
2010-02-05 11:21:37 +00:00
|
|
|
|
str = r_core_cmd_str (core, ptr+1);
|
2011-06-26 21:49:11 +00:00
|
|
|
|
for (i=0; str[i]; i++)
|
|
|
|
|
if (str[i]=='\n')
|
|
|
|
|
str[i]=' ';
|
2010-02-05 11:21:37 +00:00
|
|
|
|
cmd = r_str_concat (strdup (cmd), r_str_concat (str, ptr2+1));
|
|
|
|
|
ret = r_core_cmd_subst (core, cmd);
|
|
|
|
|
free (cmd);
|
|
|
|
|
free (str);
|
2009-12-31 00:27:03 +00:00
|
|
|
|
return ret;
|
2009-03-21 22:59:35 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-12-31 00:27:03 +00:00
|
|
|
|
/* grep the content */
|
2010-02-05 11:21:37 +00:00
|
|
|
|
ptr = strchr (cmd, '~');
|
2009-03-21 22:59:35 +00:00
|
|
|
|
if (ptr) {
|
2011-06-26 21:49:11 +00:00
|
|
|
|
*ptr = '\0';
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_cons_grep (ptr+1);
|
|
|
|
|
} else r_cons_grep (NULL);
|
2009-03-21 22:59:35 +00:00
|
|
|
|
|
2009-12-31 00:27:03 +00:00
|
|
|
|
/* seek commands */
|
2011-06-26 21:49:11 +00:00
|
|
|
|
if (*cmd!='(' && *cmd!='"')
|
2011-01-26 22:40:16 +00:00
|
|
|
|
ptr = strchr (cmd, '@');
|
|
|
|
|
else ptr = NULL;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (ptr) {
|
2010-08-10 10:34:10 +00:00
|
|
|
|
ut64 tmpoff, tmpbsz;
|
|
|
|
|
char *ptr2 = strchr (ptr+1, ':');
|
|
|
|
|
*ptr = '\0';
|
2010-08-16 11:59:48 +00:00
|
|
|
|
cmd = r_str_clean (cmd);
|
2010-08-10 10:34:10 +00:00
|
|
|
|
tmpoff = core->offset;
|
|
|
|
|
tmpbsz = core->blocksize;
|
|
|
|
|
if (ptr2) {
|
|
|
|
|
*ptr2 = '\0';
|
|
|
|
|
r_core_block_size (core, r_num_math (core->num, ptr2+1));
|
|
|
|
|
}
|
|
|
|
|
|
2009-02-05 21:08:46 +00:00
|
|
|
|
if (ptr[1]=='@') {
|
2009-03-21 02:17:43 +00:00
|
|
|
|
// TODO: remove temporally seek (should be done by cmd_foreach)
|
2010-03-05 12:18:44 +00:00
|
|
|
|
ret = r_core_cmd_foreach (core, cmd, ptr+2);
|
|
|
|
|
//ret = -1; /* do not run out-of-foreach cmd */
|
2009-12-31 00:27:03 +00:00
|
|
|
|
} else {
|
2011-05-21 13:45:43 +00:00
|
|
|
|
if (!ptr[1] || r_core_seek (core, r_num_math (core->num, ptr+1), 1)) {
|
|
|
|
|
r_core_block_read (core, 0);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
ret = r_cmd_call (core->cmd, r_str_trim_head (cmd));
|
2011-05-21 13:45:43 +00:00
|
|
|
|
} else ret = 0;
|
2009-12-31 00:27:03 +00:00
|
|
|
|
}
|
2010-08-10 10:34:10 +00:00
|
|
|
|
if (ptr2) {
|
|
|
|
|
*ptr2 = ':';
|
|
|
|
|
r_core_block_size (core, tmpbsz);
|
|
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_core_seek (core, tmpoff, 1);
|
2010-08-10 10:34:10 +00:00
|
|
|
|
*ptr = '@';
|
2009-12-31 00:27:03 +00:00
|
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
2009-03-20 21:05:12 +00:00
|
|
|
|
|
2010-05-19 22:59:42 +00:00
|
|
|
|
ret = r_cmd_call (core->cmd, r_str_trim_head (cmd));
|
2010-03-07 23:18:58 +00:00
|
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
R_API int r_core_cmd_foreach(RCore *core, const char *cmd, char *each) {
|
2009-03-20 21:05:12 +00:00
|
|
|
|
int i=0,j;
|
|
|
|
|
char ch;
|
|
|
|
|
char *word = NULL;
|
2009-03-21 22:59:35 +00:00
|
|
|
|
char *str, *ostr;
|
2010-12-23 23:51:01 +00:00
|
|
|
|
RListIter *iter;
|
|
|
|
|
RFlagItem *flag;
|
2009-07-08 11:49:55 +00:00
|
|
|
|
ut64 oseek, addr;
|
2009-03-20 21:05:12 +00:00
|
|
|
|
|
2010-02-28 21:58:21 +00:00
|
|
|
|
for (; *each==' '; each++);
|
|
|
|
|
for (; *cmd==' '; cmd++);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
|
2010-01-12 01:12:18 +00:00
|
|
|
|
oseek = core->offset;
|
2009-03-21 22:59:35 +00:00
|
|
|
|
ostr = str = strdup(each);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
//radare_controlc();
|
|
|
|
|
|
2010-02-28 21:58:21 +00:00
|
|
|
|
switch (each[0]) {
|
2009-03-20 21:05:12 +00:00
|
|
|
|
case '?':
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Foreach '@@' iterator command:\n"
|
|
|
|
|
" This command is used to repeat a command over a list of offsets.\n"
|
|
|
|
|
" x @@ sym. Run 'x' over all flags matching 'sym.'\n"
|
|
|
|
|
" x @@.file \"\" over the offsets specified in the file (one offset per line)\n"
|
|
|
|
|
" x @@=off1 off2 .. Manual list of offsets\n"
|
|
|
|
|
" x @@=`pdf~call[0]` Run 'x' at every call offset of the current function\n");
|
2009-03-20 21:05:12 +00:00
|
|
|
|
break;
|
|
|
|
|
case '=':
|
|
|
|
|
/* foreach list of items */
|
2009-03-21 22:59:35 +00:00
|
|
|
|
each = str+1;
|
2009-03-20 21:05:12 +00:00
|
|
|
|
do {
|
2010-02-05 11:21:37 +00:00
|
|
|
|
while (each[0]==' ')
|
|
|
|
|
each = each+1;
|
2009-03-21 22:59:35 +00:00
|
|
|
|
if (!*each) break;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
str = strchr (each, ' ');
|
2009-03-21 02:17:43 +00:00
|
|
|
|
if (str) {
|
2009-03-20 21:05:12 +00:00
|
|
|
|
str[0]='\0';
|
2010-05-19 22:59:42 +00:00
|
|
|
|
addr = r_num_math (core->num, each);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
str[0]=' ';
|
2010-05-19 22:59:42 +00:00
|
|
|
|
} else addr = r_num_math (core->num, each);
|
2010-04-14 11:02:23 +00:00
|
|
|
|
eprintf ("; 0x%08"PFMT64x":\n", addr);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
each = str+1;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_core_seek (core, addr, 1);
|
|
|
|
|
r_core_cmd (core, cmd, 0);
|
|
|
|
|
r_cons_flush ();
|
|
|
|
|
} while (str != NULL);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
break;
|
|
|
|
|
case '.':
|
|
|
|
|
if (each[1]=='(') {
|
|
|
|
|
char cmd2[1024];
|
|
|
|
|
// TODO: use controlc() here
|
2010-02-05 11:21:37 +00:00
|
|
|
|
// XXX whats this 999 ?
|
2010-05-19 22:59:42 +00:00
|
|
|
|
for(core->cmd->macro.counter=0;i<999;core->cmd->macro.counter++) {
|
|
|
|
|
r_cmd_macro_call (&core->cmd->macro, each+2);
|
|
|
|
|
if (core->cmd->macro.brk_value == NULL)
|
2009-03-20 21:05:12 +00:00
|
|
|
|
break;
|
|
|
|
|
|
2010-05-19 22:59:42 +00:00
|
|
|
|
addr = core->cmd->macro._brk_value;
|
2010-04-14 11:02:23 +00:00
|
|
|
|
sprintf (cmd2, "%s @ 0x%08"PFMT64x"", cmd, addr);
|
|
|
|
|
eprintf ("0x%08"PFMT64x" (%s)\n", addr, cmd2);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_core_seek (core, addr, 1);
|
|
|
|
|
r_core_cmd (core, cmd2, 0);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
char buf[1024];
|
|
|
|
|
char cmd2[1024];
|
2010-02-05 11:21:37 +00:00
|
|
|
|
FILE *fd = fopen (each+1, "r");
|
2009-09-24 10:29:05 +00:00
|
|
|
|
if (fd) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
core->cmd->macro.counter=0;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
while (!feof (fd)) {
|
|
|
|
|
buf[0] = '\0';
|
|
|
|
|
if (fgets (buf, 1024, fd) == NULL)
|
|
|
|
|
break;
|
2010-05-19 22:59:42 +00:00
|
|
|
|
addr = r_num_math (core->num, buf);
|
2010-04-14 11:02:23 +00:00
|
|
|
|
eprintf ("0x%08"PFMT64x": %s\n", addr, cmd);
|
|
|
|
|
sprintf (cmd2, "%s @ 0x%08"PFMT64x"", cmd, addr);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_core_seek (core, addr, 1); // XXX
|
|
|
|
|
r_core_cmd (core, cmd2, 0);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
core->cmd->macro.counter++;
|
2009-03-20 21:05:12 +00:00
|
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
|
fclose (fd);
|
|
|
|
|
} else eprintf ("Cannot open file '%s' to read offsets\n", each+1);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-05-19 22:59:42 +00:00
|
|
|
|
core->cmd->macro.counter = 0;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
//while(str[i]) && !core->interrupted) {
|
2011-06-07 15:53:15 +00:00
|
|
|
|
// split by keywords
|
2010-02-05 11:21:37 +00:00
|
|
|
|
while (str[i]) {
|
2009-03-20 21:05:12 +00:00
|
|
|
|
j = i;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
for (;str[j]&&str[j]==' ';j++); // skip spaces
|
|
|
|
|
for (i=j;str[i]&&str[i]!=' ';i++); // find EOS
|
2009-03-20 21:05:12 +00:00
|
|
|
|
ch = str[i];
|
|
|
|
|
str[i] = '\0';
|
2010-02-05 11:21:37 +00:00
|
|
|
|
word = strdup (str+j);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
if (word == NULL)
|
|
|
|
|
break;
|
|
|
|
|
str[i] = ch;
|
2011-06-07 15:53:15 +00:00
|
|
|
|
{
|
2009-03-20 21:05:12 +00:00
|
|
|
|
/* for all flags in current flagspace */
|
2011-06-07 15:53:15 +00:00
|
|
|
|
// XXX: dont ask why, but this only works with _prev..
|
|
|
|
|
r_list_foreach_prev (core->flags->flags, iter, flag) {
|
2010-02-18 15:36:55 +00:00
|
|
|
|
if (r_cons_singleton()->breaked)
|
2009-03-21 02:17:43 +00:00
|
|
|
|
break;
|
2009-03-20 21:05:12 +00:00
|
|
|
|
/* filter per flag spaces */
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if ((core->flags->space_idx != -1) && (flag->space != core->flags->space_idx))
|
2009-03-20 21:05:12 +00:00
|
|
|
|
continue;
|
2011-06-07 15:53:15 +00:00
|
|
|
|
if (r_str_glob (flag->name, word)) {
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_core_seek (core, flag->offset, 1);
|
2010-04-14 11:02:23 +00:00
|
|
|
|
//r_cons_printf ("# @@ 0x%08"PFMT64x" (%s)\n", core->offset, flag->name);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_core_cmd (core, cmd, 0);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
#if 0
|
|
|
|
|
/* ugly copypasta from tmpseek .. */
|
|
|
|
|
if (strstr(word, each)) {
|
|
|
|
|
if (word[i]=='+'||word[i]=='-')
|
2010-05-19 22:59:42 +00:00
|
|
|
|
core->offset = core->offset + r_num_math (get_math(core->num, word);
|
|
|
|
|
else core->offset = r_num_math (get_math(core->num, word);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
radare_read(0);
|
2010-04-14 11:02:23 +00:00
|
|
|
|
cons_printf("; @@ 0x%08"PFMT64x"\n", core->offset);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
radare_cmd(cmd,0);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_cons_break (NULL, NULL);
|
2009-03-20 21:05:12 +00:00
|
|
|
|
|
2010-05-19 22:59:42 +00:00
|
|
|
|
core->cmd->macro.counter++ ;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
free (word);
|
|
|
|
|
word = NULL;
|
2009-03-20 21:05:12 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
|
r_cons_break_end ();
|
2009-03-21 02:17:43 +00:00
|
|
|
|
// XXX: use r_core_seek here
|
2010-01-12 01:12:18 +00:00
|
|
|
|
core->offset = oseek;
|
2009-03-20 21:05:12 +00:00
|
|
|
|
|
2010-02-05 11:21:37 +00:00
|
|
|
|
free (word);
|
|
|
|
|
free (ostr);
|
2009-04-02 10:23:32 +00:00
|
|
|
|
return R_TRUE;
|
2009-03-20 21:05:12 +00:00
|
|
|
|
}
|
|
|
|
|
|
2011-04-06 09:35:18 +00:00
|
|
|
|
R_API int r_core_cmd(RCore *core, const char *cstr, int log) {
|
2011-06-04 01:14:04 +00:00
|
|
|
|
int rep, ret = R_FALSE;
|
2010-01-21 01:38:52 +00:00
|
|
|
|
char *cmd, *ocmd;
|
2011-06-28 22:36:52 +00:00
|
|
|
|
if (cstr==NULL)
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
if (!*cstr)
|
2011-06-04 01:14:04 +00:00
|
|
|
|
return R_FALSE;
|
|
|
|
|
/* list cstr plugins */
|
|
|
|
|
if (!strcmp (cstr, ":")) {
|
|
|
|
|
RListIter *iter = r_list_iterator (core->cmd->plist);
|
|
|
|
|
while (r_list_iter_next (iter)) {
|
|
|
|
|
RCmdPlugin *cp = (RCmdPlugin*) r_list_iter_get (iter);
|
|
|
|
|
r_cons_printf ("%s: %s\n", cp->name, cp->desc);
|
2010-06-03 09:53:42 +00:00
|
|
|
|
}
|
2011-06-04 01:14:04 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
ocmd = cmd = malloc (strlen (cstr)+8192);
|
|
|
|
|
if (ocmd == NULL)
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
r_str_cpy (cmd, cstr);
|
|
|
|
|
cmd = r_str_trim_head_tail (cmd);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
|
2011-06-04 01:14:04 +00:00
|
|
|
|
rep = atoi (cmd);
|
|
|
|
|
if (rep<1) rep = 1;
|
|
|
|
|
if (rep>0) {
|
|
|
|
|
ret = R_TRUE;
|
|
|
|
|
while (*cmd>='0'&&*cmd<='9')
|
|
|
|
|
cmd++;
|
|
|
|
|
while (rep--) {
|
|
|
|
|
ret = r_core_cmd_subst (core, cmd);
|
|
|
|
|
if (ret<0)
|
|
|
|
|
break;
|
2010-01-21 01:38:52 +00:00
|
|
|
|
}
|
2010-02-05 11:21:37 +00:00
|
|
|
|
}
|
2011-06-04 01:14:04 +00:00
|
|
|
|
if (log) r_line_hist_add (cstr);
|
|
|
|
|
|
|
|
|
|
free (ocmd);
|
|
|
|
|
free (core->oobi);
|
|
|
|
|
core->oobi = NULL;
|
|
|
|
|
core->oobi_len = 0;
|
2009-09-24 10:29:05 +00:00
|
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-30 21:12:19 +00:00
|
|
|
|
R_API int r_core_cmd_file(RCore *core, const char *file) {
|
2010-03-30 22:03:59 +00:00
|
|
|
|
int ret = R_TRUE;
|
|
|
|
|
char *data, *odata = r_file_slurp (file, NULL);
|
|
|
|
|
if (odata != NULL) {
|
|
|
|
|
char *nl = strchr (odata, '\n');
|
|
|
|
|
if (nl) {
|
|
|
|
|
data = odata;
|
|
|
|
|
do {
|
|
|
|
|
*nl = '\0';
|
|
|
|
|
if (r_core_cmd (core, data, 0) == -1) {
|
|
|
|
|
eprintf ("r_core_cmd_file: Failed to run '%s'\n", data);
|
|
|
|
|
ret = R_FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2011-06-05 23:07:27 +00:00
|
|
|
|
r_cons_flush ();
|
2010-03-30 22:03:59 +00:00
|
|
|
|
data = nl+1;
|
|
|
|
|
} while ((nl = strchr (data, '\n')));
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
2010-03-30 22:03:59 +00:00
|
|
|
|
free (odata);
|
|
|
|
|
} else ret = R_FALSE;
|
|
|
|
|
return ret;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-03-30 21:12:19 +00:00
|
|
|
|
R_API int r_core_cmd_command(RCore *core, const char *command) {
|
2009-12-30 10:03:18 +00:00
|
|
|
|
int len;
|
2010-02-15 21:59:26 +00:00
|
|
|
|
char *buf, *rcmd, *ptr;
|
|
|
|
|
rcmd = ptr = buf = r_sys_cmd_str (command, 0, &len);
|
2009-12-30 10:03:18 +00:00
|
|
|
|
if (buf == NULL)
|
|
|
|
|
return -1;
|
2010-01-21 01:38:52 +00:00
|
|
|
|
while ((ptr = strstr (rcmd, "\n"))) {
|
2009-12-30 10:03:18 +00:00
|
|
|
|
*ptr = '\0';
|
2010-01-21 01:38:52 +00:00
|
|
|
|
if (r_core_cmd (core, rcmd, 0) == -1) {
|
|
|
|
|
eprintf ("Error running command '%s'\n", rcmd);
|
2010-02-15 21:59:26 +00:00
|
|
|
|
break;
|
2009-12-30 10:03:18 +00:00
|
|
|
|
}
|
2010-01-21 01:38:52 +00:00
|
|
|
|
rcmd += strlen (rcmd)+1;
|
2009-12-30 10:03:18 +00:00
|
|
|
|
}
|
|
|
|
|
r_str_free(buf);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-05 11:21:37 +00:00
|
|
|
|
static void cmd_dm(RCore *core, const char *input) {
|
|
|
|
|
switch (input[0]) {
|
|
|
|
|
case '?':
|
|
|
|
|
r_cons_printf (
|
|
|
|
|
"Usage: dm [size]\n"
|
|
|
|
|
" dm List memory maps of target process\n"
|
|
|
|
|
" dm* Same as above but in radare commands\n"
|
|
|
|
|
" dm 4096 Allocate 4096 bytes in child process\n"
|
|
|
|
|
" dm-0x8048 Deallocate memory map of address 0x8048\n"
|
2010-08-17 11:15:18 +00:00
|
|
|
|
" dmi [addr|libname] [symname] List symbols of target lib\n"
|
|
|
|
|
" dmi* [addr|libname] [symname] Same as above but in radare commands\n"
|
2010-03-05 00:49:12 +00:00
|
|
|
|
//" dm rw- esp 9K set 9KB of the stack as read+write (no exec)\n"
|
2010-02-05 11:21:37 +00:00
|
|
|
|
"TODO: map files in process memory.\n");
|
|
|
|
|
break;
|
2010-08-16 12:35:15 +00:00
|
|
|
|
case 'i':
|
|
|
|
|
{ // Move to a separate function
|
|
|
|
|
ut64 addr = 0LL;
|
2010-08-17 11:15:18 +00:00
|
|
|
|
char *libname = NULL, *symname = NULL;
|
|
|
|
|
char *ptr = strdup (r_str_trim_head ((char*)input+2));
|
2010-08-16 14:07:45 +00:00
|
|
|
|
char cmd[1024], *cmdret;
|
2010-08-17 11:15:18 +00:00
|
|
|
|
int i, len;
|
|
|
|
|
|
|
|
|
|
i = r_str_word_set0 (ptr);
|
|
|
|
|
switch (i) {
|
|
|
|
|
case 2: // get symname
|
|
|
|
|
symname = r_str_word_get0 (ptr, 1);
|
|
|
|
|
case 1: // get addr|libname
|
|
|
|
|
addr = r_num_math (core->num, r_str_word_get0 (ptr, 0));
|
|
|
|
|
if (!addr) libname = r_str_word_get0 (ptr, 0);
|
|
|
|
|
}
|
2010-08-16 12:35:15 +00:00
|
|
|
|
r_debug_map_sync (core->dbg); // update process memory maps
|
|
|
|
|
RListIter *iter = r_list_iterator (core->dbg->maps);
|
|
|
|
|
while (r_list_iter_next (iter)) {
|
|
|
|
|
RDebugMap *map = r_list_iter_get (iter);
|
|
|
|
|
if ((addr != -1 && (addr >= map->addr && addr < map->addr_end)) ||
|
|
|
|
|
(libname != NULL && (strstr (map->name, libname)))) {
|
2010-08-17 11:15:18 +00:00
|
|
|
|
if (symname)
|
|
|
|
|
snprintf (cmd, sizeof (cmd), "rabin2 -b 0x%08"PFMT64x" -s%svn %s %s",
|
|
|
|
|
map->addr, input[1]=='*'?"r":"", symname, map->name);
|
|
|
|
|
else
|
|
|
|
|
snprintf (cmd, sizeof (cmd), "rabin2 -b 0x%08"PFMT64x" -s%sv %s",
|
|
|
|
|
map->addr, input[1]=='*'?"r":"", map->name);
|
2010-08-16 14:07:45 +00:00
|
|
|
|
if ((cmdret = r_sys_cmd_str (cmd, 0, &len))) {
|
|
|
|
|
r_cons_printf (cmdret);
|
|
|
|
|
free (cmdret);
|
|
|
|
|
}
|
2010-08-16 12:35:15 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
2010-08-17 11:15:18 +00:00
|
|
|
|
free (ptr);
|
2010-08-16 12:35:15 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2010-02-05 11:21:37 +00:00
|
|
|
|
case '*':
|
|
|
|
|
case '-':
|
|
|
|
|
case ' ':
|
|
|
|
|
eprintf ("TODO\n");
|
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_map_sync (core->dbg); // update process memory maps
|
|
|
|
|
r_debug_map_list (core->dbg, core->offset);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-23 11:30:04 +00:00
|
|
|
|
static int step_until(RCore *core, ut64 addr) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
ut64 off = r_debug_reg_get (core->dbg, "pc");
|
2010-03-23 11:30:04 +00:00
|
|
|
|
if (off == 0LL) {
|
|
|
|
|
eprintf ("Cannot 'drn pc'\n");
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (addr == 0LL) {
|
|
|
|
|
eprintf ("Cannot continue until address 0\n");
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
do {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_step (core->dbg, 1);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
if (checkbpcallback (core)) {
|
|
|
|
|
eprintf ("Interrupted by a breakpoint\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-05-19 22:59:42 +00:00
|
|
|
|
off = r_debug_reg_get (core->dbg, "pc");
|
2010-03-23 11:30:04 +00:00
|
|
|
|
// check breakpoint here
|
|
|
|
|
} while (off != addr);
|
|
|
|
|
return R_TRUE;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-28 21:58:21 +00:00
|
|
|
|
static int step_line(RCore *core, int times) {
|
|
|
|
|
char file[512], file2[512];
|
|
|
|
|
int find_meta, line, line2;
|
2010-06-27 19:33:11 +00:00
|
|
|
|
ut64 off = r_debug_reg_get (core->dbg, "pc");
|
2010-02-28 21:58:21 +00:00
|
|
|
|
if (off == 0LL) {
|
|
|
|
|
eprintf ("Cannot 'drn pc'\n");
|
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
2010-05-19 22:59:42 +00:00
|
|
|
|
if (r_bin_meta_get_line (core->bin, off, file, sizeof (file), &line)) {
|
2010-04-14 11:02:23 +00:00
|
|
|
|
eprintf ("--> 0x%08"PFMT64x" %s : %d\n", off, file, line);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
eprintf ("--> %s\n", r_file_slurp_line (file, line, 0));
|
|
|
|
|
find_meta = R_FALSE;
|
|
|
|
|
} else {
|
|
|
|
|
eprintf ("--> Stepping until dwarf line\n");
|
|
|
|
|
find_meta = R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
do {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_step (core->dbg, 1);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
if (checkbpcallback (core)) {
|
|
|
|
|
eprintf ("Interrupted by a breakpoint\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-05-19 22:59:42 +00:00
|
|
|
|
off = r_debug_reg_get (core->dbg, "pc");
|
|
|
|
|
if (!r_bin_meta_get_line (core->bin, off, file2, sizeof (file2), &line2)) {
|
2010-02-28 21:58:21 +00:00
|
|
|
|
if (find_meta)
|
|
|
|
|
continue;
|
2010-04-14 11:02:23 +00:00
|
|
|
|
eprintf ("Cannot retrieve dwarf info at 0x%08"PFMT64x"\n", off);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
return R_FALSE;
|
|
|
|
|
}
|
|
|
|
|
} while (!strcmp (file, file2) && line == line2);
|
2010-04-14 11:02:23 +00:00
|
|
|
|
eprintf ("--> 0x%08"PFMT64x" %s : %d\n", off, file2, line2);
|
2010-02-28 21:58:21 +00:00
|
|
|
|
eprintf ("--> %s\n", r_file_slurp_line (file2, line2, 0));
|
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-03-12 17:46:11 +00:00
|
|
|
|
static void cmd_debug_pid(RCore *core, const char *input) {
|
|
|
|
|
const char *ptr;
|
|
|
|
|
int pid, sig;
|
2010-06-27 19:33:11 +00:00
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case 'k':
|
2010-03-12 17:46:11 +00:00
|
|
|
|
/* XXX: not for threads? signal is for a whole process!! */
|
|
|
|
|
/* XXX: but we want fine-grained access to process resources */
|
|
|
|
|
pid = atoi (input+2);
|
|
|
|
|
ptr = strchr (input, ' ');
|
|
|
|
|
if (ptr) sig = atoi (ptr+1);
|
|
|
|
|
else sig = 0;
|
|
|
|
|
if (pid > 0) {
|
|
|
|
|
eprintf ("Sending signal '%d' to pid '%d'\n",
|
|
|
|
|
sig, pid);
|
2010-11-16 23:56:48 +00:00
|
|
|
|
r_debug_kill (core->dbg, R_FALSE, sig);
|
2010-03-12 17:46:11 +00:00
|
|
|
|
} else eprintf ("Invalid arguments\n");
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
2010-11-18 10:41:17 +00:00
|
|
|
|
case 'n':
|
|
|
|
|
eprintf ("TODO: debug_fork: %d\n", r_debug_fork (core->dbg));
|
|
|
|
|
break;
|
2010-06-27 19:33:11 +00:00
|
|
|
|
case 't':
|
2010-11-18 10:41:17 +00:00
|
|
|
|
if (input[2] == 'n') {
|
|
|
|
|
eprintf ("TODO: debug_clone: %d\n", r_debug_clone (core->dbg));
|
|
|
|
|
} else
|
2010-03-12 17:46:11 +00:00
|
|
|
|
if (input[2]=='=' || input[2]==' ')
|
2010-11-16 23:56:48 +00:00
|
|
|
|
r_debug_select (core->dbg, core->dbg->pid,
|
2010-05-19 22:59:42 +00:00
|
|
|
|
(int) r_num_math (core->num, input+3));
|
|
|
|
|
else r_debug_thread_list (core->dbg, core->dbg->pid);
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
|
|
|
|
case '?':
|
2010-03-12 17:46:11 +00:00
|
|
|
|
r_cons_printf ("Usage: dp[=][pid]\n"
|
|
|
|
|
" dp list current pid and childrens\n"
|
|
|
|
|
" dp 748 list childs of pid\n"
|
|
|
|
|
" dp* list all attachable pids\n"
|
|
|
|
|
" dpa 377 attach and select this pid\n"
|
|
|
|
|
" dp=748 select this pid\n"
|
2010-11-18 10:41:17 +00:00
|
|
|
|
" dpn Create new process (fork)\n"
|
|
|
|
|
" dpnt Create new thread (clone)\n"
|
2010-03-12 17:46:11 +00:00
|
|
|
|
" dpt List threads of current pid\n"
|
|
|
|
|
" dpt 74 List threads of given process\n"
|
|
|
|
|
" dpt=64 Attach to thread\n"
|
|
|
|
|
" dpk P S send signal S to P process id\n");
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'a':
|
2011-03-24 10:03:23 +00:00
|
|
|
|
r_debug_use (core->dbg, NULL);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_attach (core->dbg,
|
|
|
|
|
(int) r_num_math (core->num, input+2));
|
2010-11-17 01:31:56 +00:00
|
|
|
|
r_debug_select (core->dbg, core->dbg->pid, core->dbg->tid);
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'f':
|
2011-01-20 22:28:20 +00:00
|
|
|
|
r_debug_select (core->dbg, core->file->fd->fd, core->dbg->tid);
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
|
|
|
|
case '=':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_select (core->dbg,
|
2010-11-16 23:56:48 +00:00
|
|
|
|
(int) r_num_math (core->num, input+2), core->dbg->tid);
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
|
|
|
|
case '*':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_pid_list (core->dbg, 0);
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_pid_list (core->dbg,
|
|
|
|
|
(int) r_num_math (core->num, input+2));
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2011-05-20 18:42:25 +00:00
|
|
|
|
eprintf ("selected: %d %d\n", core->dbg->pid, core->dbg->tid);
|
2010-06-27 19:33:11 +00:00
|
|
|
|
r_debug_pid_list (core->dbg, core->dbg->pid);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-03-12 17:46:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-09-25 02:04:51 +00:00
|
|
|
|
static int cmd_debug(void *data, const char *input) {
|
2010-02-28 21:58:21 +00:00
|
|
|
|
RCore *core = (RCore *)data;
|
2011-02-24 13:06:49 +00:00
|
|
|
|
struct r_anal_op_t analop;
|
2011-06-28 22:54:49 +00:00
|
|
|
|
int len, times, sig, follow=0;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
ut64 addr;
|
2009-04-01 22:44:43 +00:00
|
|
|
|
char *ptr;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
|
2010-01-19 10:25:17 +00:00
|
|
|
|
switch (input[0]) {
|
2010-09-23 18:42:35 +00:00
|
|
|
|
case 'x': // XXX : only for testing
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_execute (core->dbg, (ut8*)
|
2010-02-15 21:59:26 +00:00
|
|
|
|
"\xc7\xc0\x03\x00\x00\x00\x33\xdb\x33"
|
|
|
|
|
"\xcc\xc7\xc2\x10\x00\x00\x00\xcd\x80", 18);
|
2010-02-05 11:21:37 +00:00
|
|
|
|
break;
|
2010-03-12 17:46:11 +00:00
|
|
|
|
case 't':
|
|
|
|
|
// TODO: Add support to change the tag
|
2010-06-03 22:56:44 +00:00
|
|
|
|
if (input[1]=='r') {
|
|
|
|
|
r_debug_trace_free (core->dbg);
|
|
|
|
|
core->dbg->trace = r_debug_trace_new ();
|
|
|
|
|
} else r_debug_trace_list (core->dbg, -1);
|
2010-03-01 09:49:04 +00:00
|
|
|
|
break;
|
2010-03-07 23:18:58 +00:00
|
|
|
|
case 'd':
|
|
|
|
|
eprintf ("TODO: dd: file descriptors\n");
|
2010-06-18 09:09:19 +00:00
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case 0:
|
|
|
|
|
// r_debug_desc_list()
|
|
|
|
|
break;
|
|
|
|
|
case '*':
|
|
|
|
|
// r_debug_desc_list(1)
|
|
|
|
|
break;
|
|
|
|
|
case 's':
|
|
|
|
|
// r_debug_desc_seek()
|
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
// r_debug_desc_dup()
|
|
|
|
|
break;
|
|
|
|
|
case 'r':
|
|
|
|
|
// r_debug_desc_read()
|
|
|
|
|
break;
|
|
|
|
|
case 'w':
|
|
|
|
|
// r_debug_desc_write()
|
|
|
|
|
break;
|
|
|
|
|
case '-':
|
|
|
|
|
// close file
|
|
|
|
|
break;
|
|
|
|
|
case ' ':
|
|
|
|
|
// open file
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-03-07 23:18:58 +00:00
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case 's':
|
2010-02-28 21:58:21 +00:00
|
|
|
|
times = atoi (input+2);
|
|
|
|
|
if (times<1) times = 1;
|
2010-06-27 19:33:11 +00:00
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case '?':
|
2010-03-07 23:18:58 +00:00
|
|
|
|
r_cons_printf ("Usage: ds[ol] [count]\n"
|
2010-03-23 11:30:04 +00:00
|
|
|
|
" ds step one instruction\n"
|
|
|
|
|
" ds 4 step 4 instructions\n"
|
|
|
|
|
" dso 3 step over 3 instructions\n"
|
|
|
|
|
" dsu addr step until address\n"
|
|
|
|
|
" dsl step one source line\n"
|
|
|
|
|
" dsl 40 step 40 source lines\n");
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'u':
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
step_until (core, r_num_math (core->num, input+2)); // XXX dupped by times
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'o':
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_step_over (core->dbg, times);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
if (checkbpcallback (core)) {
|
|
|
|
|
eprintf ("Interrupted by a breakpoint\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'l':
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
2010-03-23 11:30:04 +00:00
|
|
|
|
step_line (core, times);
|
2010-06-27 19:33:11 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
|
|
|
|
r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE);
|
2010-06-27 19:33:11 +00:00
|
|
|
|
r_debug_step (core->dbg, times);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
if (checkbpcallback (core)) {
|
|
|
|
|
eprintf ("Interrupted by a breakpoint\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-06-27 19:33:11 +00:00
|
|
|
|
}
|
2011-06-28 22:54:49 +00:00
|
|
|
|
follow = r_config_get_i (core->config, "dbg.follow");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'b':
|
2010-01-19 10:25:17 +00:00
|
|
|
|
r_core_cmd_bp (core, input);
|
2009-04-12 22:46:44 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'H':
|
2010-02-28 21:58:21 +00:00
|
|
|
|
eprintf ("TODO: transplant process\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'c':
|
2010-01-19 10:25:17 +00:00
|
|
|
|
switch (input[1]) {
|
|
|
|
|
case '?':
|
|
|
|
|
eprintf("Usage: dc[?] -- continue execution\n"
|
2010-03-03 10:35:03 +00:00
|
|
|
|
" dc? show this help\n"
|
|
|
|
|
" dc continue execution of all childs\n"
|
2010-06-27 19:33:11 +00:00
|
|
|
|
" dcf continue until fork (TODO)\n"
|
2010-03-03 12:34:38 +00:00
|
|
|
|
" dct [len] traptrace from curseek to len, no argument to list\n"
|
2010-03-03 10:35:03 +00:00
|
|
|
|
" dcu [addr] continue until address\n"
|
2011-05-12 18:28:44 +00:00
|
|
|
|
" dcu [addr] [end] continue until given address range\n"
|
2010-03-07 23:18:58 +00:00
|
|
|
|
" dco [num] step over N instructions\n"
|
2010-03-03 10:35:03 +00:00
|
|
|
|
" dcs [num] continue until syscall\n"
|
2010-05-24 15:51:51 +00:00
|
|
|
|
" dcc continue until call (use step into)\n"
|
|
|
|
|
" dcr continue until ret (uses step over)\n"
|
2010-03-03 10:35:03 +00:00
|
|
|
|
" dck [sig] [pid] continue sending kill 9 to process\n"
|
|
|
|
|
" dc [pid] continue execution of pid\n"
|
|
|
|
|
" dc[-pid] stop execution of pid\n"
|
2010-05-24 15:51:51 +00:00
|
|
|
|
"TODO: dcu/dcr needs dbg.untilover=true??\n"
|
|
|
|
|
"TODO: same for only user/libs side, to avoid steping into libs\n"
|
2010-01-19 10:25:17 +00:00
|
|
|
|
"TODO: support for threads?\n");
|
|
|
|
|
break;
|
2010-05-24 10:07:54 +00:00
|
|
|
|
case 'c':
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
2010-05-24 15:51:51 +00:00
|
|
|
|
r_debug_continue_until_optype (core->dbg, R_ANAL_OP_TYPE_CALL, 0);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
checkbpcallback (core);
|
2010-05-24 10:07:54 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'r':
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
2010-05-24 15:51:51 +00:00
|
|
|
|
r_debug_continue_until_optype (core->dbg, R_ANAL_OP_TYPE_RET, 1);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
checkbpcallback (core);
|
2010-05-24 10:07:54 +00:00
|
|
|
|
break;
|
2010-01-19 10:25:17 +00:00
|
|
|
|
case 'k':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
// select pid and r_debug_continue_kill (core->dbg,
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
ptr = strchr (input+3, ' ');
|
|
|
|
|
if (ptr) {
|
2010-10-28 19:20:44 +00:00
|
|
|
|
bypassbp (core);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
int old_pid = core->dbg->pid;
|
2010-11-17 01:31:56 +00:00
|
|
|
|
int old_tid = core->dbg->tid;
|
2010-01-19 10:25:17 +00:00
|
|
|
|
int pid = atoi (ptr+1);
|
2010-11-17 01:31:56 +00:00
|
|
|
|
int tid = pid; // XXX
|
2010-01-19 10:25:17 +00:00
|
|
|
|
*ptr = 0;
|
2010-11-17 01:31:56 +00:00
|
|
|
|
r_debug_select (core->dbg, pid, tid);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_continue_kill (core->dbg, atoi (input+2));
|
2010-11-17 01:31:56 +00:00
|
|
|
|
r_debug_select (core->dbg, old_pid, old_tid);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
} else r_debug_continue_kill (core->dbg, atoi (input+2));
|
2010-07-12 23:20:57 +00:00
|
|
|
|
checkbpcallback (core);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
2010-03-02 10:18:49 +00:00
|
|
|
|
case 's':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
sig = r_num_math (core->num, input+2);
|
2010-03-02 10:18:49 +00:00
|
|
|
|
eprintf ("Continue until syscall %d\n", sig);
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_continue_syscall (core->dbg, sig);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
checkbpcallback (core);
|
2010-03-02 10:18:49 +00:00
|
|
|
|
/* TODO : use r_syscall here, to retrieve syscall info */
|
|
|
|
|
break;
|
2010-02-28 21:58:21 +00:00
|
|
|
|
case 'u':
|
2011-05-12 18:28:44 +00:00
|
|
|
|
ptr = strchr (input+3, ' ');
|
2011-05-13 08:22:28 +00:00
|
|
|
|
if (ptr) { // TODO: put '\0' in *ptr to avoid
|
|
|
|
|
ut64 from, to, pc;
|
|
|
|
|
from = r_num_math (core->num, input+3);
|
|
|
|
|
to = r_num_math (core->num, ptr+1);
|
|
|
|
|
do {
|
|
|
|
|
r_debug_step (core->dbg, 1);
|
|
|
|
|
r_debug_reg_sync (core->dbg, R_REG_TYPE_GPR, R_FALSE);
|
|
|
|
|
pc = r_debug_reg_get (core->dbg, "pc");
|
|
|
|
|
eprintf ("Continue 0x%08"PFMT64x" > 0x%08"PFMT64x" < 0x%08"PFMT64x"\n",
|
|
|
|
|
from, pc, to);
|
|
|
|
|
} while (pc < from || pc > to);
|
2011-05-12 18:28:44 +00:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
2010-05-19 22:59:42 +00:00
|
|
|
|
addr = r_num_math (core->num, input+2);
|
2010-03-19 03:02:23 +00:00
|
|
|
|
if (addr) {
|
2010-04-14 11:02:23 +00:00
|
|
|
|
eprintf ("Continue until 0x%08"PFMT64x"\n", addr);
|
2010-10-28 19:20:44 +00:00
|
|
|
|
bypassbp (core);
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_bp_add_sw (core->dbg->bp, addr, 1, R_BP_PROT_EXEC);
|
|
|
|
|
r_debug_continue (core->dbg);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
checkbpcallback (core);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_bp_del (core->dbg->bp, addr);
|
2010-03-19 03:02:23 +00:00
|
|
|
|
} else eprintf ("Cannot continue until address 0\n");
|
2010-02-28 21:58:21 +00:00
|
|
|
|
break;
|
2010-01-19 10:25:17 +00:00
|
|
|
|
case ' ':
|
2010-09-23 18:42:35 +00:00
|
|
|
|
{
|
2010-05-19 22:59:42 +00:00
|
|
|
|
int old_pid = core->dbg->pid;
|
2010-01-19 10:25:17 +00:00
|
|
|
|
int pid = atoi (input+2);
|
2010-10-28 19:20:44 +00:00
|
|
|
|
bypassbp (core);
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
2010-11-17 01:31:56 +00:00
|
|
|
|
r_debug_select (core->dbg, pid, core->dbg->tid);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_continue (core->dbg);
|
2010-11-17 01:31:56 +00:00
|
|
|
|
r_debug_select (core->dbg, old_pid, core->dbg->tid);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
checkbpcallback (core);
|
2010-09-23 18:42:35 +00:00
|
|
|
|
}
|
2010-01-19 10:25:17 +00:00
|
|
|
|
break;
|
2010-03-03 10:35:03 +00:00
|
|
|
|
case 't':
|
2010-05-19 22:59:42 +00:00
|
|
|
|
len = r_num_math (core->num, input+2);
|
2010-03-03 12:34:38 +00:00
|
|
|
|
if (len == 0) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_bp_traptrace_list (core->dbg->bp);
|
2010-03-03 10:35:03 +00:00
|
|
|
|
} else {
|
2010-06-13 10:51:44 +00:00
|
|
|
|
ut64 oaddr = 0LL;
|
2010-04-14 11:02:23 +00:00
|
|
|
|
eprintf ("Trap tracing 0x%08"PFMT64x"-0x%08"PFMT64x"\n", core->offset, core->offset+len);
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_bp_traptrace_reset (core->dbg->bp, R_TRUE);
|
|
|
|
|
r_bp_traptrace_add (core->dbg->bp, core->offset, core->offset+len);
|
|
|
|
|
r_bp_traptrace_enable (core->dbg->bp, R_TRUE);
|
2010-03-03 10:35:03 +00:00
|
|
|
|
do {
|
|
|
|
|
ut8 buf[32];
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_continue (core->dbg);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
if (checkbpcallback (core)) {
|
|
|
|
|
eprintf ("Interrupted by breakpoint\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-05-19 22:59:42 +00:00
|
|
|
|
addr = r_debug_reg_get (core->dbg, "pc");
|
2010-03-03 10:35:03 +00:00
|
|
|
|
if (addr == 0LL) {
|
|
|
|
|
eprintf ("pc=0\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
2010-06-13 10:51:44 +00:00
|
|
|
|
if (addr == oaddr) {
|
|
|
|
|
eprintf ("pc=opc\n");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
oaddr = addr;
|
2010-03-03 10:35:03 +00:00
|
|
|
|
/* XXX Bottleneck..we need to reuse the bytes read by traptrace */
|
|
|
|
|
// XXX Do asm.arch should define the max size of opcode?
|
|
|
|
|
r_core_read_at (core, addr, buf, 32); // XXX longer opcodes?
|
2011-02-24 13:06:49 +00:00
|
|
|
|
r_anal_op (core->anal, &analop, addr, buf, sizeof (buf));
|
2010-05-19 22:59:42 +00:00
|
|
|
|
} while (r_bp_traptrace_at (core->dbg->bp, addr, analop.length));
|
|
|
|
|
r_bp_traptrace_enable (core->dbg->bp, R_FALSE);
|
2010-03-03 10:35:03 +00:00
|
|
|
|
}
|
|
|
|
|
break;
|
2010-01-19 10:25:17 +00:00
|
|
|
|
default:
|
2010-10-28 18:47:21 +00:00
|
|
|
|
bypassbp (core);
|
2010-09-23 18:42:35 +00:00
|
|
|
|
r_reg_arena_swap (core->dbg->reg, R_TRUE);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_continue (core->dbg);
|
2010-07-12 23:20:57 +00:00
|
|
|
|
checkbpcallback (core);
|
2010-01-19 10:25:17 +00:00
|
|
|
|
}
|
2011-06-28 22:54:49 +00:00
|
|
|
|
follow = r_config_get_i (core->config, "dbg.follow");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
2009-03-22 02:36:00 +00:00
|
|
|
|
case 'm':
|
2010-02-05 11:21:37 +00:00
|
|
|
|
cmd_dm (core, input+1);
|
2009-03-22 02:36:00 +00:00
|
|
|
|
break;
|
2009-02-05 21:08:46 +00:00
|
|
|
|
case 'r':
|
2010-02-05 11:21:37 +00:00
|
|
|
|
cmd_reg (core, input+1);
|
2010-03-19 03:02:23 +00:00
|
|
|
|
//r_core_cmd (core, "|reg", 0);
|
2009-02-18 00:43:57 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'p':
|
2010-03-12 17:46:11 +00:00
|
|
|
|
cmd_debug_pid (core, input);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
case 'h':
|
2009-09-24 10:29:05 +00:00
|
|
|
|
if (input[1]==' ')
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_debug_use (core->dbg, input+2);
|
2010-05-26 16:25:35 +00:00
|
|
|
|
else r_debug_plugin_list (core->dbg);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
default:
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_cons_printf ("Usage: d[sbhcrbo] [arg]\n"
|
2010-02-03 17:15:31 +00:00
|
|
|
|
" dh [handler] list or set debugger handler\n"
|
|
|
|
|
" dH [handler] transplant process to a new handler\n"
|
2010-06-18 09:09:19 +00:00
|
|
|
|
" dd file descriptors (!fd in r1)\n"
|
2010-03-07 23:18:58 +00:00
|
|
|
|
" ds[ol] N step, over, source line\n"
|
2010-03-12 17:46:11 +00:00
|
|
|
|
" dp[=*?t][pid] list, attach to process or thread id\n"
|
2010-02-28 21:58:21 +00:00
|
|
|
|
" dc[?] continue execution. dc? for more\n"
|
2010-02-03 17:15:31 +00:00
|
|
|
|
" dr[?] cpu registers, dr? for extended help\n"
|
|
|
|
|
" db[?] breakpoints\n"
|
2010-03-12 17:46:11 +00:00
|
|
|
|
" dbt display backtrace\n"
|
|
|
|
|
" dt[r] [tag] display instruction traces (dtr=reset)\n"
|
2010-03-05 00:49:12 +00:00
|
|
|
|
" dm show memory maps\n");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
break;
|
|
|
|
|
}
|
2011-06-28 22:54:49 +00:00
|
|
|
|
if (follow>0) {
|
|
|
|
|
ut64 pc = r_debug_reg_get (core->dbg, "pc");
|
|
|
|
|
if ((pc<core->offset) || (pc > (core->offset+follow)))
|
|
|
|
|
r_core_cmd0 (core, "sr pc");
|
|
|
|
|
}
|
2009-02-05 21:08:46 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-09 17:13:10 +00:00
|
|
|
|
//TODO: Fix disasm loop is mandatory
|
2010-10-09 11:54:08 +00:00
|
|
|
|
R_API char *r_core_disassemble_instr(RCore *core, ut64 addr, int l) {
|
|
|
|
|
char *cmd, *ret = NULL;
|
|
|
|
|
cmd = r_str_dup_printf ("pd %i @ 0x%08"PFMT64x, l, addr);
|
|
|
|
|
if (cmd) {
|
|
|
|
|
ret = r_core_cmd_str (core, cmd);
|
|
|
|
|
free (cmd);
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
R_API char *r_core_disassemble_bytes(RCore *core, ut64 addr, int b) {
|
|
|
|
|
char *cmd, *ret = NULL;
|
|
|
|
|
cmd = r_str_dup_printf ("pD %i @ 0x%08"PFMT64x, b, addr);
|
|
|
|
|
if (cmd) {
|
|
|
|
|
ret = r_core_cmd_str (core, cmd);
|
|
|
|
|
free (cmd);
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
R_API int r_core_cmd_buffer(void *user, const char *buf) {
|
2010-06-20 22:48:06 +00:00
|
|
|
|
char *ptr, *optr, *str = strdup (buf);
|
|
|
|
|
optr = str;
|
|
|
|
|
ptr = strchr (str, '\n');
|
2010-02-28 21:58:21 +00:00
|
|
|
|
while (ptr) {
|
2009-03-14 11:39:37 +00:00
|
|
|
|
ptr[0]='\0';
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_core_cmd (user, optr, 0);
|
2009-03-14 11:39:37 +00:00
|
|
|
|
optr = ptr+1;
|
2010-06-20 22:48:06 +00:00
|
|
|
|
ptr = strchr (str, '\n');
|
2009-03-14 11:39:37 +00:00
|
|
|
|
}
|
2010-02-28 21:58:21 +00:00
|
|
|
|
r_core_cmd (user, optr, 0);
|
|
|
|
|
free (str);
|
2009-03-14 11:39:37 +00:00
|
|
|
|
return R_TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
R_API int r_core_cmdf(void *user, const char *fmt, ...) {
|
2009-02-18 00:43:57 +00:00
|
|
|
|
char string[1024];
|
|
|
|
|
int ret;
|
|
|
|
|
va_list ap;
|
2010-02-01 10:55:56 +00:00
|
|
|
|
va_start (ap, fmt);
|
2010-06-20 22:48:06 +00:00
|
|
|
|
vsnprintf (string, sizeof (string), fmt, ap);
|
2010-03-30 21:12:19 +00:00
|
|
|
|
ret = r_core_cmd ((RCore *)user, string, 0);
|
2009-02-18 00:43:57 +00:00
|
|
|
|
va_end(ap);
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2010-02-22 23:26:13 +00:00
|
|
|
|
R_API int r_core_cmd0(void *user, const char *cmd) {
|
2010-03-30 21:12:19 +00:00
|
|
|
|
return r_core_cmd ((RCore *)user, cmd, 0);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
|
2010-06-20 22:48:06 +00:00
|
|
|
|
/* return: pointer to a buffer with the output of the command */
|
2010-03-30 21:12:19 +00:00
|
|
|
|
R_API char *r_core_cmd_str(RCore *core, const char *cmd) {
|
2009-09-20 00:16:14 +00:00
|
|
|
|
char *retstr = NULL;
|
2010-02-01 10:55:56 +00:00
|
|
|
|
r_cons_reset ();
|
|
|
|
|
if (r_core_cmd (core, cmd, 0) == -1) {
|
|
|
|
|
eprintf ("Invalid command: %s\n", cmd);
|
|
|
|
|
retstr = strdup ("");
|
2009-02-05 21:08:46 +00:00
|
|
|
|
} else {
|
2010-08-16 23:27:24 +00:00
|
|
|
|
r_cons_filter ();
|
|
|
|
|
const char *static_str = r_cons_get_buffer ();
|
2010-08-12 10:19:25 +00:00
|
|
|
|
retstr = strdup (static_str?static_str:"");
|
2010-08-16 23:27:24 +00:00
|
|
|
|
r_cons_reset ();
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|
|
|
|
|
return retstr;
|
|
|
|
|
}
|
|
|
|
|
|
2010-06-20 22:48:06 +00:00
|
|
|
|
void r_core_cmd_init(RCore *core) {
|
2010-05-19 22:59:42 +00:00
|
|
|
|
core->cmd = r_cmd_new ();
|
|
|
|
|
core->cmd->macro.num = core->num;
|
|
|
|
|
core->cmd->macro.user = core;
|
|
|
|
|
core->cmd->macro.cmd = r_core_cmd0;
|
|
|
|
|
r_cmd_set_data (core->cmd, core);
|
|
|
|
|
r_cmd_add (core->cmd, "x", "alias for px", &cmd_hexdump);
|
2011-01-11 23:01:06 +00:00
|
|
|
|
r_cmd_add (core->cmd, "mount", "mount filesystem", &cmd_mount);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_cmd_add (core->cmd, "analysis", "analysis", &cmd_anal);
|
|
|
|
|
r_cmd_add (core->cmd, "flag", "get/set flags", &cmd_flag);
|
|
|
|
|
r_cmd_add (core->cmd, "debug", "debugger operations", &cmd_debug);
|
|
|
|
|
r_cmd_add (core->cmd, "info", "get file info", &cmd_info);
|
|
|
|
|
r_cmd_add (core->cmd, "cmp", "compare memory", &cmd_cmp);
|
|
|
|
|
r_cmd_add (core->cmd, "seek", "seek to an offset", &cmd_seek);
|
|
|
|
|
r_cmd_add (core->cmd, "zign", "zignatures", &cmd_zign);
|
|
|
|
|
r_cmd_add (core->cmd, "Section", "setup section io information", &cmd_section);
|
|
|
|
|
r_cmd_add (core->cmd, "bsize", "change block size", &cmd_bsize);
|
|
|
|
|
r_cmd_add (core->cmd, "eval", "evaluate configuration variable", &cmd_eval);
|
|
|
|
|
r_cmd_add (core->cmd, "print", "print current block", &cmd_print);
|
|
|
|
|
r_cmd_add (core->cmd, "write", "write bytes", &cmd_write);
|
|
|
|
|
r_cmd_add (core->cmd, "Code", "code metadata", &cmd_meta);
|
2010-05-24 16:51:01 +00:00
|
|
|
|
r_cmd_add (core->cmd, "Project", "project", &cmd_project);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_cmd_add (core->cmd, "open", "open or map file", &cmd_open);
|
|
|
|
|
r_cmd_add (core->cmd, "yank", "yank bytes", &cmd_yank);
|
2011-02-05 11:51:37 +00:00
|
|
|
|
r_cmd_add (core->cmd, "resize", "change file size", &cmd_resize);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_cmd_add (core->cmd, "Visual", "enter visual mode", &cmd_visual);
|
|
|
|
|
r_cmd_add (core->cmd, "!", "run system command", &cmd_system);
|
2010-08-23 04:39:23 +00:00
|
|
|
|
r_cmd_add (core->cmd, "=", "io pipe", &cmd_rap);
|
2010-05-19 22:59:42 +00:00
|
|
|
|
r_cmd_add (core->cmd, "#", "calculate hash", &cmd_hash);
|
|
|
|
|
r_cmd_add (core->cmd, "?", "help message", &cmd_help);
|
|
|
|
|
r_cmd_add (core->cmd, ".", "interpret", &cmd_interpret);
|
|
|
|
|
r_cmd_add (core->cmd, "/", "search kw, pattern aes", &cmd_search);
|
|
|
|
|
r_cmd_add (core->cmd, "(", "macro", &cmd_macro);
|
|
|
|
|
r_cmd_add (core->cmd, "quit", "exit program session", &cmd_quit);
|
2009-02-05 21:08:46 +00:00
|
|
|
|
}
|