10 #if __APPLE__ && DEBUGGER
13 #define EXCEPTION_PORT 0
16 #include <mach/exception_types.h>
17 #include <mach/mach_host.h>
18 #include <mach/host_priv.h>
19 #include <mach/mach_init.h>
20 #include <mach/mach_port.h>
21 #include <mach/mach_traps.h>
22 #include <mach/processor_set.h>
23 #include <mach/mach_error.h>
24 #include <mach/task.h>
25 #include <mach/task_info.h>
26 #include <mach/thread_act.h>
27 #include <mach/thread_info.h>
28 #include <mach/vm_map.h>
29 #include <mach-o/loader.h>
30 #include <mach-o/nlist.h>
31 #include <sys/ptrace.h>
32 #include <sys/types.h>
33 #include <sys/types.h>
38 #define MACH_ERROR_STRING(ret) \
39 (mach_error_string(ret) ? mach_error_string(ret) : "(unknown)")
41 #define RZ_MACH_MAGIC rz_str_djb2_hash("mach")
61 host_t myhost = mach_host_self();
62 mach_port_t psDefault = 0;
63 mach_port_t psDefault_control = 0;
64 task_array_t tasks =
NULL;
65 mach_msg_type_number_t numTasks = 0;
66 kern_return_t kr = -1;
70 return MACH_PORT_NULL;
72 kr = processor_set_default(myhost, &psDefault);
73 if (kr != KERN_SUCCESS) {
74 return MACH_PORT_NULL;
76 kr = host_processor_set_priv(myhost, psDefault, &psDefault_control);
77 if (kr != KERN_SUCCESS) {
80 return MACH_PORT_NULL;
83 kr = processor_set_tasks(psDefault_control, &tasks, &numTasks);
84 if (kr != KERN_SUCCESS) {
86 return MACH_PORT_NULL;
92 for (
i = 0;
i < numTasks;
i++) {
94 pid_for_task(
i, &pid2);
99 return MACH_PORT_NULL;
103 task_t task = MACH_PORT_NULL;
104 host_get_special_port(mach_host_self(), HOST_LOCAL_NODE, 4, &task);
110 static task_t old_task = 0;
111 static int old_pid = -1;
115 RzIOMach *riom =
NULL;
118 if (riom && riom->task) {
119 old_task = riom->task;
125 if (old_pid ==
pid) {
130 kr = mach_port_deallocate(mach_task_self(), old_task);
131 if (kr != KERN_SUCCESS) {
132 eprintf(
"pid_to_task: fail to deallocate port\n");
136 int err = task_for_pid(mach_task_self(), (
pid_t)
pid, &task);
137 if ((
err != KERN_SUCCESS) || !MACH_PORT_VALID(task)) {
139 if (task == MACH_PORT_NULL) {
141 if (task != MACH_PORT_NULL) {
154 unsigned int count = 0;
155 kern_return_t kr = mach_port_get_refs(mach_task_self(),
157 return (kr != KERN_SUCCESS || !
count);
163 struct vm_region_submap_info_64
info;
164 vm_address_t address = MACH_VM_MIN_ADDRESS;
165 vm_size_t
size = (vm_size_t)0;
166 vm_size_t osize = (vm_size_t)0;
169 int tid = __get_pid(
fd);
172 #if __arm64__ || __aarch64__
173 size = osize = 16384;
182 mach_msg_type_number_t info_count;
183 info_count = VM_REGION_SUBMAP_INFO_COUNT_64;
185 kr = vm_region_recurse_64(task, &address, &
size,
186 &depth, (vm_region_recurse_info_t)&
info, &info_count);
187 if (kr != KERN_SUCCESS) {
193 if (
info.is_submap) {
200 if (address < lower) {
215 int blen,
err, copied = 0;
231 if (io->
off < 4096) {
235 copied = getNextValid(io,
desc, io->
off) - io->
off;
239 while (copied <
len) {
242 err = vm_read_overwrite(task,
244 (pointer_t)
buf + copied, &
size);
246 case KERN_PROTECTION_FAILURE:
249 case KERN_INVALID_ADDRESS:
252 return size + copied;
276 static int tsk_getperm(
RzIO *io, task_t task, vm_address_t
addr) {
280 mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
281 vm_region_flavor_t flavor = VM_REGION_BASIC_INFO_64;
282 vm_region_basic_info_data_64_t
info;
283 kr = vm_region_64(task, &
addr, &vmsize, flavor, (vm_region_info_t)&
info, &info_count, &
object);
284 return (kr != KERN_SUCCESS ? 0 :
info.protection);
288 int tid = __get_pid(
desc);
290 static vm_size_t pagesize = 0;
293 : (host_page_size(task, &pagesize) == KERN_SUCCESS)
299 vm_address_t pagesize = tsk_pagesize(
desc);
300 return (
addr & ~(pagesize - 1));
303 static bool tsk_setperm(
RzIO *io, task_t task, vm_address_t
addr,
int len,
int perm) {
305 kr = vm_protect(task,
addr,
len, 0, perm);
306 if (kr != KERN_SUCCESS) {
307 perror(
"tsk_setperm");
313 static bool tsk_write(task_t task, vm_address_t
addr,
const ut8 *
buf,
int len) {
314 kern_return_t kr = vm_write(task,
addr, (vm_offset_t)
buf, (mach_msg_type_number_t)
len);
315 if (kr != KERN_SUCCESS) {
322 vm_address_t vaddr =
addr;
323 vm_address_t pageaddr;
325 vm_size_t total_size;
333 if (
len < 1 || task_is_dead(
desc, task)) {
336 pageaddr = tsk_getpagebase(
desc,
addr);
337 pagesize = tsk_pagesize(
desc);
338 total_size = (
len > pagesize)
339 ? pagesize * (1 + (
len / pagesize))
341 if (tsk_write(task, vaddr,
buf,
len)) {
344 operms = tsk_getperm(io, task, pageaddr);
346 eprintf(
"io.mach: Cannot set page perms for %d byte(s) at 0x%08" PFMT64x "\n", (
int)pagesize, (
ut64)pageaddr);
349 if (!tsk_write(task, vaddr,
buf,
len)) {
350 eprintf(
"io.mach: Cannot write on memory\n");
354 if (!tsk_setperm(io, task, pageaddr, total_size, operms)) {
355 eprintf(
"io.mach: Cannot restore page perms\n");
367 return (!strncmp(
file,
"attach://", 9) || !strncmp(
file,
"mach://", 7));
372 RzIOMach *riom =
NULL;
374 char *pidpath, *endptr;
390 if (
pid > 0 && !strncmp(
file,
"smach://", 8)) {
396 eprintf(
"Operation not permitted\n");
399 perror(
"ptrace: Cannot attach");
400 eprintf(
"\n\nPlease ensure your rizin binary is signed and it has the right entitlements to make debugger work. ");
401 eprintf(
"Be aware that binaries signed by Apple cannot be debugged due to the Apple System Integrity Protection (SIP).\n");
402 eprintf(
"\nFor more info look at: https://book.rizin.re/debugger/apple.html#sign-rizin-binary\n\n");
403 eprintf(
"ERRNO: %d (EINVAL)\n", errno);
406 eprintf(
"unknown error in debug_attach\n");
429 if (!strncmp(
file,
"smach://", 8)) {
463 if (iodd->
magic != RZ_MACH_MAGIC) {
467 kr = mach_port_deallocate(mach_task_self(), task);
468 if (kr != KERN_SUCCESS) {
469 perror(
"__close io_mach");
472 return kr == KERN_SUCCESS;
476 if (!io || !
fd || !
cmd || !
fd->data) {
480 if (iodd->
magic != RZ_MACH_MAGIC) {
486 if (!strcmp(
cmd,
"")) {
489 if (!strncmp(
cmd,
"perm", 4)) {
492 int pagesize = tsk_pagesize(
fd);
493 tsk_setperm(io, task, io->
off, pagesize, perm);
495 eprintf(
"Usage: R!perm [rwx]\n");
499 if (!strncmp(
cmd,
"pid", 3)) {
501 RzIOMach *riom = iodd->
data;
502 const char *pidstr =
cmd + 3;
511 if (!strcmp(pidstr,
"0")) {
528 eprintf(
"io_mach_system: Invalid pid %d\n",
pid);
530 eprintf(
"Try: 'R!pid' or 'R!perm'\n");
542 if (iodd->
magic != RZ_MACH_MAGIC) {
553 .desc =
"Attach to mach debugger instance",
555 .uris =
"attach://,mach://,smach://",
571 .desc =
"mach debug io (unsupported in this platform)",
576 #ifndef RZ_PLUGIN_INCORE
RzBinInfo * info(RzBinFile *bf)
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags cmd
static int __read(RzIO *io, RzIODesc *fd, ut8 *buf, int count)
static bool __plugin_open(RzIO *io, const char *pathname, bool many)
static RzIODesc * __open(RzIO *io, const char *pathname, int rw, int mode)
static int __write(RzIO *io, RzIODesc *fd, const ut8 *buf, int count)
static ut64 __lseek(RzIO *io, RzIODesc *fd, ut64 offset, int whence)
static int __close(RzIODesc *fd)
static char * __system(RzIO *io, RzIODesc *fd, const char *cmd)
RZ_API RzLibStruct rizin_plugin
RzIOPlugin rz_io_plugin_mach
return memset(p, 0, total)
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc kill
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc pid
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API RzIODesc * rz_io_desc_new(RzIO *io, RzIOPlugin *plugin, const char *uri, int flags, int mode, void *data)
RZ_API ut64 rz_str_djb2_hash(const char *str)
RZ_API int rz_str_rwx(const char *str)
RZ_API char * rz_sys_pid_to_path(int pid)
if(dbg->bits==RZ_SYS_BITS_64)
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static task_t task_for_pid_workaround(int Pid)
static task_t task_for_pid_ios9pangu(int pid)
task_t pid_to_task(int pid)
static const z80_opcode fd[]
static const z80_opcode dd[]