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

View File

@ -4,18 +4,14 @@
#include "r_types.h"
#include "list.h"
#define R_IO_READ 0
#define R_IO_WRITE 1
#define R_IO_EXEC 4
#define R_IO_READ 4
#define R_IO_WRITE 2
#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
// DEPRECATE ??
#define R_IO_RW R_IO_READ|R_IO_WRITE
@ -26,9 +22,6 @@ enum {
#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
struct r_io_map_t {
@ -43,13 +36,25 @@ struct r_io_map_t {
/* stores write and seek changes */
#define R_IO_UNDOS 64
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_lock;
/* seek stuff */
ut64 seek[R_IO_UNDOS];
int fd[R_IO_UNDOS];
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 {
@ -65,6 +70,7 @@ struct r_io_t {
ut8 *write_mask_buf;
int write_mask_len;
struct r_io_handle_t *plugin;
struct r_io_undo_t undo;
struct list_head io_list;
ut64 last_align;
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 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);
/* 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
#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)

View File

@ -9,7 +9,7 @@ STATIC_OBJS=
include ../config.mk
include ${STATIC_IO_PLUGINS}
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:
@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;
}
#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
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)
{
io->cached = 0; // IO cached
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)
{
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);
}
#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 <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)
{
io->write_mask_fd = -1;
io->last_align = 0;
io->redirect = NULL;
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_map_init(io);
r_io_section_init(io);
r_io_handle_init(io);
r_io_desc_init(io);
r_io_undo_init(&io->undo);
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)
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) {
r_io_set_fd(io, fd);
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;
}
R_API int r_io_read(struct r_io_t *io, ut8 *buf, int len)
{
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
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)
{
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));
}

View File

@ -1,170 +1,138 @@
/*
* 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
*
*/
/* radare - LGPL - Copyright 2007-2009 pancake<nopcode.org> */
#include "main.h"
#include "radare.h"
#include "list.h"
#include "undo.h"
#include <r_io.h>
#define cons_printf printf
#define cons_newline() printf("\n");
#if 0
* Handle changes in write and seeks
* Per-fd history log
* TODO:
* - make path of indirections shortr (io->undo.foo is slow) */
* - Handle changes in write and seeks
* - Per-fd history log
#endif
#if 0
/* 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)
R_API int r_io_undo_init(struct r_io_t *io)
{
u->undo_w_init = 0;
u->undo_w_lock = 0;
u->undos_idx = 0;
u->undos_lim = 0;
io->undo.w_init = 0;
io->undo.w_lock = 0;
io->undo.idx = 0;
io->undo.limit = 0;
io->undo.enable = 0;
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 config.seek;
return undos[undos_idx-2];
return (io->undo.idx)?
io->undo.seek[io->undo.idx-2] : io->seek;
}
void undo_seek()
R_API void r_io_undo_seek(struct r_io_t *io)
{
if (--undos_idx<0)
undos_idx = 0;
else config.seek = undos[undos_idx-1];
if (--io->undo.idx<0)
io->undo.idx = 0;
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) {
undos_idx+=2;
undo_seek();
if (io->undo.idx<io->undo.limit) {
io->undo.idx += 2;
r_io_undo_seek(io);
}
}
void undo_push()
R_API void r_io_undo_push(struct r_io_t *io)
{
int i;
if (undos[undos_idx-1] == config.seek)
if (io->undo.seek[io->undo.idx-1] == io->seek)
return;
undos[undos_idx] = config.seek;
if (undos_idx==UNDOS-1) {
for(i=1;i<UNDOS;i++)
undos[i-1] = undos[i];
} else
undos_idx++;
io->undo.seek[io->undo.idx] = io->seek;
if (io->undo.idx==R_IO_UNDOS-1) {
for(i=1;i<R_IO_UNDOS;i++)
io->undo.seek[i-1] = io->undo.seek[i];
} else io->undo.idx++;
if (undos_lim<undos_idx)
undos_lim = undos_idx;
if (io->undo.limit<io->undo.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;
if (undos_idx<1)
eprintf("-no seeks done-\n");
else {
cons_printf("f undo_idx @ %d\n", undos_idx);
for(i=undos_idx-1;i!=0;i--)
cons_printf("f undo_%d @ 0x%llx\n", undos_idx-1-i, undos[i-1]);
}
if (io->undo.idx>0) {
cons_printf("f undo_idx @ %d\n", io->undo.idx);
for(i=io->undo.idx-1;i!=0;i--)
cons_printf("f undo_%d @ 0x%llx\n",
io->undo.idx-1-i, io->undo.seek[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;
if (undo_w_lock)
return;
if (!undo_w_init) {
undo_w_init = 1;
INIT_LIST_HEAD(&(undo_w_list));
if (!io->undo.w_init) {
io->undo.w_init = 1;
INIT_LIST_HEAD(&(io->undo.w_list));
}
/* undo changes */
uw->set = UNDO_WRITE_SET;
uw->set = R_TRUE;
uw->off = off;
uw->len = len;
uw->n = (ut8*) malloc(len);
memcpy(uw->n, data, len);
uw->o = (ut8*) malloc(len);
radare_read_at(off, uw->o, len);
list_add_tail(&(uw->list), &(undo_w_list));
r_io_read_at(io, off, uw->o, len);
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
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;
int i = 0;
if (undo_w_init)
list_for_each_prev(p, &(undo_w_list)) {
if (io->undo.w_init)
list_for_each_prev(p, &(io->undo.w_list)) {
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 */
struct list_head *p;
int i = 0, j, len;
if (undo_w_init)
list_for_each_prev(p, &(undo_w_list)) {
struct undow_t *u = list_entry(p, struct undow_t, list);
if (io->undo.w_init)
list_for_each_prev(p, &(io->undo.w_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);
len = (u->len>BW)?BW:u->len;
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) {
radare_write_at(u->off, u->n, u->len);
u->set = UNDO_WRITE_SET;
r_io_write_at(io, u->off, u->n, u->len);
u->set = R_TRUE;
} else {
radare_write_at(u->off, u->o, u->len);
u->set = UNDO_WRITE_UNSET;
r_io_write_at(io, u->off, u->o, u->len);
u->set = R_FALSE;
}
undo_w_lock = 0;
io->undo.w_lock = 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;
if (undo_w_init)
list_for_each_prev(p, &(undo_w_list)) {
struct undow_t *u = list_entry(p, struct undow_t, list);
undo_write_set_t(u, set); //UNDO_WRITE_UNSET);
if (io->undo.w_init)
list_for_each_prev(p, &(io->undo.w_list)) {
struct r_io_undo_w_t *u = list_entry(p, struct r_io_undo_w_t, list);
r_io_undo_write_set_t(io, u, set); //UNDO_WRITE_UNSET);
eprintf("%s 0x%08llx\n", set?"redo":"undo", u->off);
}
}
/* sets or unsets the writes done */
/* 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;
int i = 0;
if (undo_w_init) {
list_for_each_prev(p, &(undo_w_list)) {
if (io->undo.w_init) {
list_for_each_prev(p, &(io->undo.w_list)) {
if (i++ == n) {
u = list_entry(p, struct undow_t, list);
u = list_entry(p, struct r_io_undo_w_t, list);
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("no writes done\n");
} else eprintf("no writes done\n");
return 0;
}

View File

@ -17,6 +17,7 @@ namespace Radare
CUR = 1,
END = 2,
}
/**
* Do the io! :D
*/
@ -41,6 +42,12 @@ namespace Radare
public int close(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 */
public struct Handle {
string name;