Changeset 150 for trunk


Ignore:
Timestamp:
Nov 1, 2006, 10:55:03 PM (19 years ago)
Author:
dmik
Message:

Common: System Exceptions:

  • Added exploring and writing the context and call stack of all other threads of the process.
  • The 'Process/Module' tag is now a single line (for easier visual lookup with line wrapping turned off).
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/tools/qsysxcpt_pm.cpp

    r149 r150  
    4242 */
    4343
     44/// @todo (r=dmik) use plain DosWrite() and friends instead of fprintf() and
     45//  friends (LIBC may be in a inconsistent state at the point when an exception
     46//  is thrown (see kLIBC's logstrict.c for some sprintf like stuff)
     47 
    4448#if !defined(QT_OS2_NO_SYSEXCEPTIONS)
    4549 
     
    5458#include <errno.h>
    5559#include <sys/stat.h>
    56 
    57 /// @todo (r=dmik) add locking to:
    58 //  a) handle simultaneous independent exceptions from different threads
    59 //  b) raise (user) exceptions on all other threads in order to write their
    60 //     contexts to the trap file when a real exception happens on one thread
    6160
    6261/** @class QtOS2SysXcptMainHandler qt_os2.h
     
    227226            {
    228227                fprintf (file, " flags=\"%08lX\"", ulFlags);
    229                 if (ulFlags & (PAG_COMMIT | PAG_READ) == (PAG_COMMIT | PAG_READ))
     228                if ((ulFlags & (PAG_COMMIT | PAG_READ)) ==
     229                    (PAG_COMMIT | PAG_READ))
    230230                    fprintf (file, " word=\"%08lX\"/>\n", *(ULONG *) ulValue);
    231231                else
     
    238238        {
    239239            fprintf (file, ">\n");
    240             qt_excWriteErrorMsg (file, 7, "DosQueryMem returned %lu"
     240            qt_excWriteErrorMsg (file, 7, "DosQueryMem returned %lu "
    241241                                 "and flags %08lX", arc, ulFlags);
    242242            fprintf (file, "      </Register>\n");
     
    266266
    267267    if (arc != NO_ERROR)
    268         qt_excWriteErrorMsg (file, 8, "%s: DosQueryModFromEIP returned %lu",
    269                              szMod, arc);
     268        qt_excWriteErrorMsg (file, 8, "DosQueryModFromEIP returned %lu", arc);
    270269    else
    271270        fprintf (file, "        <Module ID=\"%04lX\" segment=\"%04lX\" "
     
    303302            else if (arc == ERROR_INVALID_ADDRESS)
    304303            {
    305                 if (((ULONG) pch) & 0xFFFFF000 == ulRegEip & 0xFFFFF000)
     304                if ((((ULONG) pch) & 0xFFFFF000) == (ulRegEip & 0xFFFFF000))
    306305                    break; /* the same page, ulAddress inaccessible */
    307306                pch = (UCHAR *) (ulRegEip & 0xFFFFF000);
     
    310309        fprintf (file, "        <Dump address=\"%08lX\">\n         ", pch);
    311310        if (arc == NO_ERROR &&
    312             ulFlags & (PAG_COMMIT|PAG_READ) == (PAG_COMMIT | PAG_READ))
     311            (ulFlags & (PAG_COMMIT | PAG_READ)) == (PAG_COMMIT | PAG_READ))
    313312        {
    314313            for (; pch < pchEnd; ++pch)
     
    318317        }
    319318        else
    320             qt_excWriteErrorMsg (file, 0, "%08lX: DosQueryMem returned %lu"
     319            qt_excWriteErrorMsg (file, 0, "%08lX: DosQueryMem returned %lu "
    321320                                 "and flags %08lX", pch, arc, ulFlags);
    322321        fprintf (file, "        </Dump>\n");
     
    329328/** \internal
    330329 *  Walks the stack and writes information about stack frames.
    331  */
    332 static void qt_excWriteStackFrames (FILE *file, PTIB ptib,
     330 *  @note This function should be in sync with qt_excWriteModulesOnStack()
     331 *        because they share the same logic.
     332 */
     333static void qt_excWriteStackFrames (FILE *file, ULONG ulStackLimit,
    333334                                    PCONTEXTRECORD pContextRec)
    334335{
     
    345346     * trapping address itself even if EBP there is invalid. */
    346347
    347     while (ulRegEbp != 0 && ulRegEbp < (ULONG) ptib->tib_pstacklimit)
     348    while (ulRegEbp != 0 && ulRegEbp < ulStackLimit)
    348349    {
    349350        /* skip the trapping stack frame -- already written above */
     
    359360            if (   (arc != NO_ERROR)
    360361                || (   arc == NO_ERROR
    361                     && (ulFlags & (PAG_COMMIT|PAG_READ))
    362                         != (PAG_COMMIT|PAG_READ)))
     362                    && (ulFlags & (PAG_COMMIT | PAG_READ))
     363                        != (PAG_COMMIT | PAG_READ)))
    363364            {
    364365                fprintf (file, "      <Frame pointer=\"%08lX\">\n", ulRegEbp);
     
    367368                fprintf (file, "      </Frame>\n");
    368369                /* try go to the next page */
    369                 /// @todo (r=dmik) I don't know how much it is accurate,
     370                /// @todo (r=dmik) I don't know how much is it accurate,
    370371                //  I've just taken the logic from xwphelpers sources.
    371372                ulRegEbp += 0x1000;
     
    391392                                   PCONTEXTRECORD pContextRec)
    392393{
     394    ULONG ulStackBase = 0, ulStackLimit = 0;
     395    ULONG ulCount = 0, ulFlags = 0;
     396    ULONG ul = 0;
     397    APIRET arc = NO_ERROR;
     398   
    393399    if (ptib)
    394400    {
     
    449455    /* *** stack */
    450456
    451     fprintf (file, "    <Stack base=\"%08lX\" limit=\"%08lX\">\n",
    452              (ULONG) ptib->tib_pstack,
    453              (ULONG) ptib->tib_pstacklimit);
    454    
     457    if (ptib)
     458    {
     459        ulStackBase = (ULONG) ptib->tib_pstack;
     460        ulStackLimit = (ULONG) ptib->tib_pstacklimit;
     461    }
     462    else
    455463    if (pContextRec->ContextFlags & CONTEXT_CONTROL)
    456464    {
    457         qt_excWriteStackFrames (file, ptib, pContextRec);
    458     }   
    459    
    460     fprintf (file, "    </Stack>\n"
    461                    "   </Thread>\n");
     465        /* first, try to find the end of the stack object */
     466        ulCount = 0xFFFFFFFF;
     467        arc = DosQueryMem ((void *) pContextRec->ctx_RegEbp,
     468                           &ulCount, &ulFlags);
     469        if (arc == NO_ERROR)
     470        {
     471            ulStackLimit = pContextRec->ctx_RegEbp + ulCount;
     472            /* next, try to find the start of the stack object */
     473            ul = (pContextRec->ctx_RegEbp & 0xFFFFF000);
     474            while (arc == NO_ERROR && !(ulFlags & PAG_BASE))
     475            {
     476                ulCount = 0x1000;
     477                ul -= 0x1000;
     478                arc = DosQueryMem ((void *) ul, &ulCount, &ulFlags);
     479            }
     480            if (arc == NO_ERROR)
     481                ulStackBase = ul;
     482        }
     483    }
     484
     485    fprintf (file, "    <Stack");
     486    if (ulStackBase)
     487        fprintf (file, " base=\"%08lX\"", ulStackBase);
     488    if (ulStackLimit)
     489        fprintf (file, " limit=\"%08lX\"", ulStackLimit);
     490    fprintf (file, ">\n");
     491   
     492    if (pContextRec->ContextFlags & CONTEXT_CONTROL)
     493        qt_excWriteStackFrames (file, ulStackLimit, pContextRec);
     494
     495    fprintf (file, "    </Stack>\n");
     496    fprintf (file, "   </Thread>\n");
    462497}
    463498
     
    550585                achBuf [1 + *achBuf] = 0;
    551586                /* write the description attribute */
    552                 fprintf (file, "\n          desc=\"%s\"", achBuf + 1);
     587                fprintf (file, " desc=\"%s\"", achBuf + 1);
    553588                bFound = TRUE;
    554589            }
     
    582617    if ((ulOrigin >= 1 && ulOrigin <= 3) || arc == NO_ERROR)
    583618    {
    584         fprintf (file, "\n           ");
    585619        if (ulOrigin >= 1 && ulOrigin <= 3)
    586620            fprintf (file, " origin=\"%s\"",
     
    647681 *  Used only when DosQuerySysState() fails (so qt_excWriteModules() is not
    648682 *  applicable). We use recursiveness to avoid module record duplicates.
     683 *  @note This function should be in sync with qt_excWriteStackFrames()
     684 *        because they share the same logic.
    649685 */
    650686static void qt_excWriteModulesOnStack (WMOS_STATE *pState)
     
    701737                if (   (arc != NO_ERROR)
    702738                    || (   arc == NO_ERROR
    703                         && (ulFlags & (PAG_COMMIT|PAG_READ))
    704                             != (PAG_COMMIT|PAG_READ)))
     739                        && (ulFlags & (PAG_COMMIT | PAG_READ))
     740                            != (PAG_COMMIT | PAG_READ)))
    705741                {
    706742                    /* try go to the next page */
    707                     /// @todo (r=dmik) I don't know how much it is accurate,
     743                    /// @todo (r=dmik) I don't know how much is it accurate,
    708744                    //  I've just taken the logic from xwphelpers sources.
    709745                    pState->ulRegEbp += 0x1000;
     
    752788    ULONG ul = 0;
    753789    ULONG aulBuf [3];
     790
     791    QSTREC *pThrdRec = NULL;
    754792
    755793    /* *** application info */
     
    843881   
    844882    /* first, the current thread */
    845     QSTREC *pThrdRec = pInfo->bHaveSysState ? pInfo->pProcRec->pThrdRec : NULL;
     883    pThrdRec = pInfo->bHaveSysState ? pInfo->pProcRec->pThrdRec : NULL;
    846884    if (pThrdRec)
    847885    {
     
    854892    }
    855893    qt_excWriteThreadInfo (file, pInfo->ptib, pThrdRec, pContextRec);
     894
     895    /* then, all other threads */
     896    pThrdRec = pInfo->bHaveSysState ? pInfo->pProcRec->pThrdRec : NULL;
     897    if (pThrdRec)
     898    {
     899        /* important to set ContextFlags to CONTEXT_FULL, otherwise we'll
     900         * get nothing */
     901        CONTEXTRECORD ContextRec = {CONTEXT_FULL, 0};
     902        APIRET arc = NO_ERROR;
     903        /* enter the critical section to effectively suspend all other threads
     904         * while reading their contexts and walking their stacks */
     905        DosEnterCritSec();
     906        for (ul = 0; ul < pInfo->pProcRec->cTCB; ++ ul, ++ pThrdRec)
     907        {
     908            if ((ULONG) pThrdRec->tid == pInfo->ptib->tib_ptib2->tib2_ultid)
     909                continue;
     910            arc = DosQueryThreadContext (pThrdRec->tid, CONTEXT_FULL,
     911                                         &ContextRec);
     912            if (arc == NO_ERROR)
     913                qt_excWriteThreadInfo (file, NULL, pThrdRec, &ContextRec);
     914            else
     915            {
     916                fprintf (file, "   <Thread ID=\"%04lX\">", pThrdRec->tid);
     917                qt_excWriteErrorMsg (file, 3, "DosQueryThreadContext returned "
     918                                              "%lu", arc);
     919                fprintf (file, "   </Thread>\n");
     920            }
     921        }
     922        /* exit the critical section */
     923        DosExitCritSec();       
     924    }
    856925   
    857926    fprintf (file, "  </Threads>\n");
Note: See TracChangeset for help on using the changeset viewer.