De-include xnu_threads.c and xnu_excthreads.c

With XNU_USE_PTRACE removed, these source files can now be compiled as
standalone objects unconditionally.
This commit is contained in:
Florian Märkl 2022-07-10 15:25:48 +02:00
parent c671083925
commit c90ebb6b68
6 changed files with 105 additions and 92 deletions

View file

@ -93,8 +93,8 @@ if has_debugger
'p/native/xnu/xnu_debug.c',
#'p/native/xnu/trap_arm.c',
#'p/native/xnu/trap_x86.c',
#'p/native/xnu/xnu_excthreads.c',
#'p/native/xnu/xnu_threads.c',
'p/native/xnu/xnu_excthreads.c',
'p/native/xnu/xnu_threads.c',
]
endif

View file

@ -2,10 +2,6 @@
// SPDX-FileCopyrightText: 2015-2019 alvaro_fe <alvaro.felipe91@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_userconf.h>
// ------------------------------------
#include <rz_debug.h>
#include <rz_reg.h>
#include <rz_lib.h>
@ -21,8 +17,7 @@
static task_t task_dbg = 0;
#include "xnu_debug.h"
#include "xnu_threads.c"
#include "xnu_excthreads.c"
#include "xnu_threads.h"
extern int proc_regionfilename(int pid, uint64_t address, void *buffer, uint32_t buffersize);
@ -59,50 +54,6 @@ typedef struct {
ut64 image_file_mod_date;
} DyldImageInfo64;
/* XXX: right now it just returns the first thread, not the one selected in dbg->tid */
static thread_t getcurthread(RzDebug *dbg) {
thread_t th;
thread_array_t threads = NULL;
unsigned int n_threads = 0;
task_t t = pid_to_task(dbg->pid);
if (!t) {
return -1;
}
if (task_threads(t, &threads, &n_threads) != KERN_SUCCESS) {
return -1;
}
if (n_threads > 0) {
memcpy(&th, threads, sizeof(th));
} else {
th = -1;
}
vm_deallocate(t, (vm_address_t)threads, n_threads * sizeof(thread_act_t));
return th;
}
static xnu_thread_t *get_xnu_thread(RzDebug *dbg, int tid) {
if (!dbg || tid < 0) {
return NULL;
}
if (!xnu_update_thread_list(dbg)) {
eprintf("Failed to update thread_list xnu_udpate_thread_list\n");
return NULL;
}
// TODO get the current thread
RzListIter *it = rz_list_find(dbg->threads, (const void *)(size_t)&tid,
(RzListComparator)&thread_find);
if (!it) {
tid = getcurthread(dbg);
it = rz_list_find(dbg->threads, (const void *)(size_t)&tid,
(RzListComparator)&thread_find);
if (!it) {
eprintf("Thread not found get_xnu_thread\n");
return NULL;
}
}
return (xnu_thread_t *)it->data;
}
static task_t task_for_pid_workaround(int Pid) {
host_t myhost = mach_host_self();
mach_port_t psDefault = 0;
@ -154,10 +105,6 @@ static task_t task_for_pid_ios9pangu(int pid) {
return task;
}
int xnu_wait(RzDebug *dbg, int pid) {
return __xnu_wait(dbg, pid);
}
bool xnu_step(RzDebug *dbg) {
// we must find a way to get the current thread not just the first one
task_t task = pid_to_task(dbg->pid);
@ -165,11 +112,11 @@ bool xnu_step(RzDebug *dbg) {
eprintf("step failed on task %d for pid %d\n", task, dbg->tid);
return false;
}
xnu_thread_t *th = get_xnu_thread(dbg, getcurthread(dbg));
xnu_thread_t *th = rz_xnu_get_thread(dbg, rz_xnu_get_cur_thread(dbg));
if (!th) {
return false;
}
int ret = set_trace_bit(dbg, th);
int ret = xnu_set_trace_bit(dbg, th);
if (!ret) {
eprintf("xnu_step modificy_trace_bit error\n");
return false;
@ -257,14 +204,14 @@ int xnu_continue(RzDebug *dbg, int pid, int tid, int sig) {
return false;
}
// TODO free refs count threads
xnu_thread_t *th = get_xnu_thread(dbg, getcurthread(dbg));
xnu_thread_t *th = rz_xnu_get_thread(dbg, rz_xnu_get_cur_thread(dbg));
if (!th) {
eprintf("failed to get thread in xnu_continue\n");
return false;
}
// disable trace bit if enable
if (th->stepping) {
if (!clear_trace_bit(dbg, th)) {
if (!xnu_clear_trace_bit(dbg, th)) {
eprintf("error clearing trace bit in xnu_continue\n");
return false;
}
@ -305,7 +252,7 @@ char *xnu_reg_profile(RzDebug *dbg) {
// is not implemented yet i don't care so much
int xnu_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size) {
bool ret;
xnu_thread_t *th = get_xnu_thread(dbg, getcurthread(dbg));
xnu_thread_t *th = rz_xnu_get_thread(dbg, rz_xnu_get_cur_thread(dbg));
if (!th) {
return 0;
}
@ -324,7 +271,7 @@ int xnu_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size) {
#elif __arm || __armv7 || __arm__ || __armv7__
memcpy(&th->debug.drx, buf, RZ_MIN(size, sizeof(th->debug.drx)));
#endif
ret = xnu_thread_set_drx(dbg, th);
ret = rz_xnu_thread_set_drx(dbg, th);
break;
default:
// th->gpr has a header and the state we should copy on the state only
@ -333,14 +280,14 @@ int xnu_reg_write(RzDebug *dbg, int type, const ut8 *buf, int size) {
#else
memcpy(&th->gpr.uts, buf, RZ_MIN(size, sizeof(th->gpr.uts)));
#endif
ret = xnu_thread_set_gpr(dbg, th);
ret = rz_xnu_thread_set_gpr(dbg, th);
break;
}
return ret;
}
int xnu_reg_read(RzDebug *dbg, int type, ut8 *buf, int size) {
xnu_thread_t *th = get_xnu_thread(dbg, getcurthread(dbg));
xnu_thread_t *th = rz_xnu_get_thread(dbg, rz_xnu_get_cur_thread(dbg));
if (!th) {
return 0;
}
@ -348,12 +295,12 @@ int xnu_reg_read(RzDebug *dbg, int type, ut8 *buf, int size) {
case RZ_REG_TYPE_SEG:
case RZ_REG_TYPE_FLG:
case RZ_REG_TYPE_GPR:
if (!xnu_thread_get_gpr(dbg, th)) {
if (!rz_xnu_thread_get_gpr(dbg, th)) {
return 0;
}
break;
case RZ_REG_TYPE_DRX:
if (!xnu_thread_get_drx(dbg, th)) {
if (!rz_xnu_thread_get_drx(dbg, th)) {
return 0;
}
break;
@ -373,7 +320,7 @@ int xnu_reg_read(RzDebug *dbg, int type, ut8 *buf, int size) {
RzDebugMap *xnu_map_alloc(RzDebug *dbg, ut64 addr, int size) {
kern_return_t ret;
ut8 *base = (ut8 *)addr;
xnu_thread_t *th = get_xnu_thread(dbg, dbg->tid);
xnu_thread_t *th = rz_xnu_get_thread(dbg, dbg->tid);
bool anywhere = !VM_FLAGS_ANYWHERE;
if (!th) {
return NULL;
@ -393,7 +340,7 @@ RzDebugMap *xnu_map_alloc(RzDebug *dbg, ut64 addr, int size) {
}
int xnu_map_dealloc(RzDebug *dbg, ut64 addr, int size) {
xnu_thread_t *th = get_xnu_thread(dbg, dbg->tid);
xnu_thread_t *th = rz_xnu_get_thread(dbg, dbg->tid);
if (!th) {
return false;
}
@ -488,10 +435,10 @@ RzList *xnu_thread_list(RzDebug *dbg, int pid, RzList *list) {
RzListIter *iter;
xnu_thread_t *thread;
RZ_REG_T state;
xnu_update_thread_list(dbg);
rz_xnu_update_thread_list(dbg);
list->free = (RzListFree)&rz_debug_pid_free;
rz_list_foreach (dbg->threads, iter, thread) {
if (!xnu_thread_get_gpr(dbg, thread)) {
if (!rz_xnu_thread_get_gpr(dbg, thread)) {
eprintf("Failed to get gpr registers xnu_thread_list\n");
continue;
}

View file

@ -12,6 +12,7 @@
#define _XNU_DEBUG_H
#include <rz_util/rz_log.h>
#include <rz_debug.h>
#define LOG_MACH_ERROR(name, rc) \
do { \
@ -282,7 +283,7 @@ RzDebugMap *xnu_map_alloc(RzDebug *dbg, ut64 addr, int size);
int xnu_map_dealloc(RzDebug *dbg, ut64 addr, int size);
int xnu_map_protect(RzDebug *dbg, ut64 addr, int size, int perms);
int xnu_init(void);
int xnu_wait(RzDebug *dbg, int pid);
RZ_IPI int xnu_wait(RzDebug *dbg, int pid);
RzDebugPid *xnu_get_pid(int pid);
RzList *xnu_dbg_maps(RzDebug *dbg, int only_modules);
RzList *xnu_thread_list(RzDebug *dbg, int pid, RzList *list);

View file

@ -1,13 +1,12 @@
// SPDX-FileCopyrightText: 2022 Florian Märkl <info@florianmaerkl.de>
// SPDX-FileCopyrightText: 2015 alvarofe <alvaro.felipe91@gmail.com>
// SPDX-License-Identifier: LGPL-3.0-only
// FIXME deallocate all the port when they are not longer needed
#include "xnu_debug.h"
#include "xnu_threads.h"
#define set_trace_bit(dbg, thread) modify_trace_bit(dbg, thread, 1)
#define clear_trace_bit(dbg, thread) modify_trace_bit(dbg, thread, 0)
#if defined __i386__ || __x86_64__ // intel processors
/* Set/clear bit 8 (Trap Flag) of the EFLAGS processor control
@ -15,10 +14,10 @@
ENABLE is a boolean, indicating whether to set (1) the Trap Flag
or clear it (0). */
static bool modify_trace_bit(RzDebug *dbg, xnu_thread_t *th, int enable) {
RZ_IPI bool xnu_modify_trace_bit(RzDebug *dbg, xnu_thread_t *th, int enable) {
RZ_REG_T *state;
int ret;
ret = xnu_thread_get_gpr(dbg, th);
ret = rz_xnu_thread_get_gpr(dbg, th);
if (!ret) {
eprintf("error to get gpr registers in trace bit intel\n");
return false;
@ -36,7 +35,7 @@ static bool modify_trace_bit(RzDebug *dbg, xnu_thread_t *th, int enable) {
eprintf("Invalid bit size\n");
return false;
}
if (!xnu_thread_set_gpr(dbg, th)) {
if (!rz_xnu_thread_set_gpr(dbg, th)) {
eprintf("error xnu_thread_set_gpr in modify_trace_bit intel\n");
return false;
}
@ -46,11 +45,11 @@ static bool modify_trace_bit(RzDebug *dbg, xnu_thread_t *th, int enable) {
#elif __POWERPC__ // ppc processor
// XXX poor support at this stage i don't care so much. Once intel and arm done it could be done
// TODO add better support for ppc
static bool modify_trace_bit(RzDebug *dbg, void *th, int enable) {
RZ_IPI bool xnu_modify_trace_bit(RzDebug *dbg, void *th, int enable) {
return false;
}
#if 0
static bool modify_trace_bit(RzDebug *dbg, xnu_thread *th, int enable) {
static bool xnu_modify_trace_bit(RzDebug *dbg, xnu_thread *th, int enable) {
return false;
RZ_REG_T state;
unsigned int state_count = RZ_REG_STATE_SZ;
@ -115,8 +114,8 @@ static bool is_thumb_32(ut16 op) {
}
#endif
static int modify_trace_bit(RzDebug *dbg, xnu_thread_t *th, int enable) {
int ret = xnu_thread_get_drx(dbg, th);
RZ_IPI bool xnu_modify_trace_bit(RzDebug *dbg, xnu_thread_t *th, int enable) {
int ret = rz_xnu_thread_get_drx(dbg, th);
if (!ret) {
eprintf("error to get drx registers modificy_trace_bit arm\n");
return false;
@ -142,7 +141,7 @@ static int modify_trace_bit(RzDebug *dbg, xnu_thread_t *th, int enable) {
int i = 0;
arm_debug_state_t *state = &th->debug.drx;
RZ_REG_T *regs;
ret = xnu_thread_get_gpr(dbg, th);
ret = rz_xnu_thread_get_gpr(dbg, th);
if (!ret) {
eprintf("error to get gpr register modificy_trace_bit arm\n");
return false;
@ -205,7 +204,7 @@ static int modify_trace_bit(RzDebug *dbg, xnu_thread_t *th, int enable) {
return false;
}
// set state
if (!xnu_thread_set_drx(dbg, th)) {
if (!rz_xnu_thread_set_drx(dbg, th)) {
eprintf("error to set drx modificy_trace_bit arm\n");
return false;
}
@ -224,7 +223,7 @@ static int modify_trace_bit(RzDebug *dbg, xnu_thread *th, int enable) {
// TODO: Tuck this into RzDebug; `void *user` seems like a good candidate.
static xnu_exception_info ex = { { 0 } };
static bool xnu_restore_exception_ports(int pid) {
RZ_IPI bool xnu_restore_exception_ports(int pid) {
kern_return_t kr;
int i;
task_t task = pid_to_task(pid);
@ -375,7 +374,7 @@ static int handle_exception_message(RzDebug *dbg, exc_msg *msg, int *ret_code) {
}
// TODO improve this code
static int __xnu_wait(RzDebug *dbg, int pid) {
RZ_IPI int xnu_wait(RzDebug *dbg, int pid) {
// here comes the important thing
kern_return_t kr;
int ret_code, reason = RZ_DEBUG_REASON_UNKNOWN;
@ -440,7 +439,7 @@ static int __xnu_wait(RzDebug *dbg, int pid) {
return reason;
}
bool xnu_create_exception_thread(RzDebug *dbg) {
RZ_IPI bool xnu_create_exception_thread(RzDebug *dbg) {
#if __POWERPC__
return false;
#else

View file

@ -1,7 +1,7 @@
// SPDX-FileCopyrightText: 2009-2019 pancake <pancake@nopcode.org>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_userconf.h>
#include <rz_debug.h>
// TODO much work remains to be done
#include "xnu_debug.h"
@ -23,7 +23,7 @@ static void xnu_thread_free(xnu_thread_t *thread) {
}
// XXX this should work as long as in arm trace bit relies on this
static bool xnu_thread_get_drx(RzDebug *dbg, xnu_thread_t *thread) {
RZ_IPI bool rz_xnu_thread_get_drx(RzDebug *dbg, xnu_thread_t *thread) {
rz_return_val_if_fail(dbg && thread, false);
kern_return_t rc;
#if __x86_64__ || __i386__
@ -67,7 +67,7 @@ static bool xnu_thread_get_drx(RzDebug *dbg, xnu_thread_t *thread) {
return true;
}
static bool xnu_thread_set_drx(RzDebug *dbg, xnu_thread_t *thread) {
RZ_IPI bool rz_xnu_thread_set_drx(RzDebug *dbg, xnu_thread_t *thread) {
rz_return_val_if_fail(dbg && thread, false);
kern_return_t rc;
#if __i386__ || __x86_64__
@ -127,7 +127,7 @@ static bool xnu_thread_set_drx(RzDebug *dbg, xnu_thread_t *thread) {
return true;
}
static bool xnu_thread_set_gpr(RzDebug *dbg, xnu_thread_t *thread) {
RZ_IPI bool rz_xnu_thread_set_gpr(RzDebug *dbg, xnu_thread_t *thread) {
rz_return_val_if_fail(dbg && thread, false);
kern_return_t rc;
RZ_REG_T *regs = (RZ_REG_T *)&thread->gpr;
@ -181,7 +181,7 @@ static bool xnu_thread_set_gpr(RzDebug *dbg, xnu_thread_t *thread) {
return true;
}
static bool xnu_thread_get_gpr(RzDebug *dbg, xnu_thread_t *thread) {
RZ_IPI bool rz_xnu_thread_get_gpr(RzDebug *dbg, xnu_thread_t *thread) {
rz_return_val_if_fail(dbg && thread, false);
RZ_REG_T *regs = &thread->gpr;
if (!regs) {
@ -287,7 +287,7 @@ static int thread_find(thread_t *port, xnu_thread_t *a) {
return (a && port && (a->port == *port)) ? 0 : 1;
}
static int xnu_update_thread_list(RzDebug *dbg) {
RZ_IPI int rz_xnu_update_thread_list(RzDebug *dbg) {
thread_array_t thread_list = NULL;
unsigned int thread_count = 0;
xnu_thread_t *thread;
@ -374,3 +374,47 @@ static int xnu_update_thread_list(RzDebug *dbg) {
thread_count * sizeof(thread_t));
return true;
}
RZ_IPI xnu_thread_t *rz_xnu_get_thread(RzDebug *dbg, int tid) {
if (!dbg || tid < 0) {
return NULL;
}
if (!rz_xnu_update_thread_list(dbg)) {
eprintf("Failed to update thread_list xnu_udpate_thread_list\n");
return NULL;
}
// TODO get the current thread
RzListIter *it = rz_list_find(dbg->threads, (const void *)(size_t)&tid,
(RzListComparator)&thread_find);
if (!it) {
tid = rz_xnu_get_cur_thread(dbg);
it = rz_list_find(dbg->threads, (const void *)(size_t)&tid,
(RzListComparator)&thread_find);
if (!it) {
eprintf("Thread not found get_xnu_thread\n");
return NULL;
}
}
return (xnu_thread_t *)it->data;
}
/* XXX: right now it just returns the first thread, not the one selected in dbg->tid */
RZ_IPI thread_t rz_xnu_get_cur_thread(RzDebug *dbg) {
thread_t th;
thread_array_t threads = NULL;
unsigned int n_threads = 0;
task_t t = pid_to_task(dbg->pid);
if (!t) {
return -1;
}
if (task_threads(t, &threads, &n_threads) != KERN_SUCCESS) {
return -1;
}
if (n_threads > 0) {
memcpy(&th, threads, sizeof(th));
} else {
th = -1;
}
vm_deallocate(t, (vm_address_t)threads, n_threads * sizeof(thread_act_t));
return th;
}

View file

@ -4,6 +4,9 @@
#ifndef _INCLUDE_XNU_THREADS_H_
#define _INCLUDE_XNU_THREADS_H_
#include <rz_debug.h>
#include <mach/mach_vm.h>
#if __POWERPC__
// TODO add better support for PPC
#define RZ_REG_T ppc_thread_state_t
@ -91,4 +94,23 @@ typedef struct _rep_msg {
kern_return_t ret_code;
} rep_msg;
RZ_IPI int rz_xnu_update_thread_list(RzDebug *dbg);
RZ_IPI xnu_thread_t *rz_xnu_get_thread(RzDebug *dbg, int tid);
RZ_IPI thread_t rz_xnu_get_cur_thread(RzDebug *dbg);
RZ_IPI bool rz_xnu_thread_set_drx(RzDebug *dbg, xnu_thread_t *thread);
RZ_IPI bool rz_xnu_thread_set_gpr(RzDebug *dbg, xnu_thread_t *thread);
RZ_IPI bool rz_xnu_thread_get_gpr(RzDebug *dbg, xnu_thread_t *thread);
RZ_IPI bool rz_xnu_thread_get_drx(RzDebug *dbg, xnu_thread_t *thread);
RZ_IPI bool xnu_modify_trace_bit(RzDebug *dbg, xnu_thread_t *th, int enable);
static inline bool xnu_set_trace_bit(RzDebug *dbg, xnu_thread_t *th) {
return xnu_modify_trace_bit(dbg, th, 1);
}
static inline bool xnu_clear_trace_bit(RzDebug *dbg, xnu_thread_t *th) {
return xnu_modify_trace_bit(dbg, th, 0);
}
RZ_IPI bool xnu_create_exception_thread(RzDebug *dbg);
RZ_IPI bool xnu_restore_exception_ports(int pid);
#endif