static void setExceptionThread(void) { kern_return_t r; // char *nullAddr = NULL; bailOut = FALSE; /* save the old exception port for this task */ r = task_get_exception_port(task_self(), &(ports.old_exc_port)); if (r != KERN_SUCCESS) { mach_error("task_get_exception_port",r); exit(1); } if (!ports.exc_port) { /* create a new exception port for this task */ r = port_allocate(task_self(), &(ports.exc_port)); if (r != KERN_SUCCESS) { mach_error("port_allocate",r); exit(1); } /* Fork the thread that listens to the exception port. */ cthread_detach(cthread_fork((cthread_fn_t)exc_thread,(any_t)&ports)); ports.clear_port = thread_reply(); } /* install the new exception port for this task */ r = task_set_exception_port(task_self(), (ports.exc_port)); if (r != KERN_SUCCESS) { mach_error("task_set_exception_port",r); exit(1); } }
static void restoreExceptionThread(void) { /* install the old port again */ kern_return_t r = task_set_exception_port(task_self(), (ports.old_exc_port)); if (r != KERN_SUCCESS) { mach_error("task_set_exception_port",r); exit(1); } }
void next_create_inferior_for_task (struct next_inferior_status *inferior, task_t task, int pid) { kern_return_t ret; CHECK_FATAL (inferior != NULL); next_inferior_destroy (inferior); next_inferior_reset (inferior); inferior->task = task; inferior->pid = pid; inferior->attached_in_ptrace = 0; inferior->stopped_in_ptrace = 0; inferior->suspend_count = 0; /* */ dyld_init_paths (&inferior->dyld_status.path_info); /* get notification messages for current task */ ret = port_allocate (task_self (), &inferior->notify_port); MACH_CHECK_ERROR (ret); ret = port_set_backlog (task_self (), inferior->notify_port, PORT_BACKLOG_MAX); MACH_CHECK_ERROR (ret); if (inferior_bind_notify_port_flag) { ret = task_set_notify_port (task_self (), inferior->notify_port); MACH_CHECK_ERROR (ret); } /* initialize signal port */ ret = port_allocate (task_self (), &inferior->signal_port); MACH_CHECK_ERROR (ret); ret = port_set_backlog (task_self (), inferior->signal_port, PORT_BACKLOG_MAX); MACH_CHECK_ERROR (ret); /* initialize dyld port */ ret = port_allocate (task_self (), &inferior->dyld_port); MACH_WARN_ERROR (ret); ret = port_set_backlog (task_self (), inferior->dyld_port, PORT_BACKLOG_MAX); MACH_CHECK_ERROR (ret); /* initialize gdb exception port */ ret = port_allocate (task_self (), &inferior->exception_port); MACH_CHECK_ERROR (ret); ret = port_set_backlog (task_self (), inferior->exception_port, PORT_BACKLOG_MAX); MACH_CHECK_ERROR (ret); ret = port_allocate (task_self (), &inferior->exception_reply_port); MACH_CHECK_ERROR (ret); ret = port_set_backlog (task_self (), inferior->exception_reply_port, PORT_BACKLOG_MAX); MACH_CHECK_ERROR (ret); /* commandeer inferior exception port */ if (inferior_bind_exception_port_flag) { next_save_exception_ports (inferior->task, &inferior->saved_exceptions); ret = task_set_exception_port (task, inferior->exception_port); MACH_CHECK_ERROR (ret); } inferior->last_thread = next_primary_thread_of_task (inferior->task); }
int main (int argc, char **argv) { const task_t my_task = mach_task_self(); error_t err; memory_object_t defpager; err = get_privileged_ports (&bootstrap_master_host_port, &bootstrap_master_device_port); if (err) error (1, err, "cannot get privileged ports"); defpager = MACH_PORT_NULL; err = vm_set_default_memory_manager (bootstrap_master_host_port, &defpager); if (err) error (1, err, "cannot check current default memory manager"); if (MACH_PORT_VALID (defpager)) error (2, 0, "Another default memory manager is already running"); if (!(argc == 2 && !strcmp (argv[1], "-d"))) { /* We don't use the `daemon' function because we might exit back to the parent before the daemon has completed vm_set_default_memory_manager. Instead, the parent waits for a SIGUSR1 from the child before exitting, and the child sends that signal after it is set up. */ sigset_t set; signal (SIGUSR1, nohandler); sigemptyset (&set); sigaddset (&set, SIGUSR1); sigprocmask (SIG_BLOCK, &set, 0); switch (fork ()) { case -1: error (1, errno, "cannot become daemon"); case 0: setsid (); chdir ("/"); close (0); close (1); close (2); break; default: sigemptyset (&set); sigsuspend (&set); _exit (0); } } /* Mark us as important. */ mach_port_t proc = getproc (); if (proc == MACH_PORT_NULL) error (3, err, "cannot get a handle to our process"); err = proc_mark_important (proc); /* This might fail due to permissions or because the old proc server is still running, ignore any such errors. */ if (err && err != EPERM && err != EMIG_BAD_ID) error (3, err, "cannot mark us as important"); mach_port_deallocate (mach_task_self (), proc); printf_init(bootstrap_master_device_port); /* * Set up the default pager. */ partition_init(); /* * task_set_exception_port and task_set_bootstrap_port * both require a send right. */ (void) mach_port_insert_right(my_task, default_pager_exception_port, default_pager_exception_port, MACH_MSG_TYPE_MAKE_SEND); /* * Change our exception port. */ if (!debug) (void) task_set_exception_port(my_task, default_pager_exception_port); default_pager_initialize (bootstrap_master_host_port); if (!(argc == 2 && !strcmp (argv[1], "-d"))) kill (getppid (), SIGUSR1); /* * Become the default pager */ default_pager(); /*NOTREACHED*/ return -1; }