bool MachTask::StartExceptionThread(DNBError &err) { DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s ( )", __FUNCTION__); task_t task = TaskPortForProcessID(err); if (MachTask::IsValid(task)) { // Got the mach port for the current process mach_port_t task_self = mach_task_self (); // Allocate an exception port that we will use to track our child process err = ::mach_port_allocate (task_self, MACH_PORT_RIGHT_RECEIVE, &m_exception_port); if (err.Fail()) return false; // Add the ability to send messages on the new exception port err = ::mach_port_insert_right (task_self, m_exception_port, m_exception_port, MACH_MSG_TYPE_MAKE_SEND); if (err.Fail()) return false; // Save the original state of the exception ports for our child process SaveExceptionPortInfo(); // We weren't able to save the info for our exception ports, we must stop... if (m_exc_port_info.mask == 0) { err.SetErrorString("failed to get exception port info"); return false; } // Set the ability to get all exceptions on this port err = ::task_set_exception_ports (task, m_exc_port_info.mask, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); if (DNBLogCheckLogBit(LOG_EXCEPTIONS) || err.Fail()) { err.LogThreaded("::task_set_exception_ports ( task = 0x%4.4x, exception_mask = 0x%8.8x, new_port = 0x%4.4x, behavior = 0x%8.8x, new_flavor = 0x%8.8x )", task, m_exc_port_info.mask, m_exception_port, (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), THREAD_STATE_NONE); } if (err.Fail()) return false; // Create the exception thread err = ::pthread_create (&m_exception_thread, NULL, MachTask::ExceptionThread, this); return err.Success(); } else { DNBLogError("MachTask::%s (): task invalid, exception thread start failed.", __FUNCTION__); } return false; }
nub_addr_t MachTask::GetDYLDAllImageInfosAddress (DNBError& err) { struct hack_task_dyld_info dyld_info; mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; // Make sure that COUNT isn't bigger than our hacked up struct hack_task_dyld_info. // If it is, then make COUNT smaller to match. if (count > (sizeof(struct hack_task_dyld_info) / sizeof(natural_t))) count = (sizeof(struct hack_task_dyld_info) / sizeof(natural_t)); task_t task = TaskPortForProcessID (err); if (err.Success()) { err = ::task_info (task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count); if (err.Success()) { // We now have the address of the all image infos structure return dyld_info.all_image_info_addr; } } return INVALID_NUB_ADDRESS; }
bool MachTask::StartExceptionThread(DNBError &err) { DNBLogThreadedIf(LOG_EXCEPTIONS, "MachTask::%s ( )", __FUNCTION__); task_t task = TaskPortForProcessID(err); if (MachTask::IsValid(task)) { // Got the mach port for the current process mach_port_t task_self = mach_task_self (); // Allocate an exception port that we will use to track our child process err = ::mach_port_allocate (task_self, MACH_PORT_RIGHT_RECEIVE, &m_exception_port); if (err.Fail()) return false; // Add the ability to send messages on the new exception port err = ::mach_port_insert_right (task_self, m_exception_port, m_exception_port, MACH_MSG_TYPE_MAKE_SEND); if (err.Fail()) return false; // Save the original state of the exception ports for our child process SaveExceptionPortInfo(); // Set the ability to get all exceptions on this port err = ::task_set_exception_ports (task, EXC_MASK_ALL, m_exception_port, EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE); if (err.Fail()) return false; // Create the exception thread err = ::pthread_create (&m_exception_thread, NULL, MachTask::ExceptionThread, this); return err.Success(); } else { DNBLogError("MachTask::%s (): task invalid, exception thread start failed.", __FUNCTION__); } return false; }