2018-01-10 06:43:23 +00:00
|
|
|
/* radare - LGPL - Copyright 2008-2018 - pancake */
|
2009-09-08 02:14:19 +00:00
|
|
|
|
2019-06-20 04:45:00 +00:00
|
|
|
// TODO: implement a more intelligent way to store cached memory
|
2009-09-08 02:14:19 +00:00
|
|
|
|
|
|
|
#include "r_io.h"
|
|
|
|
|
2018-01-10 07:22:45 +00:00
|
|
|
#if 0
|
2018-01-10 06:43:23 +00:00
|
|
|
#define CACHE_CONTAINER(x) container_of ((RBNode*)x, RCache, rb)
|
|
|
|
|
|
|
|
static void _fcn_tree_calc_max_addr(RBNode *node) {
|
|
|
|
RIOCache *c = CACHE_CONTAINER (node);
|
|
|
|
}
|
2018-01-10 07:22:45 +00:00
|
|
|
#endif // 0
|
2018-01-10 06:43:23 +00:00
|
|
|
|
2014-06-04 23:50:56 +00:00
|
|
|
static void cache_item_free(RIOCache *cache) {
|
2017-12-18 00:44:22 +00:00
|
|
|
if (!cache) {
|
2012-02-07 00:51:56 +00:00
|
|
|
return;
|
2017-12-18 00:44:22 +00:00
|
|
|
}
|
2014-10-07 00:52:47 +00:00
|
|
|
free (cache->data);
|
|
|
|
free (cache->odata);
|
2012-02-07 00:51:56 +00:00
|
|
|
free (cache);
|
|
|
|
}
|
|
|
|
|
2017-12-18 00:44:22 +00:00
|
|
|
R_API bool r_io_cache_at(RIO *io, ut64 addr) {
|
|
|
|
RIOCache *c;
|
2018-01-10 01:35:11 +00:00
|
|
|
RListIter *iter;
|
2017-12-18 00:44:22 +00:00
|
|
|
r_list_foreach (io->cache, iter, c) {
|
2018-01-10 01:35:11 +00:00
|
|
|
if (r_itv_contain (c->itv, addr)) {
|
2017-12-18 00:44:22 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-03-30 21:12:19 +00:00
|
|
|
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);
|
2018-08-12 18:26:28 +00:00
|
|
|
io->buffer = r_cache_new ();
|
|
|
|
io->cached = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_io_cache_fini (RIO *io) {
|
|
|
|
r_list_free (io->cache);
|
|
|
|
r_cache_free (io->buffer);
|
|
|
|
io->cache = NULL;
|
|
|
|
io->buffer = NULL;
|
2017-09-15 09:32:01 +00:00
|
|
|
io->cached = 0;
|
2009-09-08 18:16:52 +00:00
|
|
|
}
|
|
|
|
|
2014-10-07 00:52:47 +00:00
|
|
|
R_API void r_io_cache_commit(RIO *io, ut64 from, ut64 to) {
|
2012-02-07 00:51:56 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RIOCache *c;
|
2018-01-10 06:43:23 +00:00
|
|
|
RInterval range = (RInterval){from, to - from};
|
2014-10-07 00:52:47 +00:00
|
|
|
r_list_foreach (io->cache, iter, c) {
|
2018-01-10 01:35:11 +00:00
|
|
|
// if (from <= c->to - 1 && c->from <= to - 1) {
|
2018-06-14 23:20:39 +00:00
|
|
|
if (r_itv_overlap (c->itv, range)) {
|
2017-09-15 09:32:01 +00:00
|
|
|
int cached = io->cached;
|
|
|
|
io->cached = 0;
|
2018-01-10 01:35:11 +00:00
|
|
|
if (r_io_write_at (io, r_itv_begin (c->itv), c->data, r_itv_size (c->itv))) {
|
2016-03-22 12:16:32 +00:00
|
|
|
c->written = true;
|
2017-09-01 06:41:03 +00:00
|
|
|
} else {
|
2018-06-14 23:20:39 +00:00
|
|
|
eprintf ("Error writing change at 0x%08"PFMT64x"\n", r_itv_begin (c->itv));
|
2017-09-01 06:41:03 +00:00
|
|
|
}
|
|
|
|
io->cached = cached;
|
|
|
|
break; // XXX old behavior, revisit this
|
2010-03-30 21:12:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_io_cache_reset(RIO *io, int set) {
|
2010-03-23 22:26:59 +00:00
|
|
|
io->cached = set;
|
2012-02-07 00:51:56 +00:00
|
|
|
r_list_purge (io->cache);
|
2009-09-08 18:16:52 +00:00
|
|
|
}
|
|
|
|
|
2010-03-30 21:12:19 +00:00
|
|
|
R_API int r_io_cache_invalidate(RIO *io, ut64 from, ut64 to) {
|
2018-08-26 15:38:11 +00:00
|
|
|
int invalidated = 0;
|
|
|
|
RListIter *iter, *tmp;
|
2012-02-07 00:51:56 +00:00
|
|
|
RIOCache *c;
|
2018-08-26 15:38:11 +00:00
|
|
|
RInterval range = (RInterval){from, to - from};
|
|
|
|
r_list_foreach_prev_safe (io->cache, iter, tmp, c) {
|
|
|
|
if (r_itv_overlap (c->itv, range)) {
|
|
|
|
int cached = io->cached;
|
|
|
|
io->cached = 0;
|
|
|
|
r_io_write_at (io, r_itv_begin (c->itv), c->odata, r_itv_size (c->itv));
|
|
|
|
io->cached = cached;
|
|
|
|
c->written = false;
|
|
|
|
r_list_delete (io->cache, iter);
|
|
|
|
invalidated++;
|
2011-06-21 22:19:02 +00:00
|
|
|
}
|
|
|
|
}
|
2018-08-26 15:38:11 +00:00
|
|
|
return invalidated;
|
2009-09-17 09:48:36 +00:00
|
|
|
}
|
|
|
|
|
2010-03-30 21:12:19 +00:00
|
|
|
R_API int r_io_cache_list(RIO *io, int rad) {
|
2011-06-21 22:19:02 +00:00
|
|
|
int i, j = 0;
|
2012-02-07 00:51:56 +00:00
|
|
|
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
|
|
|
}
|
2012-02-07 00:51:56 +00:00
|
|
|
r_list_foreach (io->cache, iter, c) {
|
2018-06-14 23:20:39 +00:00
|
|
|
const int dataSize = r_itv_size (c->itv);
|
2016-07-19 21:55:36 +00:00
|
|
|
if (rad == 1) {
|
2016-07-20 16:43:28 +00:00
|
|
|
io->cb_printf ("wx ");
|
2018-01-10 01:35:11 +00:00
|
|
|
for (i = 0; i < dataSize; i++) {
|
2016-07-20 16:43:28 +00:00
|
|
|
io->cb_printf ("%02x", (ut8)(c->data[i] & 0xff));
|
|
|
|
}
|
2018-06-14 23:20:39 +00:00
|
|
|
io->cb_printf (" @ 0x%08"PFMT64x, r_itv_begin (c->itv));
|
2016-07-20 16:43:28 +00:00
|
|
|
io->cb_printf (" # replaces: ");
|
2018-01-10 01:35:11 +00:00
|
|
|
for (i = 0; i < dataSize; i++) {
|
2016-07-20 16:43:28 +00:00
|
|
|
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) {
|
2018-01-10 01:35:11 +00:00
|
|
|
io->cb_printf ("{\"idx\":%"PFMT64d",\"addr\":%"PFMT64d",\"size\":%d,",
|
2018-06-14 23:20:39 +00:00
|
|
|
j, r_itv_begin (c->itv), dataSize);
|
2016-07-20 16:43:28 +00:00
|
|
|
io->cb_printf ("\"before\":\"");
|
2018-01-10 01:35:11 +00:00
|
|
|
for (i = 0; i < dataSize; i++) {
|
2016-07-20 16:43:28 +00:00
|
|
|
io->cb_printf ("%02x", c->odata[i]);
|
|
|
|
}
|
|
|
|
io->cb_printf ("\",\"after\":\"");
|
2018-01-10 01:35:11 +00:00
|
|
|
for (i = 0; i < dataSize; i++) {
|
2016-07-20 16:43:28 +00:00
|
|
|
io->cb_printf ("%02x", c->data[i]);
|
|
|
|
}
|
2018-01-10 06:43:23 +00:00
|
|
|
io->cb_printf ("\",\"written\":%s}%s", c->written
|
|
|
|
? "true": "false", iter->n? ",": "");
|
2016-07-19 21:55:36 +00:00
|
|
|
} else if (rad == 0) {
|
2018-06-14 23:20:39 +00:00
|
|
|
io->cb_printf ("idx=%d addr=0x%08"PFMT64x" size=%d ", j, r_itv_begin (c->itv), dataSize);
|
2018-01-10 01:35:11 +00:00
|
|
|
for (i = 0; i < dataSize; i++) {
|
2015-08-08 18:15:13 +00:00
|
|
|
io->cb_printf ("%02x", c->odata[i]);
|
2016-07-20 16:43:28 +00:00
|
|
|
}
|
2015-08-08 18:15:13 +00:00
|
|
|
io->cb_printf (" -> ");
|
2018-01-10 01:35:11 +00:00
|
|
|
for (i = 0; i < dataSize; i++) {
|
2015-08-08 18:15:13 +00:00
|
|
|
io->cb_printf ("%02x", c->data[i]);
|
2016-07-20 16:43:28 +00:00
|
|
|
}
|
2015-11-16 09:29:03 +00:00
|
|
|
io->cb_printf (" %s\n", c->written? "(written)": "(not written)");
|
2011-06-21 22:19:02 +00:00
|
|
|
}
|
|
|
|
j++;
|
2010-03-30 15:37:15 +00:00
|
|
|
}
|
2018-01-09 15:05:50 +00:00
|
|
|
if (rad == 2) {
|
2018-03-10 13:15:29 +00:00
|
|
|
io->cb_printf ("]\n");
|
2018-01-09 15:05:50 +00:00
|
|
|
}
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2010-03-30 15:37:15 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 14:52:40 +00:00
|
|
|
R_API bool r_io_cache_write(RIO *io, ut64 addr, const ut8 *buf, int len) {
|
2014-10-07 00:52:47 +00:00
|
|
|
RIOCache *ch;
|
2014-11-23 21:44:38 +00:00
|
|
|
ch = R_NEW0 (RIOCache);
|
2017-04-26 09:33:26 +00:00
|
|
|
if (!ch) {
|
2017-08-22 14:52:40 +00:00
|
|
|
return false;
|
2017-04-26 09:33:26 +00:00
|
|
|
}
|
2018-01-10 01:35:11 +00:00
|
|
|
ch->itv = (RInterval){addr, 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) {
|
2017-08-26 11:08:53 +00:00
|
|
|
free (ch);
|
2017-08-22 14:52:40 +00:00
|
|
|
return false;
|
2017-04-26 09:33:26 +00:00
|
|
|
}
|
2017-05-03 15:19:49 +00:00
|
|
|
ch->data = (ut8*)calloc (1, len + 1);
|
|
|
|
if (!ch->data) {
|
|
|
|
free (ch->odata);
|
2017-08-26 11:08:53 +00:00
|
|
|
free (ch);
|
2017-08-22 14:52:40 +00:00
|
|
|
return false;
|
2017-04-26 09:33:26 +00:00
|
|
|
}
|
2017-09-15 09:32:01 +00:00
|
|
|
ch->written = false;
|
2017-12-18 00:44:22 +00:00
|
|
|
{
|
|
|
|
bool cm = io->cachemode;
|
|
|
|
io->cachemode = false;
|
|
|
|
r_io_read_at (io, addr, ch->odata, len);
|
|
|
|
io->cachemode = cm;
|
|
|
|
}
|
2010-03-23 22:26:59 +00:00
|
|
|
memcpy (ch->data, buf, len);
|
2012-02-07 00:51:56 +00:00
|
|
|
r_list_append (io->cache, ch);
|
2017-08-22 14:52:40 +00:00
|
|
|
return true;
|
2009-09-08 02:14:19 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 14:52:40 +00:00
|
|
|
R_API bool r_io_cache_read(RIO *io, ut64 addr, ut8 *buf, int len) {
|
2017-08-14 16:58:18 +00:00
|
|
|
int l, covered = 0;
|
2012-02-07 00:51:56 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RIOCache *c;
|
2018-01-10 01:35:11 +00:00
|
|
|
RInterval range = (RInterval){ addr, len };
|
2012-02-07 00:51:56 +00:00
|
|
|
r_list_foreach (io->cache, iter, c) {
|
2018-06-14 23:20:39 +00:00
|
|
|
if (r_itv_overlap (c->itv, range)) {
|
|
|
|
const ut64 begin = r_itv_begin (c->itv);
|
2018-01-10 01:35:11 +00:00
|
|
|
if (addr < begin) {
|
2018-06-14 23:20:39 +00:00
|
|
|
l = R_MIN (addr + len - begin, r_itv_size (c->itv));
|
2018-01-10 01:35:11 +00:00
|
|
|
memcpy (buf + begin - addr, c->data, l);
|
2010-03-30 15:37:15 +00:00
|
|
|
} else {
|
2018-06-14 23:20:39 +00:00
|
|
|
l = R_MIN (r_itv_end (c->itv) - addr, len);
|
2018-01-10 01:35:11 +00:00
|
|
|
memcpy (buf, c->data + addr - begin, l);
|
2010-03-30 15:37:15 +00:00
|
|
|
}
|
2015-12-08 13:59:30 +00:00
|
|
|
covered += l;
|
2009-09-08 02:14:19 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-22 14:52:40 +00:00
|
|
|
return (covered == 0) ? false: true;
|
2009-09-08 02:14:19 +00:00
|
|
|
}
|
2018-01-10 01:35:11 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2018-01-10 06:43:23 +00:00
|
|
|
#if 0
|
2018-01-10 01:35:11 +00:00
|
|
|
R_API bool r_io_cache_ll_read(RIO *io, ut64 addr, ut8 *buf, int len) {
|
|
|
|
// UnownedRList *list = r
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API bool r_io_cache_ll_write(RIO *io, ut64 addr, ut8 *buf, int len) {
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API bool r_io_cache_ll_invalidate(RIO *io, ut64 addr, int len) {
|
|
|
|
}
|
2018-01-10 06:43:23 +00:00
|
|
|
#endif
|