Better 'wc' command and cache/history capabilities

This commit is contained in:
pancake 2014-10-07 02:52:47 +02:00
parent 2642b03076
commit 67acee60f9
5 changed files with 104 additions and 41 deletions

View File

@ -330,7 +330,7 @@ static int cmd_write(void *data, const char *input) {
case 'c':
switch (input[1]) {
case 'i':
r_io_cache_commit (core->io);
r_io_cache_commit (core->io, 0, UT64_MAX);
r_core_block_read (core, 0);
break;
case 'r':
@ -341,6 +341,31 @@ static int cmd_write(void *data, const char *input) {
memset (core->block, 0xff, core->blocksize);
r_core_block_read (core, 0);
break;
case '+':
if (input[2]=='*') {
//r_io_cache_reset (core->io, R_TRUE);
eprintf ("TODO\n");
} 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_commit (core->io, from, to);
} else {
eprintf ("Invalidate write cache at 0x%08"PFMT64x"\n", core->offset);
r_io_cache_commit (core->io, core->offset, core->offset+1);
}
break;
case '-':
if (input[2]=='*') {
r_io_cache_reset (core->io, R_TRUE);
@ -371,9 +396,10 @@ static int cmd_write(void *data, const char *input) {
case '?':
{
const char* help_msg[] = {
"Usage:", "wc[ir*?]"," # Note: requires io.cache=true",
"Usage:", "wc[ir+-*?]"," # NOTE: Uses io.cache=true",
"wc","","list all write changes",
"wc-"," [a] [b]","remove write op at curseek or given addr",
"wc-"," [from] [to]","remove write op at curseek or given addr",
"wc+"," [addr]","commit change from cache to io",
"wc*","","\"\" in radare commands",
"wcr","","reset all write changes in cache",
"wci","","commit write cache",
@ -386,8 +412,8 @@ static int cmd_write(void *data, const char *input) {
r_io_cache_list (core->io, R_TRUE);
break;
case '\0':
if (!r_config_get_i (core->config, "io.cache"))
eprintf ("[warning] e io.cache must be true\n");
//if (!r_config_get_i (core->config, "io.cache"))
// eprintf ("[warning] e io.cache must be true\n");
r_io_cache_list (core->io, R_FALSE);
break;
}

View File

@ -12,20 +12,12 @@ R_API void r_core_hack_help(RCore *core) {
"NOTE: those operations are only implemented for x86 atm. (TODO)\n");
}
// TODO: needs refactoring to make it cross-architecture
R_API int r_core_hack(RCore *core, const char *op) {
R_API int r_core_hack_x86(RCore *core, const char *op, RAnalOp *analop) {
ut8 *b = core->block;
RAnalOp analop;
if (strstr (r_config_get (core->config, "asm.arch"), "x86"))
eprintf ("TODO: write hacks are only for x86\n");
if (!r_anal_op (core->anal, &analop, core->offset, core->block, core->blocksize)) {
eprintf ("anal op fail\n");
return R_FALSE;
}
if (!strcmp (op, "nop")) {
int nopsize = 1; // XXX x86 only
const char *nopcode = "90"; // XXX x86 only
int len = analop.size;
int nopsize = 1;
const char *nopcode = "90";
int len = analop->size;
if (len%nopsize) {
eprintf ("Invalid nopcode size\n");
return R_FALSE;
@ -66,3 +58,15 @@ R_API int r_core_hack(RCore *core, const char *op) {
} else eprintf ("Invalid operation\n");
return R_FALSE;
}
// TODO: needs refactoring to make it cross-architecture
R_API int r_core_hack(RCore *core, const char *op) {
RAnalOp analop;
if (!strstr (r_config_get (core->config, "asm.arch"), "x86"))
eprintf ("TODO: write hacks are only for x86\n");
if (!r_anal_op (core->anal, &analop, core->offset, core->block, core->blocksize)) {
eprintf ("anal op fail\n");
return R_FALSE;
}
return r_core_hack_x86 (core, op, &analop);
}

View File

@ -225,6 +225,8 @@ typedef struct r_io_cache_t {
ut64 to;
int size;
ut8 *data;
ut8 *odata;
int written;
} RIOCache;
typedef struct r_io_range_t {
@ -322,7 +324,7 @@ R_API void r_io_sort_maps (RIO *io);
/* io/cache.c */
R_API int r_io_cache_invalidate(RIO *io, ut64 from, ut64 to);
R_API void r_io_cache_commit(RIO *io);
R_API void r_io_cache_commit(RIO *io, ut64 from, ut64 to);
R_API void r_io_cache_enable(RIO *io, int read, int write);
R_API void r_io_cache_init(RIO *io);
R_API int r_io_cache_list(RIO *io, int rad);

View File

@ -8,8 +8,8 @@
static void cache_item_free(RIOCache *cache) {
if (!cache)
return;
if (cache->data)
free (cache->data);
free (cache->data);
free (cache->odata);
free (cache);
}
@ -25,19 +25,21 @@ R_API void r_io_cache_enable(RIO *io, int read, int write) {
io->cached_read = read;
}
R_API void r_io_cache_commit(RIO *io) {
R_API void r_io_cache_commit(RIO *io, ut64 from, ut64 to) {
RListIter *iter;
RIOCache *c;
if (io->cached) {
io->cached = R_FALSE;
r_list_foreach (io->cache, iter, c) {
int ioc = io->cached;
io->cached = 2;
r_list_foreach (io->cache, iter, c) {
if (c->from >= from && c->to <= to) {
if (!r_io_write_at (io, c->from, c->data, c->size))
eprintf ("Error writing change at 0x%08"PFMT64x"\n", c->from);
else c->written = R_TRUE;
break;
}
io->cached = R_TRUE;
r_io_cache_reset (io, io->cached);
}
io->cached = ioc;
}
R_API void r_io_cache_reset(RIO *io, int set) {
@ -48,15 +50,25 @@ R_API void r_io_cache_reset(RIO *io, int set) {
R_API int r_io_cache_invalidate(RIO *io, ut64 from, ut64 to) {
RListIter *iter, *iter_tmp;
RIOCache *c;
int done = R_FALSE;
if (from>=to) return R_FALSE;
r_list_foreach_safe (io->cache, iter, iter_tmp, c) {
if (c->from >= from && c->to <= to) {
r_list_delete (io->cache, iter);
if (from<to) {
//r_list_foreach_safe (io->cache, iter, iter_tmp, c) {
r_list_foreach (io->cache, iter, c) {
if (c->from >= from && c->to <= to) {
int ioc = io->cached;
io->cached = 2; // magic number to skip caching this write
r_io_write_at (io, c->from, c->odata, c->size);
io->cached = ioc;
if (!c->written)
r_list_delete (io->cache, iter);
c->written = R_FALSE;
done = R_TRUE;
break;
}
}
}
return R_FALSE;
return done;
}
R_API int r_io_cache_list(RIO *io, int rad) {
@ -69,13 +81,20 @@ R_API int r_io_cache_list(RIO *io, int rad) {
io->printf ("wx ");
for (i=0; i<c->size; i++)
io->printf ("%02x", c->data[i]);
io->printf (" @ 0x%08"PFMT64x"\n", c->from);
io->printf (" @ 0x%08"PFMT64x, c->from);
io->printf (" # replaces: ");
for (i=0; i<c->size; i++)
io->printf ("%02x", c->odata[i]);
io->printf ("\n");
} else {
io->printf ("idx=%d addr=0x%08"PFMT64x" size=%d ",
j, c->from, c->size);
for (i=0; i<c->size; i++)
io->printf ("%02x", c->odata[i]);
io->printf (" -> ");
for (i=0; i<c->size; i++)
io->printf ("%02x", c->data[i]);
io->printf ("\n");
io->printf (" %s\n", c->written?"(written)":"(not written)");
}
j++;
}
@ -83,11 +102,17 @@ R_API int r_io_cache_list(RIO *io, int rad) {
}
R_API int r_io_cache_write(RIO *io, ut64 addr, const ut8 *buf, int len) {
RIOCache *ch = R_NEW (RIOCache);
RIOCache *ch;
if (io->cached == 2) // magic hackaround
return 0;
ch = R_NEW (RIOCache);
ch->from = addr;
ch->to = addr + len;
ch->size = len;
ch->odata = (ut8*)malloc (len);
ch->data = (ut8*)malloc (len);
r_io_read_at (io, addr, ch->odata, len);
ch->written = io->cached? 0: 1;
memcpy (ch->data, buf, len);
r_list_append (io->cache, ch);
return len;

View File

@ -584,6 +584,9 @@ R_API int r_io_write(RIO *io, const ut8 *buf, int len) {
buf += ret;
}
}
if (1) { //io->history) {
r_io_cache_write (io, io->off, buf, len);
}
/* TODO: implement IO cache here. to avoid dupping work on vm for example */
@ -602,20 +605,23 @@ R_API int r_io_write(RIO *io, const ut8 *buf, int len) {
r_io_map_select (io, io->off);
if (io->plugin) {
if (io->plugin->write)
if (io->plugin->write) {
ret = io->plugin->write (io, io->desc, buf, len);
else eprintf ("r_io_write: io handler with no write callback\n");
} else {
eprintf ("r_io_write: io handler with no write callback\n");
ret = -1;
}
} else {
ret = write (io->desc->fd, buf, len);
}
if (ret == -1)
if (ret == -1) {
eprintf ("r_io_write: cannot write on fd %d\n", io->desc->fd);
else{
r_io_cache_invalidate (io, io->off, io->off+1);
} else {
r_io_map_write_update (io, io->desc->fd, io->off, ret);
io->off += ret;
}
if (data)
free (data);
free (data);
return ret;
}