Fix single-step in the iOS-arm64 native debugger ##debug

This commit is contained in:
pancake 2019-07-18 02:30:45 +02:00
parent 55e3da3c32
commit 1aebd0a26d
7 changed files with 127 additions and 115 deletions

View file

@ -1,6 +1,6 @@
#if 0
__ut64 __x[29]; /* General purpose registers x0-x28 */
__ut64 __fp; /* Frame pointer x29 */
__ut64 __fp; /* Frame pointer x29 */ //// 232
__ut64 __lr; /* Link register x30 */
__ut64 __sp; /* Stack pointer x31 */
__ut64 __pc; /* Program counter */
@ -83,11 +83,11 @@ return strdup (
"gpr zr .64 ? 0\n" // w0
// TODO complete w list ...
// special registers
"gpr fp .64 236 0\n" // FP
"gpr lr .64 240 0\n" // LR
"gpr sp .64 248 0\n" // SP
"gpr pc .64 256 0\n" // PC
"gpr pstate .64 272 0\n" // FLAGS
"gpr fp .64 232 0\n" // FP
"gpr lr .64 236 0\n" // LR
"gpr sp .64 240 0\n" // SP
"gpr pc .64 248 0\n" // PC
"gpr pstate .64 256 0\n" // FLAGS
// TODO flags
"gpr nf .1 .2176 0 sign\n" // XXX wrong offset
);

View file

