/*++ Function: GetThreadContext See MSDN doc. --*/ BOOL CONTEXT_GetThreadContext( DWORD dwProcessId, pthread_t self, LPCONTEXT lpContext) { BOOL ret = FALSE; if (lpContext == NULL) { ERROR("Invalid lpContext parameter value\n"); SetLastError(ERROR_NOACCESS); goto EXIT; } if (GetCurrentProcessId() == dwProcessId) { if (self != pthread_self()) { // the target thread is in the current process, but isn't // the current one: extract the CONTEXT from the Mach thread. mach_port_t mptPort; mptPort = pthread_mach_thread_np(self); ret = (CONTEXT_GetThreadContextFromPort(mptPort, lpContext) == KERN_SUCCESS); } else { CONTEXT_CaptureContext(lpContext); ret = TRUE; } } else { ASSERT("Cross-process GetThreadContext() is not supported on this platform\n"); SetLastError(ERROR_NOACCESS); } EXIT: return ret; }
kern_return_t catch_exception_raise( mach_port_t exception_port, // [in] Mach Port that is listening to the exception mach_port_t thread, // [in] thread the exception happened on mach_port_t task, // [in] task the exception happened on exception_type_t exception, // [in] The type of the exception exception_data_t code, // [in] A machine dependent array indicating a particular instance of exception mach_msg_type_number_t code_count) // [in] The size of the buffer (in natural-sized units). { kern_return_t MachRet; ppc_thread_state_t ThreadState; unsigned int count = sizeof(ThreadState)/sizeof(unsigned); CONTEXT ThreadContext; EXCEPTION_RECORD ExceptionRecord; void *FramePointer; ThreadContext.ContextFlags = CONTEXT_FULL; CONTEXT_GetThreadContextFromPort(thread, &ThreadContext); // We need to hijack the thread to point to PAL_DispatchException MachRet = thread_get_state(thread, MACHINE_THREAD_STATE, (thread_state_t)&ThreadState, &count); if (MachRet != KERN_SUCCESS) { UTIL_SetLastErrorFromMach(MachRet); ExitProcess(GetLastError()); } ExceptionRecord.ExceptionCode = exception_from_trap_code(exception, code, code_count); // If we're in single step mode, disable it since we're going to call PAL_DispatchException if (ExceptionRecord.ExceptionCode == EXCEPTION_SINGLE_STEP) { ThreadState.srr1 &= ~0x400UL; } ExceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL; ExceptionRecord.ExceptionRecord = NULL; ExceptionRecord.ExceptionAddress = (void *)ThreadContext.Iar; ExceptionRecord.NumberParameters = 0; FramePointer =(void *) ThreadState.r1; // Make sure it's naturally aligned FramePointer = FramePointer - ((unsigned)FramePointer % 8); // Move it pass the red zone FramePointer -= C_RED_ZONE; // Put the Context on the stack FramePointer -= sizeof(CONTEXT); *(CONTEXT *)FramePointer = ThreadContext; ThreadState.r3 = (unsigned)FramePointer; // Put the exception record on the stack FramePointer -= sizeof(EXCEPTION_RECORD); *(EXCEPTION_RECORD *)FramePointer = ExceptionRecord; ThreadState.r4 = (unsigned)FramePointer; // Add room for the args to spill FramePointer -= 2*sizeof(void *); // Add room for the linking area (24 bytes) FramePointer -= 24; *(unsigned *)FramePointer = ThreadState.r1; // Make the instruction register point to DispatchException ThreadState.srr0 =(unsigned) &PAL_DispatchException; ThreadState.r1 = (unsigned)FramePointer; // Now set the thread state for the faulting thread so that PAL_DispatchException executes next MachRet = thread_set_state(thread, MACHINE_THREAD_STATE, (thread_state_t)&ThreadState, count); if (MachRet != KERN_SUCCESS) { UTIL_SetLastErrorFromMach(MachRet); ExitProcess(GetLastError()); } // We're done! return KERN_SUCCESS ; }