mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-03 12:12:06 +00:00
Better 'wc' command and cache/history capabilities
This commit is contained in:
parent
2642b03076
commit
67acee60f9
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
18
libr/io/io.c
18
libr/io/io.c
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user