diff --git a/libr/core/cmd.c b/libr/core/cmd.c index 59d50345a3..5d3c03cb33 100644 --- a/libr/core/cmd.c +++ b/libr/core/cmd.c @@ -2621,18 +2621,47 @@ static int cmd_write(void *data, const char *input) { switch (input[1]) { case 'i': r_io_cache_commit (core->io); + r_core_block_read (core, 1); break; case 'r': r_io_cache_reset (core->io, R_TRUE); + 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 (toto)\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); break; case '?': r_cons_printf ( "Usage: wc[ir*?]\n" - " wc list all write changes\n" - " wc* \"\" in radare commands\n" - " wcr reset all write changes in cache\n" - " wci commit write cache\n" - "NOTE: Needs io.cache=true\n"); + " 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"); break; case '*': r_io_cache_list (core->io, R_TRUE); diff --git a/libr/io/cache.c b/libr/io/cache.c index 44b814e9a0..f71a807e2e 100644 --- a/libr/io/cache.c +++ b/libr/io/cache.c @@ -1,7 +1,6 @@ /* radare - LGPL - Copyright 2008-2011 pancake */ -// XXX This has been stolen from r_vm !!! we must adapt this -// XXX to work with r_io correctly +// TODO: USE RList here // r_io_cache_t has not been defined // TODO: implement a more inteligent way to store cached memory // TODO: define limit of max mem to cache @@ -40,6 +39,7 @@ R_API void r_io_cache_reset(RIO *io, int set) { RIOCache *c = list_entry (pos, RIOCache, list); free (c->data); free (c); + list_del (pos); } // is this necessary at all? INIT_LIST_HEAD (&io->cache); @@ -47,12 +47,22 @@ R_API void r_io_cache_reset(RIO *io, int set) { R_API int r_io_cache_invalidate(RIO *io, ut64 from, ut64 to) { int ret = R_FALSE; - /* TODO: Implement: invalidate ranged cached read ops between from/to */ + struct list_head *pos, *n; + if (fromcache) { + RIOCache *c = list_entry (pos, RIOCache, list); + if (c->from >= from && c->to <= to) { + /* REMOVE ITEM */ + free (c->data); + free (c); + list_del (pos); + } + } return ret; } R_API int r_io_cache_list(RIO *io, int rad) { - int i; + int i, j = 0; struct list_head *pos, *n; list_for_each_safe (pos, n, &io->cache) { RIOCache *c = list_entry (pos, RIOCache, list); @@ -61,7 +71,13 @@ R_API int r_io_cache_list(RIO *io, int rad) { for (i=0; isize; i++) io->printf ("%02x", c->data[i]); io->printf (" @ 0x%08"PFMT64x"\n", c->from); - } else io->printf ("addr=0x%08"PFMT64x" size=%d\n", c->from, c->size); + } else { + io->printf ("idx=%d addr=0x%08"PFMT64x" size=%d ", j, c->from, c->size); + for (i=0; isize; i++) + io->printf ("%02x", c->data[i]); + io->printf ("\n"); + } + j++; } return R_FALSE; } diff --git a/libr/io/io.c b/libr/io/io.c index 6beb4ea03b..53d1aad42d 100644 --- a/libr/io/io.c +++ b/libr/io/io.c @@ -155,20 +155,8 @@ R_API int r_io_read(RIO *io, ut8 *buf, int len) { /* check section permissions */ if (io->enforce_rwx && !(r_io_section_get_rwx (io, io->off) & R_IO_READ)) return -1; -#if 0 - if (io->cached) { - ret = r_io_cache_read (io, io->off, buf, len); - if (ret == len) - return len; - if (ret > 0) { - len -= ret; - buf += ret; - } - // partial reads - if (ret == len) - return len; - } -#endif + + off = io->off; ret = -1; if (io->plugin && io->plugin->read) { @@ -178,6 +166,19 @@ R_API int r_io_read(RIO *io, ut8 *buf, int len) { } else ret = read (io->fd->fd, buf, len); if (ret>0 && retcached) { + ret = r_io_cache_read (io, io->off, buf, len); + if (ret == len) { + return len; + } + if (ret > 0) { + len -= ret; + buf += ret; + } + // partial reads + if (ret == len) + return len; + } // this must be before?? r_io_cache_read (io, io->off, buf, len); // eprintf ("--RET-- %llx\n", r_io_seek (io, off, R_IO_SEEK_SET)); diff --git a/test/cachetest b/test/cachetest new file mode 100644 index 0000000000..bf9dbe0427 --- /dev/null +++ b/test/cachetest @@ -0,0 +1,13 @@ +e io.cache=1 +x +wx 0102 +x +wc +!echo RESET +wcr +!echo LIST +wc +s+1 +x +s-1 +x