* Add 'r_io_undo'

* Added deinitializators for r_io_cache
This commit is contained in:
pancake 2009-09-08 18:16:52 +00:00
parent 780e424cbe
commit fdf164e229
9 changed files with 182 additions and 165 deletions

2
TODO
View File

@ -7,7 +7,7 @@
----------------------------------------[ todo ----------------------------------------[ todo
<{include libr/TODO}> <{include libr/TODO}>
* correct result (R_TRUFAE), but with warnings (implement r_errno and r_errstr in r_util?) * correct result (R_TRUFAE), but with warnings (implement r_errno and r_errstr in r_util?)
- Quantic computation ftw \o/ - Quantic computation ftw \o/
* r_cmd must provide a nesting char table indexing for commands * r_cmd must provide a nesting char table indexing for commands

View File

@ -4,18 +4,14 @@
#include "r_types.h" #include "r_types.h"
#include "list.h" #include "list.h"
#define R_IO_READ 0 #define R_IO_READ 4
#define R_IO_WRITE 1 #define R_IO_WRITE 2
#define R_IO_EXEC 4 #define R_IO_EXEC 1
#define R_IO_SEEK_SET 0
#define R_IO_SEEK_CUR 1
#define R_IO_SEEK_END 2
#if 0
// TODO: rename SECTION to PERMISION or so
enum {
R_IO_SECTION_R = 4,
R_IO_SECTION_W = 2,
R_IO_SECTION_X = 1,
};
#endif
#if 0 #if 0
// DEPRECATE ?? // DEPRECATE ??
#define R_IO_RW R_IO_READ|R_IO_WRITE #define R_IO_RW R_IO_READ|R_IO_WRITE
@ -26,9 +22,6 @@ enum {
#define R_IO_NFDS 32 #define R_IO_NFDS 32
#define R_IO_SEEK_SET 0
#define R_IO_SEEK_CUR 1
#define R_IO_SEEK_END 2
#define IO_MAP_N 128 #define IO_MAP_N 128
struct r_io_map_t { struct r_io_map_t {
@ -43,13 +36,25 @@ struct r_io_map_t {
/* stores write and seek changes */ /* stores write and seek changes */
#define R_IO_UNDOS 64 #define R_IO_UNDOS 64
struct r_io_undo_t { struct r_io_undo_t {
struct list_head undo_w_list; int enable;
/* write stuff */
struct list_head w_list;
int w_init; int w_init;
int w_lock; int w_lock;
/* seek stuff */
ut64 seek[R_IO_UNDOS]; ut64 seek[R_IO_UNDOS];
int fd[R_IO_UNDOS]; int fd[R_IO_UNDOS];
int idx; int idx;
int lim; int limit;
};
struct r_io_undo_w_t {
int set;
ut64 off;
ut8 *o; /* old data */
ut8 *n; /* new data */
int len; /* length */
struct list_head list;
}; };
struct r_io_t { struct r_io_t {
@ -65,6 +70,7 @@ struct r_io_t {
ut8 *write_mask_buf; ut8 *write_mask_buf;
int write_mask_len; int write_mask_len;
struct r_io_handle_t *plugin; struct r_io_handle_t *plugin;
struct r_io_undo_t undo;
struct list_head io_list; struct list_head io_list;
ut64 last_align; ut64 last_align;
struct list_head sections; struct list_head sections;
@ -205,6 +211,26 @@ R_API int r_io_desc_add(struct r_io_t *io, int fd, const char *file, int flags,
R_API int r_io_desc_del(struct r_io_t *io, int fd); R_API int r_io_desc_del(struct r_io_t *io, int fd);
R_API struct r_io_desc_t *r_io_desc_get(struct r_io_t *io, int fd); R_API struct r_io_desc_t *r_io_desc_get(struct r_io_t *io, int fd);
R_API int r_io_desc_generate(struct r_io_t *io); R_API int r_io_desc_generate(struct r_io_t *io);
/* undo api */
// track seeks and writes
// TODO: needs cleanup..kinda big?
R_API int r_io_undo_init(struct r_io_t *io);
R_API void r_io_undo_enable(struct r_io_t *io, int set);
R_API ut64 r_io_undo_get_last_seek(struct r_io_t *io);
R_API void r_io_undo_seek(struct r_io_t *io);
R_API void r_io_undo_redo(struct r_io_t *io);
R_API void r_io_undo_push(struct r_io_t *io);
R_API void r_io_undo_reset(struct r_io_t *io);
R_API void r_io_undo_list(struct r_io_t *io);
R_API void r_io_undo_write_new(struct r_io_t *io, ut64 off, const ut8 *data, int len);
R_API void r_io_undo_write_clear(struct r_io_t *io);
R_API int r_io_undo_write_size(struct r_io_t *io);
R_API void r_io_undo_write_list(struct r_io_t *io);
R_API int r_io_undo_write_set_t(struct r_io_t *io, struct r_io_undo_w_t *u, int set) ;
R_API void r_io_undo_write_set_all(struct r_io_t *io, int set);
R_API int r_io_undo_write_set(struct r_io_t *io, int n, int set);
#if 0 #if 0
#define CB_READ int (*cb_read)(struct r_io_t *user, int pid, ut64 addr, ut8 *buf, int len) #define CB_READ int (*cb_read)(struct r_io_t *user, int pid, ut64 addr, ut8 *buf, int len)
#define CB_WRITE int (*cb_write)(struct r_io_t *user, int pid, ut64 addr, const ut8 *buf, int len) #define CB_WRITE int (*cb_write)(struct r_io_t *user, int pid, ut64 addr, const ut8 *buf, int len)

View File

@ -9,7 +9,7 @@ STATIC_OBJS=
include ../config.mk include ../config.mk
include ${STATIC_IO_PLUGINS} include ${STATIC_IO_PLUGINS}
STATIC_OBJS=$(subst ..,p/..,$(subst io_,p/io_,$(STATIC_OBJ))) STATIC_OBJS=$(subst ..,p/..,$(subst io_,p/io_,$(STATIC_OBJ)))
OBJ=${STATIC_OBJS} io.o handle.o map.o section.o desc.o bind.o cache.o OBJ=${STATIC_OBJS} io.o handle.o map.o section.o desc.o bind.o cache.o undo.o
pre: pre:
@echo STATICOBJS: ${STATIC_OBJS} @echo STATICOBJS: ${STATIC_OBJS}

View File

@ -8,6 +8,22 @@ R_API int r_io_bind(struct r_io_t *io, struct r_io_bind_t *bnd)
return R_TRUE; return R_TRUE;
} }
#if 0
// define callback for other APIs to use with current io
static int _cb_read(struct r_io_t *io, int pid, ut64 addr, ut8 *buf, int len)
{
}
static int _cb_write(struct r_io_t *io, int pid, ut64 addr, const ut8 *buf, int len)
{
}
R_API int r_io_hook(struct r_io_t *io, CB_IO)
{
return cb_io(user, _cb_read, _cb_write
}
#endif
#if 0 #if 0
this api must be used from r_vm, r_bin ... this api must be used from r_vm, r_bin ...

View File

@ -8,9 +8,30 @@
R_API void r_io_cache_init(struct r_io_t *io) R_API void r_io_cache_init(struct r_io_t *io)
{ {
io->cached = 0; // IO cached
INIT_LIST_HEAD(&io->cache); INIT_LIST_HEAD(&io->cache);
} }
R_API void r_io_cache_enable(struct r_io_t *io, int set)
{
io->cached = set;
}
R_API void r_io_cache_free(struct r_io_t *io, int set)
{
io->cached = set;
struct r_io_cache_t *c;
struct list_head *pos, *n;
list_for_each_safe(pos, n, &io->cache) {
c = list_entry(pos, struct r_io_cache_t, list);
free(c->data);
free(c);
}
// is this necessary at all?
INIT_LIST_HEAD(&io->cache);
}
R_API int r_io_cache_write(struct r_io_t *io, ut64 addr, const ut8 *buf, int len) R_API int r_io_cache_write(struct r_io_t *io, ut64 addr, const ut8 *buf, int len)
{ {
struct r_io_cache_t *ch = MALLOC_STRUCT(struct r_io_cache_t); struct r_io_cache_t *ch = MALLOC_STRUCT(struct r_io_cache_t);
@ -57,8 +78,3 @@ R_API int r_io_cache_write(struct r_io_t *io, ut64 off, ut8 *data, int len)
return r_io_write_at(io, off, data, len); return r_io_write_at(io, off, data, len);
} }
#endif #endif
R_API void r_io_cache_enable(struct r_io_t *io, int set)
{
io->cached = set;
}

View File

@ -4,22 +4,21 @@
#include "r_util.h" #include "r_util.h"
#include <stdio.h> #include <stdio.h>
// TODO: R_API int r_io_fetch(struct r_io_t *io, ut8 *buf, int len)
// --- check for EXEC perms in section (use cached read to accelerate)
R_API struct r_io_t *r_io_init(struct r_io_t *io) R_API struct r_io_t *r_io_init(struct r_io_t *io)
{ {
io->write_mask_fd = -1; io->write_mask_fd = -1;
io->last_align = 0; io->last_align = 0;
io->redirect = NULL; io->redirect = NULL;
io->printf = printf; io->printf = printf;
io->enforce_rwx = 0; // do not enforce RWX section permissions by default
io->enforce_seek = 0; // do not limit seeks out of the file by default
io->enforce_rwx = 0;
io->enforce_seek = 0;
io->cached = 0; // IO cached
r_io_cache_init(io); r_io_cache_init(io);
r_io_map_init(io); r_io_map_init(io);
r_io_section_init(io); r_io_section_init(io);
r_io_handle_init(io); r_io_handle_init(io);
r_io_desc_init(io); r_io_desc_init(io);
r_io_undo_init(&io->undo);
return io; return io;
} }
@ -97,7 +96,8 @@ R_API int r_io_open(struct r_io_t *io, const char *file, int flags, int mode)
} }
} }
if (fd == -2) if (fd == -2)
fd = open(file, flags, mode); // XXX RDONLY; READ; WRITE AND MORE SOO...
fd = open(file, O_RDONLY, mode); // XXX drop posix depz here
if (fd >= 0) { if (fd >= 0) {
r_io_set_fd(io, fd); r_io_set_fd(io, fd);
r_io_desc_add(io, fd, file, flags, io->plugin); r_io_desc_add(io, fd, file, flags, io->plugin);
@ -116,6 +116,7 @@ R_API int r_io_set_fd(struct r_io_t *io, int fd)
return io->fd; return io->fd;
} }
R_API int r_io_read(struct r_io_t *io, ut8 *buf, int len) R_API int r_io_read(struct r_io_t *io, ut8 *buf, int len)
{ {
int ret; int ret;
@ -312,19 +313,3 @@ R_API int r_io_close(struct r_io_t *io, int fd)
io->fd = -1; // unset current fd io->fd = -1; // unset current fd
return close(fd); return close(fd);
} }
#if 0
// define callback for other APIs to use with current io
static int _cb_read(struct r_io_t *io, int pid, ut64 addr, ut8 *buf, int len)
{
}
static int _cb_write(struct r_io_t *io, int pid, ut64 addr, const ut8 *buf, int len)
{
}
R_API int r_io_hook(struct r_io_t *io, CB_IO)
{
return cb_io(user, _cb_read, _cb_write
}
#endif

View File

@ -7,6 +7,8 @@
R_API void r_io_section_init(struct r_io_t *io) R_API void r_io_section_init(struct r_io_t *io)
{ {
io->enforce_rwx = 0; // do not enforce RWX section permissions by default
io->enforce_seek = 0; // do not limit seeks out of the file by default
INIT_LIST_HEAD(&(io->sections)); INIT_LIST_HEAD(&(io->sections));
} }

View File

@ -1,170 +1,138 @@
/* /* radare - LGPL - Copyright 2007-2009 pancake<nopcode.org> */
* Copyright (C) 2007, 2008, 2009
* pancake <@youterm.com>
*
* radare is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* radare is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with radare; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "main.h" #include <r_io.h>
#include "radare.h"
#include "list.h" #define cons_printf printf
#include "undo.h" #define cons_newline() printf("\n");
#if 0 #if 0
* Handle changes in write and seeks * TODO:
* Per-fd history log * - make path of indirections shortr (io->undo.foo is slow) */
* - Handle changes in write and seeks
* - Per-fd history log
#endif #endif
#if 0 R_API int r_io_undo_init(struct r_io_t *io)
/* History for writes support indexing and undo/redo with state flags */
static struct list_head undo_w_list;
static int undo_w_init = 0;
static int undo_w_lock = 0;
/* History for the N last seeks, stack-like access */
#define UNDOS 64
static ut64 undos[UNDOS];
static int undos_idx = 0;
static int undos_lim = 0;
#endif
int r_io_undo_init(struct r_io_undo_t *undo)
{ {
u->undo_w_init = 0; io->undo.w_init = 0;
u->undo_w_lock = 0; io->undo.w_lock = 0;
u->undos_idx = 0; io->undo.idx = 0;
u->undos_lim = 0; io->undo.limit = 0;
io->undo.enable = 0;
return R_TRUE; return R_TRUE;
} }
// ut64 r_io_undo_get_last() R_API void r_io_undo_enable(struct r_io_t *io, int set)
{ {
io->undo.enable = set;
} }
ut64 undo_get_last_seek() R_API ut64 r_io_undo_get_last_seek(struct r_io_t *io)
{ {
if (undos_idx==0) return (io->undo.idx)?
return config.seek; io->undo.seek[io->undo.idx-2] : io->seek;
return undos[undos_idx-2];
} }
void undo_seek() R_API void r_io_undo_seek(struct r_io_t *io)
{ {
if (--undos_idx<0) if (--io->undo.idx<0)
undos_idx = 0; io->undo.idx = 0;
else config.seek = undos[undos_idx-1]; else io->seek = io->undo.seek[io->undo.idx-1];
} }
void undo_redo() R_API void r_io_undo_redo(struct r_io_t *io)
{ {
if (undos_idx<undos_lim) { if (io->undo.idx<io->undo.limit) {
undos_idx+=2; io->undo.idx += 2;
undo_seek(); r_io_undo_seek(io);
} }
} }
void undo_push() R_API void r_io_undo_push(struct r_io_t *io)
{ {
int i; int i;
if (undos[undos_idx-1] == config.seek) if (io->undo.seek[io->undo.idx-1] == io->seek)
return; return;
undos[undos_idx] = config.seek; io->undo.seek[io->undo.idx] = io->seek;
if (undos_idx==UNDOS-1) { if (io->undo.idx==R_IO_UNDOS-1) {
for(i=1;i<UNDOS;i++) for(i=1;i<R_IO_UNDOS;i++)
undos[i-1] = undos[i]; io->undo.seek[i-1] = io->undo.seek[i];
} else } else io->undo.idx++;
undos_idx++;
if (undos_lim<undos_idx) if (io->undo.limit<io->undo.idx)
undos_lim = undos_idx; io->undo.limit = io->undo.idx;
} }
void undo_reset() R_API void r_io_undo_reset(struct r_io_t *io)
{ {
undos_idx = 0; io->undo.idx = 0;
} }
void undo_list() R_API void r_io_undo_list(struct r_io_t *io)
{ {
int i; int i;
if (undos_idx<1) if (io->undo.idx>0) {
eprintf("-no seeks done-\n"); cons_printf("f undo_idx @ %d\n", io->undo.idx);
else { for(i=io->undo.idx-1;i!=0;i--)
cons_printf("f undo_idx @ %d\n", undos_idx); cons_printf("f undo_%d @ 0x%llx\n",
for(i=undos_idx-1;i!=0;i--) io->undo.idx-1-i, io->undo.seek[i-1]);
cons_printf("f undo_%d @ 0x%llx\n", undos_idx-1-i, undos[i-1]); } else eprintf("-no seeks done-\n");
}
} }
void undo_write_new(ut64 off, const ut8 *data, int len) R_API void r_io_undo_write_new(struct r_io_t *io, ut64 off, const ut8 *data, int len)
{ {
struct undow_t *uw = (struct undow_t *)malloc(sizeof(struct undow_t)); struct r_io_undo_w_t *uw = MALLOC_STRUCT(struct r_io_undo_w_t);
if (!config_get_i("file.undowrite")) if (io->undo.w_lock)
return; return;
if (undo_w_lock) if (!io->undo.w_init) {
return; io->undo.w_init = 1;
INIT_LIST_HEAD(&(io->undo.w_list));
if (!undo_w_init) {
undo_w_init = 1;
INIT_LIST_HEAD(&(undo_w_list));
} }
/* undo changes */ /* undo changes */
uw->set = UNDO_WRITE_SET; uw->set = R_TRUE;
uw->off = off; uw->off = off;
uw->len = len; uw->len = len;
uw->n = (ut8*) malloc(len); uw->n = (ut8*) malloc(len);
memcpy(uw->n, data, len); memcpy(uw->n, data, len);
uw->o = (ut8*) malloc(len); uw->o = (ut8*) malloc(len);
radare_read_at(off, uw->o, len); r_io_read_at(io, off, uw->o, len);
list_add_tail(&(uw->list), &(undo_w_list)); list_add_tail(&(uw->list), &(io->undo.w_list));
} }
void undo_write_clear() R_API void r_io_undo_write_clear(struct r_io_t *io)
{ {
// XXX memory leak // XXX memory leak
INIT_LIST_HEAD(&(undo_w_list)); INIT_LIST_HEAD(&(io->undo.w_list));
} }
int undo_write_size() // rename to r_io_undo_length
R_API int r_io_undo_write_size(struct r_io_t *io)
{ {
struct list_head *p; struct list_head *p;
int i = 0; int i = 0;
if (undo_w_init) if (io->undo.w_init)
list_for_each_prev(p, &(undo_w_list)) { list_for_each_prev(p, &(io->undo.w_list)) {
i++; i++;
} }
return i; return i;
} }
void undo_write_list() // TODO: Deprecate or so? iterators must be language-wide, but helpers are useful
R_API void r_io_undo_write_list(struct r_io_t *io)
{ {
#define BW 8 /* byte wrap */ #define BW 8 /* byte wrap */
struct list_head *p; struct list_head *p;
int i = 0, j, len; int i = 0, j, len;
if (undo_w_init) if (io->undo.w_init)
list_for_each_prev(p, &(undo_w_list)) { list_for_each_prev(p, &(io->undo.w_list)) {
struct undow_t *u = list_entry(p, struct undow_t, list); struct r_io_undo_w_t *u = list_entry(p, struct r_io_undo_w_t, list);
cons_printf("%02d %c %d %08llx: ", i, u->set?'+':'-', u->len, u->off); cons_printf("%02d %c %d %08llx: ", i, u->set?'+':'-', u->len, u->off);
len = (u->len>BW)?BW:u->len; len = (u->len>BW)?BW:u->len;
for(j=0;j<len;j++) cons_printf("%02x ", u->o[j]); for(j=0;j<len;j++) cons_printf("%02x ", u->o[j]);
@ -177,52 +145,49 @@ void undo_write_list()
} }
} }
int undo_write_set_t(struct undow_t *u, int set) R_API int r_io_undo_write_set_t(struct r_io_t *io, struct r_io_undo_w_t *u, int set)
{ {
undo_w_lock = 1; io->undo.w_lock = 1;
if (set) { if (set) {
radare_write_at(u->off, u->n, u->len); r_io_write_at(io, u->off, u->n, u->len);
u->set = UNDO_WRITE_SET; u->set = R_TRUE;
} else { } else {
radare_write_at(u->off, u->o, u->len); r_io_write_at(io, u->off, u->o, u->len);
u->set = UNDO_WRITE_UNSET; u->set = R_FALSE;
} }
undo_w_lock = 0; io->undo.w_lock = 0;
return 0; return 0;
} }
void undo_write_set_all(int set) R_API void r_io_undo_write_set_all(struct r_io_t *io, int set)
{ {
struct list_head *p; struct list_head *p;
if (undo_w_init) if (io->undo.w_init)
list_for_each_prev(p, &(undo_w_list)) { list_for_each_prev(p, &(io->undo.w_list)) {
struct undow_t *u = list_entry(p, struct undow_t, list); struct r_io_undo_w_t *u = list_entry(p, struct r_io_undo_w_t, list);
undo_write_set_t(u, set); //UNDO_WRITE_UNSET); r_io_undo_write_set_t(io, u, set); //UNDO_WRITE_UNSET);
eprintf("%s 0x%08llx\n", set?"redo":"undo", u->off); eprintf("%s 0x%08llx\n", set?"redo":"undo", u->off);
} }
} }
/* sets or unsets the writes done */ /* sets or unsets the writes done */
/* if ( set == 0 ) unset(n) */ /* if ( set == 0 ) unset(n) */
int undo_write_set(int n, int set) R_API int r_io_undo_write_set(struct r_io_t *io, int n, int set)
{ {
struct undow_t *u = NULL; struct r_io_undo_w_t *u = NULL;
struct list_head *p; struct list_head *p;
int i = 0; int i = 0;
if (io->undo.w_init) {
if (undo_w_init) { list_for_each_prev(p, &(io->undo.w_list)) {
list_for_each_prev(p, &(undo_w_list)) {
if (i++ == n) { if (i++ == n) {
u = list_entry(p, struct undow_t, list); u = list_entry(p, struct r_io_undo_w_t, list);
break; break;
} }
} }
if (u) undo_write_set_t(u, set); if (u) r_io_undo_write_set_t(io, u, set);
else eprintf("invalid undo-write index\n"); else eprintf("invalid undo-write index\n");
} else } else eprintf("no writes done\n");
eprintf("no writes done\n");
return 0; return 0;
} }

View File

@ -17,6 +17,7 @@ namespace Radare
CUR = 1, CUR = 1,
END = 2, END = 2,
} }
/** /**
* Do the io! :D * Do the io! :D
*/ */
@ -41,6 +42,12 @@ namespace Radare
public int close(int fd); public int close(int fd);
public uint64 size(int fd); public uint64 size(int fd);
/* undo */
public void undo_enable(int set);
public uint64 undo_seek();
public void undo_redo();
public void undo_push();
/* handle */ /* handle */
public struct Handle { public struct Handle {
string name; string name;