VirtualBox

Changeset 68976 in vbox for trunk/src/VBox/Runtime/r3


Ignore:
Timestamp:
Oct 4, 2017 12:03:42 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
118244
Message:

init-win.cpp: Install unhandled exception filter callback that tries to LogRel() or Log() the exception details.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/r3/win/init-win.cpp

    r66220 r68976  
    4040#include <iprt/assert.h>
    4141#include <iprt/err.h>
     42#include <iprt/log.h>
     43#include <iprt/param.h>
    4244#include <iprt/string.h>
     45#include <iprt/thread.h>
    4346#include "../init.h"
     47
     48
     49/*********************************************************************************************************************************
     50*   Structures and Typedefs                                                                                                      *
     51*********************************************************************************************************************************/
     52typedef VOID (WINAPI *PFNGETCURRENTTHREADSTACKLIMITS)(PULONG_PTR puLow, PULONG_PTR puHigh);
     53typedef LPTOP_LEVEL_EXCEPTION_FILTER (WINAPI * PFNSETUNHANDLEDEXCEPTIONFILTER)(LPTOP_LEVEL_EXCEPTION_FILTER);
    4454
    4555
     
    5969/** GetSystemWindowsDirectoryW or GetWindowsDirectoryW (NT4). */
    6070DECLHIDDEN(PFNGETWINSYSDIR)     g_pfnGetSystemWindowsDirectoryW = NULL;
    61 
     71/** The GetCurrentThreadStackLimits API. */
     72static PFNGETCURRENTTHREADSTACKLIMITS g_pfnGetCurrentThreadStackLimits = NULL;
     73/** SetUnhandledExceptionFilter. */
     74static PFNSETUNHANDLEDEXCEPTIONFILTER g_pfnSetUnhandledExceptionFilter = NULL;
     75/** The previous unhandled exception filter. */
     76static LPTOP_LEVEL_EXCEPTION_FILTER   g_pfnUnhandledXcptFilter = NULL;
     77
     78
     79/*********************************************************************************************************************************
     80*   Internal Functions                                                                                                           *
     81*********************************************************************************************************************************/
     82static LONG CALLBACK rtR3WinUnhandledXcptFilter(PEXCEPTION_POINTERS);
    6283
    6384
     
    301322    }
    302323
     324    /*
     325     * Register an unhandled exception callback if we can.
     326     */
     327    g_pfnGetCurrentThreadStackLimits = (PFNGETCURRENTTHREADSTACKLIMITS)GetProcAddress(g_hModKernel32, "GetCurrentThreadStackLimits");
     328    g_pfnSetUnhandledExceptionFilter = (PFNSETUNHANDLEDEXCEPTIONFILTER)GetProcAddress(g_hModKernel32, "SetUnhandledExceptionFilter");
     329    if (g_pfnSetUnhandledExceptionFilter && !g_pfnUnhandledXcptFilter)
     330    {
     331        g_pfnUnhandledXcptFilter = g_pfnSetUnhandledExceptionFilter(rtR3WinUnhandledXcptFilter);
     332        AssertStmt(g_pfnUnhandledXcptFilter != rtR3WinUnhandledXcptFilter, g_pfnUnhandledXcptFilter = NULL);
     333    }
     334
    303335    return rc;
    304336}
     
    348380}
    349381
     382
     383/**
     384 * Unhandled exception filter callback.
     385 *
     386 * Will try log stuff.
     387 */
     388static LONG CALLBACK rtR3WinUnhandledXcptFilter(PEXCEPTION_POINTERS pPtrs)
     389{
     390    /*
     391     * Try get the logger and log exception details.
     392     *
     393     * Note! We'll be using RTLogLogger for now, though we should probably add
     394     *       a less deadlock prone API here and gives up pretty fast if it
     395     *       cannot get the lock...
     396     */
     397    PRTLOGGER pLogger = RTLogRelGetDefaultInstance();
     398    if (!pLogger)
     399        pLogger = RTLogGetDefaultInstance();
     400    if (pLogger)
     401    {
     402        RTLogLogger(pLogger, NULL, "\nrtR3WinUnhandledXcptFilter: !Exception!\n");
     403        RTLogLogger(pLogger, NULL,  "Thread ID:   %p\n", RTThreadNativeSelf());
     404
     405        /*
     406         * Dump the exception record.
     407         */
     408        PEXCEPTION_RECORD pXcptRec = RT_VALID_PTR(pPtrs) && RT_VALID_PTR(pPtrs->ExceptionRecord) ? pPtrs->ExceptionRecord : NULL;
     409        if (pXcptRec)
     410        {
     411            RTLogLogger(pLogger, NULL, "ExceptionCode=%#010x ExceptionFlags=%#010x ExceptionAddress=%p\n",
     412                        pXcptRec->ExceptionCode, pXcptRec->ExceptionFlags, pXcptRec->ExceptionAddress);
     413            for (uint32_t i = 0; i < RT_MIN(pXcptRec->NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS); i++)
     414                RTLogLogger(pLogger, NULL, "ExceptionInformation[%d]=%p\n", i, pXcptRec->ExceptionInformation[i]);
     415
     416            /* Nested? Display one level only. */
     417            PEXCEPTION_RECORD pNestedRec = pXcptRec->ExceptionRecord;
     418            if (RT_VALID_PTR(pNestedRec))
     419            {
     420                RTLogLogger(pLogger, NULL, "Nested: ExceptionCode=%#010x ExceptionFlags=%#010x ExceptionAddress=%p (nested %p)\n",
     421                            pNestedRec->ExceptionCode, pNestedRec->ExceptionFlags, pNestedRec->ExceptionAddress,
     422                            pNestedRec->ExceptionRecord);
     423                for (uint32_t i = 0; i < RT_MIN(pNestedRec->NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS); i++)
     424                    RTLogLogger(pLogger, NULL, "Nested: ExceptionInformation[%d]=%p\n", i, pNestedRec->ExceptionInformation[i]);
     425            }
     426        }
     427
     428        /*
     429         * Dump the context record.
     430         */
     431        volatile char   szMarker[] = "stackmarker";
     432        uintptr_t       uXcptSP = (uintptr_t)&szMarker[0];
     433        PCONTEXT pXcptCtx = RT_VALID_PTR(pPtrs) && RT_VALID_PTR(pPtrs->ContextRecord)   ? pPtrs->ContextRecord   : NULL;
     434        if (pXcptCtx)
     435        {
     436#ifdef RT_ARCH_AMD64
     437            RTLogLogger(pLogger, NULL, "cs:rip=%04x:%016RX64\n", pXcptCtx->SegCs, pXcptCtx->Rip);
     438            RTLogLogger(pLogger, NULL, "ss:rsp=%04x:%016RX64 rbp=%016RX64\n", pXcptCtx->SegSs, pXcptCtx->Rsp, pXcptCtx->Rbp);
     439            RTLogLogger(pLogger, NULL, "rax=%016RX64 rcx=%016RX64 rdx=%016RX64 rbx=%016RX64\n",
     440                        pXcptCtx->Rax, pXcptCtx->Rcx, pXcptCtx->Rdx, pXcptCtx->Rbx);
     441            RTLogLogger(pLogger, NULL, "rsi=%016RX64 rdi=%016RX64 rsp=%016RX64 rbp=%016RX64\n",
     442                        pXcptCtx->Rsi, pXcptCtx->Rdi, pXcptCtx->Rsp, pXcptCtx->Rbp);
     443            RTLogLogger(pLogger, NULL, "r8 =%016RX64 r9 =%016RX64 r10=%016RX64 r11=%016RX64\n",
     444                        pXcptCtx->R8,  pXcptCtx->R9,  pXcptCtx->R10, pXcptCtx->R11);
     445            RTLogLogger(pLogger, NULL, "r12=%016RX64 r13=%016RX64 r14=%016RX64 r15=%016RX64\n",
     446                        pXcptCtx->R12,  pXcptCtx->R13,  pXcptCtx->R14, pXcptCtx->R15);
     447            RTLogLogger(pLogger, NULL, "ds=%04x es=%04x fs=%04x gs=%04x eflags=%08x\n",
     448                        pXcptCtx->SegDs, pXcptCtx->SegEs, pXcptCtx->SegFs, pXcptCtx->SegGs, pXcptCtx->EFlags);
     449            RTLogLogger(pLogger, NULL, "p1home=%016RX64 p2home=%016RX64 pe3home=%016RX64\n",
     450                        pXcptCtx->P1Home, pXcptCtx->P2Home, pXcptCtx->P3Home);
     451            RTLogLogger(pLogger, NULL, "p4home=%016RX64 p5home=%016RX64 pe6home=%016RX64\n",
     452                        pXcptCtx->P4Home, pXcptCtx->P5Home, pXcptCtx->P6Home);
     453            RTLogLogger(pLogger, NULL, "   LastBranchToRip=%016RX64    LastBranchFromRip=%016RX64\n",
     454                        pXcptCtx->LastBranchToRip, pXcptCtx->LastBranchFromRip);
     455            RTLogLogger(pLogger, NULL, "LastExceptionToRip=%016RX64 LastExceptionFromRip=%016RX64\n",
     456                        pXcptCtx->LastExceptionToRip, pXcptCtx->LastExceptionFromRip);
     457            uXcptSP = pXcptCtx->Rsp;
     458
     459#elif defined(RT_ARCH_X86)
     460            RTLogLogger(pLogger, NULL, "cs:eip=%04x:%08RX32\n", pXcptCtx->SegCs, pXcptCtx->Eip);
     461            RTLogLogger(pLogger, NULL, "ss:esp=%04x:%08RX32 ebp=%08RX32\n", pXcptCtx->SegSs, pXcptCtx->Esp, pXcptCtx->Ebp);
     462            RTLogLogger(pLogger, NULL, "eax=%08RX32 ecx=%08RX32 edx=%08RX32 ebx=%08RX32\n",
     463                        pXcptCtx->Eax, pXcptCtx->Ecx,  pXcptCtx->Edx,  pXcptCtx->Ebx);
     464            RTLogLogger(pLogger, NULL, "esi=%08RX32 edi=%08RX32 esp=%08RX32 ebp=%08RX32\n",
     465                        pXcptCtx->Esi, pXcptCtx->Edi,  pXcptCtx->Esp,  pXcptCtx->Ebp);
     466            RTLogLogger(pLogger, NULL, "ds=%04x es=%04x fs=%04x gs=%04x eflags=%08x\n",
     467                        pXcptCtx->SegDs, pXcptCtx->SegEs, pXcptCtx->SegFs, pXcptCtx->SegGs, pXcptCtx->EFlags);
     468            uXcptSP = pXcptCtx->Esp;
     469#endif
     470        }
     471
     472        /*
     473         * Dump stack.
     474         */
     475        void  *pvStack  = (void *)&szMarker[0];
     476        size_t cbToDump = PAGE_SIZE - ((uintptr_t)pvStack & PAGE_OFFSET_MASK);
     477        if (cbToDump < 512)
     478            cbToDump += PAGE_SIZE;
     479        size_t cbToXcpt = uXcptSP - (uintptr_t)pvStack;
     480        while (cbToXcpt > cbToDump && cbToXcpt <= _16K)
     481            cbToDump += PAGE_SIZE;
     482        ULONG_PTR uLow  = (uintptr_t)&szMarker[0];
     483        ULONG_PTR uHigh = (uintptr_t)&szMarker[0];
     484        if (g_pfnGetCurrentThreadStackLimits)
     485        {
     486            g_pfnGetCurrentThreadStackLimits(&uLow, &uHigh);
     487            size_t cbToTop = RT_MAX(uLow, uHigh) - (uintptr_t)pvStack;
     488            if (cbToTop < _1M)
     489                cbToDump = cbToTop;
     490        }
     491
     492        RTLogLogger(pLogger, NULL, "\nStack %p, dumping %#x bytes (low=%p, high=%p)\n", pvStack, cbToDump, uLow, uHigh);
     493        RTLogLogger(pLogger, NULL, "%.*Rhxd\n", cbToDump, pvStack);
     494
     495        /*
     496         * Try figure the thread name.
     497         *
     498         * Note! This involves the thread db lock, so it may deadlock, which
     499         *       is why it's at the end.
     500         */
     501        RTLogLogger(pLogger, NULL,  "Thread ID:   %p\n", RTThreadNativeSelf());
     502        RTLogLogger(pLogger, NULL,  "Thread name: %s\n", RTThreadSelfName());
     503        RTLogLogger(pLogger, NULL,  "Thread IPRT: %p\n", RTThreadSelf());
     504    }
     505
     506    /*
     507     * Do the default stuff, never mind us.
     508     */
     509    if (g_pfnUnhandledXcptFilter)
     510        return g_pfnUnhandledXcptFilter(pPtrs);
     511    return EXCEPTION_CONTINUE_SEARCH;
     512}
     513
     514
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette