2021-03-14 16:55:57 +01:00
|
|
|
/* radare2 - LGPL - Copyright 2008-2021 - condret, pancake, alvaro_fe */
|
2009-02-05 22:08:46 +01:00
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
#include <r_io.h>
|
|
|
|
#include <sdb.h>
|
|
|
|
#include <config.h>
|
2018-08-31 11:57:06 +02:00
|
|
|
#include "io_private.h"
|
2017-05-09 14:25:57 +02:00
|
|
|
|
2014-01-21 15:40:10 +01:00
|
|
|
R_LIB_VERSION (r_io);
|
2013-06-14 02:51:33 +02:00
|
|
|
|
2021-10-04 14:47:22 +02:00
|
|
|
static int fd_read_at_wrap(RIO *io, int fd, ut64 addr, ut8 *buf, int len, RIOMap *map, void *user) {
|
2017-08-31 23:41:03 -07:00
|
|
|
return r_io_fd_read_at (io, fd, addr, buf, len);
|
2017-08-24 18:12:02 +00:00
|
|
|
}
|
|
|
|
|
2021-10-04 14:47:22 +02:00
|
|
|
static int fd_write_at_wrap(RIO *io, int fd, ut64 addr, ut8 *buf, int len, RIOMap *map, void *user) {
|
2017-08-31 23:41:03 -07:00
|
|
|
return r_io_fd_write_at (io, fd, addr, buf, len);
|
2017-08-24 18:12:02 +00:00
|
|
|
}
|
|
|
|
|
2017-08-31 23:41:03 -07:00
|
|
|
typedef int (*cbOnIterMap)(RIO *io, int fd, ut64 addr, ut8 *buf, int len, RIOMap *map, void *user);
|
2017-08-23 16:45:05 +02:00
|
|
|
|
2017-09-17 19:29:29 -07:00
|
|
|
// If prefix_mode is true, returns the number of bytes of operated prefix; returns < 0 on error.
|
|
|
|
// If prefix_mode is false, operates in non-stop mode and returns true iff all IO operations on overlapped maps are complete.
|
|
|
|
static st64 on_map_skyline(RIO *io, ut64 vaddr, ut8 *buf, int len, int match_flg, cbOnIterMap op, bool prefix_mode) {
|
2020-11-23 01:36:32 -03:00
|
|
|
RVector *skyline = &io->map_skyline.v;
|
2017-09-17 19:29:29 -07:00
|
|
|
ut64 addr = vaddr;
|
2018-07-30 14:54:47 +02:00
|
|
|
size_t i;
|
2017-09-17 19:29:29 -07:00
|
|
|
bool ret = true, wrap = !prefix_mode && vaddr + len < vaddr;
|
2020-11-23 01:36:32 -03:00
|
|
|
#define CMP(addr, part) ((addr) < r_itv_end (((RSkylineItem *)(part))->itv) - 1 ? -1 : \
|
|
|
|
(addr) > r_itv_end (((RSkylineItem *)(part))->itv) - 1 ? 1 : 0)
|
2017-09-17 19:29:29 -07:00
|
|
|
// Let i be the first skyline part whose right endpoint > addr
|
|
|
|
if (!len) {
|
2020-11-23 01:36:32 -03:00
|
|
|
i = r_vector_len (skyline);
|
2017-09-17 19:29:29 -07:00
|
|
|
} else {
|
2020-11-23 01:36:32 -03:00
|
|
|
r_vector_lower_bound (skyline, addr, i, CMP);
|
|
|
|
if (i == r_vector_len (skyline) && wrap) {
|
2017-09-17 19:29:29 -07:00
|
|
|
wrap = false;
|
|
|
|
i = 0;
|
|
|
|
addr = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#undef CMP
|
2020-11-23 01:36:32 -03:00
|
|
|
while (i < r_vector_len (skyline)) {
|
|
|
|
const RSkylineItem *part = r_vector_index_ptr (skyline, i);
|
2017-09-17 19:29:29 -07:00
|
|
|
// Right endpoint <= addr
|
|
|
|
if (r_itv_end (part->itv) - 1 < addr) {
|
|
|
|
i++;
|
2020-11-23 01:36:32 -03:00
|
|
|
if (wrap && i == r_vector_len (skyline)) {
|
2017-09-17 19:29:29 -07:00
|
|
|
wrap = false;
|
|
|
|
i = 0;
|
|
|
|
addr = 0;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (addr < part->itv.addr) {
|
|
|
|
// [addr, part->itv.addr) is a gap
|
|
|
|
if (prefix_mode || len <= part->itv.addr - vaddr) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
addr = part->itv.addr;
|
|
|
|
}
|
|
|
|
// Now left endpoint <= addr < right endpoint
|
|
|
|
ut64 len1 = R_MIN (vaddr + len - addr, r_itv_end (part->itv) - addr);
|
2019-08-30 15:08:19 +02:00
|
|
|
if (len1 < 1) {
|
|
|
|
break;
|
|
|
|
}
|
2020-11-23 01:36:32 -03:00
|
|
|
RIOMap *map = part->user;
|
2017-09-17 19:29:29 -07:00
|
|
|
// The map satisfies the permission requirement or p_cache is enabled
|
2020-11-23 01:36:32 -03:00
|
|
|
if (((map->perm & match_flg) == match_flg || io->p_cache)) {
|
2020-12-08 08:57:08 -06:00
|
|
|
st64 result = op (io, map->fd, map->delta + addr - r_io_map_begin(map),
|
2020-11-23 01:36:32 -03:00
|
|
|
buf + (addr - vaddr), len1, map, NULL);
|
2017-09-17 19:29:29 -07:00
|
|
|
if (prefix_mode) {
|
|
|
|
if (result < 0) {
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
addr += result;
|
|
|
|
if (result != len1) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (result != len1) {
|
|
|
|
ret = false;
|
|
|
|
}
|
|
|
|
addr += len1;
|
|
|
|
}
|
|
|
|
} else if (prefix_mode) {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
addr += len1;
|
2018-02-17 17:05:04 -08:00
|
|
|
ret = false;
|
2017-09-17 19:29:29 -07:00
|
|
|
}
|
|
|
|
// Reaches the end
|
|
|
|
if (addr == vaddr + len) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
// Wrap to the beginning of skyline if address wraps
|
|
|
|
if (!addr) {
|
|
|
|
i = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return prefix_mode ? addr - vaddr : ret;
|
|
|
|
}
|
|
|
|
|
2020-06-14 16:08:32 +02:00
|
|
|
R_API RIO* r_io_new(void) {
|
2017-08-22 07:42:16 +00:00
|
|
|
return r_io_init (R_NEW0 (RIO));
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API RIO* r_io_init(RIO* io) {
|
2018-12-20 15:31:18 +01:00
|
|
|
r_return_val_if_fail (io, NULL);
|
2017-09-04 12:41:09 -07:00
|
|
|
io->addrbytes = 1;
|
2021-05-28 13:02:12 +02:00
|
|
|
io->cb_printf = printf; // r_cons_printf;
|
2011-04-19 00:59:16 +02:00
|
|
|
r_io_desc_init (io);
|
2021-03-14 19:16:51 +01:00
|
|
|
r_io_bank_init (io);
|
2021-09-22 16:44:54 +02:00
|
|
|
RIOBank *bank = r_io_bank_new ("default");
|
|
|
|
if (bank) {
|
|
|
|
io->bank = bank->id;
|
|
|
|
r_io_bank_add (io, bank);
|
|
|
|
void **p;
|
|
|
|
r_pvector_foreach (&io->maps, p) {
|
|
|
|
RIOMap *map = (RIOMap*) p;
|
|
|
|
r_io_bank_map_add_top (io, bank->id, map->id);
|
|
|
|
}
|
|
|
|
}
|
2020-11-23 01:36:32 -03:00
|
|
|
r_skyline_init (&io->map_skyline);
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_map_init (io);
|
2014-01-21 15:40:10 +01:00
|
|
|
r_io_cache_init (io);
|
|
|
|
r_io_plugin_init (io);
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_undo_init (io);
|
2020-10-29 19:46:48 -03:00
|
|
|
io->event = r_event_new (io);
|
2010-05-20 17:40:58 +02:00
|
|
|
return io;
|
2009-08-22 01:54:24 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API void r_io_free(RIO *io) {
|
2019-03-16 20:46:11 +01:00
|
|
|
if (io) {
|
|
|
|
r_io_fini (io);
|
|
|
|
r_cache_free (io->buffer);
|
|
|
|
free (io);
|
2016-12-15 10:22:40 +01:00
|
|
|
}
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2018-09-21 02:16:54 +02:00
|
|
|
R_API RIODesc *r_io_open_buffer(RIO *io, RBuffer *b, int perm, int mode) {
|
2019-04-15 13:24:15 +02:00
|
|
|
ut64 bufSize = r_buf_size (b);
|
2020-10-13 16:26:15 +02:00
|
|
|
char *uri = r_str_newf ("malloc://%" PFMT64d, bufSize);
|
2018-09-21 02:16:54 +02:00
|
|
|
RIODesc *desc = r_io_open_nomap (io, uri, perm, mode);
|
2018-01-11 01:03:29 +01:00
|
|
|
if (desc) {
|
2019-05-15 15:34:06 +02:00
|
|
|
const ut8 *tmp = r_buf_data (b, &bufSize);
|
2019-04-15 13:24:15 +02:00
|
|
|
r_io_desc_write (desc, tmp, bufSize);
|
2018-01-11 01:03:29 +01:00
|
|
|
}
|
2020-02-20 22:54:16 +01:00
|
|
|
free (uri);
|
2018-01-11 01:03:29 +01:00
|
|
|
return desc;
|
2009-09-07 20:01:34 +00:00
|
|
|
}
|
|
|
|
|
2018-09-21 02:16:54 +02:00
|
|
|
R_API RIODesc *r_io_open_nomap(RIO *io, const char *uri, int perm, int mode) {
|
2019-03-16 20:46:11 +01:00
|
|
|
r_return_val_if_fail (io && uri, NULL);
|
2018-09-21 02:16:54 +02:00
|
|
|
RIODesc *desc = r_io_desc_open (io, uri, perm, mode);
|
2017-08-19 02:23:51 +00:00
|
|
|
if ((io->autofd || !io->desc) && desc) {
|
2017-05-03 17:19:49 +02:00
|
|
|
io->desc = desc;
|
|
|
|
}
|
2017-08-19 02:23:51 +00:00
|
|
|
//set desc as current if autofd or io->desc==NULL
|
2011-01-20 22:52:16 +01:00
|
|
|
return desc;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
/* opens a file and maps it to 0x0 */
|
2018-09-21 02:16:54 +02:00
|
|
|
R_API RIODesc* r_io_open(RIO* io, const char* uri, int perm, int mode) {
|
2020-04-07 12:43:41 +02:00
|
|
|
r_return_val_if_fail (io, NULL);
|
2018-09-21 02:16:54 +02:00
|
|
|
RIODesc* desc = r_io_open_nomap (io, uri, perm, mode);
|
2019-03-16 20:46:11 +01:00
|
|
|
if (desc) {
|
|
|
|
r_io_map_new (io, desc->fd, desc->perm, 0LL, 0LL, r_io_desc_size (desc));
|
2016-07-03 22:36:42 +02:00
|
|
|
}
|
2014-09-05 16:53:08 +02:00
|
|
|
return desc;
|
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
/* opens a file and maps it to an offset specified by the "at"-parameter */
|
2018-09-21 02:16:54 +02:00
|
|
|
R_API RIODesc* r_io_open_at(RIO* io, const char* uri, int perm, int mode, ut64 at) {
|
2020-04-07 12:43:41 +02:00
|
|
|
r_return_val_if_fail (io && uri, NULL);
|
2019-03-16 20:46:11 +01:00
|
|
|
|
|
|
|
RIODesc* desc = r_io_open_nomap (io, uri, perm, mode);
|
2017-08-22 07:42:16 +00:00
|
|
|
if (!desc) {
|
2014-09-06 00:30:52 +02:00
|
|
|
return NULL;
|
2014-01-23 21:05:35 -06:00
|
|
|
}
|
2019-03-16 20:46:11 +01:00
|
|
|
ut64 size = r_io_desc_size (desc);
|
2017-08-22 07:42:16 +00:00
|
|
|
// second map
|
2017-08-24 13:39:12 +08:00
|
|
|
if (size && ((UT64_MAX - size + 1) < at)) {
|
2017-08-22 07:42:16 +00:00
|
|
|
// split map into 2 maps if only 1 big map results into interger overflow
|
2021-10-09 23:44:07 +02:00
|
|
|
r_io_map_new (io, desc->fd, desc->perm, UT64_MAX - at + 1, 0LL, size - (UT64_MAX - at) - 1);
|
2017-08-22 07:42:16 +00:00
|
|
|
// someone pls take a look at this confusing stuff
|
2017-08-24 13:39:12 +08:00
|
|
|
size = UT64_MAX - at + 1;
|
2014-10-20 10:29:32 +02:00
|
|
|
}
|
2017-09-16 14:57:44 -07:00
|
|
|
// skyline not updated
|
2018-09-21 02:16:54 +02:00
|
|
|
r_io_map_new (io, desc->fd, desc->perm, 0LL, at, size);
|
2017-08-22 07:42:16 +00:00
|
|
|
return desc;
|
2014-10-20 10:29:32 +02:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
/* opens many files, without mapping them. This should be discussed */
|
2018-09-21 02:16:54 +02:00
|
|
|
R_API RList* r_io_open_many(RIO* io, const char* uri, int perm, int mode) {
|
2017-08-22 07:42:16 +00:00
|
|
|
RList* desc_list;
|
|
|
|
RListIter* iter;
|
|
|
|
RIODesc* desc;
|
2018-12-20 15:31:18 +01:00
|
|
|
r_return_val_if_fail (io && io->files && uri, NULL);
|
2017-08-22 07:42:16 +00:00
|
|
|
RIOPlugin* plugin = r_io_plugin_resolve (io, uri, 1);
|
|
|
|
if (!plugin || !plugin->open_many || !plugin->close) {
|
|
|
|
return NULL;
|
2017-05-03 17:19:49 +02:00
|
|
|
}
|
2018-09-21 02:16:54 +02:00
|
|
|
if (!(desc_list = plugin->open_many (io, uri, perm, mode))) {
|
2017-08-22 07:42:16 +00:00
|
|
|
return NULL;
|
2017-05-03 17:19:49 +02:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
r_list_foreach (desc_list, iter, desc) {
|
|
|
|
if (desc) {
|
|
|
|
if (!desc->plugin) {
|
|
|
|
desc->plugin = plugin;
|
|
|
|
}
|
|
|
|
if (!desc->uri) {
|
|
|
|
desc->uri = strdup (uri);
|
|
|
|
}
|
|
|
|
//should autofd be honored here?
|
|
|
|
r_io_desc_add (io, desc);
|
2017-08-24 13:39:12 +08:00
|
|
|
if (!io->desc) {
|
2017-08-22 07:42:16 +00:00
|
|
|
io->desc = desc;
|
|
|
|
}
|
2017-05-03 17:19:49 +02:00
|
|
|
}
|
|
|
|
}
|
2021-01-10 11:34:38 -05:00
|
|
|
// ensure no double free with r_list_close and r_io_free
|
|
|
|
desc_list->free = NULL;
|
2017-08-22 07:42:16 +00:00
|
|
|
return desc_list;
|
2009-08-22 04:54:41 +00:00
|
|
|
}
|
|
|
|
|
2018-09-21 02:16:54 +02:00
|
|
|
R_API bool r_io_reopen(RIO* io, int fd, int perm, int mode) {
|
2021-10-04 14:47:22 +02:00
|
|
|
RIODesc *od = r_io_desc_get (io, fd);
|
|
|
|
if (!od) {
|
2017-08-22 07:42:16 +00:00
|
|
|
return false;
|
2014-04-23 18:04:25 -05:00
|
|
|
}
|
2021-10-04 14:47:22 +02:00
|
|
|
const char *uri = od->referer? od->referer: od->uri;
|
2019-10-07 10:48:31 +02:00
|
|
|
#if __WINDOWS__ //TODO: workaround, see https://github.com/radareorg/radare2/issues/8840
|
2021-10-04 14:47:22 +02:00
|
|
|
if (od->plugin->close && !od->plugin->close (od)) {
|
2018-03-01 11:49:40 +01:00
|
|
|
return false;
|
|
|
|
}
|
2021-10-04 14:47:22 +02:00
|
|
|
#endif
|
|
|
|
RIODesc *nd = r_io_open_nomap (io, uri, perm, mode);
|
|
|
|
if (nd) {
|
|
|
|
r_io_desc_exchange (io, od->fd, nd->fd);
|
|
|
|
r_io_desc_del (io, od->fd);
|
2021-10-04 20:56:34 +02:00
|
|
|
// bool res = r_io_desc_close (od);
|
2021-10-04 14:47:22 +02:00
|
|
|
if (nd->perm & R_PERM_W) {
|
|
|
|
io->corebind.cmdf (io->corebind.core, "omfg");
|
|
|
|
}
|
2021-10-04 20:56:34 +02:00
|
|
|
return true;
|
2014-04-05 00:39:17 -05:00
|
|
|
}
|
2021-10-04 14:47:22 +02:00
|
|
|
return false;
|
2011-10-25 20:30:05 +02:00
|
|
|
}
|
|
|
|
|
2021-10-04 14:47:22 +02:00
|
|
|
R_API bool r_io_close_all(RIO* io) {
|
|
|
|
r_return_val_if_fail (io, false);
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_desc_fini (io);
|
|
|
|
r_io_map_fini (io);
|
|
|
|
ls_free (io->plugins);
|
|
|
|
r_io_desc_init (io);
|
|
|
|
r_io_map_init (io);
|
2018-08-12 20:26:28 +02:00
|
|
|
r_io_cache_fini (io);
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_plugin_init (io);
|
|
|
|
return true;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
2013-03-18 00:38:04 +01:00
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API int r_io_pread_at(RIO* io, ut64 paddr, ut8* buf, int len) {
|
2019-02-14 18:07:08 +01:00
|
|
|
r_return_val_if_fail (io && buf && len >= 0, -1);
|
2017-05-03 17:19:49 +02:00
|
|
|
if (io->ff) {
|
2017-09-18 13:14:25 -07:00
|
|
|
memset (buf, io->Oxff, len);
|
2017-04-24 19:45:33 +00:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
return r_io_desc_read_at (io->desc, paddr, buf, len);
|
2017-05-03 17:19:49 +02:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API int r_io_pwrite_at(RIO* io, ut64 paddr, const ut8* buf, int len) {
|
2018-12-20 15:31:18 +01:00
|
|
|
r_return_val_if_fail (io && buf && len > 0, -1);
|
2017-08-22 07:42:16 +00:00
|
|
|
return r_io_desc_write_at (io->desc, paddr, buf, len);
|
2009-09-02 00:10:51 +00:00
|
|
|
}
|
|
|
|
|
2018-02-27 09:41:52 -08:00
|
|
|
// Returns true iff all reads on mapped regions are successful and complete.
|
|
|
|
R_API bool r_io_vread_at_mapped(RIO* io, ut64 vaddr, ut8* buf, int len) {
|
2018-12-20 15:31:18 +01:00
|
|
|
r_return_val_if_fail (io && buf && len > 0, false);
|
2017-08-22 07:42:16 +00:00
|
|
|
if (io->ff) {
|
2017-09-18 13:14:25 -07:00
|
|
|
memset (buf, io->Oxff, len);
|
2016-12-22 00:13:16 +03:00
|
|
|
}
|
2018-09-21 02:16:54 +02:00
|
|
|
return on_map_skyline (io, vaddr, buf, len, R_PERM_R, fd_read_at_wrap, false);
|
2017-08-22 14:52:40 +00:00
|
|
|
}
|
|
|
|
|
2018-02-27 09:41:52 -08:00
|
|
|
static bool r_io_vwrite_at(RIO* io, ut64 vaddr, const ut8* buf, int len) {
|
2018-09-21 02:16:54 +02:00
|
|
|
return on_map_skyline (io, vaddr, (ut8*)buf, len, R_PERM_W, fd_write_at_wrap, false);
|
2014-03-24 22:00:26 -05:00
|
|
|
}
|
2017-08-22 23:55:18 +02:00
|
|
|
|
2021-03-14 16:55:57 +01:00
|
|
|
static bool internal_r_io_read_at(RIO *io, ut64 addr, ut8 *buf, int len) {
|
|
|
|
if (len < 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
bool ret = (io->va)
|
2021-09-22 16:44:54 +02:00
|
|
|
? (io->use_banks)
|
|
|
|
? r_io_bank_read_at (io, io->bank, addr, buf, len)
|
|
|
|
: r_io_vread_at_mapped (io, addr, buf, len)
|
2021-03-14 16:55:57 +01:00
|
|
|
: r_io_pread_at (io, addr, buf, len) > 0;
|
|
|
|
if (io->cached & R_PERM_R) {
|
|
|
|
(void)r_io_cache_read (io, addr, buf, len);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-02-27 09:41:52 -08:00
|
|
|
// Deprecated, use either r_io_read_at_mapped or r_io_nread_at instead.
|
|
|
|
// For virtual mode, returns true if all reads on mapped regions are successful
|
|
|
|
// and complete.
|
|
|
|
// For physical mode, the interface is broken because the actual read bytes are
|
|
|
|
// not available. This requires fixes in all call sites.
|
|
|
|
R_API bool r_io_read_at(RIO *io, ut64 addr, ut8 *buf, int len) {
|
2019-02-14 18:07:08 +01:00
|
|
|
r_return_val_if_fail (io && buf && len >= 0, false);
|
|
|
|
if (len == 0) {
|
|
|
|
return false;
|
|
|
|
}
|
2021-03-14 16:55:57 +01:00
|
|
|
if (io->mask) {
|
|
|
|
ut64 p = addr;
|
|
|
|
ut8 *b = buf;
|
|
|
|
size_t q = 0;
|
|
|
|
while (q < len) {
|
|
|
|
p &= io->mask;
|
|
|
|
size_t sz = io->mask - p + 1;
|
|
|
|
size_t left = len - q;
|
|
|
|
if (sz > left) {
|
|
|
|
sz = left;
|
|
|
|
}
|
|
|
|
if (!internal_r_io_read_at (io, p, buf + q, sz)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
q += sz;
|
|
|
|
b += sz;
|
|
|
|
p = 0;
|
|
|
|
}
|
|
|
|
return true;
|
2018-02-27 09:41:52 -08:00
|
|
|
}
|
2021-03-14 16:55:57 +01:00
|
|
|
return internal_r_io_read_at (io, addr, buf, len);
|
2018-02-27 09:41:52 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Returns true iff all reads on mapped regions are successful and complete.
|
|
|
|
// Unmapped regions are filled with io->Oxff in both physical and virtual modes.
|
|
|
|
// Use this function if you want to ignore gaps or do not care about the number
|
|
|
|
// of read bytes.
|
|
|
|
R_API bool r_io_read_at_mapped(RIO *io, ut64 addr, ut8 *buf, int len) {
|
|
|
|
bool ret;
|
2018-12-20 15:31:18 +01:00
|
|
|
r_return_val_if_fail (io && buf, false);
|
2018-02-27 09:41:52 -08:00
|
|
|
if (io->ff) {
|
2018-08-11 19:18:58 +02:00
|
|
|
memset (buf, io->Oxff, len);
|
2018-02-27 09:41:52 -08:00
|
|
|
}
|
|
|
|
if (io->va) {
|
2018-09-21 02:16:54 +02:00
|
|
|
ret = on_map_skyline (io, addr, buf, len, R_PERM_R, fd_read_at_wrap, false);
|
2018-02-27 09:41:52 -08:00
|
|
|
} else {
|
2018-08-11 19:18:58 +02:00
|
|
|
ret = r_io_pread_at (io, addr, buf, len) > 0;
|
2018-02-27 09:41:52 -08:00
|
|
|
}
|
2018-09-21 02:16:54 +02:00
|
|
|
if (io->cached & R_PERM_R) {
|
2018-02-27 09:41:52 -08:00
|
|
|
(void)r_io_cache_read(io, addr, buf, len);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
// For both virtual and physical mode, returns the number of bytes of read
|
|
|
|
// prefix.
|
|
|
|
// Returns -1 on error.
|
|
|
|
R_API int r_io_nread_at(RIO *io, ut64 addr, ut8 *buf, int len) {
|
|
|
|
int ret;
|
2019-02-14 18:07:08 +01:00
|
|
|
r_return_val_if_fail (io && buf && len >= 0, -1);
|
|
|
|
if (len == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
2018-02-27 09:41:52 -08:00
|
|
|
if (io->va) {
|
|
|
|
if (io->ff) {
|
2018-08-11 19:18:58 +02:00
|
|
|
memset (buf, io->Oxff, len);
|
2018-02-27 09:41:52 -08:00
|
|
|
}
|
2018-09-21 02:16:54 +02:00
|
|
|
ret = on_map_skyline (io, addr, buf, len, R_PERM_R, fd_read_at_wrap, true);
|
2018-02-27 09:41:52 -08:00
|
|
|
} else {
|
2018-08-11 19:18:58 +02:00
|
|
|
ret = r_io_pread_at (io, addr, buf, len);
|
2018-02-27 09:41:52 -08:00
|
|
|
}
|
2018-09-21 02:16:54 +02:00
|
|
|
if (ret > 0 && io->cached & R_PERM_R) {
|
2018-08-11 19:18:58 +02:00
|
|
|
(void)r_io_cache_read (io, addr, buf, len);
|
2016-12-19 06:56:27 +03:00
|
|
|
}
|
2009-02-05 22:08:46 +01:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-08-22 14:52:40 +00:00
|
|
|
R_API bool r_io_write_at(RIO* io, ut64 addr, const ut8* buf, int len) {
|
|
|
|
int i;
|
2017-09-07 15:47:39 +00:00
|
|
|
bool ret = false;
|
2017-08-14 00:55:47 +00:00
|
|
|
ut8 *mybuf = (ut8*)buf;
|
2018-12-20 15:31:18 +01:00
|
|
|
r_return_val_if_fail (io && buf && len > 0, false);
|
2017-08-22 07:42:16 +00:00
|
|
|
if (io->write_mask) {
|
2017-08-14 00:55:47 +00:00
|
|
|
mybuf = r_mem_dup ((void*)buf, len);
|
|
|
|
for (i = 0; i < len; i++) {
|
|
|
|
//this sucks
|
2017-08-22 16:09:45 -07:00
|
|
|
mybuf[i] &= io->write_mask[i % io->write_mask_len];
|
2017-08-14 00:55:47 +00:00
|
|
|
}
|
|
|
|
}
|
2018-09-21 02:16:54 +02:00
|
|
|
if (io->cached & R_PERM_W) {
|
2017-09-15 02:32:01 -07:00
|
|
|
ret = r_io_cache_write (io, addr, mybuf, len);
|
2017-08-14 00:55:47 +00:00
|
|
|
} else if (io->va) {
|
|
|
|
ret = r_io_vwrite_at (io, addr, mybuf, len);
|
|
|
|
} else {
|
2018-02-27 09:41:52 -08:00
|
|
|
ret = r_io_pwrite_at (io, addr, mybuf, len) > 0;
|
2017-08-14 00:55:47 +00:00
|
|
|
}
|
|
|
|
if (buf != mybuf) {
|
|
|
|
free (mybuf);
|
|
|
|
}
|
|
|
|
return ret;
|
2009-09-02 00:10:51 +00:00
|
|
|
}
|
2009-08-22 04:54:41 +00:00
|
|
|
|
2017-08-22 14:52:40 +00:00
|
|
|
R_API bool r_io_read(RIO* io, ut8* buf, int len) {
|
2018-08-12 20:26:28 +02:00
|
|
|
if (io && r_io_read_at (io, io->off, buf, len)) {
|
2017-08-22 14:52:40 +00:00
|
|
|
io->off += len;
|
|
|
|
return true;
|
2016-06-20 09:12:44 +02:00
|
|
|
}
|
2017-08-22 14:52:40 +00:00
|
|
|
return false;
|
2017-08-22 07:42:16 +00:00
|
|
|
}
|
|
|
|
|
2017-08-22 14:52:40 +00:00
|
|
|
R_API bool r_io_write(RIO* io, ut8* buf, int len) {
|
2018-08-12 20:26:28 +02:00
|
|
|
if (io && buf && len > 0 && r_io_write_at (io, io->off, buf, len)) {
|
2017-08-22 14:52:40 +00:00
|
|
|
io->off += len;
|
|
|
|
return true;
|
2016-06-20 11:08:21 +02:00
|
|
|
}
|
2017-08-22 14:52:40 +00:00
|
|
|
return false;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API ut64 r_io_size(RIO* io) {
|
2017-08-24 13:39:12 +08:00
|
|
|
// TODO: rethink this, maybe not needed
|
2017-05-03 17:19:49 +02:00
|
|
|
return io? r_io_desc_size (io->desc): 0LL;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API bool r_io_is_listener(RIO* io) {
|
|
|
|
if (io && io->desc && io->desc->plugin && io->desc->plugin->listener) {
|
|
|
|
return io->desc->plugin->listener (io->desc);
|
2016-10-09 23:56:52 +02:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2017-10-22 23:52:07 +02:00
|
|
|
R_API char *r_io_system(RIO* io, const char* cmd) {
|
2017-08-22 07:42:16 +00:00
|
|
|
if (io && io->desc && io->desc->plugin && io->desc->plugin->system) {
|
|
|
|
return io->desc->plugin->system (io, io->desc, cmd);
|
|
|
|
}
|
2017-10-22 23:52:07 +02:00
|
|
|
return NULL;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API bool r_io_resize(RIO* io, ut64 newsize) {
|
2017-08-31 15:23:31 +00:00
|
|
|
if (io) {
|
2021-03-12 20:28:48 +01:00
|
|
|
RList *maps = r_io_map_get_by_fd (io, io->desc->fd);
|
2017-09-15 11:25:38 +02:00
|
|
|
RIOMap *current_map;
|
|
|
|
RListIter *iter;
|
|
|
|
ut64 fd_size = r_io_fd_size (io, io->desc->fd);
|
|
|
|
r_list_foreach (maps, iter, current_map) {
|
|
|
|
// we just resize map of the same size of its fd
|
2020-12-08 08:57:08 -06:00
|
|
|
if (r_io_map_size (current_map) == fd_size) {
|
2017-09-15 11:25:38 +02:00
|
|
|
r_io_map_resize (io, current_map->id, newsize);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_list_free (maps);
|
2017-08-31 15:23:31 +00:00
|
|
|
return r_io_desc_resize (io->desc, newsize);
|
2016-06-20 00:29:41 +02:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
return false;
|
2016-06-20 00:29:41 +02:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API bool r_io_close(RIO *io) {
|
|
|
|
return io ? r_io_desc_close (io->desc) : false;
|
2009-02-05 22:08:46 +01:00
|
|
|
}
|
2009-09-10 20:51:34 +00:00
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API int r_io_extend_at(RIO* io, ut64 addr, ut64 size) {
|
|
|
|
ut64 cur_size, tmp_size;
|
|
|
|
ut8* buffer;
|
|
|
|
if (!io || !io->desc || !io->desc->plugin || !size) {
|
|
|
|
return false;
|
2017-03-02 22:47:59 +01:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
if (io->desc->plugin->extend) {
|
|
|
|
int ret;
|
|
|
|
ut64 cur_off = io->off;
|
|
|
|
r_io_seek (io, addr, R_IO_SEEK_SET);
|
2017-09-01 17:09:17 +02:00
|
|
|
ret = r_io_desc_extend (io->desc, size);
|
2017-08-22 07:42:16 +00:00
|
|
|
//no need to seek here
|
2017-08-24 13:39:12 +08:00
|
|
|
io->off = cur_off;
|
2017-08-22 07:42:16 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2018-09-21 02:16:54 +02:00
|
|
|
if ((io->desc->perm & R_PERM_RW) != R_PERM_RW) {
|
2017-08-22 07:42:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
cur_size = r_io_desc_size (io->desc);
|
|
|
|
if (addr > cur_size) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if ((UT64_MAX - size) < cur_size) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (!r_io_resize (io, cur_size + size)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if ((tmp_size = cur_size - addr) == 0LL) {
|
|
|
|
return true;
|
|
|
|
}
|
2017-08-23 01:33:36 +02:00
|
|
|
if (!(buffer = calloc (1, (size_t) tmp_size + 1))) {
|
2017-08-22 07:42:16 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
r_io_pread_at (io, addr, buffer, (int) tmp_size);
|
2017-08-23 01:33:36 +02:00
|
|
|
/* fill with null bytes */
|
|
|
|
ut8 *empty = calloc (1, size);
|
|
|
|
if (empty) {
|
|
|
|
r_io_pwrite_at (io, addr, empty, size);
|
|
|
|
free (empty);
|
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_pwrite_at (io, addr + size, buffer, (int) tmp_size);
|
|
|
|
free (buffer);
|
|
|
|
return true;
|
2015-01-22 02:22:29 +01:00
|
|
|
}
|
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API bool r_io_set_write_mask(RIO* io, const ut8* mask, int len) {
|
|
|
|
if (!io || len < 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
free (io->write_mask);
|
|
|
|
if (!mask) {
|
|
|
|
io->write_mask = NULL;
|
|
|
|
io->write_mask_len = 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
io->write_mask = (ut8*) malloc (len);
|
|
|
|
memcpy (io->write_mask, mask, len);
|
|
|
|
io->write_mask_len = len;
|
|
|
|
return true;
|
2017-05-03 17:19:49 +02:00
|
|
|
}
|
|
|
|
|
2019-04-15 13:22:27 +02:00
|
|
|
R_API ut64 r_io_p2v(RIO *io, ut64 pa) {
|
|
|
|
RIOMap *map = r_io_map_get_paddr (io, pa);
|
|
|
|
if (map) {
|
2020-12-08 08:57:08 -06:00
|
|
|
return pa - map->delta + r_io_map_begin (map);
|
2019-04-15 13:22:27 +02:00
|
|
|
}
|
|
|
|
return UT64_MAX;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API ut64 r_io_v2p(RIO *io, ut64 va) {
|
2021-03-12 16:35:12 +01:00
|
|
|
RIOMap *map = r_io_map_get_at (io, va);
|
2019-04-15 13:22:27 +02:00
|
|
|
if (map) {
|
2020-12-08 08:57:08 -06:00
|
|
|
st64 delta = va - r_io_map_begin (map);
|
|
|
|
return r_io_map_begin (map) + map->delta + delta;
|
2019-04-15 13:22:27 +02:00
|
|
|
}
|
|
|
|
return UT64_MAX;
|
|
|
|
}
|
|
|
|
|
2018-10-21 01:27:15 +02:00
|
|
|
R_API void r_io_bind(RIO *io, RIOBind *bnd) {
|
|
|
|
r_return_if_fail (io && bnd);
|
|
|
|
|
2009-09-10 20:51:34 +00:00
|
|
|
bnd->io = io;
|
2015-09-14 02:08:31 +02:00
|
|
|
bnd->init = true;
|
2017-05-03 17:19:49 +02:00
|
|
|
bnd->desc_use = r_io_use_fd;
|
|
|
|
bnd->desc_get = r_io_desc_get;
|
|
|
|
bnd->desc_size = r_io_desc_size;
|
2019-04-15 13:22:27 +02:00
|
|
|
bnd->p2v = r_io_p2v;
|
|
|
|
bnd->v2p = r_io_v2p;
|
2017-05-03 17:19:49 +02:00
|
|
|
bnd->open = r_io_open_nomap;
|
|
|
|
bnd->open_at = r_io_open_at;
|
2017-08-22 07:42:16 +00:00
|
|
|
bnd->close = r_io_fd_close;
|
2009-09-10 20:51:34 +00:00
|
|
|
bnd->read_at = r_io_read_at;
|
|
|
|
bnd->write_at = r_io_write_at;
|
2016-10-08 02:39:50 +02:00
|
|
|
bnd->system = r_io_system;
|
2017-08-22 21:07:35 +00:00
|
|
|
bnd->fd_open = r_io_fd_open;
|
|
|
|
bnd->fd_close = r_io_fd_close;
|
|
|
|
bnd->fd_seek = r_io_fd_seek;
|
|
|
|
bnd->fd_size = r_io_fd_size;
|
2019-05-15 15:34:06 +02:00
|
|
|
bnd->fd_resize = r_io_fd_resize;
|
2017-08-22 21:07:35 +00:00
|
|
|
bnd->fd_read = r_io_fd_read;
|
|
|
|
bnd->fd_write = r_io_fd_write;
|
|
|
|
bnd->fd_read_at = r_io_fd_read_at;
|
|
|
|
bnd->fd_write_at = r_io_fd_write_at;
|
2017-08-23 00:04:47 +00:00
|
|
|
bnd->fd_is_dbg = r_io_fd_is_dbg;
|
|
|
|
bnd->fd_get_name = r_io_fd_get_name;
|
2021-03-12 20:28:48 +01:00
|
|
|
bnd->fd_get_map = r_io_map_get_by_fd;
|
2018-02-01 09:06:26 -08:00
|
|
|
bnd->fd_remap = r_io_map_remap_fd;
|
2017-08-23 22:19:57 +00:00
|
|
|
bnd->is_valid_offset = r_io_is_valid_offset;
|
2021-03-12 16:35:12 +01:00
|
|
|
bnd->map_get_at = r_io_map_get_at;
|
2019-04-21 17:00:45 +08:00
|
|
|
bnd->map_get_paddr = r_io_map_get_paddr;
|
2018-02-20 23:55:11 +01:00
|
|
|
bnd->addr_is_mapped = r_io_addr_is_mapped;
|
2019-01-31 17:53:34 +01:00
|
|
|
bnd->map_add = r_io_map_add;
|
2018-10-12 12:20:18 +02:00
|
|
|
#if HAVE_PTRACE
|
|
|
|
bnd->ptrace = r_io_ptrace;
|
2018-11-20 01:13:30 +01:00
|
|
|
bnd->ptrace_func = r_io_ptrace_func;
|
2018-10-12 12:20:18 +02:00
|
|
|
#endif
|
2009-09-10 20:51:34 +00:00
|
|
|
}
|
2011-02-05 00:20:28 +01:00
|
|
|
|
2011-02-05 12:51:37 +01:00
|
|
|
/* moves bytes up (+) or down (-) within the specified range */
|
2020-04-13 17:49:13 +02:00
|
|
|
R_API bool r_io_shift(RIO* io, ut64 start, ut64 end, st64 move) {
|
2017-08-22 07:42:16 +00:00
|
|
|
ut8* buf;
|
2011-02-07 09:46:01 +01:00
|
|
|
ut64 chunksize = 0x10000;
|
2017-10-08 01:47:58 +02:00
|
|
|
ut64 saved_off = io->off;
|
2017-08-22 07:42:16 +00:00
|
|
|
ut64 src, shiftsize = r_num_abs (move);
|
|
|
|
if (!shiftsize || (end - start) <= shiftsize) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ut64 rest = (end - start) - shiftsize;
|
|
|
|
if (!(buf = calloc (1, chunksize + 1))) {
|
2016-09-26 00:45:28 +02:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (move > 0) {
|
2015-12-08 22:35:39 +01:00
|
|
|
src = end - shiftsize;
|
2016-09-26 00:45:28 +02:00
|
|
|
} else {
|
|
|
|
src = start + shiftsize;
|
|
|
|
}
|
2015-12-08 22:35:39 +01:00
|
|
|
while (rest > 0) {
|
2016-10-09 23:56:52 +02:00
|
|
|
if (chunksize > rest) {
|
|
|
|
chunksize = rest;
|
|
|
|
}
|
|
|
|
if (move > 0) {
|
|
|
|
src -= chunksize;
|
|
|
|
}
|
2011-02-05 12:51:37 +01:00
|
|
|
r_io_read_at (io, src, buf, chunksize);
|
2015-12-08 22:35:39 +01:00
|
|
|
r_io_write_at (io, src + move, buf, chunksize);
|
2016-10-09 23:56:52 +02:00
|
|
|
if (move < 0) {
|
|
|
|
src += chunksize;
|
|
|
|
}
|
2011-02-05 12:51:37 +01:00
|
|
|
rest -= chunksize;
|
|
|
|
}
|
|
|
|
free (buf);
|
2017-10-08 01:47:58 +02:00
|
|
|
io->off = r_io_desc_seek (io->desc, saved_off, R_IO_SEEK_SET);
|
2015-09-14 02:08:31 +02:00
|
|
|
return true;
|
2011-02-05 12:51:37 +01:00
|
|
|
}
|
2012-07-06 02:17:44 +02:00
|
|
|
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API ut64 r_io_seek(RIO* io, ut64 offset, int whence) {
|
2014-09-18 21:27:06 +02:00
|
|
|
if (!io) {
|
2017-08-22 14:52:40 +00:00
|
|
|
return 0LL;
|
2017-04-05 10:59:37 +02:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
switch (whence) {
|
|
|
|
case R_IO_SEEK_SET:
|
|
|
|
io->off = offset;
|
|
|
|
break;
|
|
|
|
case R_IO_SEEK_CUR:
|
|
|
|
io->off += offset;
|
|
|
|
break;
|
|
|
|
case R_IO_SEEK_END:
|
|
|
|
default:
|
2017-08-26 11:03:46 +02:00
|
|
|
io->off = r_io_desc_seek (io->desc, offset, whence);
|
2017-08-22 07:42:16 +00:00
|
|
|
break;
|
2016-08-07 14:07:52 +02:00
|
|
|
}
|
2017-08-22 07:42:16 +00:00
|
|
|
return io->off;
|
2017-05-03 17:19:49 +02:00
|
|
|
}
|
|
|
|
|
2018-10-12 12:20:18 +02:00
|
|
|
#if HAVE_PTRACE
|
|
|
|
|
|
|
|
#if USE_PTRACE_WRAP
|
|
|
|
#include <ptrace_wrap.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
static ptrace_wrap_instance *io_ptrace_wrap_instance(RIO *io) {
|
|
|
|
if (!io->ptrace_wrap) {
|
|
|
|
io->ptrace_wrap = R_NEW (ptrace_wrap_instance);
|
|
|
|
if (!io->ptrace_wrap) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (ptrace_wrap_instance_start (io->ptrace_wrap) < 0) {
|
2018-11-14 00:41:28 +02:00
|
|
|
R_FREE (io->ptrace_wrap);
|
2018-10-12 12:20:18 +02:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return io->ptrace_wrap;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
R_API long r_io_ptrace(RIO *io, r_ptrace_request_t request, pid_t pid, void *addr, r_ptrace_data_t data) {
|
|
|
|
#if USE_PTRACE_WRAP
|
2021-04-21 12:07:01 +02:00
|
|
|
if (io->want_ptrace_wrap) {
|
|
|
|
ptrace_wrap_instance *wrap = io_ptrace_wrap_instance (io);
|
|
|
|
if (!wrap) {
|
|
|
|
errno = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return ptrace_wrap (wrap, request, pid, addr, data);
|
2018-10-12 12:20:18 +02:00
|
|
|
}
|
|
|
|
#endif
|
2021-04-21 12:07:01 +02:00
|
|
|
return ptrace (request, pid, addr, data);
|
2018-10-12 12:20:18 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API pid_t r_io_ptrace_fork(RIO *io, void (*child_callback)(void *), void *child_callback_user) {
|
|
|
|
#if USE_PTRACE_WRAP
|
2021-04-21 12:07:01 +02:00
|
|
|
if (io->want_ptrace_wrap) {
|
|
|
|
ptrace_wrap_instance *wrap = io_ptrace_wrap_instance (io);
|
|
|
|
if (!wrap) {
|
|
|
|
errno = 0;
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return ptrace_wrap_fork (wrap, child_callback, child_callback_user);
|
2018-10-12 12:20:18 +02:00
|
|
|
}
|
2021-04-21 12:07:01 +02:00
|
|
|
#endif
|
2018-10-12 12:20:18 +02:00
|
|
|
pid_t r = r_sys_fork ();
|
|
|
|
if (r == 0) {
|
|
|
|
child_callback (child_callback_user);
|
|
|
|
}
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2018-11-20 01:13:30 +01:00
|
|
|
R_API void *r_io_ptrace_func(RIO *io, void *(*func)(void *), void *user) {
|
|
|
|
#if USE_PTRACE_WRAP
|
|
|
|
ptrace_wrap_instance *wrap = io_ptrace_wrap_instance (io);
|
|
|
|
if (wrap) {
|
|
|
|
return ptrace_wrap_func (wrap, func, user);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return func (user);
|
|
|
|
}
|
2018-12-11 11:26:52 +00:00
|
|
|
#endif
|
2018-11-20 01:13:30 +01:00
|
|
|
|
2021-09-23 15:49:18 +02:00
|
|
|
//remove all banks, maps and descs
|
2017-08-22 07:42:16 +00:00
|
|
|
R_API int r_io_fini(RIO* io) {
|
|
|
|
if (!io) {
|
|
|
|
return false;
|
2017-05-03 17:19:49 +02:00
|
|
|
}
|
2021-03-14 19:16:51 +01:00
|
|
|
r_io_bank_fini (io);
|
2017-08-22 07:42:16 +00:00
|
|
|
r_io_map_fini (io);
|
2021-09-23 15:49:18 +02:00
|
|
|
r_io_desc_cache_fini_all (io);
|
|
|
|
r_io_desc_fini (io);
|
2017-08-22 07:42:16 +00:00
|
|
|
ls_free (io->plugins);
|
2020-11-23 01:36:32 -03:00
|
|
|
r_io_cache_fini (io);
|
2017-08-22 07:42:16 +00:00
|
|
|
r_list_free (io->undo.w_list);
|
|
|
|
if (io->runprofile) {
|
|
|
|
R_FREE (io->runprofile);
|
2017-05-03 17:19:49 +02:00
|
|
|
}
|
2020-10-29 19:46:48 -03:00
|
|
|
r_event_free (io->event);
|
2018-10-12 12:20:18 +02:00
|
|
|
#if R_IO_USE_PTRACE_WRAP
|
|
|
|
if (io->ptrace_wrap) {
|
|
|
|
ptrace_wrap_instance_stop (io->ptrace_wrap);
|
|
|
|
free (io->ptrace_wrap);
|
|
|
|
}
|
|
|
|
#endif
|
2017-08-22 07:42:16 +00:00
|
|
|
return true;
|
2014-09-18 21:27:06 +02:00
|
|
|
}
|