radare2/libr/io/cache.c
pancake 1e52015eee Add px[QW], fix segmented io and handle ! pipes
Handle `!` with r_core_cmd_str_pipe
Fix 'afl' output
Add help for 'px' command
Add pxQ and pxW to show one word per line
Fix segmented io with maps and sections
Some test cases got fixed
Add test-r_anal.py
2012-10-25 12:55:28 +02:00

125 lines
2.6 KiB
C

/* radare - LGPL - Copyright 2008-2012 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_free(RIOCache *cache) {
if (!cache)
return;
if (cache->data)
free (cache->data);
free (cache);
}
R_API void r_io_cache_init(RIO *io) {
io->cache = r_list_new ();
io->cache->free = (RListFree)cache_free;
io->cached = R_FALSE; // cache write ops
io->cached_read = R_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) {
RListIter *iter;
RIOCache *c;
if (io->cached) {
io->cached = R_FALSE;
r_list_foreach (io->cache, iter, c) {
if (!r_io_write_at (io, c->from, c->data, c->size))
eprintf ("Error writing change at 0x%08"PFMT64x"\n", c->from);
}
io->cached = R_TRUE;
r_io_cache_reset (io, io->cached);
}
}
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) {
RListIter *iter, *iter_tmp;
RIOCache *c;
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);
}
}
return R_FALSE;
}
R_API int r_io_cache_list(RIO *io, int rad) {
int i, j = 0;
RListIter *iter;
RIOCache *c;
r_list_foreach (io->cache, iter, c) {
if (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);
} 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->data[i]);
io->printf ("\n");
}
j++;
}
return R_FALSE;
}
R_API int r_io_cache_write(RIO *io, ut64 addr, const ut8 *buf, int len) {
RIOCache *ch = R_NEW (RIOCache);
ch->from = addr;
ch->to = addr + len;
ch->size = len;
ch->data = (ut8*)malloc (len);
memcpy (ch->data, buf, len);
r_list_append (io->cache, ch);
return len;
}
R_API int r_io_cache_read(RIO *io, ut64 addr, ut8 *buf, int len) {
int l, ret, da, db;
RListIter *iter;
RIOCache *c;
r_list_foreach (io->cache, iter, c) {
if (r_range_overlap (addr, addr+len-1, c->from, c->to, &ret)) {
if (ret>0) {
da = ret;
db = 0;
l = c->size;
} else if (ret<0) {
da = 0;
db = -ret;
l = c->size-db;
} else {
da = 0;
db = 0;
l = c->size;
}
if (l>len)
l = len;
if (l<1) l = 1; // XXX: fail
memcpy (buf+da, c->data+db, l);
}
}
return len;
}