radare2/libr/io/cache.c

163 lines
4.0 KiB
C
Raw Normal View History

/* radare - LGPL - Copyright 2008-2015 - pancake */
// TODO: implement a more inteligent way to store cached memory
// TODO: define limit of max mem to cache
#include "r_io.h"
static void cache_item_free(RIOCache *cache) {
if (!cache)
return;
free (cache->data);
free (cache->odata);
free (cache);
}
R_API void r_io_cache_init(RIO *io) {
2016-03-29 21:39:32 +00:00
io->cache = r_list_newf ((RListFree)cache_item_free);
2015-09-14 00:08:31 +00:00
io->cached = false; // cache write ops
io->cached_read = false; // cached read ops
}
R_API void r_io_cache_enable(RIO *io, int read, int write) {
io->cached = read | write;
io->cached_read = read;
}
R_API void r_io_cache_commit(RIO *io, ut64 from, ut64 to) {
RListIter *iter;
RIOCache *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 = true;
break;
}
}
io->cached = ioc;
}
R_API void r_io_cache_reset(RIO *io, int set) {
io->cached = set;
r_list_purge (io->cache);
}
R_API int r_io_cache_invalidate(RIO *io, ut64 from, ut64 to) {
2014-10-26 00:47:08 +00:00
RListIter *iter;
RIOCache *c;
2015-09-14 00:08:31 +00:00
int done = false;
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);
2015-09-14 00:08:31 +00:00
c->written = false;
done = true;
break;
}
}
}
return done;
}
R_API int r_io_cache_list(RIO *io, int rad) {
int i, j = 0;
RListIter *iter;
RIOCache *c;
2016-07-20 16:43:28 +00:00
if (rad == 2) {
2016-07-19 21:55:36 +00:00
io->cb_printf ("[");
2016-07-20 16:43:28 +00:00
}
r_list_foreach (io->cache, iter, c) {
2016-07-19 21:55:36 +00:00
if (rad == 1) {
2016-07-20 16:43:28 +00:00
io->cb_printf ("wx ");
for (i = 0; i < c->size; i++) {
io->cb_printf ("%02x", (ut8)(c->data[i] & 0xff));
}
io->cb_printf (" @ 0x%08"PFMT64x, c->from);
io->cb_printf (" # replaces: ");
for (i = 0; i < c->size; i++) {
io->cb_printf ("%02x", (ut8)(c->odata[i] & 0xff));
}
io->cb_printf ("\n");
2016-07-19 21:55:36 +00:00
} else if (rad == 2) {
2016-07-20 16:43:28 +00:00
io->cb_printf ("{\"idx\":%"PFMT64d",\"addr\":%"PFMT64d",\"size\":%d,", j, c->from, c->size);
io->cb_printf ("\"before\":\"");
for (i = 0; i < c->size; i++) {
io->cb_printf ("%02x", c->odata[i]);
}
io->cb_printf ("\",\"after\":\"");
for (i = 0; i < c->size; i++) {
io->cb_printf ("%02x", c->data[i]);
}
io->cb_printf ("\",\"written\":%s}%s", c->written? "true": "false",iter->n? ",": "");
2016-07-19 21:55:36 +00:00
} else if (rad == 0) {
2016-07-20 16:43:28 +00:00
io->cb_printf ("idx=%d addr=0x%08"PFMT64x" size=%d ", j, c->from, c->size);
for (i = 0; i < c->size; i++) {
io->cb_printf ("%02x", c->odata[i]);
2016-07-20 16:43:28 +00:00
}
io->cb_printf (" -> ");
2016-07-20 16:43:28 +00:00
for (i = 0; i < c->size; i++) {
io->cb_printf ("%02x", c->data[i]);
2016-07-20 16:43:28 +00:00
}
io->cb_printf (" %s\n", c->written? "(written)": "(not written)");
}
j++;
}
2016-07-19 21:55:36 +00:00
if (rad == 2)
io->cb_printf ("]");
2015-09-14 00:08:31 +00:00
return false;
}
R_API int r_io_cache_write(RIO *io, ut64 addr, const ut8 *buf, int len) {
RIOCache *ch;
ch = R_NEW0 (RIOCache);
2017-04-26 09:33:26 +00:00
if (!ch) {
return 0;
}
ch->from = addr;
ch->to = addr + len;
ch->size = len;
2017-05-03 15:19:49 +00:00
ch->odata = (ut8*)calloc (1, len + 1);
2017-04-26 09:33:26 +00:00
if (!ch->odata) {
return 0;
}
2017-05-03 15:19:49 +00:00
ch->data = (ut8*)calloc (1, len + 1);
if (!ch->data) {
free (ch->odata);
2017-04-26 09:33:26 +00:00
return 0;
}
2017-05-03 15:19:49 +00:00
ch->written = io->cached? false: true;
r_io_read_at (io, addr, ch->odata, len);
memcpy (ch->data, buf, len);
r_list_append (io->cache, ch);
}
R_API int r_io_cache_read(RIO *io, ut64 addr, ut8 *buf, int len) {
int l, covered = 0;
RListIter *iter;
RIOCache *c;
r_list_foreach (io->cache, iter, c) {
if (addr < c->to && c->from < addr + len) {
if (addr < c->from) {
l = R_MIN (addr + len - c->from, c->size);
memcpy (buf + c->from - addr, c->data, l);
} else {
l = R_MIN (c->to - addr, len);
memcpy (buf, c->data + addr - c->from, l);
}
covered += l;
}
}
return covered;
}