2016-07-28 15:12:05 +00:00
|
|
|
/* radare - LGPL - Copyright 2014-2016 - pancake */
|
2014-02-10 02:31:12 +00:00
|
|
|
|
|
|
|
#include <r_userconf.h>
|
|
|
|
#include <r_io.h>
|
|
|
|
#include <r_lib.h>
|
2014-11-22 10:50:51 +00:00
|
|
|
#include <r_cons.h>
|
2016-07-29 13:13:41 +00:00
|
|
|
|
2015-04-14 15:11:52 +00:00
|
|
|
#if DEBUGGER
|
2014-02-10 02:31:12 +00:00
|
|
|
#if __APPLE__
|
|
|
|
#include <mach/vm_map.h>
|
|
|
|
#include <mach/mach_init.h>
|
|
|
|
#include <mach/mach_port.h>
|
|
|
|
#include <mach/mach_interface.h>
|
|
|
|
#include <mach/mach_traps.h>
|
|
|
|
#include <mach/mach_types.h>
|
2015-07-06 22:23:08 +00:00
|
|
|
//#include <mach/mach_vm.h>
|
2014-02-10 02:31:12 +00:00
|
|
|
#include <mach/mach_error.h>
|
|
|
|
#include <mach/task.h>
|
|
|
|
#include <mach/task_info.h>
|
2016-03-13 23:11:31 +00:00
|
|
|
void macosx_debug_regions (RIO *io, task_t task, mach_vm_address_t address, int max);
|
2018-10-30 22:50:36 +00:00
|
|
|
#elif __FreeBSD__
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <sys/user.h>
|
|
|
|
#include <libutil.h>
|
|
|
|
bool bsd_proc_vmmaps(RIO *io, int pid);
|
2014-02-10 02:31:12 +00:00
|
|
|
#endif
|
2017-05-09 21:53:20 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
#include <process.h> // to compile getpid for msvc windows
|
|
|
|
#endif
|
2014-02-10 02:31:12 +00:00
|
|
|
|
|
|
|
typedef struct {
|
2014-11-22 01:51:35 +00:00
|
|
|
char *name;
|
2014-02-10 02:31:12 +00:00
|
|
|
ut64 from;
|
|
|
|
ut64 to;
|
|
|
|
int perm;
|
|
|
|
} RIOSelfSection;
|
|
|
|
|
|
|
|
static RIOSelfSection self_sections[1024];
|
2014-03-02 03:19:36 +00:00
|
|
|
static int self_sections_count = 0;
|
2016-07-28 15:12:05 +00:00
|
|
|
static bool mameio = false;
|
2014-02-10 02:31:12 +00:00
|
|
|
|
2016-03-13 23:11:31 +00:00
|
|
|
static int self_in_section(RIO *io, ut64 addr, int *left, int *perm) {
|
2014-02-10 02:31:12 +00:00
|
|
|
int i;
|
2016-07-28 15:12:05 +00:00
|
|
|
for (i = 0; i < self_sections_count; i++) {
|
|
|
|
if (addr >= self_sections[i].from && addr < self_sections[i].to) {
|
|
|
|
if (left) {
|
|
|
|
*left = self_sections[i].to-addr;
|
2014-02-10 02:31:12 +00:00
|
|
|
}
|
2016-07-28 15:12:05 +00:00
|
|
|
if (perm) {
|
|
|
|
*perm = self_sections[i].perm;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2014-02-10 02:31:12 +00:00
|
|
|
}
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2014-02-10 02:31:12 +00:00
|
|
|
}
|
|
|
|
|
2016-03-13 23:11:31 +00:00
|
|
|
static int update_self_regions(RIO *io, int pid) {
|
2014-02-10 02:31:12 +00:00
|
|
|
self_sections_count = 0;
|
|
|
|
#if __APPLE__
|
2016-07-28 15:12:05 +00:00
|
|
|
mach_port_t task;
|
|
|
|
kern_return_t rc;
|
|
|
|
rc = task_for_pid (mach_task_self (), pid, &task);
|
2014-02-10 02:31:12 +00:00
|
|
|
if (rc) {
|
|
|
|
eprintf ("task_for_pid failed\n");
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2014-02-10 02:31:12 +00:00
|
|
|
}
|
2016-03-13 23:11:31 +00:00
|
|
|
macosx_debug_regions (io, task, (size_t)1, 1000);
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2014-02-10 02:31:12 +00:00
|
|
|
#elif __linux__
|
|
|
|
char *pos_c;
|
2014-03-02 03:19:36 +00:00
|
|
|
int i, l, perm;
|
2014-02-10 02:31:12 +00:00
|
|
|
char path[1024], line[1024];
|
|
|
|
char region[100], region2[100], perms[5];
|
2016-07-28 15:12:05 +00:00
|
|
|
snprintf (path, sizeof (path) - 1, "/proc/%d/maps", pid);
|
2014-03-02 03:19:36 +00:00
|
|
|
FILE *fd = fopen (path, "r");
|
2018-09-13 08:17:26 +00:00
|
|
|
if (!fd) {
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2018-09-13 08:17:26 +00:00
|
|
|
}
|
2014-02-10 02:31:12 +00:00
|
|
|
|
|
|
|
while (!feof (fd)) {
|
|
|
|
line[0]='\0';
|
|
|
|
fgets (line, sizeof (line)-1, fd);
|
2016-07-28 15:12:05 +00:00
|
|
|
if (line[0] == '\0') {
|
2014-02-10 02:31:12 +00:00
|
|
|
break;
|
2016-07-28 15:12:05 +00:00
|
|
|
}
|
2014-02-10 02:31:12 +00:00
|
|
|
path[0]='\0';
|
2016-04-19 13:22:31 +00:00
|
|
|
sscanf (line, "%s %s %*s %*s %*s %[^\n]", region+2, perms, path);
|
2014-03-02 03:19:36 +00:00
|
|
|
memcpy (region, "0x", 2);
|
2016-07-28 15:12:05 +00:00
|
|
|
pos_c = strchr (region + 2, '-');
|
2014-03-02 03:19:36 +00:00
|
|
|
if (pos_c) {
|
|
|
|
*pos_c++ = 0;
|
|
|
|
memcpy (region2, "0x", 2);
|
|
|
|
l = strlen (pos_c);
|
2016-07-28 15:12:05 +00:00
|
|
|
memcpy (region2 + 2, pos_c, l);
|
|
|
|
region2[2 + l] = 0;
|
2014-11-23 09:58:05 +00:00
|
|
|
} else {
|
|
|
|
region2[0] = 0;
|
2014-03-02 03:19:36 +00:00
|
|
|
}
|
|
|
|
perm = 0;
|
2016-07-28 15:12:05 +00:00
|
|
|
for (i = 0; i < 4 && perms[i]; i++) {
|
2014-02-10 02:31:12 +00:00
|
|
|
switch (perms[i]) {
|
2018-09-21 00:16:54 +00:00
|
|
|
case 'r': perm |= R_PERM_R; break;
|
|
|
|
case 'w': perm |= R_PERM_W; break;
|
|
|
|
case 'x': perm |= R_PERM_X; break;
|
2014-02-10 02:31:12 +00:00
|
|
|
}
|
2016-07-28 15:12:05 +00:00
|
|
|
}
|
2014-02-10 02:31:12 +00:00
|
|
|
self_sections[self_sections_count].from = r_num_get (NULL, region);
|
|
|
|
self_sections[self_sections_count].to = r_num_get (NULL, region2);
|
2014-11-22 01:51:35 +00:00
|
|
|
self_sections[self_sections_count].name = strdup (path);
|
2014-02-10 02:31:12 +00:00
|
|
|
self_sections[self_sections_count].perm = perm;
|
|
|
|
self_sections_count++;
|
|
|
|
r_num_get (NULL, region2);
|
|
|
|
}
|
2014-04-29 22:38:04 +00:00
|
|
|
fclose (fd);
|
2014-11-22 01:51:35 +00:00
|
|
|
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2018-10-30 22:50:36 +00:00
|
|
|
#elif __FreeBSD__
|
|
|
|
return bsd_proc_vmmaps(io, pid);
|
2017-05-09 12:25:57 +00:00
|
|
|
#else
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma message ("Not yet implemented for this platform")
|
2014-02-10 02:31:12 +00:00
|
|
|
#else
|
|
|
|
#warning not yet implemented for this platform
|
2017-05-09 12:25:57 +00:00
|
|
|
#endif
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2014-02-10 02:31:12 +00:00
|
|
|
#endif
|
2014-11-22 01:51:35 +00:00
|
|
|
}
|
2015-07-02 00:02:40 +00:00
|
|
|
|
2016-06-19 22:29:41 +00:00
|
|
|
static bool __plugin_open(RIO *io, const char *file, bool many) {
|
2014-11-22 01:51:35 +00:00
|
|
|
return (!strncmp (file, "self://", 7));
|
|
|
|
}
|
|
|
|
|
|
|
|
static RIODesc *__open(RIO *io, const char *file, int rw, int mode) {
|
|
|
|
int ret, pid = getpid ();
|
2018-09-13 08:17:26 +00:00
|
|
|
if (r_sandbox_enable (0)) {
|
2014-12-22 00:11:16 +00:00
|
|
|
return NULL;
|
2018-09-13 08:17:26 +00:00
|
|
|
}
|
2015-09-14 00:08:31 +00:00
|
|
|
io->va = true; // nop
|
2016-03-13 23:11:31 +00:00
|
|
|
ret = update_self_regions (io, pid);
|
2014-11-22 01:51:35 +00:00
|
|
|
if (ret) {
|
2017-05-03 15:19:49 +00:00
|
|
|
return r_io_desc_new (io, &r_io_plugin_self,
|
|
|
|
file, rw, mode, NULL);
|
2014-11-22 01:51:35 +00:00
|
|
|
}
|
2014-02-10 02:31:12 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __read(RIO *io, RIODesc *fd, ut8 *buf, int len) {
|
2016-07-28 15:12:05 +00:00
|
|
|
int left, perm;
|
2016-03-13 23:11:31 +00:00
|
|
|
if (self_in_section (io, io->off, &left, &perm)) {
|
2018-09-21 00:16:54 +00:00
|
|
|
if (perm & R_PERM_R) {
|
2014-02-10 02:31:12 +00:00
|
|
|
int newlen = R_MIN (len, left);
|
|
|
|
ut8 *ptr = (ut8*)(size_t)io->off;
|
|
|
|
memcpy (buf, ptr, newlen);
|
|
|
|
return newlen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __write(RIO *io, RIODesc *fd, const ut8 *buf, int len) {
|
2018-09-21 00:16:54 +00:00
|
|
|
if (fd->perm & R_PERM_W) {
|
2014-02-10 02:31:12 +00:00
|
|
|
int left, perm;
|
2016-03-13 23:11:31 +00:00
|
|
|
if (self_in_section (io, io->off, &left, &perm)) {
|
2014-02-10 02:31:12 +00:00
|
|
|
int newlen = R_MIN (len, left);
|
|
|
|
ut8 *ptr = (ut8*)(size_t)io->off;
|
2016-07-30 12:15:29 +00:00
|
|
|
if (newlen > 0) {
|
2014-02-10 02:31:12 +00:00
|
|
|
memcpy (ptr, buf, newlen);
|
2016-07-30 12:15:29 +00:00
|
|
|
}
|
2014-02-10 02:31:12 +00:00
|
|
|
return newlen;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static ut64 __lseek(RIO *io, RIODesc *fd, ut64 offset, int whence) {
|
|
|
|
switch (whence) {
|
|
|
|
case SEEK_SET: return offset;
|
|
|
|
case SEEK_CUR: return io->off + offset;
|
|
|
|
case SEEK_END: return UT64_MAX;
|
|
|
|
}
|
|
|
|
return offset;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int __close(RIODesc *fd) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2016-07-28 15:12:05 +00:00
|
|
|
static void got_alarm(int sig) {
|
2016-07-29 11:37:17 +00:00
|
|
|
#if (!defined(__WINDOWS__)) || defined(__CYGWIN__)
|
2016-07-28 15:12:05 +00:00
|
|
|
// !!! may die if not running from r2preload !!! //
|
|
|
|
kill (getpid (), SIGUSR1);
|
2016-07-29 11:37:17 +00:00
|
|
|
#endif
|
2016-07-28 15:12:05 +00:00
|
|
|
}
|
|
|
|
|
2017-10-22 21:52:07 +00:00
|
|
|
static char *__system(RIO *io, RIODesc *fd, const char *cmd) {
|
2014-11-22 01:51:35 +00:00
|
|
|
if (!strcmp (cmd, "pid")) {
|
2017-10-22 21:52:07 +00:00
|
|
|
return r_str_newf ("%d", fd->fd);
|
2016-06-16 20:52:25 +00:00
|
|
|
} else if (!strncmp (cmd, "pid", 3)) {
|
|
|
|
/* do nothing here */
|
2016-07-29 11:45:54 +00:00
|
|
|
#if (!defined(__WINDOWS__)) || defined(__CYGWIN__)
|
2016-07-28 15:12:05 +00:00
|
|
|
} else if (!strncmp (cmd, "kill", 4)) {
|
|
|
|
if (r_sandbox_enable (false)) {
|
|
|
|
eprintf ("This is unsafe, so disabled by the sandbox\n");
|
2017-10-22 21:52:07 +00:00
|
|
|
return NULL;
|
2016-07-28 15:12:05 +00:00
|
|
|
}
|
|
|
|
/* do nothing here */
|
2018-08-29 16:18:14 +00:00
|
|
|
kill (getpid (), SIGKILL);
|
2016-07-29 11:45:54 +00:00
|
|
|
#endif
|
2016-07-28 15:12:05 +00:00
|
|
|
} else if (!strncmp (cmd, "call ", 5)) {
|
|
|
|
size_t cbptr = 0;
|
|
|
|
if (r_sandbox_enable (false)) {
|
|
|
|
eprintf ("This is unsafe, so disabled by the sandbox\n");
|
2017-10-22 21:52:07 +00:00
|
|
|
return NULL;
|
2016-07-28 15:12:05 +00:00
|
|
|
}
|
|
|
|
ut64 result = 0;
|
|
|
|
char *argv = strdup (cmd + 5);
|
|
|
|
int argc = r_str_word_set0 (argv);
|
|
|
|
if (argc == 0) {
|
|
|
|
eprintf ("Usage: =!call [fcnptr] [a0] [a1] ...\n");
|
2016-08-01 12:46:17 +00:00
|
|
|
free (argv);
|
2017-10-22 21:52:07 +00:00
|
|
|
return NULL;
|
2016-07-28 15:12:05 +00:00
|
|
|
}
|
|
|
|
const char *sym = r_str_word_get0 (argv, 0);
|
|
|
|
if (sym) {
|
|
|
|
const char *symbol = cmd + 6;
|
2016-07-30 12:15:29 +00:00
|
|
|
void *lib = r_lib_dl_open (NULL);
|
2016-07-28 17:59:40 +00:00
|
|
|
void *ptr = r_lib_dl_sym (lib, symbol);
|
2016-07-28 15:12:05 +00:00
|
|
|
if (ptr) {
|
|
|
|
cbptr = (ut64)(size_t)ptr;
|
|
|
|
} else {
|
|
|
|
cbptr = r_num_math (NULL, symbol);
|
|
|
|
}
|
2016-07-28 17:59:40 +00:00
|
|
|
r_lib_dl_close (lib);
|
2016-07-28 15:12:05 +00:00
|
|
|
}
|
|
|
|
if (argc == 1) {
|
|
|
|
size_t (*cb)() = (size_t(*)())cbptr;
|
2016-09-05 02:34:16 +00:00
|
|
|
if (cb) {
|
|
|
|
result = cb ();
|
|
|
|
} else {
|
|
|
|
eprintf ("No callback defined\n");
|
|
|
|
}
|
2016-07-28 15:12:05 +00:00
|
|
|
} else if (argc == 2) {
|
|
|
|
size_t (*cb)(size_t a0) = (size_t(*)(size_t))cbptr;
|
2016-09-05 02:34:16 +00:00
|
|
|
if (cb) {
|
|
|
|
ut64 a0 = r_num_math (NULL, r_str_word_get0 (argv, 1));
|
|
|
|
result = cb (a0);
|
|
|
|
} else {
|
|
|
|
eprintf ("No callback defined\n");
|
|
|
|
}
|
2016-07-28 15:12:05 +00:00
|
|
|
} else if (argc == 3) {
|
|
|
|
size_t (*cb)(size_t a0, size_t a1) = (size_t(*)(size_t,size_t))cbptr;
|
|
|
|
ut64 a0 = r_num_math (NULL, r_str_word_get0 (argv, 1));
|
|
|
|
ut64 a1 = r_num_math (NULL, r_str_word_get0 (argv, 2));
|
2016-09-05 02:34:16 +00:00
|
|
|
if (cb) {
|
|
|
|
result = cb (a0, a1);
|
|
|
|
} else {
|
|
|
|
eprintf ("No callback defined\n");
|
|
|
|
}
|
2016-07-28 15:12:05 +00:00
|
|
|
} else if (argc == 4) {
|
|
|
|
size_t (*cb)(size_t a0, size_t a1, size_t a2) = \
|
|
|
|
(size_t(*)(size_t,size_t,size_t))cbptr;
|
|
|
|
ut64 a0 = r_num_math (NULL, r_str_word_get0 (argv, 1));
|
|
|
|
ut64 a1 = r_num_math (NULL, r_str_word_get0 (argv, 2));
|
|
|
|
ut64 a2 = r_num_math (NULL, r_str_word_get0 (argv, 3));
|
2016-11-08 13:46:50 +00:00
|
|
|
if (cb) {
|
|
|
|
result = cb (a0, a1, a2);
|
|
|
|
} else {
|
|
|
|
eprintf ("No callback defined\n");
|
|
|
|
}
|
2016-07-28 15:12:05 +00:00
|
|
|
} else if (argc == 5) {
|
|
|
|
size_t (*cb)(size_t a0, size_t a1, size_t a2, size_t a3) = \
|
|
|
|
(size_t(*)(size_t,size_t,size_t,size_t))cbptr;
|
|
|
|
ut64 a0 = r_num_math (NULL, r_str_word_get0 (argv, 1));
|
|
|
|
ut64 a1 = r_num_math (NULL, r_str_word_get0 (argv, 2));
|
|
|
|
ut64 a2 = r_num_math (NULL, r_str_word_get0 (argv, 3));
|
|
|
|
ut64 a3 = r_num_math (NULL, r_str_word_get0 (argv, 4));
|
2016-09-05 02:34:16 +00:00
|
|
|
if (cb) {
|
|
|
|
result = cb (a0, a1, a2, a3);
|
|
|
|
} else {
|
|
|
|
eprintf ("No callback defined\n");
|
|
|
|
}
|
2016-07-28 15:12:05 +00:00
|
|
|
} else if (argc == 6) {
|
|
|
|
size_t (*cb)(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4) = \
|
|
|
|
(size_t(*)(size_t,size_t,size_t,size_t,size_t))cbptr;
|
|
|
|
ut64 a0 = r_num_math (NULL, r_str_word_get0 (argv, 1));
|
|
|
|
ut64 a1 = r_num_math (NULL, r_str_word_get0 (argv, 2));
|
|
|
|
ut64 a2 = r_num_math (NULL, r_str_word_get0 (argv, 3));
|
|
|
|
ut64 a3 = r_num_math (NULL, r_str_word_get0 (argv, 4));
|
|
|
|
ut64 a4 = r_num_math (NULL, r_str_word_get0 (argv, 5));
|
2016-09-05 02:34:16 +00:00
|
|
|
if (cb) {
|
|
|
|
result = cb (a0, a1, a2, a3, a4);
|
|
|
|
} else {
|
|
|
|
eprintf ("No callback defined\n");
|
|
|
|
}
|
2016-07-28 15:12:05 +00:00
|
|
|
} else {
|
|
|
|
eprintf ("Unsupported number of arguments in call\n");
|
|
|
|
}
|
|
|
|
eprintf ("RES %"PFMT64d"\n", result);
|
2016-08-01 12:46:17 +00:00
|
|
|
free (argv);
|
2016-07-29 11:37:17 +00:00
|
|
|
#if (!defined(__WINDOWS__)) || defined(__CYGWIN__)
|
2016-07-28 15:12:05 +00:00
|
|
|
} else if (!strncmp (cmd, "alarm ", 6)) {
|
|
|
|
signal (SIGALRM, got_alarm);
|
|
|
|
// TODO: use setitimer
|
|
|
|
alarm (atoi (cmd + 6));
|
2017-05-09 12:25:57 +00:00
|
|
|
#else
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#pragma message ("self:// alarm is not implemented for this platform yet")
|
2016-07-29 11:37:17 +00:00
|
|
|
#else
|
|
|
|
#warning "self:// alarm is not implemented for this platform yet"
|
2017-05-09 12:25:57 +00:00
|
|
|
#endif
|
2016-07-29 11:37:17 +00:00
|
|
|
#endif
|
2016-07-28 15:12:05 +00:00
|
|
|
} else if (!strncmp (cmd, "dlsym ", 6)) {
|
|
|
|
const char *symbol = cmd + 6;
|
2016-07-28 17:59:40 +00:00
|
|
|
void *lib = r_lib_dl_open (NULL);
|
|
|
|
void *ptr = r_lib_dl_sym (lib, symbol);
|
2016-07-28 15:12:05 +00:00
|
|
|
eprintf ("(%s) 0x%08"PFMT64x"\n", symbol, (ut64)(size_t)ptr);
|
2016-07-28 17:59:40 +00:00
|
|
|
r_lib_dl_close (lib);
|
2016-07-28 15:12:05 +00:00
|
|
|
} else if (!strcmp (cmd, "mameio")) {
|
2016-07-28 17:59:40 +00:00
|
|
|
void *lib = r_lib_dl_open (NULL);
|
|
|
|
void *ptr = r_lib_dl_sym (lib, "_ZN12device_debug2goEj");
|
2016-07-28 15:12:05 +00:00
|
|
|
// void *readmem = dlsym (lib, "_ZN23device_memory_interface11memory_readE16address_spacenumjiRy");
|
|
|
|
// readmem(0, )
|
|
|
|
if (ptr) {
|
|
|
|
// gothis =
|
|
|
|
eprintf ("TODO: No MAME IO implemented yet\n");
|
|
|
|
mameio = true;
|
|
|
|
} else {
|
|
|
|
eprintf ("This process is not a MAME!");
|
|
|
|
}
|
2016-07-28 17:59:40 +00:00
|
|
|
r_lib_dl_close (lib);
|
2015-07-02 00:02:40 +00:00
|
|
|
} else if (!strcmp (cmd, "maps")) {
|
2014-11-22 01:51:35 +00:00
|
|
|
int i;
|
2016-07-28 15:12:05 +00:00
|
|
|
for (i = 0; i < self_sections_count; i++) {
|
2014-11-22 01:51:35 +00:00
|
|
|
eprintf ("0x%08"PFMT64x" - 0x%08"PFMT64x" %s %s\n",
|
|
|
|
self_sections[i].from, self_sections[i].to,
|
|
|
|
r_str_rwx_i (self_sections[i].perm),
|
|
|
|
self_sections[i].name);
|
|
|
|
}
|
|
|
|
} else {
|
2016-07-28 15:12:05 +00:00
|
|
|
eprintf ("|Usage: =![cmd] [args]\n");
|
|
|
|
eprintf ("| =!pid show getpid()\n");
|
|
|
|
eprintf ("| =!maps show map regions\n");
|
|
|
|
eprintf ("| =!kill commit suicide\n");
|
2016-07-29 13:13:41 +00:00
|
|
|
#if (!defined(__WINDOWS__)) || defined(__CYGWIN__)
|
2016-07-28 15:12:05 +00:00
|
|
|
eprintf ("| =!alarm [secs] setup alarm signal to raise r2 prompt\n");
|
2016-07-29 13:13:41 +00:00
|
|
|
#endif
|
2016-07-28 15:12:05 +00:00
|
|
|
eprintf ("| =!dlsym [sym] dlopen\n");
|
|
|
|
eprintf ("| =!call [sym] [...] nativelly call a function\n");
|
|
|
|
eprintf ("| =!mameio enter mame IO mode\n");
|
2014-11-22 01:51:35 +00:00
|
|
|
}
|
2017-10-22 21:52:07 +00:00
|
|
|
return NULL;
|
2014-11-22 01:51:35 +00:00
|
|
|
}
|
|
|
|
|
2016-07-28 15:12:05 +00:00
|
|
|
RIOPlugin r_io_plugin_self = {
|
2014-02-10 02:31:12 +00:00
|
|
|
.name = "self",
|
|
|
|
.desc = "read memory from myself using 'self://'",
|
|
|
|
.license = "LGPL3",
|
|
|
|
.open = __open,
|
|
|
|
.close = __close,
|
|
|
|
.read = __read,
|
2016-06-19 22:29:41 +00:00
|
|
|
.check = __plugin_open,
|
2014-02-10 02:31:12 +00:00
|
|
|
.lseek = __lseek,
|
2014-11-22 01:51:35 +00:00
|
|
|
.system = __system,
|
2014-02-10 02:31:12 +00:00
|
|
|
.write = __write,
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifndef CORELIB
|
2018-09-15 20:52:12 +00:00
|
|
|
R_API RLibStruct radare_plugin = {
|
2014-02-10 02:31:12 +00:00
|
|
|
.type = R_LIB_TYPE_IO,
|
2015-07-12 14:04:10 +00:00
|
|
|
.data = &r_io_plugin_mach,
|
|
|
|
.version = R2_VERSION
|
2014-02-10 02:31:12 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if __APPLE__
|
2015-07-06 22:23:08 +00:00
|
|
|
// mach/mach_vm.h not available for iOS
|
2016-07-28 15:12:05 +00:00
|
|
|
kern_return_t mach_vm_region (
|
2015-07-06 22:23:08 +00:00
|
|
|
vm_map_t target_task,
|
|
|
|
mach_vm_address_t *address,
|
|
|
|
mach_vm_size_t *size,
|
|
|
|
vm_region_flavor_t flavor,
|
|
|
|
vm_region_info_t info,
|
|
|
|
mach_msg_type_number_t *infoCnt,
|
|
|
|
mach_port_t *object_name
|
|
|
|
);
|
2014-02-10 02:31:12 +00:00
|
|
|
// taken from vmmap.c ios clone
|
2014-11-22 01:51:35 +00:00
|
|
|
// XXX. this code is dupped in libr/debug/p/debug_native.c
|
|
|
|
// but this one looks better, the other one seems to work too.
|
|
|
|
// TODO: unify that implementation in a single reusable place
|
2016-03-13 23:11:31 +00:00
|
|
|
void macosx_debug_regions (RIO *io, task_t task, mach_vm_address_t address, int max) {
|
2014-02-10 02:31:12 +00:00
|
|
|
kern_return_t kret;
|
|
|
|
|
|
|
|
mach_vm_address_t prev_address;
|
|
|
|
/* @TODO: warning - potential overflow here - gotta fix this.. */
|
|
|
|
vm_region_basic_info_data_t prev_info, info;
|
|
|
|
mach_vm_size_t size, prev_size;
|
|
|
|
|
|
|
|
mach_port_t object_name;
|
|
|
|
mach_msg_type_number_t count;
|
|
|
|
|
|
|
|
int nsubregions = 0;
|
|
|
|
int num_printed = 0;
|
|
|
|
|
|
|
|
count = VM_REGION_BASIC_INFO_COUNT_64;
|
|
|
|
kret = mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO,
|
|
|
|
(vm_region_info_t) &info, &count, &object_name);
|
|
|
|
|
|
|
|
if (kret) {
|
2014-11-22 01:51:35 +00:00
|
|
|
eprintf ("mach_vm_region: Error %d - %s", kret, mach_error_string(kret));
|
2014-02-10 02:31:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_t));
|
|
|
|
prev_address = address;
|
|
|
|
prev_size = size;
|
|
|
|
nsubregions = 1;
|
|
|
|
self_sections_count = 0;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
int print = 0;
|
|
|
|
int done = 0;
|
|
|
|
|
|
|
|
address = prev_address + prev_size;
|
|
|
|
|
|
|
|
/* Check to see if address space has wrapped around. */
|
|
|
|
if (address == 0)
|
|
|
|
print = done = 1;
|
|
|
|
|
|
|
|
if (!done) {
|
|
|
|
// Even on iOS, we use VM_REGION_BASIC_INFO_COUNT_64. This works.
|
|
|
|
count = VM_REGION_BASIC_INFO_COUNT_64;
|
2016-07-28 15:12:05 +00:00
|
|
|
kret = mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO,
|
2014-02-10 02:31:12 +00:00
|
|
|
(vm_region_info_t) &info, &count, &object_name);
|
2016-07-28 15:12:05 +00:00
|
|
|
if (kret != KERN_SUCCESS) {
|
2014-02-10 02:31:12 +00:00
|
|
|
/* iOS 6 workaround - attempt to reget the task port to avoiD */
|
|
|
|
/* "(ipc/send) invalid destination port" (1000003 or something) */
|
|
|
|
task_for_pid(mach_task_self(),getpid (), &task);
|
2016-07-28 15:12:05 +00:00
|
|
|
kret = mach_vm_region (task, &address, &size, VM_REGION_BASIC_INFO,
|
2014-02-10 02:31:12 +00:00
|
|
|
(vm_region_info_t) &info, &count, &object_name);
|
|
|
|
}
|
|
|
|
if (kret != KERN_SUCCESS) {
|
2014-11-22 01:51:35 +00:00
|
|
|
eprintf ("mach_vm_region failed for address %p - Error: %x\n",
|
2014-04-28 09:37:48 +00:00
|
|
|
(void*)(size_t)address, kret);
|
2014-02-10 02:31:12 +00:00
|
|
|
size = 0;
|
2016-07-28 15:12:05 +00:00
|
|
|
if (address >= 0x4000000) {
|
|
|
|
return;
|
|
|
|
}
|
2014-02-10 02:31:12 +00:00
|
|
|
print = done = 1;
|
|
|
|
}
|
|
|
|
}
|
2016-07-28 15:12:05 +00:00
|
|
|
if (address != prev_address + prev_size) {
|
2014-02-10 02:31:12 +00:00
|
|
|
print = 1;
|
2016-07-28 15:12:05 +00:00
|
|
|
}
|
2014-02-10 02:31:12 +00:00
|
|
|
if ((info.protection != prev_info.protection)
|
|
|
|
|| (info.max_protection != prev_info.max_protection)
|
|
|
|
|| (info.inheritance != prev_info.inheritance)
|
|
|
|
|| (info.shared != prev_info.reserved)
|
|
|
|
|| (info.reserved != prev_info.reserved))
|
|
|
|
print = 1;
|
|
|
|
|
|
|
|
if (print) {
|
2016-07-28 15:12:05 +00:00
|
|
|
int print_size;
|
2014-02-10 02:31:12 +00:00
|
|
|
char *print_size_unit;
|
|
|
|
|
2016-07-28 15:12:05 +00:00
|
|
|
io->cb_printf (num_printed? " ... ": "Region ");
|
2014-02-10 02:31:12 +00:00
|
|
|
//findListOfBinaries(task, prev_address, prev_size);
|
|
|
|
/* Quick hack to show size of segment, which GDB does not */
|
|
|
|
print_size = prev_size;
|
|
|
|
if (print_size > 1024) { print_size /= 1024; print_size_unit = "K"; }
|
|
|
|
if (print_size > 1024) { print_size /= 1024; print_size_unit = "M"; }
|
|
|
|
if (print_size > 1024) { print_size /= 1024; print_size_unit = "G"; }
|
|
|
|
/* End Quick hack */
|
2016-03-13 23:11:31 +00:00
|
|
|
io->cb_printf (" %p - %p [%d%s](%x/%x; %d, %s, %s)",
|
2014-04-28 09:37:48 +00:00
|
|
|
(void*)(size_t)(prev_address),
|
2016-07-28 15:12:05 +00:00
|
|
|
(void*)(size_t)(prev_address + prev_size),
|
|
|
|
print_size,
|
|
|
|
print_size_unit,
|
|
|
|
prev_info.protection,
|
|
|
|
prev_info.max_protection,
|
|
|
|
prev_info.inheritance,
|
|
|
|
prev_info.shared ? "shared" : "private",
|
|
|
|
prev_info.reserved ? "reserved" : "not-reserved");
|
2014-02-10 02:31:12 +00:00
|
|
|
|
|
|
|
self_sections[self_sections_count].from = prev_address;
|
|
|
|
self_sections[self_sections_count].to = prev_address+prev_size;
|
2018-09-21 00:16:54 +00:00
|
|
|
self_sections[self_sections_count].perm = R_PERM_R; //prev_info.protection;
|
2014-02-10 02:31:12 +00:00
|
|
|
self_sections_count++;
|
2016-07-28 15:12:05 +00:00
|
|
|
if (nsubregions > 1) {
|
2016-03-13 23:11:31 +00:00
|
|
|
io->cb_printf (" (%d sub-regions)", nsubregions);
|
2016-07-28 15:12:05 +00:00
|
|
|
}
|
2016-03-13 23:11:31 +00:00
|
|
|
io->cb_printf ("\n");
|
2014-02-10 02:31:12 +00:00
|
|
|
|
|
|
|
prev_address = address;
|
|
|
|
prev_size = size;
|
|
|
|
memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_t));
|
|
|
|
nsubregions = 1;
|
|
|
|
|
|
|
|
num_printed++;
|
|
|
|
} else {
|
|
|
|
prev_size += size;
|
|
|
|
nsubregions++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((max > 0) && (num_printed >= max)) {
|
2014-11-22 01:51:35 +00:00
|
|
|
eprintf ("Max %d num_printed %d\n", max, num_printed);
|
2014-02-10 02:31:12 +00:00
|
|
|
done = 1;
|
|
|
|
}
|
2016-07-28 15:12:05 +00:00
|
|
|
if (done) {
|
2014-02-10 02:31:12 +00:00
|
|
|
break;
|
2016-07-28 15:12:05 +00:00
|
|
|
}
|
2014-02-10 02:31:12 +00:00
|
|
|
}
|
|
|
|
}
|
2018-10-30 22:50:36 +00:00
|
|
|
#elif __FreeBSD__
|
|
|
|
bool bsd_proc_vmmaps(RIO *io, int pid) {
|
|
|
|
int mib[4] = {
|
|
|
|
CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, pid
|
|
|
|
};
|
|
|
|
size_t size;
|
|
|
|
bool ret = false;
|
|
|
|
int s = sysctl (mib, sizeof (mib), NULL, &size, NULL, 0);
|
|
|
|
if (s == -1) {
|
|
|
|
eprintf ("sysctl failed\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
ut8 *p = malloc (size);
|
|
|
|
if (p) {
|
|
|
|
size = size * 4 / 3;
|
|
|
|
s = sysctl (mib, sizeof (mib), p, &size, NULL, 0);
|
|
|
|
if (s == -1) {
|
|
|
|
eprintf ("sysctl failed\n");
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
ut8 *p_start = p;
|
|
|
|
ut8 *p_end = p + size;
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
while (p_start < p_end) {
|
|
|
|
struct kinfo_vmentry *entry = (struct kinfo_vmentry *)p_start;
|
|
|
|
size_t sz = entry->kve_structsize;
|
|
|
|
if (sz == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
p_start += sz;
|
|
|
|
n ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct kinfo_vmentry *entries = calloc(n, sizeof(*entries));
|
|
|
|
if (!entries) {
|
|
|
|
eprintf ("entries allocation failed\n");
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
p_start = p;
|
|
|
|
|
|
|
|
while (p_start < p_end) {
|
|
|
|
struct kinfo_vmentry *entry = (struct kinfo_vmentry *)p_start;
|
|
|
|
size_t sz = entry->kve_structsize;
|
|
|
|
int perm = 0;
|
|
|
|
if (sz == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (entry->kve_protection & KVME_PROT_READ) {
|
|
|
|
perm |= R_PERM_R;
|
|
|
|
}
|
|
|
|
if (entry->kve_protection & KVME_PROT_WRITE) {
|
|
|
|
perm |= R_PERM_W;
|
|
|
|
}
|
|
|
|
if (entry->kve_protection & KVME_PROT_EXEC) {
|
|
|
|
perm |= R_PERM_X;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (entry->kve_path[0] != '\0') {
|
|
|
|
io->cb_printf (" %p - %p (%s)\n",
|
|
|
|
(void *)entry->kve_start,
|
|
|
|
(void *)entry->kve_end,
|
|
|
|
entry->kve_path);
|
|
|
|
}
|
|
|
|
|
|
|
|
self_sections[self_sections_count].from = entry->kve_start;
|
|
|
|
self_sections[self_sections_count].to = entry->kve_end;
|
|
|
|
self_sections[self_sections_count].name = strdup (entry->kve_path);
|
|
|
|
self_sections[self_sections_count].perm = perm;
|
|
|
|
self_sections_count++;
|
|
|
|
p_start += sz;
|
|
|
|
}
|
|
|
|
|
|
|
|
free (entries);
|
|
|
|
ret = true;
|
|
|
|
} else {
|
|
|
|
eprintf ("buffer allocation failed\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
free (p);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-02-10 02:31:12 +00:00
|
|
|
#endif
|
2015-04-14 15:11:52 +00:00
|
|
|
|
|
|
|
#else // DEBUGGER
|
2016-09-05 02:34:16 +00:00
|
|
|
RIOPlugin r_io_plugin_self = {
|
2015-04-14 15:11:52 +00:00
|
|
|
.name = "self",
|
|
|
|
.desc = "read memory from myself using 'self://' (UNSUPPORTED)",
|
|
|
|
};
|
|
|
|
|
|
|
|
#ifndef CORELIB
|
2018-09-15 20:52:12 +00:00
|
|
|
R_API RLibStruct radare_plugin = {
|
2015-04-14 15:11:52 +00:00
|
|
|
.type = R_LIB_TYPE_IO,
|
2015-07-12 14:04:10 +00:00
|
|
|
.data = &r_io_plugin_mach,
|
|
|
|
.version = R2_VERSION
|
2015-04-14 15:11:52 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
#endif
|