* Add XML to ldid r2 debugger for iOS
* Fix build of the r2 debugger on darwin-arm * Implement list of threads and memory regions on darwin-arm - just a draft, needs more work * Add attach:// IO handler to mach plugin * darwin does not needs -ldl
This commit is contained in:
parent
1c779dfd3c
commit
cfa24e1879
|
@ -5,6 +5,9 @@ BINDEPS+=r_sign r_print r_lang r_asm r_syscall r_hash r_line r_socket r_flags r_
|
||||||
|
|
||||||
include ../binr.mk
|
include ../binr.mk
|
||||||
|
|
||||||
|
sign:
|
||||||
|
ldid -Sradare2.xml radare2
|
||||||
|
|
||||||
ifeq ($(WITHNONPIC),1)
|
ifeq ($(WITHNONPIC),1)
|
||||||
LDFLAGS+=${DL_LIBS} -lm -lpthread
|
LDFLAGS+=${DL_LIBS} -lm -lpthread
|
||||||
ifeq ($(HAVE_LIB_GMP),1)
|
ifeq ($(HAVE_LIB_GMP),1)
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>app-identifier</key>
|
||||||
|
<true/>
|
||||||
|
<key>get-task-allow</key>
|
||||||
|
<true/>
|
||||||
|
<key>task_for_pid-allow</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
This file must be used to 'sign' the 'radare' binary
|
||||||
|
after compiling to permit debugging on the iphone-os
|
||||||
|
$ ldid -Sradare2.xml radare2
|
||||||
|
-->
|
|
@ -21,7 +21,10 @@ VERSION=@VERSION@
|
||||||
# ./configure --with-ostype=[linux,osx,solaris,windows] # TODO: rename to w32, w64?
|
# ./configure --with-ostype=[linux,osx,solaris,windows] # TODO: rename to w32, w64?
|
||||||
OSTYPE=@USEROSTYPE@
|
OSTYPE=@USEROSTYPE@
|
||||||
HOST_OS=@HOST_OS@
|
HOST_OS=@HOST_OS@
|
||||||
|
# hack: must be fixed in acr
|
||||||
|
ifneq($(OSTYPE),darwin)
|
||||||
DL_LIBS=@DL_LIBS@
|
DL_LIBS=@DL_LIBS@
|
||||||
|
endif
|
||||||
WITHPIC=@WITHPIC@
|
WITHPIC=@WITHPIC@
|
||||||
WITHNONPIC=@WITHNONPIC@
|
WITHNONPIC=@WITHNONPIC@
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,11 @@ static HANDLE tid2handler(int tid) {
|
||||||
#include <mach/exception_types.h>
|
#include <mach/exception_types.h>
|
||||||
#include <mach/mach_init.h>
|
#include <mach/mach_init.h>
|
||||||
#include <mach/mach_port.h>
|
#include <mach/mach_port.h>
|
||||||
|
#include <mach/mach_interface.h>
|
||||||
#include <mach/mach_traps.h>
|
#include <mach/mach_traps.h>
|
||||||
|
#include <mach/mach_types.h>
|
||||||
|
#include <mach/mach_vm.h>
|
||||||
|
#include <mach/mach_error.h>
|
||||||
#include <mach/task.h>
|
#include <mach/task.h>
|
||||||
#include <mach/task_info.h>
|
#include <mach/task_info.h>
|
||||||
#include <mach/thread_act.h>
|
#include <mach/thread_act.h>
|
||||||
|
@ -136,7 +140,7 @@ task_t pid_to_task(int pid) {
|
||||||
if (old_task!= -1) //old_pid != -1 && old_pid == pid)
|
if (old_task!= -1) //old_pid != -1 && old_pid == pid)
|
||||||
return old_task;
|
return old_task;
|
||||||
|
|
||||||
err = task_for_pid(mach_task_self(), (pid_t)pid, &task);
|
err = task_for_pid (mach_task_self(), (pid_t)pid, &task);
|
||||||
if ((err != KERN_SUCCESS) || !MACH_PORT_VALID(task)) {
|
if ((err != KERN_SUCCESS) || !MACH_PORT_VALID(task)) {
|
||||||
eprintf ("Failed to get task %d for pid %d.\n", (int)task, (int)pid);
|
eprintf ("Failed to get task %d for pid %d.\n", (int)task, (int)pid);
|
||||||
eprintf ("Reason: 0x%x: %s\n", err, (char *)MACH_ERROR_STRING (err));
|
eprintf ("Reason: 0x%x: %s\n", err, (char *)MACH_ERROR_STRING (err));
|
||||||
|
@ -225,7 +229,7 @@ static int r_debug_native_detach(int pid) {
|
||||||
#if __WINDOWS__
|
#if __WINDOWS__
|
||||||
return w32_detach (pid)? 0 : -1;
|
return w32_detach (pid)? 0 : -1;
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
return ptrace (PT_DETACH, pid, NULL, NULL);
|
return ptrace (PT_DETACH, pid, NULL, 0);
|
||||||
#else
|
#else
|
||||||
return ptrace (PTRACE_DETACH, pid, NULL, NULL);
|
return ptrace (PTRACE_DETACH, pid, NULL, NULL);
|
||||||
#endif
|
#endif
|
||||||
|
@ -561,7 +565,7 @@ static RList *r_debug_native_pids(int pid) {
|
||||||
continue;
|
continue;
|
||||||
read (fd, cmdline, 1024);
|
read (fd, cmdline, 1024);
|
||||||
cmdline[1023] = '\0';
|
cmdline[1023] = '\0';
|
||||||
r_list_append (list, r_debug_pid_new (cmdline, i, 's'));
|
r_list_append (list, r_debug_pid_new (cmdline, i, 's', 0));
|
||||||
}
|
}
|
||||||
close (fd);
|
close (fd);
|
||||||
}
|
}
|
||||||
|
@ -578,7 +582,7 @@ static RList *r_debug_native_pids(int pid) {
|
||||||
read (fd, cmdline, sizeof (cmdline));
|
read (fd, cmdline, sizeof (cmdline));
|
||||||
cmdline[sizeof (cmdline)-1] = '\0';
|
cmdline[sizeof (cmdline)-1] = '\0';
|
||||||
close (fd);
|
close (fd);
|
||||||
r_list_append (list, r_debug_pid_new (cmdline, i, 's'));
|
r_list_append (list, r_debug_pid_new (cmdline, i, 's', 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -591,7 +595,35 @@ static RList *r_debug_native_threads(int pid) {
|
||||||
#if __WINDOWS__
|
#if __WINDOWS__
|
||||||
eprintf ("pids: TODO\n");
|
eprintf ("pids: TODO\n");
|
||||||
#elif __APPLE__
|
#elif __APPLE__
|
||||||
eprintf ("pids: TODO\n");
|
#if __arm__
|
||||||
|
#define OSX_PC state.r15
|
||||||
|
#undef THREAD_STATE
|
||||||
|
#define THREAD_STATE ARM_THREAD_STATE
|
||||||
|
#elif __POWERPC__
|
||||||
|
#define OSX_PC state.srr0
|
||||||
|
#else
|
||||||
|
#define OSX_PC state.__eip
|
||||||
|
#endif
|
||||||
|
int i, tid, err;
|
||||||
|
unsigned int gp_count;
|
||||||
|
static thread_array_t inferior_threads = NULL;
|
||||||
|
static unsigned int inferior_thread_count = 0;
|
||||||
|
R_DEBUG_REG_T state;
|
||||||
|
|
||||||
|
if (task_threads (pid_to_task (pid), &inferior_threads,
|
||||||
|
&inferior_thread_count) != KERN_SUCCESS) {
|
||||||
|
eprintf ("Failed to get list of task's threads.\n");
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
for (i = 0; i < inferior_thread_count; i++) {
|
||||||
|
tid = inferior_threads[i];
|
||||||
|
if ((err = thread_get_state (tid, ARM_THREAD_STATE,
|
||||||
|
(thread_state_t) &state, &gp_count)) != KERN_SUCCESS) {
|
||||||
|
// eprintf ("debug_list_threads: %s\n", MACH_ERROR_STRING(err));
|
||||||
|
OSX_PC = 0;
|
||||||
|
}
|
||||||
|
r_list_append (list, r_debug_pid_new ("???", i, 's', OSX_PC));
|
||||||
|
}
|
||||||
#elif __linux__
|
#elif __linux__
|
||||||
int i, fd, thid = 0;
|
int i, fd, thid = 0;
|
||||||
char *ptr, cmdline[1024];
|
char *ptr, cmdline[1024];
|
||||||
|
@ -650,9 +682,6 @@ static int r_debug_native_reg_read(RDebug *dbg, int type, ut8 *buf, int size) {
|
||||||
R_DEBUG_REG_T *regs = (R_DEBUG_REG_T *)buf;
|
R_DEBUG_REG_T *regs = (R_DEBUG_REG_T *)buf;
|
||||||
unsigned int gp_count = sizeof (R_DEBUG_REG_T);
|
unsigned int gp_count = sizeof (R_DEBUG_REG_T);
|
||||||
|
|
||||||
//thread_act_port_array_t thread_list;
|
|
||||||
//mach_msg_type_number_t thread_count;
|
|
||||||
|
|
||||||
ret = task_threads (pid_to_task (pid), &inferior_threads, &inferior_thread_count);
|
ret = task_threads (pid_to_task (pid), &inferior_threads, &inferior_thread_count);
|
||||||
if (ret != KERN_SUCCESS) {
|
if (ret != KERN_SUCCESS) {
|
||||||
eprintf ("debug_getregs\n");
|
eprintf ("debug_getregs\n");
|
||||||
|
@ -661,8 +690,8 @@ static int r_debug_native_reg_read(RDebug *dbg, int type, ut8 *buf, int size) {
|
||||||
|
|
||||||
if (inferior_thread_count>0) {
|
if (inferior_thread_count>0) {
|
||||||
/* TODO: allow to choose the thread */
|
/* TODO: allow to choose the thread */
|
||||||
if ((ret = thread_get_state (inferior_threads[0], R_DEBUG_STATE_T,
|
if (thread_get_state (inferior_threads[0], R_DEBUG_STATE_T,
|
||||||
(thread_state_t) regs, &gp_count)) != KERN_SUCCESS) {
|
(thread_state_t) regs, &gp_count) != KERN_SUCCESS) {
|
||||||
eprintf ("debug_getregs: Failed to get thread %d %d.error (%x). (%s)\n",
|
eprintf ("debug_getregs: Failed to get thread %d %d.error (%x). (%s)\n",
|
||||||
(int)pid, pid_to_task (pid), (int)ret, MACH_ERROR_STRING (ret));
|
(int)pid, pid_to_task (pid), (int)ret, MACH_ERROR_STRING (ret));
|
||||||
perror ("thread_get_state");
|
perror ("thread_get_state");
|
||||||
|
@ -670,7 +699,6 @@ static int r_debug_native_reg_read(RDebug *dbg, int type, ut8 *buf, int size) {
|
||||||
}
|
}
|
||||||
} else eprintf ("There are no threads!\n");
|
} else eprintf ("There are no threads!\n");
|
||||||
return R_TRUE; //gp_count;
|
return R_TRUE; //gp_count;
|
||||||
|
|
||||||
#elif __linux__ || __sun || __NetBSD__ || __FreeBSD__ || __OpenBSD__
|
#elif __linux__ || __sun || __NetBSD__ || __FreeBSD__ || __OpenBSD__
|
||||||
int ret;
|
int ret;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
@ -706,10 +734,8 @@ static int r_debug_native_reg_read(RDebug *dbg, int type, ut8 *buf, int size) {
|
||||||
R_DEBUG_REG_T regs;
|
R_DEBUG_REG_T regs;
|
||||||
memset (®s, 0, sizeof (regs));
|
memset (®s, 0, sizeof (regs));
|
||||||
memset (buf, 0, size);
|
memset (buf, 0, size);
|
||||||
|
|
||||||
#if __NetBSD__ || __FreeBSD__ || __OpenBSD__
|
#if __NetBSD__ || __FreeBSD__ || __OpenBSD__
|
||||||
ret = ptrace (PTRACE_GETREGS, pid, ®s, sizeof (regs));
|
ret = ptrace (PTRACE_GETREGS, pid, ®s, sizeof (regs));
|
||||||
|
|
||||||
#elif __linux__ && __powerpc__
|
#elif __linux__ && __powerpc__
|
||||||
ret = ptrace (PTRACE_GETREGS, pid, ®s, NULL);
|
ret = ptrace (PTRACE_GETREGS, pid, ®s, NULL);
|
||||||
#else
|
#else
|
||||||
|
@ -770,15 +796,168 @@ static int r_debug_native_reg_write(int pid, int type, const ut8* buf, int size)
|
||||||
return R_FALSE;
|
return R_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if __APPLE__
|
||||||
|
static const char * unparse_inheritance (vm_inherit_t i) {
|
||||||
|
switch (i) {
|
||||||
|
case VM_INHERIT_SHARE: return "share";
|
||||||
|
case VM_INHERIT_COPY: return "copy";
|
||||||
|
case VM_INHERIT_NONE: return "none";
|
||||||
|
default: return "???";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: move to p/native/darwin.c
|
||||||
|
static RList *darwin_dbg_maps (RDebug *dbg) {
|
||||||
|
RDebugMap *mr;
|
||||||
|
RList *list = r_list_new ();
|
||||||
|
|
||||||
|
char buf[128];
|
||||||
|
int i;
|
||||||
|
kern_return_t kret;
|
||||||
|
vm_region_basic_info_data_64_t info, prev_info;
|
||||||
|
mach_vm_address_t prev_address;
|
||||||
|
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;
|
||||||
|
// XXX: wrong for 64bits
|
||||||
|
size_t address = 0;
|
||||||
|
|
||||||
|
int max = 100; // XXX
|
||||||
|
task_t task = pid_to_task (dbg->pid);
|
||||||
|
/*
|
||||||
|
count = VM_REGION_BASIC_INFO_COUNT_64;
|
||||||
|
kret = mach_vm_region (pid_to_task (dbg->pid), &address, &size, VM_REGION_BASIC_INFO_64,
|
||||||
|
(vm_region_info_t) &info, &count, &object_name);
|
||||||
|
if (kret != KERN_SUCCESS) {
|
||||||
|
printf("No memory regions.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
|
||||||
|
*/
|
||||||
|
memset (&prev_info, 0, sizeof (prev_info));
|
||||||
|
prev_address = address;
|
||||||
|
prev_size = size;
|
||||||
|
nsubregions = 1;
|
||||||
|
|
||||||
|
for (i=0; ; i++) {
|
||||||
|
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) {
|
||||||
|
count = VM_REGION_BASIC_INFO_COUNT_64;
|
||||||
|
kret = mach_vm_region (task, (mach_vm_address_t *)&address,
|
||||||
|
&size, VM_REGION_BASIC_INFO_64,
|
||||||
|
(vm_region_info_t) &info, &count, &object_name);
|
||||||
|
if (kret != KERN_SUCCESS) {
|
||||||
|
size = 0;
|
||||||
|
print = done = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (address != prev_address + prev_size)
|
||||||
|
print = 1;
|
||||||
|
|
||||||
|
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 0
|
||||||
|
mr = malloc(sizeof(MAP_REG));
|
||||||
|
mr->ini = (ut32) prev_address;
|
||||||
|
mr->end = (ut32) (prev_address+ prev_size);
|
||||||
|
mr->size = (ut32) prev_size;
|
||||||
|
|
||||||
|
mr->bin = strdup(buf);
|
||||||
|
mr->perms = darwin_prot_to_unix(prev_info.protection); // XXX is this ok?
|
||||||
|
//mr->flags = // FLAG_NOPERM // FLAG_USERCODE ...
|
||||||
|
//mr->perms = prev_info.max_protection;
|
||||||
|
|
||||||
|
add_regmap(mr);
|
||||||
|
#endif
|
||||||
|
sprintf(buf, "unk%d-%s-%s-%s", i,
|
||||||
|
unparse_inheritance (prev_info.inheritance),
|
||||||
|
prev_info.shared ? "shar" : "priv",
|
||||||
|
prev_info.reserved ? "reserved" : "not-reserved");
|
||||||
|
// TODO: MAPS can have min and max protection rules
|
||||||
|
// :: prev_info.max_protection
|
||||||
|
mr = r_debug_map_new (buf, prev_address, prev_address+prev_size, prev_info.protection, 0);
|
||||||
|
if (mr == NULL) {
|
||||||
|
eprintf ("Cannot create r_debug_map_new\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
r_list_append (list, mr);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (1==0 && rest) { /* XXX never pritn this info here */
|
||||||
|
addr = 0LL;
|
||||||
|
addr = (ut64) (ut32) prev_address;
|
||||||
|
if (num_printed == 0)
|
||||||
|
fprintf(stderr, "Region ");
|
||||||
|
else fprintf(stderr, " ... ");
|
||||||
|
fprintf(stderr, " 0x%08llx - 0x%08llx %s (%s) %s, %s, %s",
|
||||||
|
addr, addr + prev_size,
|
||||||
|
unparse_protection (prev_info.protection),
|
||||||
|
unparse_protection (prev_info.max_protection),
|
||||||
|
unparse_inheritance (prev_info.inheritance),
|
||||||
|
prev_info.shared ? "shared" : " private",
|
||||||
|
prev_info.reserved ? "reserved" : "not-reserved");
|
||||||
|
|
||||||
|
if (nsubregions > 1)
|
||||||
|
fprintf(stderr, " (%d sub-regions)", nsubregions);
|
||||||
|
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
prev_address = address;
|
||||||
|
prev_size = size;
|
||||||
|
memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
|
||||||
|
nsubregions = 1;
|
||||||
|
|
||||||
|
num_printed++;
|
||||||
|
} else {
|
||||||
|
#endif
|
||||||
|
#if 0
|
||||||
|
prev_size += size;
|
||||||
|
nsubregions++;
|
||||||
|
#else
|
||||||
|
prev_address = address;
|
||||||
|
prev_size = size;
|
||||||
|
memcpy (&prev_info, &info, sizeof (vm_region_basic_info_data_64_t));
|
||||||
|
nsubregions = 1;
|
||||||
|
|
||||||
|
num_printed++;
|
||||||
|
#endif
|
||||||
|
// }
|
||||||
|
|
||||||
|
if ((max > 0) && (num_printed >= max))
|
||||||
|
done = 1;
|
||||||
|
|
||||||
|
if (done)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static RList *r_debug_native_map_get(RDebug *dbg) {
|
static RList *r_debug_native_map_get(RDebug *dbg) {
|
||||||
char path[1024];
|
|
||||||
RList *list = NULL;
|
RList *list = NULL;
|
||||||
#if __WINDOWS__
|
#if __APPLE__
|
||||||
list = w32_dbg_maps ();
|
list = darwin_dbg_maps (dbg);
|
||||||
|
#elif __WINDOWS__
|
||||||
// TODO
|
list = w32_dbg_maps (); // TODO: moar?
|
||||||
#else
|
#else
|
||||||
#if __sun
|
#if __sun
|
||||||
|
char path[1024];
|
||||||
/* TODO: On solaris parse /proc/%d/map */
|
/* TODO: On solaris parse /proc/%d/map */
|
||||||
sprintf (path, "pmap %d > /dev/stderr", ps.tid);
|
sprintf (path, "pmap %d > /dev/stderr", ps.tid);
|
||||||
system (path);
|
system (path);
|
||||||
|
@ -786,8 +965,8 @@ static RList *r_debug_native_map_get(RDebug *dbg) {
|
||||||
RDebugMap *map;
|
RDebugMap *map;
|
||||||
int i, perm, unk = 0;
|
int i, perm, unk = 0;
|
||||||
char *pos_c;
|
char *pos_c;
|
||||||
|
char path[1024], line[1024];
|
||||||
char region[100], region2[100], perms[5], null[16];
|
char region[100], region2[100], perms[5], null[16];
|
||||||
char line[1024];
|
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
#if __FreeBSD__
|
#if __FreeBSD__
|
||||||
sprintf (path, "/proc/%d/map", dbg->pid);
|
sprintf (path, "/proc/%d/map", dbg->pid);
|
||||||
|
@ -796,7 +975,7 @@ static RList *r_debug_native_map_get(RDebug *dbg) {
|
||||||
#endif
|
#endif
|
||||||
fd = fopen (path, "r");
|
fd = fopen (path, "r");
|
||||||
if (!fd) {
|
if (!fd) {
|
||||||
perror ("debug_init_maps");
|
perror ("debug_init_maps: /proc");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1018,8 +1197,8 @@ int drx_del(RDebug *dbg, ut64 addr, int rwx) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int r_debug_native_bp(void *user, int add, ut64 addr, int hw, int rwx) {
|
static int r_debug_native_bp(void *user, int add, ut64 addr, int hw, int rwx) {
|
||||||
RDebug *dbg = user;
|
|
||||||
#if __i386__ || __x86_64__
|
#if __i386__ || __x86_64__
|
||||||
|
RDebug *dbg = user;
|
||||||
if (hw) {
|
if (hw) {
|
||||||
if (add) return drx_add (dbg, addr, rwx);
|
if (add) return drx_add (dbg, addr, rwx);
|
||||||
return drx_del (dbg, addr, rwx);
|
return drx_del (dbg, addr, rwx);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
include ../../config.mk
|
include ../../config.mk
|
||||||
BINDEPS=r_reg r_bp r_util r_io
|
BINDEPS=r_reg r_bp r_util r_io r_anal
|
||||||
|
|
||||||
CFLAGS+=-Ilibgdbwrap/include
|
CFLAGS+=-Ilibgdbwrap/include
|
||||||
ifeq (${OSTYPE},windows)
|
ifeq (${OSTYPE},windows)
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int pids_cmdline(int pid, char *cmdline) {
|
||||||
|
int fd;
|
||||||
|
sprintf(cmdline, "/proc/%d/cmdline", pid);
|
||||||
|
fd = open(cmdline, O_RDONLY);
|
||||||
|
cmdline[0] = '\0';
|
||||||
|
if (fd != -1) {
|
||||||
|
read(fd, cmdline, 1024);
|
||||||
|
cmdline[1024] = '\0';
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX
|
||||||
|
int pids_sons_of_r(int pid, int recursive, int limit) {
|
||||||
|
int p;
|
||||||
|
int n = 0;
|
||||||
|
int mola;
|
||||||
|
char buf[128];
|
||||||
|
int tmp;
|
||||||
|
char tmp2[1024];
|
||||||
|
char tmp3[8];
|
||||||
|
struct dirent *file;
|
||||||
|
FILE *fd;
|
||||||
|
DIR *dh = opendir("/proc/");
|
||||||
|
|
||||||
|
if (pid == 0 || dh == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while((file=(struct dirent *)readdir(dh)) ) {
|
||||||
|
p = atoi(file->d_name);
|
||||||
|
if (p) {
|
||||||
|
sprintf(buf,"/proc/%s/stat", file->d_name);
|
||||||
|
fd = fopen(buf, "r");
|
||||||
|
if (fd) {
|
||||||
|
mola = 0;
|
||||||
|
fscanf(fd,"%d %s %s %d",
|
||||||
|
&tmp, tmp2, tmp3, &mola);
|
||||||
|
if (mola == pid) {
|
||||||
|
pids_cmdline(p, tmp2);
|
||||||
|
//for(i=0; i<recursive*2;i++)
|
||||||
|
// printf(" ");
|
||||||
|
cons_printf(" `- %d : %s (%s)\n", p, tmp2, (tmp3[0]=='S')?"sleeping":(tmp3[0]=='T')?"stopped":"running");
|
||||||
|
n++;
|
||||||
|
if (recursive<limit)
|
||||||
|
n+=pids_sons_of_r(p, recursive+1, limit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
|
@ -14,7 +14,9 @@ enum {
|
||||||
R_DBG_PROC_STOP = 's',
|
R_DBG_PROC_STOP = 's',
|
||||||
R_DBG_PROC_RUN = 'r',
|
R_DBG_PROC_RUN = 'r',
|
||||||
R_DBG_PROC_SLEEP = 'S',
|
R_DBG_PROC_SLEEP = 'S',
|
||||||
R_DBG_PROC_ZOMBIE = 'z'
|
R_DBG_PROC_ZOMBIE = 'z',
|
||||||
|
R_DBG_PROC_DEAD = 'd',
|
||||||
|
R_DBG_PROC_RAISED = 'R' // has produced a signal, breakpoint, etc..
|
||||||
};
|
};
|
||||||
|
|
||||||
// signal handling must support application and debugger level options
|
// signal handling must support application and debugger level options
|
||||||
|
@ -152,9 +154,7 @@ typedef struct r_debug_pid_t {
|
||||||
char status; /* stopped, running, zombie, sleeping ,... */
|
char status; /* stopped, running, zombie, sleeping ,... */
|
||||||
int runnable; /* when using 'run', 'continue', .. this proc will be runnable */
|
int runnable; /* when using 'run', 'continue', .. this proc will be runnable */
|
||||||
const char *path;
|
const char *path;
|
||||||
//struct list_head threads;
|
ut64 pc;
|
||||||
//struct list_head childs;
|
|
||||||
//struct r_debug_pid_t *parent;
|
|
||||||
} RDebugPid;
|
} RDebugPid;
|
||||||
|
|
||||||
#ifdef R_API
|
#ifdef R_API
|
||||||
|
@ -174,7 +174,7 @@ R_API int r_debug_continue_syscall(struct r_debug_t *dbg, int sc);
|
||||||
//R_API int r_debug_pid_del(struct r_debug_t *dbg);
|
//R_API int r_debug_pid_del(struct r_debug_t *dbg);
|
||||||
//R_API int r_debug_pid_del_thread(struct r_debug_t *dbg);
|
//R_API int r_debug_pid_del_thread(struct r_debug_t *dbg);
|
||||||
R_API int r_debug_pid_list(RDebug *dbg, int pid);
|
R_API int r_debug_pid_list(RDebug *dbg, int pid);
|
||||||
R_API RDebugPid *r_debug_pid_new(char *path, int pid, char status);
|
R_API RDebugPid *r_debug_pid_new(char *path, int pid, char status, ut64 pc);
|
||||||
R_API RDebugPid *r_debug_pid_free(RDebugPid *pid);
|
R_API RDebugPid *r_debug_pid_free(RDebugPid *pid);
|
||||||
|
|
||||||
R_API int r_debug_use(struct r_debug_t *dbg, const char *str);
|
R_API int r_debug_use(struct r_debug_t *dbg, const char *str);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <mach/mach_init.h>
|
#include <mach/mach_init.h>
|
||||||
#include <mach/mach_port.h>
|
#include <mach/mach_port.h>
|
||||||
#include <mach/mach_traps.h>
|
#include <mach/mach_traps.h>
|
||||||
|
#include <mach/mach_error.h>
|
||||||
#include <mach/task.h>
|
#include <mach/task.h>
|
||||||
#include <mach/task_info.h>
|
#include <mach/task_info.h>
|
||||||
#include <mach/thread_act.h>
|
#include <mach/thread_act.h>
|
||||||
|
@ -48,10 +49,10 @@ static task_t pid_to_task(int pid) {
|
||||||
if (old_task!= -1) //old_pid != -1 && old_pid == pid)
|
if (old_task!= -1) //old_pid != -1 && old_pid == pid)
|
||||||
return old_task;
|
return old_task;
|
||||||
|
|
||||||
err = task_for_pid(mach_task_self(), (pid_t)pid, &task);
|
err = task_for_pid (mach_task_self (), (pid_t)pid, &task);
|
||||||
if ((err != KERN_SUCCESS) || !MACH_PORT_VALID(task)) {
|
if ((err != KERN_SUCCESS) || !MACH_PORT_VALID(task)) {
|
||||||
fprintf(stderr, "Failed to get task %d for pid %d.\n", (int)task, (int)pid);
|
fprintf(stderr, "Failed to get task %d for pid %d.\n", (int)task, (int)pid);
|
||||||
eprintf ("Reason: 0x%x: %s\n", err, MACH_ERROR_STRING(err));
|
eprintf ("Reason: 0x%x: %s\n", err, MACH_ERROR_STRING (err));
|
||||||
eprintf ("You probably need to add user to procmod group.\n"
|
eprintf ("You probably need to add user to procmod group.\n"
|
||||||
" Or chmod g+s radare && chown root:procmod radare\n");
|
" Or chmod g+s radare && chown root:procmod radare\n");
|
||||||
fprintf(stderr, "FMI: http://developer.apple.com/documentation/Darwin/Reference/ManPages/man8/taskgated.8.html\n");
|
fprintf(stderr, "FMI: http://developer.apple.com/documentation/Darwin/Reference/ManPages/man8/taskgated.8.html\n");
|
||||||
|
@ -63,7 +64,7 @@ static task_t pid_to_task(int pid) {
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __read(RIO *io, int pid, void *buff, int len) {
|
static int __read(RIO *io, int pid, ut8 *buff, int len) {
|
||||||
unsigned int size = 0;
|
unsigned int size = 0;
|
||||||
int err = vm_read_overwrite (pid_to_task (pid),
|
int err = vm_read_overwrite (pid_to_task (pid),
|
||||||
(unsigned int)io->off, len, (pointer_t)buff, &size);
|
(unsigned int)io->off, len, (pointer_t)buff, &size);
|
||||||
|
@ -103,7 +104,7 @@ static int __write(struct r_io_t *io, int pid, const ut8 *buf, int len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __plugin_open(struct r_io_t *io, const char *file) {
|
static int __plugin_open(struct r_io_t *io, const char *file) {
|
||||||
if (!memcmp (file, "mach://", 7))
|
if (!memcmp (file, "attach://", 9) || !memcmp (file, "mach://", 7))
|
||||||
return R_TRUE;
|
return R_TRUE;
|
||||||
return R_FALSE;
|
return R_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -159,7 +160,7 @@ static int debug_attach(int pid) {
|
||||||
static int __open(struct r_io_t *io, const char *file, int rw, int mode) {
|
static int __open(struct r_io_t *io, const char *file, int rw, int mode) {
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
if (__plugin_open (io, file)) {
|
if (__plugin_open (io, file)) {
|
||||||
int pid = atoi(file+7);
|
int pid = atoi(file+(file[0]=='a'?9:7));
|
||||||
if (pid>0) {
|
if (pid>0) {
|
||||||
ret = debug_attach (pid);
|
ret = debug_attach (pid);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
|
@ -225,8 +226,8 @@ struct r_io_plugin_t r_io_plugin_mach = {
|
||||||
#else
|
#else
|
||||||
|
|
||||||
struct r_io_plugin_t r_io_plugin_mach = {
|
struct r_io_plugin_t r_io_plugin_mach = {
|
||||||
.name = "io.ptrace",
|
.name = "io.mach ",
|
||||||
.desc = "ptrace io (NOT SUPPORTED FOR THIS PLATFORM)",
|
.desc = "mach debug io (unsupported in this platform)"
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,7 +24,7 @@ R_API RIOSection *r_io_section_get_i(RIO *io, int idx) {
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct list_head *pos;
|
struct list_head *pos;
|
||||||
list_for_each_prev (pos, &io->sections) {
|
list_for_each_prev (pos, &io->sections) {
|
||||||
RIOSection *s = (RIOSection *)list_entry(pos, RIOSection, list);
|
RIOSection *s = (RIOSection *)list_entry (pos, RIOSection, list);
|
||||||
if (i == idx)
|
if (i == idx)
|
||||||
return s;
|
return s;
|
||||||
i++;
|
i++;
|
||||||
|
|
|
@ -93,6 +93,7 @@ public class Radare.RDebug {
|
||||||
RUN,
|
RUN,
|
||||||
SLEEP,
|
SLEEP,
|
||||||
ZOMBIE,
|
ZOMBIE,
|
||||||
|
DEAD
|
||||||
}
|
}
|
||||||
|
|
||||||
[CCode (cprefix="R_DBG_REASON_", cname="int")]
|
[CCode (cprefix="R_DBG_REASON_", cname="int")]
|
||||||
|
|
Loading…
Reference in New Issue