Example #1
0
/*++
Function:
    RtlpRaiseException

Parameters:
    ExceptionRecord - the Windows exception record to throw

Note:
    The name of this function and the name of the ExceptionRecord 
    parameter is used in the sos lldb plugin code to read the exception
    record. See coreclr\src\ToolBox\SOS\lldbplugin\debugclient.cpp.
--*/
PAL_NORETURN
static void RtlpRaiseException(EXCEPTION_RECORD *ExceptionRecord)
{
    // Capture the context of RtlpRaiseException.
    CONTEXT ContextRecord;
    ZeroMemory(&ContextRecord, sizeof(CONTEXT));
    ContextRecord.ContextFlags = CONTEXT_FULL;
    CONTEXT_CaptureContext(&ContextRecord);

    // Find the caller of RtlpRaiseException.  
    PAL_VirtualUnwind(&ContextRecord, NULL);

    // The frame we're looking at now is RaiseException. We have to unwind one 
    // level further to get the actual context user code could be resumed at.
    PAL_VirtualUnwind(&ContextRecord, NULL);
#if defined(_X86_)
    ExceptionRecord->ExceptionAddress = (void *) ContextRecord.Eip;
#elif defined(_AMD64_)
    ExceptionRecord->ExceptionAddress = (void *) ContextRecord.Rip;
#elif defined(_ARM_) || defined(_ARM64_)
    ExceptionRecord->ExceptionAddress = (void *) ContextRecord.Pc;
#else
#error unsupported architecture
#endif

    EXCEPTION_POINTERS pointers;
    pointers.ExceptionRecord = ExceptionRecord;
    pointers.ContextRecord = &ContextRecord;

    SEHRaiseException(InternalGetCurrentThread(), &pointers, 0);
}
Example #2
0
void PAL_DispatchException(PCONTEXT pContext, PEXCEPTION_RECORD pExRecord)
{

    MSG_SET_THREAD MsgSet;
    kern_return_t MachRet;
    EXCEPTION_POINTERS pointers;

    pointers.ExceptionRecord = pExRecord;
    pointers.ContextRecord = pContext;

    // Raise the exception
    SEHRaiseException(&pointers, 0);

    // We need to send a message to the worker thread so that it can set our thread context

    // Setup the heaer
    MsgSet.m_MsgHdr.msgh_size = sizeof(MsgSet);
    MsgSet.m_MsgHdr.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MAKE_SEND|MACH_MSG_TYPE_MOVE_RECEIVE); // Simple Message
    MsgSet.m_MsgHdr.msgh_remote_port = s_ExceptionPort; // Send, dest port
    MsgSet.m_MsgHdr.msgh_local_port = MACH_PORT_NULL;   // We're not expecting a msg back
    MsgSet.m_MsgHdr.msgh_id = SET_THREAD_MESSAGE_ID; // Message ID
    MsgSet.m_MsgHdr.msgh_reserved = 0; // Not used

    // Setup the thread and thread context
    MsgSet.m_ThreadPort = mach_thread_self();
    MsgSet.m_ThreadContext = *pContext;

    // Send the  message to the exception port
    MachRet = mach_msg(&MsgSet.m_MsgHdr,
                       MACH_SEND_MSG,
                       MsgSet.m_MsgHdr.msgh_size,
                       0,
                       MACH_PORT_NULL,
                       MACH_MSG_TIMEOUT_NONE,
                       MACH_PORT_NULL);

    if (MachRet != KERN_SUCCESS)
    {
        UTIL_SetLastErrorFromMach(MachRet);
        ExitProcess(GetLastError());
    }

    // Make sure we don't do anything
    while(1)
    {
        sched_yield();
    }
}
Example #3
0
/*++
Function:
  RaiseException

See MSDN doc.
--*/
VOID
PALAPI
RaiseException(
           IN DWORD dwExceptionCode,
           IN DWORD dwExceptionFlags,
           IN DWORD nNumberOfArguments,
           IN CONST ULONG_PTR *lpArguments)
{
    EXCEPTION_RECORD record;
    EXCEPTION_POINTERS exceptionPointers;
    CONTEXT context;

    ENTRY("RaiseException (dwCode=%#x, dwFlags=%#x, nArgs=%u, lpArgs=%p)\n",
          dwExceptionCode, dwExceptionFlags, nNumberOfArguments, lpArguments);

    /* Validate parameters */
    if( dwExceptionCode & RESERVED_SEH_BIT)
    {
        WARN("Exception code %08x has bit 28 set : clearing it.\n",
             dwExceptionCode);
        dwExceptionCode ^= RESERVED_SEH_BIT;
    }

    if( dwExceptionFlags && ( dwExceptionFlags != EXCEPTION_NONCONTINUABLE ) )
    {
        ERROR("Unkown exception flag %08x (ignoring)\n", dwExceptionFlags);
    }

    /* Build exception record */

    TRACE("Building exception record %p\n", &record);

    record.ExceptionCode = dwExceptionCode;
    record.ExceptionAddress = RaiseException;
    record.ExceptionRecord = NULL;

    if( lpArguments != NULL )
    {
        if(nNumberOfArguments>EXCEPTION_MAXIMUM_PARAMETERS)
        {
            WARN("Number of arguments (%d) exceeds the limit "
                 "EXCEPTION_MAXIMUM_PARAMETERS (%d); truncing the extra"
                 "parameters.\n",
                  nNumberOfArguments, EXCEPTION_MAXIMUM_PARAMETERS);

            nNumberOfArguments = EXCEPTION_MAXIMUM_PARAMETERS;
        }

        memcpy(record.ExceptionInformation, lpArguments,
               nNumberOfArguments*sizeof(ULONG_PTR));
    }

    record.NumberParameters = nNumberOfArguments;

    /* from rotor_pal.doc :
       "all explicitly raised exceptions may be considered non-continuable". */
    record.ExceptionFlags = EXCEPTION_NONCONTINUABLE;

    /* from rotor_pal.h : 
      On non-Win32 platforms, the CONTEXT pointer in the
      PEXCEPTION_POINTERS will contain at least the CONTEXT_CONTROL registers.
    */
    ZeroMemory(&context, sizeof context);
    context.ContextFlags = CONTEXT_CONTROL;
    if(!GetThreadContext(GetCurrentThread(),&context))
    {
        WARN("GetThreadContext failed!! ignoring...\n");
    }

    exceptionPointers.ExceptionRecord = &record;
    exceptionPointers.ContextRecord = &context;
    
    /* Let SEHRaiseException do the work */
    SEHRaiseException(&exceptionPointers, 0);

    LOGEXIT("RaiseException returns.\n");
}