Пример #1
0
/*++
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;
}
Пример #2
0
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 ;

}