@ -9,8 +9,7 @@ static bool ios_hwstep_enable64(RDebug *dbg, bool enable) {
thread_t th = getcurthread (dbg, NULL);
mach_msg_type_number_t count = ARM_DEBUG_STATE64_COUNT;
if (thread_get_state (th, ARM_DEBUG_STATE64,
(thread_state_t)&ds, &count)) {
if (thread_get_state (th, ARM_DEBUG_STATE64, (thread_state_t)&ds, &count)) {
perror ("thread-get-state");
return false;
}
@ -25,8 +24,7 @@ static bool ios_hwstep_enable64(RDebug *dbg, bool enable) {
} else {
ds.mdscr_el1 &= ~(1ULL);
}
if (thread_set_state (th, ARM_DEBUG_STATE64,
(thread_state_t)&ds, count)) {
if (thread_set_state (th, ARM_DEBUG_STATE64, (thread_state_t)&ds, count)) {
perror ("thread-set-state");
}
return true;
@ -82,15 +80,16 @@ static bool ios_hwstep_enable32(RDebug *dbg, bool enable) {
}
}
if (thread_set_state (th, ARM_DEBUG_STATE32, (thread_state_t)&ds, ARM_DEBUG_STATE32_COUNT)) {
perror ("thread_set_state");
perror ("ios_hwstep_enable32");
return false;
}
return true;
}
bool xnu_native_hwstep_enable(RDebug *dbg, bool enable) {
if (dbg->bits == R_SYS_BITS_64)
if (dbg->bits == R_SYS_BITS_64 || dbg->bits == 64) {
return ios_hwstep_enable64 (dbg, enable);
}
return ios_hwstep_enable32 (dbg, enable);
}
#endif

View file

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2015-2017 - pancake, alvaro_fe */
/* radare2 - LGPL - Copyright 2015-2019 - pancake, alvaro_fe */
#include <r_userconf.h>
#if DEBUGGER
@ -84,7 +84,6 @@ static thread_t getcurthread (RDebug *dbg) {
}
static xnu_thread_t* get_xnu_thread(RDebug *dbg, int tid) {
RListIter *it = NULL;
if (!dbg || tid < 0) {
return NULL;
}
@ -93,7 +92,7 @@ static xnu_thread_t* get_xnu_thread(RDebug *dbg, int tid) {
return NULL;
}
//TODO get the current thread
it = r_list_find (dbg->threads, (const void *)(size_t)&tid,
RListIter *it = r_list_find (dbg->threads, (const void *)(size_t)&tid,
(RListComparator)&thread_find);
if (!it) {
tid = getcurthread (dbg);
@ -175,7 +174,6 @@ bool xnu_step(RDebug *dbg) {
}
return ret;
#else
int ret = 0;
//we must find a way to get the current thread not just the first one
task_t task = pid_to_task (dbg->pid);
if (!task) {
@ -186,7 +184,7 @@ bool xnu_step(RDebug *dbg) {
if (!th) {
return false;
}
ret = set_trace_bit (dbg, th);
int ret = set_trace_bit (dbg, th);
if (!ret) {
eprintf ("xnu_step modificy_trace_bit error\n");
return false;
@ -199,11 +197,11 @@ bool xnu_step(RDebug *dbg) {
int xnu_attach(RDebug *dbg, int pid) {
#if XNU_USE_PTRACE
#if PT_ATTACHEXC
#if PT_ATTACHEXC
if (r_debug_ptrace (dbg, PT_ATTACHEXC, pid, 0, 0) == -1) {
#else
#else
if (r_debug_ptrace (dbg, PT_ATTACH, pid, 0, 0) == -1) {
#endif
#endif
perror ("ptrace (PT_ATTACH)");
return -1;
}
@ -257,16 +255,12 @@ int xnu_stop(RDebug *dbg, int pid) {
eprintf ("xnu_stop: not implemented\n");
return false;
#else
kern_return_t kr;
task_t task;
int suspend_count;
task = pid_to_task (pid);
task_t task = pid_to_task (pid);
if (!task) {
return false;
}
suspend_count = task_suspend_count (task);
int suspend_count = task_suspend_count (task);
if (suspend_count == -1) {
return false;
}
@ -279,7 +273,7 @@ int xnu_stop(RDebug *dbg, int pid) {
return false;
}
kr = task_suspend (task);
kern_return_t kr = task_suspend (task);
if (kr != KERN_SUCCESS) {
eprintf ("failed to suspend task\n");
return false;
@ -302,7 +296,6 @@ int xnu_continue(RDebug *dbg, int pid, int tid, int sig) {
(int)(size_t)data) == 0;
#else
task_t task = pid_to_task (pid);
kern_return_t kr;
if (!task) {
return false;
}
@ -319,14 +312,10 @@ int xnu_continue(RDebug *dbg, int pid, int tid, int sig) {
return false;
}
}
kr = task_resume (task);
#if 0
// it fails because the process is in a syscall like read() waiting to finish
// so it cant resume
kern_return_t kr = task_resume (task);
if (kr != KERN_SUCCESS) {
eprintf ("Failed to resume task xnu_continue\n");
eprintf ("xnu_continue: Warning: Failed to resume task\n");
}
#endif
return true;
#endif
}
@ -370,12 +359,14 @@ int xnu_reg_write(RDebug *dbg, int type, const ut8 *buf, int size) {
memcpy (&th->drx.uds.ds32, buf, R_MIN (size, sizeof (th->drx)));
#elif __i386__
memcpy (&th->drx.uds.ds64, buf, R_MIN (size, sizeof (th->drx)));
#elif __arm || __arm64 || __aarch64
#if defined (ARM_DEBUG_STATE32) && (defined (__arm64__) || defined (__aarch64__))
memcpy (&th->debug.drx32, buf, R_MIN (size, sizeof (th->debug.drx32)));
#else
#elif __arm64 || __aarch64
if (dbg->bits == R_SYS_BITS_64) {
memcpy (&th->debug.drx64, buf, R_MIN (size, sizeof (th->debug.drx64)));
} else {
memcpy (&th->debug.drx32, buf, R_MIN (size, sizeof (th->debug.drx32)));
}
#elif __arm || __armv7 || __arm__ || __armv7__
memcpy (&th->debug.drx, buf, R_MIN (size, sizeof (th->debug.drx)));
#endif
#endif
ret = xnu_thread_set_drx (dbg, th);
break;

View file

@ -105,9 +105,11 @@ static bool modify_trace_bit(RDebug *dbg, xnu_thread *th, int enable) {
// (SS bit in the MDSCR_EL1 register)
#define SS_ENABLE ((uint32_t)(1u))
#if __arm || __arm__ || __armv7 || __armv7__
static bool is_thumb_32(ut16 op) {
return (((op & 0xE000) == 0xE000) && (op & 0x1800));
}
#endif
static int modify_trace_bit(RDebug *dbg, xnu_thread_t *th, int enable) {
int i = 0;
@ -116,10 +118,24 @@ static int modify_trace_bit(RDebug *dbg, xnu_thread_t *th, int enable) {
eprintf ("error to get drx registers modificy_trace_bit arm\n");
return false;
}
#if __arm64 || __arm64__ || __aarch64 || __aarch64__
if (th->flavor == ARM_DEBUG_STATE32) {
arm_debug_state32_t *state = &th->debug.drx32;
state->__mdscr_el1 = (state->__mdscr_el1 & SS_ENABLE) & (enable ? SS_ENABLE : 0);
} else if (th->flavor == ARM_DEBUG_STATE) {
if (enable) {
state->__mdscr_el1 = state->__mdscr_el1 | SS_ENABLE;
} else {
state->__mdscr_el1 = state->__mdscr_el1 & ~SS_ENABLE;
}
} else if (th->flavor == ARM_DEBUG_STATE64) {
arm_debug_state64_t *state = &th->debug.drx64;
if (enable) {
state->__mdscr_el1 = state->__mdscr_el1 | SS_ENABLE;
} else {
state->__mdscr_el1 = state->__mdscr_el1 & ~SS_ENABLE;
}
} else
#elif __arm || __arm__ || __armv7 || __armv7__
if (th->flavor == ARM_DEBUG_STATE) {
arm_debug_state_t *state = &th->debug.drx;
R_REG_T *regs;
ret = xnu_thread_get_gpr (dbg, th);
@ -178,7 +194,9 @@ static int modify_trace_bit(RDebug *dbg, xnu_thread_t *th, int enable) {
state->__bcr[i] = 0;
}
}
} else {
} else
#endif
{
eprintf ("Bad flavor modificy_trace_bit arm\n");
return false;
}

View file

@ -1,4 +1,4 @@
/* radare - LGPL - Copyright 2009-2016 - pancake */
/* radare - LGPL - Copyright 2009-2019 - pancake */
#include <r_userconf.h>
#if DEBUGGER
@ -36,18 +36,18 @@ static bool xnu_thread_get_drx (RDebug *dbg, xnu_thread_t *thread) {
rc = thread_get_state (thread->port, thread->flavor,
(thread_state_t)&thread->drx, &thread->count);
#elif __arm64__ || __arm64 || __aarch64 || __aarch64__
if (dbg->bits == 32) {
thread->count = ARM_DEBUG_STATE32_COUNT;
thread->flavor = ARM_DEBUG_STATE32;
rc = thread_get_state (thread->port, thread->flavor,
(thread_state_t)&thread->debug.drx32,
&thread->count);
} else {
if (dbg->bits == R_SYS_BITS_64) {
thread->count = ARM_DEBUG_STATE64_COUNT;
thread->flavor = ARM_DEBUG_STATE64;
rc = thread_get_state (thread->port, thread->flavor,
(thread_state_t)&thread->debug.drx64,
&thread->count);
} else {
thread->count = ARM_DEBUG_STATE32_COUNT;
thread->flavor = ARM_DEBUG_STATE32;
rc = thread_get_state (thread->port, thread->flavor,
(thread_state_t)&thread->debug.drx32,
&thread->count);
}
#elif __arm__ || __arm || __armv7__
thread->count = ARM_DEBUG_STATE_COUNT;
@ -60,21 +60,18 @@ static bool xnu_thread_get_drx (RDebug *dbg, xnu_thread_t *thread) {
rc = KERN_FAILURE;
#endif
if (rc != KERN_SUCCESS) {
thread->count = 0;
perror (__FUNCTION__);
thread->count = 0;
return false;
}
return true;
}
static int xnu_thread_set_drx (RDebug *dbg, xnu_thread_t *thread) {
static bool xnu_thread_set_drx (RDebug *dbg, xnu_thread_t *thread) {
r_return_val_if_fail (dbg && thread, false);
kern_return_t rc;
if (!dbg || !thread) {
return false;
}
#if __i386__ || __x86_64__
x86_debug_state_t *regs;
regs = &thread->drx;
x86_debug_state_t *regs = &thread->drx;
if (!regs) {
return false;
}
@ -89,27 +86,32 @@ static int xnu_thread_set_drx (RDebug *dbg, xnu_thread_t *thread) {
}
rc = thread_set_state (thread->port, thread->flavor,
(thread_state_t)regs, thread->count);
#elif __arm || __arm64 || __aarch64
#if defined(ARM_DEBUG_STATE32) && (defined(__arm64__) || defined(__aarch64__))
thread->count = ARM_DEBUG_STATE32_COUNT;
thread->flavor = ARM_DEBUG_STATE32;
rc = thread_set_state (thread->port, thread->flavor,
(thread_state_t)&thread->debug.drx32,
thread->count);
#elif __POWERPC__
ppc_debug_state_t *regs;
#else
thread->count = ARM_DEBUG_STATE_COUNT;
#elif __arm64__ || __arm64 || __aarch64 || __aarch64__
if (dbg->bits == R_SYS_BITS_64) {
thread->count = ARM_DEBUG_STATE64_COUNT;
thread->flavor = ARM_DEBUG_STATE64;
rc = thread_set_state (thread->port, thread->flavor,
(thread_state_t)&thread->debug.drx64,
thread->count);
} else {
thread->count = ARM_DEBUG_STATE32_COUNT;
thread->flavor = ARM_DEBUG_STATE32;
rc = thread_set_state (thread->port, thread->flavor,
(thread_state_t)&thread->debug.drx32,
thread->count);
}
#elif __arm__ || __arm || __armv7__
thread->count = ARM_DEBUG_STATE_COUNT;
thread->flavor = ARM_DEBUG_STATE;
rc = thread_set_state (thread->port, thread->flavor,
(thread_state_t)&thread->debug.drx,
thread->count);
#endif
&thread->count);
#elif __POWERPC__
/* not supported */
#ifndef PPC_DEBUG_STATE32
#define PPC_DEBUG_STATE32 1
#endif
# ifndef PPC_DEBUG_STATE32
# define PPC_DEBUG_STATE32 1
# endif
ppc_debug_state_t *regs;
//thread->flavor = PPC_DEBUG_STATE32;
//thread->count = R_MIN (thread->count, sizeof (regs->uds.ds32));
return false;
@ -118,19 +120,20 @@ static int xnu_thread_set_drx (RDebug *dbg, xnu_thread_t *thread) {
thread->count = 0;
#endif
if (rc != KERN_SUCCESS) {
perror ("thread_set_state");
thread->count = false;
perror (__FUNCTION__);
thread->count = 0;
return false;
}
return true;
}
static int xnu_thread_set_gpr (RDebug *dbg, xnu_thread_t *thread) {
static bool xnu_thread_set_gpr (RDebug *dbg, xnu_thread_t *thread) {
r_return_val_if_fail (dbg && thread, false);
kern_return_t rc;
R_REG_T *regs;
if (!dbg || !thread) return false;
regs = (R_REG_T *)&thread->gpr;
if (!regs) return false;
R_REG_T *regs = (R_REG_T *)&thread->gpr;
if (!regs) {
return false;
}
#if __i386__ || __x86_64__
// thread->flavor is used in a switch+case but in regs->tsh.flavor we
// specify
@ -145,34 +148,33 @@ static int xnu_thread_set_gpr (RDebug *dbg, xnu_thread_t *thread) {
regs->tsh.flavor = x86_THREAD_STATE32;
regs->tsh.count = x86_THREAD_STATE32_COUNT;
}
#elif __arm || __arm64 || __aarch64
#elif __arm64 || __aarch64 || __arm64__ || __aarch64__
#if 0
/* unified doesnt seems to work */
thread->flavor = ARM_UNIFIED_THREAD_STATE;
thread->count = ARM_UNIFIED_THREAD_STATE_COUNT;
if (dbg->bits == R_SYS_BITS_64) {
regs->ash.flavor = ARM_THREAD_STATE64;
regs->ash.count = ARM_THREAD_STATE64_COUNT;
} else {
regs->ash.flavor = ARM_THREAD_STATE32;
regs->ash.count = ARM_THREAD_STATE32_COUNT;
}
#endif
thread->state = regs;
//thread->state = regs;
thread->state = &regs->uts;
if (dbg->bits == R_SYS_BITS_64) {
thread->flavor = ARM_THREAD_STATE64;
thread->count = ARM_THREAD_STATE64_COUNT;
thread->state_size = sizeof (arm_thread_state64_t);
} else {
thread->flavor = ARM_THREAD_STATE;
thread->count = ARM_THREAD_STATE_COUNT;
thread->flavor = ARM_THREAD_STATE32;
thread->count = ARM_THREAD_STATE32_COUNT;
thread->state_size = sizeof (arm_thread_state32_t);
}
#elif __arm || __arm__ || __armv7__
thread->flavor = ARM_THREAD_STATE;
thread->count = ARM_THREAD_STATE_COUNT;
thread->state_size = sizeof (arm_thread_state_t);
#endif
rc = thread_set_state (thread->port, thread->flavor,
(thread_state_t)regs, thread->count);
if (rc != KERN_SUCCESS) {
perror ("xnu_thread_set_state");
perror (__FUNCTION__);
thread->count = 0;
return false;
}
@ -180,19 +182,17 @@ static int xnu_thread_set_gpr (RDebug *dbg, xnu_thread_t *thread) {
}
static bool xnu_thread_get_gpr (RDebug *dbg, xnu_thread_t *thread) {
kern_return_t rc;
R_REG_T *regs;
if (!dbg || !thread) {
return false;
}
regs = &thread->gpr;
r_return_val_if_fail (dbg && thread, false);
R_REG_T *regs = &thread->gpr;
if (!regs) {
return false;
}
kern_return_t rc;
#if __POWERPC__
thread->state = regs;
#elif __arm || __arm64 || __aarch64
thread->state = regs;
#elif __arm64 || __aarch64 || __arch64__ || __arm64__
//thread->state = regs;
thread->state = &regs->uts;
if (dbg->bits == R_SYS_BITS_64) {
thread->flavor = ARM_THREAD_STATE64;
thread->count = ARM_THREAD_STATE64_COUNT;
@ -202,6 +202,11 @@ static bool xnu_thread_get_gpr (RDebug *dbg, xnu_thread_t *thread) {
thread->count = ARM_THREAD_STATE_COUNT;
thread->state_size = sizeof (arm_thread_state32_t);
}
#elif __arm || __arm__ || __armv7__
thread->state = regs;
thread->flavor = ARM_THREAD_STATE;
thread->count = ARM_THREAD_STATE_COUNT;
thread->state_size = sizeof (arm_thread_state_t);
#elif __x86_64__ || __i386__
thread->state = &regs->uts;
thread->flavor = x86_THREAD_STATE;
@ -213,8 +218,8 @@ static bool xnu_thread_get_gpr (RDebug *dbg, xnu_thread_t *thread) {
rc = thread_get_state (thread->port, thread->flavor,
(thread_state_t)regs, &thread->count);
if (rc != KERN_SUCCESS) {
perror (__FUNCTION__);
thread->count = 0;
perror ("thread_get_state");
return false;
}
return true;
@ -225,10 +230,6 @@ static bool xnu_fill_info_thread (RDebug *dbg, xnu_thread_t *thread) {
thread->name = strdup ("unknown");
return false;
#else
#if !TARGET_OS_IPHONE
struct proc_threadinfo proc_threadinfo;
int ret_proc;
#endif
mach_msg_type_number_t count = THREAD_BASIC_INFO_COUNT;
thread_identifier_info_data_t identifier_info;
kern_return_t kr = thread_info (thread->port, THREAD_BASIC_INFO,
@ -249,7 +250,8 @@ static bool xnu_fill_info_thread (RDebug *dbg, xnu_thread_t *thread) {
// TODO proc_pidinfo here
thread->name = strdup ("unknown");
#else
ret_proc = proc_pidinfo (dbg->pid, PROC_PIDTHREADINFO,
struct proc_threadinfo proc_threadinfo;
int ret_proc = proc_pidinfo (dbg->pid, PROC_PIDTHREADINFO,
identifier_info.thread_handle,
&proc_threadinfo, PROC_PIDTHREADINFO_SIZE);
if (ret_proc && proc_threadinfo.pth_name[0]) {
@ -284,10 +286,7 @@ static int xnu_update_thread_info (RDebug *dbg, xnu_thread_t *thread) {
}
static int thread_find (thread_t *port, xnu_thread_t *a) {
if (a && port && (a->port == *port)) {
return 0; // match
}
return 1;
return (a && port && (a->port == *port))? 0: 1;
}
static int xnu_update_thread_list (RDebug *dbg) {

View file

@ -47,10 +47,13 @@ typedef struct _xnu_thread {
R_REG_T gpr; // type R_REG_T using unified API XXX bad naming
void *state;
ut32 state_size;
#if __arm || __arm64 || __aarch64
#if __arm64 || __aarch64 || __arm64__ || __aarch64__
union {
arm_debug_state32_t drx32;
arm_debug_state64_t drx64;
} debug;
#elif __arm__ || __arm || __armv7__
union {
arm_debug_state_t drx;
} debug;
#elif __x86_64__ || __i386__

View file

@ -74,10 +74,12 @@ if [ $onlymakedeb = 1 ]; then
makeDeb
else
if [ $fromscratch = 1 ]; then
make clean
./configure --prefix="${PREFIX}" --with-ostype=darwin --without-libuv \
--with-compiler=ios-sdk --target=arm-unknown-darwin
RV=$?
(cd libr/debug ; make clean)
#make clean
#./configure --prefix="${PREFIX}" --with-ostype=darwin --without-libuv \
# --with-compiler=ios-sdk --target=arm-unknown-darwin
#RV=$?
RV=0
else
RV=0
fi