Changeset 146 for trunk


Ignore:
Timestamp:
Oct 29, 2006, 6:21:57 PM (19 years ago)
Author:
dmik
Message:

Common: System Exceptions:

  • Added usage of DosQuerySysState() to determine the full list of loaded modules (not required, less information will be available if it fails).
  • Moved full module descriptions to the 'Process/Modules' tag; 'Location' tags only contain module IDs.
  • Added the 'state' attribute to the 'Thread' tag.
File:
1 edited

Legend:

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

    r145 r146  
    6464   
    6565    - must be instantiated on the stack of the main thread only
    66     - must be instantiated before a QAplication instance is created
     66    - should be instantiated before a QAplication instance is created
    6767      (does nothing otherwise)
     68    - note that callback can be called on any thread
    6869*/
    6970
     
    252253    APIRET  arc = NO_ERROR;
    253254    HMODULE hMod = NULLHANDLE;
    254     char    szMod[CCHMAXPATH] = "unknown";
     255    char   szMod[CCHMAXPATH] = "";
    255256    ULONG   ulObject = 0,
    256257            ulOffset = 0;
    257258
    258     if ( ulPointer )
    259         fprintf( file, "     <Frame pointer=\"%08lX\">\n", ulPointer );
     259    if (ulPointer)
     260        fprintf (file, "     <Frame pointer=\"%08lX\">\n", ulPointer);
    260261    else
    261         fprintf( file, "     <Frame pointer=\"current\">\n" );
    262 
    263     fprintf( file, "      <Location address=\"%08lX\">\n", ulAddress );
    264    
    265     arc = DosQueryModFromEIP( &hMod, &ulObject,
    266                               sizeof(szMod), szMod, &ulOffset,
    267                               ulAddress );
     262        fprintf (file, "     <Frame pointer=\"current\">\n");
     263
     264    fprintf (file, "      <Location address=\"%08lX\">\n", ulAddress);
     265   
     266    arc = DosQueryModFromEIP (&hMod, &ulObject,
     267                              sizeof (szMod), szMod, &ulOffset,
     268                              ulAddress);
    268269
    269270    if (arc != NO_ERROR)
    270         qt_excWriteErrorMsg( file, 7, "%s: DosQueryModFromEIP returned %lu",
    271                              szMod, arc );
     271        qt_excWriteErrorMsg (file, 7, "%s: DosQueryModFromEIP returned %lu",
     272                             szMod, arc);
    272273    else
    273274    {
    274         DosQueryModuleName( hMod, sizeof(szMod), szMod );
    275         fprintf( file, "       <Module ID=\"%04lX\" name=\"", hMod );
    276         qt_excEscapeString( file, szMod );
    277         fprintf( file, "\" \n"
    278                        "               segment=\"%04lX\" offset=\"%08lX\"/>\n",
    279                  ulObject + 1, ulOffset );
    280 /// @todo (r=dmik) use .DBG and .SYM files to get symbols
    281 //  (see debug.h and debug.c from the xwphelpers package)
    282 //        dbgPrintStackFrame(file,
    283 //                           szFullName,
    284 //                           ulObject,
    285 //                           ulOffset);
     275        fprintf (file, "       <Module ID=\"%04lX\" segment=\"%04lX\" "
     276                                      "offset=\"%08lX\"/>\n",
     277                 hMod, ulObject + 1, ulOffset);
    286278    }
    287279
     
    293285        ULONG ulFlags = 0;
    294286        APIRET arc = NO_ERROR;
    295         while ( 1 )
    296         {
    297             arc = DosQueryMem( (void *) (ULONG) pch, &ulCount, &ulFlags );
    298             if ( arc == NO_ERROR )
    299             {
    300                 if ( ulCount >= enmDelta * 2 )
     287        while (1)
     288        {
     289            arc = DosQueryMem ((void *) (ULONG) pch, &ulCount, &ulFlags);
     290            if (arc == NO_ERROR)
     291            {
     292                if (ulCount >= enmDelta * 2)
    301293                    break;
    302                 if ( pch + ulCount <= (UCHAR *) ulAddress )
    303                 {   // ulAddress is outside the pch object
     294                if (pch + ulCount <= (UCHAR *) ulAddress)
     295                {
     296                    /* ulAddress is outside the pch object */
    304297                    pch += ulCount;
    305298                    ulCount = enmDelta * 2 - ulCount;
    306299                }
    307300                else
    308                 {   // ulAddress is within the pch object
     301                {
     302                    /* ulAddress is within the pch object */
    309303                    pchEnd = pch += ulCount;
    310304                    break;
    311305                }
    312306            }
    313             else if ( arc == ERROR_INVALID_ADDRESS )
    314             {
    315                 if ( ((ULONG) pch) & 0xFFFFF000 == ulAddress & 0xFFFFF000 )
    316                     break; // the same page, ulAddress inaccessible
     307            else if (arc == ERROR_INVALID_ADDRESS)
     308            {
     309                if (((ULONG) pch) & 0xFFFFF000 == ulAddress & 0xFFFFF000)
     310                    break; /* the same page, ulAddress inaccessible */
    317311                pch = (UCHAR *) (ulAddress & 0xFFFFF000);
    318312            }
    319313        }
    320         fprintf( file, "       <Dump address=\"%08lX\">\n        ", pch );
    321         if ( arc == NO_ERROR &&
    322              ulFlags & (PAG_COMMIT|PAG_READ) == (PAG_COMMIT | PAG_READ) )
    323         {
    324             for ( ; pch < pchEnd; ++pch )
    325                 fprintf( file, "%02lX%c", (ULONG) *pch,
    326                          ulAddress - (ULONG) pch == 1 ? '-' : ' ' );
    327             fprintf( file, "\n" );
     314        fprintf (file, "       <Dump address=\"%08lX\">\n        ", pch);
     315        if (arc == NO_ERROR &&
     316            ulFlags & (PAG_COMMIT|PAG_READ) == (PAG_COMMIT | PAG_READ))
     317        {
     318            for (; pch < pchEnd; ++pch)
     319                fprintf (file, "%02lX%c", (ULONG) *pch,
     320                         ulAddress - (ULONG) pch == 1 ? '-' : ' ');
     321            fprintf (file, "\n");
    328322        }
    329323        else
    330             qt_excWriteErrorMsg( file, 0, "%08lX: DosQueryMem returned %lu"
    331                                  "and flags %08lX", pch, arc, ulFlags );
    332         fprintf( file, "       </Dump>\n" );
    333     }
    334    
    335     fprintf( file, "      </Location>\n"
    336                    "     </Frame>\n" );
     324            qt_excWriteErrorMsg (file, 0, "%08lX: DosQueryMem returned %lu"
     325                                 "and flags %08lX", pch, arc, ulFlags);
     326        fprintf (file, "       </Dump>\n");
     327    }
     328   
     329    fprintf (file, "      </Location>\n"
     330                   "     </Frame>\n");
    337331}
    338332
     
    340334    Walks the stack and writes information about stack frames.
    341335*/
    342 static void qt_excWriteStackFrames( FILE *file, PTIB ptib,
    343                                     PCONTEXTRECORD pContextRec )
     336static void qt_excWriteStackFrames (FILE *file, PTIB ptib,
     337                                    PCONTEXTRECORD pContextRec)
    344338{
    345339    PULONG pulStackWord = 0;
    346340
    347     fprintf( file, "    <Frames>\n" );
    348 
    349     // first the trapping address itself
    350     qt_excWriteStackFrame( file, 0, pContextRec->ctx_RegEip );
     341    fprintf (file, "    <Frames>\n");
     342
     343    /* first the trapping address itself */
     344    qt_excWriteStackFrame (file, 0, pContextRec->ctx_RegEip);
    351345
    352346    pulStackWord = (PULONG) pContextRec->ctx_RegEbp;
    353347   
    354     while (    pulStackWord != 0
    355             && pulStackWord < (PULONG) ptib->tib_pstacklimit )
    356     {
    357         if ( ((ULONG) pulStackWord & 0x00000FFF) == 0x00000000 )
    358         {
    359             // we're on a page boundary: check access
     348    while (   pulStackWord != 0
     349           && pulStackWord < (PULONG) ptib->tib_pstacklimit)
     350    {
     351        if (((ULONG) pulStackWord & 0x00000FFF) == 0x00000000)
     352        {
     353            /* we're on a page boundary: check access */
    360354            ULONG ulCount = 0x1000;
    361355            ULONG ulFlags = 0;
    362             APIRET arc = DosQueryMem( (void *) pulStackWord,
    363                                       &ulCount, &ulFlags );
    364             if (    (arc != NO_ERROR)
    365                  || (   arc == NO_ERROR
    366                      && (ulFlags & (PAG_COMMIT|PAG_READ))
    367                          != (PAG_COMMIT|PAG_READ)) )
    368             {
    369                 fprintf( file, "     <Frame pointer=\"%08lX\">\n",
    370                          (ULONG) pulStackWord );
    371                 qt_excWriteErrorMsg( file, 6, "DosQueryMem returned %lu "
    372                                      "and flags %08lX", arc, ulFlags );
    373                 fprintf( file, "     </Frame>\n" );
     356            APIRET arc = DosQueryMem ((void *) pulStackWord,
     357                                      &ulCount, &ulFlags);
     358            if (   (arc != NO_ERROR)
     359                || (   arc == NO_ERROR
     360                    && (ulFlags & (PAG_COMMIT|PAG_READ))
     361                        != (PAG_COMMIT|PAG_READ)))
     362            {
     363                fprintf (file, "     <Frame pointer=\"%08lX\">\n",
     364                         (ULONG) pulStackWord);
     365                qt_excWriteErrorMsg (file, 6, "DosQueryMem returned %lu "
     366                                     "and flags %08lX", arc, ulFlags);
     367                fprintf (file, "     </Frame>\n");
    374368                pulStackWord += 0x1000;
    375                 continue; // while
    376             }
    377         }
    378 
    379         qt_excWriteStackFrame( file, (ULONG) pulStackWord, *(pulStackWord + 1) );
     369                continue; /* while */
     370            }
     371        }
     372
     373        qt_excWriteStackFrame (file, (ULONG) pulStackWord, *(pulStackWord + 1));
    380374        pulStackWord = (PULONG) *(pulStackWord);
    381     } // end while
    382 
    383     fprintf( file, "    </Frames>\n" );
     375    } /* end while */
     376
     377    fprintf (file, "    </Frames>\n");
    384378}
    385379
    386380/*! \internal
    387381    Writes the thread information.
    388 */
    389 static void qt_excWriteThreadInfo( FILE *file, PTIB ptib,
    390                                    PEXCEPTIONREPORTRECORD pReportRec,
    391                                    PCONTEXTRECORD pContextRec )
    392 {
    393     ULONG       ul = 0;
    394     ULONG       ulOldPriority = ~0;
    395 
    396     // raise this thread's priority, because this
    397     // might take some time
    398     ulOldPriority = ptib->tib_ptib2->tib2_ulpri;
    399     DosSetPriority( PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, 0 );
    400 
    401     fprintf( file, "  <Thread ID=\"%04lX\" slot=\"%04lX\" "
    402                              "priority=\"%04lX\" "
    403                              "mc=\"%04lX\" mcf=\"%04lX\">\n",
    404              ptib->tib_ptib2->tib2_ultid, ptib->tib_ordinal, ulOldPriority,
    405              ptib->tib_ptib2->tib2_usMCCount, ptib->tib_ptib2->tib2_fMCForceFlag );
    406 
    407     // *** generic exception info
    408 
    409     fprintf( file,
    410              "   <Exception type=\"%08lX\" flags=\"%08lX\" address=\"%08lX\">\n",
    411              pReportRec->ExceptionNum, pReportRec->fHandlerFlags,
    412              (ULONG) pReportRec->ExceptionAddress );
    413    
    414     for ( ul = 0; ul < pReportRec->cParameters;  ++ul )
    415     {
    416         fprintf( file, "    <Param value=\"%08lX\"/>\n",
    417                  pReportRec->ExceptionInfo[ul] );
    418     }
    419 
    420     fprintf( file, "   </Exception>\n" );
    421    
    422     // *** registers
    423 
    424     fprintf( file, "   <CPU>\n"
    425                    "    <Registers>\n" );
    426 
    427     if ( pContextRec->ContextFlags & CONTEXT_SEGMENTS )
    428     {
    429         qt_excWriteReg( file, "DS", pContextRec->ctx_SegDs, FALSE );
    430         qt_excWriteReg( file, "ES", pContextRec->ctx_SegEs, FALSE );
    431         qt_excWriteReg( file, "FS", pContextRec->ctx_SegFs, FALSE );
    432         qt_excWriteReg( file, "GS", pContextRec->ctx_SegGs, FALSE );
    433     }
    434    
    435     if ( pContextRec->ContextFlags & CONTEXT_INTEGER )
    436     {
    437         qt_excWriteReg( file, "EAX", pContextRec->ctx_RegEax );
    438         qt_excWriteReg( file, "EBX", pContextRec->ctx_RegEbx );
    439         qt_excWriteReg( file, "ECX", pContextRec->ctx_RegEcx );
    440         qt_excWriteReg( file, "EDX", pContextRec->ctx_RegEdx );
    441         qt_excWriteReg( file, "ESI", pContextRec->ctx_RegEsi );
    442         qt_excWriteReg( file, "EDI", pContextRec->ctx_RegEdi );
    443     }
    444 
    445     if ( pContextRec->ContextFlags & CONTEXT_CONTROL )
    446     {
    447         qt_excWriteReg( file, "CS", pContextRec->ctx_SegCs, FALSE );
    448         qt_excWriteReg( file, "EIP", pContextRec->ctx_RegEip );
    449         qt_excWriteReg( file, "SS", pContextRec->ctx_SegSs, FALSE );
    450         qt_excWriteReg( file, "ESP", pContextRec->ctx_RegEsp );
    451         qt_excWriteReg( file, "EBP", pContextRec->ctx_RegEbp );
    452         qt_excWriteReg( file, "EFLAGS", pContextRec->ctx_EFlags, FALSE );
    453     }
    454    
    455     fprintf( file, "    </Registers>\n"
    456                    "   </CPU>\n" );
    457 
    458     // *** stack
    459 
    460     fprintf( file, "   <Stack base=\"%08lX\" limit=\"%08lX\">\n",
     382    If ptib is not NULL, the current thread's information is to be written.
     383    If ptib is NULL, pThrdRec is guaranted not to be NULL.
     384*/
     385static void qt_excWriteThreadInfo (FILE *file, PTIB ptib, QSTREC *pThrdRec,
     386                                   PCONTEXTRECORD pContextRec)
     387{
     388    if (ptib)
     389    {
     390        fprintf (file, "  <Thread ID=\"%04lX\" slot=\"%04lX\" "
     391                                 "priority=\"%04lX\" ",
     392                 ptib->tib_ptib2->tib2_ultid, ptib->tib_ordinal,
     393                 ptib->tib_ptib2->tib2_ulpri);
     394        if (pThrdRec)
     395            fprintf (file, "state=\"%02lX\" ", (ULONG) pThrdRec->state);
     396        fprintf (file, "mc=\"%04lX\" mcf=\"%04lX\">\n",
     397                 ptib->tib_ptib2->tib2_usMCCount,
     398                 ptib->tib_ptib2->tib2_fMCForceFlag);
     399    }
     400    else
     401    {
     402        fprintf (file, "  <Thread ID=\"%04lX\" slot=\"%04lX\" "
     403                                 "priority=\"%04lX\" state=\"%02lX\">\n",
     404                 pThrdRec->tid, pThrdRec->slot, pThrdRec->priority,
     405                 pThrdRec->state);
     406    }
     407
     408    /* *** registers */
     409
     410    fprintf (file, "   <CPU>\n"
     411                   "    <Registers>\n");
     412
     413    if  (pContextRec->ContextFlags & CONTEXT_SEGMENTS)
     414    {
     415        qt_excWriteReg (file, "DS", pContextRec->ctx_SegDs, FALSE);
     416        qt_excWriteReg (file, "ES", pContextRec->ctx_SegEs, FALSE);
     417        qt_excWriteReg (file, "FS", pContextRec->ctx_SegFs, FALSE);
     418        qt_excWriteReg (file, "GS", pContextRec->ctx_SegGs, FALSE);
     419    }
     420   
     421    if  (pContextRec->ContextFlags & CONTEXT_INTEGER)
     422    {
     423        qt_excWriteReg (file, "EAX", pContextRec->ctx_RegEax);
     424        qt_excWriteReg (file, "EBX", pContextRec->ctx_RegEbx);
     425        qt_excWriteReg (file, "ECX", pContextRec->ctx_RegEcx);
     426        qt_excWriteReg (file, "EDX", pContextRec->ctx_RegEdx);
     427        qt_excWriteReg (file, "ESI", pContextRec->ctx_RegEsi);
     428        qt_excWriteReg (file, "EDI", pContextRec->ctx_RegEdi);
     429    }
     430
     431    if  (pContextRec->ContextFlags & CONTEXT_CONTROL)
     432    {
     433        qt_excWriteReg (file, "CS", pContextRec->ctx_SegCs, FALSE);
     434        qt_excWriteReg (file, "EIP", pContextRec->ctx_RegEip);
     435        qt_excWriteReg (file, "SS", pContextRec->ctx_SegSs, FALSE);
     436        qt_excWriteReg (file, "ESP", pContextRec->ctx_RegEsp);
     437        qt_excWriteReg (file, "EBP", pContextRec->ctx_RegEbp);
     438        qt_excWriteReg (file, "EFLAGS", pContextRec->ctx_EFlags, FALSE);
     439    }
     440   
     441    fprintf (file, "    </Registers>\n"
     442                   "   </CPU>\n");
     443
     444    /* *** stack */
     445
     446    fprintf (file, "   <Stack base=\"%08lX\" limit=\"%08lX\">\n",
    461447             (ULONG) ptib->tib_pstack,
    462              (ULONG) ptib->tib_pstacklimit );
    463    
    464     if ( pContextRec->ContextFlags & CONTEXT_CONTROL )
    465     {
    466         qt_excWriteStackFrames( file, ptib, pContextRec );
     448             (ULONG) ptib->tib_pstacklimit);
     449   
     450    if (pContextRec->ContextFlags & CONTEXT_CONTROL)
     451    {
     452        qt_excWriteStackFrames (file, ptib, pContextRec);
    467453    }   
    468454   
    469     fprintf( file, "   </Stack>\n"
    470                    "  </Thread>\n" );
    471    
    472     // reset old priority
    473     DosSetPriority( PRTYS_THREAD, (ulOldPriority & 0x0F00) >> 8,
    474                                   (UCHAR) ulOldPriority,
    475                                   0 );
     455    fprintf (file, "   </Stack>\n"
     456                   "  </Thread>\n");
     457}
     458
     459typedef struct _PROCESSINFO
     460{
     461    /* common values */
     462    char *pszFullName;
     463    char *pszBaseName;
     464    /* direct info pointers */
     465    PPIB ppib;
     466    PTIB ptib;
     467    BOOL bHaveSysState; /**< TRUE when both pProcRec and pLibRec are not NULL */
     468    QSPREC *pProcRec;   /**< NULL when bHaveSysState is FALSE */
     469    QSLREC *pLibRec;    /**< NULL when bHaveSysState is FALSE */
     470} PROCESSINFO;
     471
     472/*! \internal
     473    Writes module information to the log file.
     474    \a ulOrigin is 1 (self), 2 (imported), or 3 (loaded). Other values are
     475    ignored.
     476*/
     477static void qt_excWriteModule (FILE *file, USHORT hmte, char *pszName,
     478                               ULONG ulOrigin = 0)
     479{
     480    static const char *apszOrigins[] = { "self", "imported", "loaded" };
     481
     482    fprintf (file, "   <Module ID=%\"%04lX\" name=\"", hmte);
     483    qt_excEscapeString (file, pszName);
     484    if (ulOrigin >= 1 && ulOrigin <= 3)
     485        fprintf (file, "\"\n"
     486                       "           origin=\"%s\"/>\n",
     487                       apszOrigins [ulOrigin - 1]);
     488    else
     489        fprintf (file, "\"/>\n");
     490}
     491
     492/*! \internal
     493    Writes module and all its imports information to the log file.
     494    \a ulOrigin is 1 (self), or 3 (loaded), other values are ignored.
     495*/
     496static void qt_excWriteModules (FILE *file, USHORT hmte, QSLREC *pFirstLibRec,
     497                                ULONG ulOrigin)
     498{
     499    QSLREC *pLibRec = pFirstLibRec;
     500    while (pLibRec)
     501    {
     502        if (pLibRec->hmte == hmte &&
     503            pLibRec->pName /* not yet visited */)
     504        {
     505            qt_excWriteModule (file, hmte, (char *) pLibRec->pName, ulOrigin);
     506            /* mark as visited */
     507            pLibRec->pName = NULL;
     508            /* go through imports */
     509            if (pLibRec->ctImpMod)
     510            {
     511                USHORT *pHmte = (USHORT *) (pLibRec + 1);
     512                for (ULONG i = 0; i < pLibRec->ctImpMod; ++ i, ++ pHmte)
     513                    qt_excWriteModules (file, *pHmte, pFirstLibRec,
     514                                        ulOrigin == 1 ? 2 : ulOrigin);
     515                break;
     516            }
     517        }
     518        pLibRec = (QSLREC *) pLibRec->pNextRec;
     519    }
     520}
     521
     522/** Struct for recursive qt_excWriteModulesOnStack() to reduce stack usage */
     523typedef struct _WMOS_STATE
     524{
     525    FILE *file;
     526    ULONG ulRegEbp;
     527    ULONG ulRegEip;
     528    ULONG ulStackLimit;
     529    USHORT hmteExe;
     530    ULONG cLevel;
     531    USHORT *pHmteOuter;
     532} WMOS_STATE;
     533
     534/*! \internal
     535    Walks the stack and writes information about all encountered modules.
     536    Used only when DosQuerySysState() fails (so qt_excWriteModules() is not
     537    applicable). We use recursiveness to avoid module record duplicates.
     538*/
     539static void qt_excWriteModulesOnStack (WMOS_STATE *pState)
     540{
     541    USHORT hmteThis = 0;
     542   
     543    {
     544        APIRET  arc = NO_ERROR;
     545        char    szMod [CCHMAXPATH] = "";
     546        ULONG   ulObject = 0, ulOffset = 0;
     547   
     548        arc = DosQueryModFromEIP ((HMODULE *) &hmteThis, &ulObject,
     549                                  sizeof (szMod), szMod, &ulOffset,
     550                                  pState->ulRegEip);
     551        if (arc == NO_ERROR && hmteThis != pState->hmteExe)
     552        {
     553            /* look if we've already seen this module using the hmteThis chain
     554             * on the stack */
     555            USHORT *pH = &hmteThis;
     556            /* calculate distance between recursive hmteThis on the stack */
     557            ULONG ulOuter = (ULONG) pState->pHmteOuter - (ULONG) pH;
     558            ULONG cL = pState->cLevel;
     559            while (cL != 0)
     560            {
     561                pH = (USHORT *)(((ULONG) pH) + ulOuter);
     562                if (*pH == hmteThis)
     563                    break;
     564                -- cL;
     565            }
     566            if (cL == 0)
     567            {
     568                /* got an unique module handle */
     569                DosQueryModuleName (hmteThis, sizeof (szMod), szMod);
     570                qt_excWriteModule (pState->file, hmteThis, szMod);
     571            }
     572        }
     573    }
     574   
     575    /* we do EBP validity check here as well as before the recursive call below
     576     * to get a chance to translate EIP passed on the first call (as taken
     577     * from the CONTEXTRECORD even if EBP there is invalid. */
     578    if (pState->ulRegEbp != 0 && pState->ulRegEbp < pState->ulStackLimit)
     579    {
     580        if ((pState->ulRegEbp & 0x00000FFF) == 0x00000000)
     581        {
     582            /* we're on a page boundary: check access */
     583            while (pState->ulRegEbp < pState->ulStackLimit)
     584            {
     585                ULONG ulCount = 0x1000;
     586                ULONG ulFlags = 0;
     587                APIRET arc = DosQueryMem ((void *) pState->ulRegEbp,
     588                                          &ulCount, &ulFlags);
     589                if (   (arc != NO_ERROR)
     590                    || (   arc == NO_ERROR
     591                        && (ulFlags & (PAG_COMMIT|PAG_READ))
     592                            != (PAG_COMMIT|PAG_READ)))
     593                {
     594                    /* try go to the next page */
     595                    /// @todo (r=dmik) I'm not sure how much it is correct,
     596                    //  I've just taken the logic from xwphelpers sources.
     597                    pState->ulRegEbp += 0x1000;
     598                    continue; /* while */
     599                }
     600                break;
     601            }
     602        }
     603
     604        /* get the return address to the previous call */
     605        pState->ulRegEip = *(((PULONG) pState->ulRegEbp) + 1);
     606        /* get the address of the outer stack frame */
     607        pState->ulRegEbp = *((PULONG) pState->ulRegEbp);
     608   
     609        if (pState->ulRegEbp != 0 && pState->ulRegEbp < pState->ulStackLimit)
     610        {
     611            pState->cLevel ++;
     612            pState->pHmteOuter = &hmteThis;
     613            qt_excWriteModulesOnStack (pState);
     614        }
     615    }
    476616}
    477617
     
    479619    Writes exception information to the log file.
    480620*/
    481 static void qt_excWriteException( FILE *file,
    482                                   const char *pszExeName,
    483                                   const char *pszExeBase,
    484                                   PPIB ppib, PTIB ptib,
     621static void qt_excWriteException (FILE *file,
     622                                  PROCESSINFO *pInfo,
    485623                                  PEXCEPTIONREPORTRECORD pReportRec,
    486                                   PCONTEXTRECORD pContextRec )
    487 {
    488     ULONG       aulBuf[3];
    489 
    490     // *** application info
    491 
    492     {
    493         fprintf( file, " <Application name=\"" );
    494         if ( XcptPvt::askCallback( QtOS2SysXcptReq_AppName ) == TRUE )
    495             XcptPvt::letCallback( QtOS2SysXcptReq_AppName );
     624                                  PCONTEXTRECORD pContextRec)
     625{
     626    ULONG ul = 0;
     627    ULONG aulBuf [3];
     628
     629    /* *** application info */
     630
     631    {
     632        fprintf (file, " <Application name=\"");
     633        if (XcptPvt::askCallback (QtOS2SysXcptReq_AppName) == TRUE)
     634            XcptPvt::letCallback (QtOS2SysXcptReq_AppName);
    496635        else
    497             qt_excEscapeString( file, pszExeBase );
    498         fprintf( file, "\" version=\"" );
    499         if ( XcptPvt::askCallback( QtOS2SysXcptReq_AppVer ) == TRUE )
    500             XcptPvt::letCallback( QtOS2SysXcptReq_AppVer );
     636            qt_excEscapeString (file, pInfo->pszBaseName);
     637        fprintf (file, "\" version=\"");
     638        if (XcptPvt::askCallback (QtOS2SysXcptReq_AppVer) == TRUE)
     639            XcptPvt::letCallback (QtOS2SysXcptReq_AppVer);
    501640        else
    502             fprintf( file, "unknown" );
    503         fprintf( file, "\">\n" );
    504 
    505         if ( XcptPvt::askCallback( QtOS2SysXcptReq_ReportTo ) == TRUE )
    506         {
    507             fprintf( file, "  <Report to=\"" );
    508             XcptPvt::letCallback( QtOS2SysXcptReq_ReportTo );
    509             if ( XcptPvt::askCallback( QtOS2SysXcptReq_ReportSubj ) == TRUE )
    510             {
    511                 fprintf( file, "\" subject=\"" );
    512                 XcptPvt::letCallback( QtOS2SysXcptReq_ReportSubj );
    513             }
    514             fprintf( file, "\"/>\n" );
     641            fprintf (file, "unknown");
     642        fprintf (file, "\">\n");
     643
     644        if (XcptPvt::askCallback (QtOS2SysXcptReq_ReportTo) == TRUE)
     645        {
     646            fprintf (file, "  <Report to=\"");
     647            XcptPvt::letCallback (QtOS2SysXcptReq_ReportTo);
     648            if (XcptPvt::askCallback (QtOS2SysXcptReq_ReportSubj) == TRUE)
     649            {
     650                fprintf (file, "\" subject=\"");
     651                XcptPvt::letCallback (QtOS2SysXcptReq_ReportSubj);
     652            }
     653            fprintf (file, "\"/>\n");
    515654        }
    516655       
    517         fprintf( file, " </Application>\n" );
    518     }
    519    
    520     // *** system info
    521 
    522     DosQuerySysInfo( QSV_VERSION_MAJOR, QSV_VERSION_REVISION,
    523                      &aulBuf, sizeof(aulBuf) );
    524     // Warp 3 is reported as 20.30
    525     // Warp 4 is reported as 20.40
    526     // Aurora is reported as 20.45
    527 
    528     fprintf( file,
     656        fprintf (file, " </Application>\n");
     657    }
     658   
     659    /* *** generic exception info */
     660
     661    fprintf (file,
     662             " <Exception type=\"%08lX\" flags=\"%08lX\" address=\"%08lX\">\n",
     663             pReportRec->ExceptionNum, pReportRec->fHandlerFlags,
     664             (ULONG) pReportRec->ExceptionAddress);
     665   
     666    for (ul = 0; ul < pReportRec->cParameters;  ++ul)
     667    {
     668        fprintf (file, "  <Param value=\"%08lX\"/>\n",
     669                 pReportRec->ExceptionInfo [ul]);
     670    }
     671
     672    fprintf (file, " </Exception>\n");
     673   
     674    /* *** system info */
     675
     676    DosQuerySysInfo (QSV_VERSION_MAJOR, QSV_VERSION_REVISION,
     677                     &aulBuf, sizeof (aulBuf));
     678    /* Warp 3 is reported as 20.30 */
     679    /* Warp 4 is reported as 20.40 */
     680    /* Aurora is reported as 20.45 */
     681
     682    fprintf (file,
    529683             " <System name=\"OS/2\" version=\"%u.%u.%u\"/>\n",
    530              aulBuf[0], aulBuf[1], aulBuf[2] );
    531 
    532     // *** process info
    533 
    534     if ( ppib )
    535     {
    536         fprintf( file,
    537                  " <Process ID=\"%04lX\" parentID=\"%04lX\">\n"
    538                  "  <Module ID=\"%04lX\" name=\"",
    539                 ppib->pib_ulpid, ppib->pib_ulppid, ppib->pib_hmte );
    540         qt_excEscapeString( file, pszExeName );
    541         fprintf( file,
    542                  "\"/>\n"
    543                  " </Process>\n" );
     684             aulBuf[0], aulBuf[1], aulBuf[2]);
     685
     686    /* *** process info */
     687
     688    fprintf (file, " <Process ID=\"%04lX\" parentID=\"%04lX\">\n",
     689             pInfo->ppib->pib_ulpid, pInfo->ppib->pib_ulppid);
     690
     691    fprintf (file, "  <Modules>\n");
     692    if (pInfo->bHaveSysState)
     693    {
     694        /* write process module and it's imports */
     695        qt_excWriteModules (file, pInfo->ppib->pib_hmte, pInfo->pLibRec, 1);
     696        /* write loaded modules and their imports */
     697        if (pInfo->pProcRec->cLib && pInfo->pProcRec->pLibRec)
     698        {
     699            for (ULONG i = 0; i < pInfo->pProcRec->cLib; ++ i)
     700                qt_excWriteModules (file, pInfo->pProcRec->pLibRec [i],
     701                                    pInfo->pLibRec, 3);
     702        }
    544703    }
    545704    else
    546         qt_excWriteErrorMsg( file, 1, "ppib is NULL" );
    547 
    548         fprintf( file, " <Threads>\n" );
    549        
    550     if ( ptib && ptib->tib_ptib2 )
    551         qt_excWriteThreadInfo( file, ptib, pReportRec, pContextRec );
    552     else if ( !ptib )
    553         qt_excWriteErrorMsg( file, 1, "ptib is NULL" );
    554     else
    555         qt_excWriteErrorMsg( file, 1, "ptib->tib_ptib2 is NULL" );
    556 
    557         fprintf( file, " </Threads>\n" );
     705    {
     706        qt_excWriteModule (file, pInfo->ppib->pib_hmte, pInfo->pszFullName, 1);
     707        WMOS_STATE State = { file, pContextRec->ctx_RegEbp,
     708                             pContextRec->ctx_RegEip,
     709                             (ULONG) pInfo->ptib->tib_pstacklimit,
     710                             pInfo->ppib->pib_hmte,
     711                             0 /* cLevel */, NULL /* pHmteOuter */ };
     712        qt_excWriteModulesOnStack (&State);
     713    }
     714    fprintf (file, "  </Modules>\n");
     715   
     716    fprintf (file, "  <Threads>\n");
     717   
     718    /* first, the current thread */
     719    QSTREC *pThrdRec = pInfo->pProcRec->pThrdRec;
     720    if (pThrdRec)
     721    {
     722        /* locate the current thread structure */
     723        for (ul = 0; ul < pInfo->pProcRec->cTCB; ++ ul, ++ pThrdRec)
     724            if ((ULONG) pThrdRec->tid == pInfo->ptib->tib_ptib2->tib2_ultid)
     725                break;
     726        if (ul == pInfo->pProcRec->cTCB)
     727            pThrdRec = NULL;
     728    }
     729    qt_excWriteThreadInfo (file, pInfo->ptib, pThrdRec, pContextRec);
     730   
     731    fprintf (file, "  </Threads>\n");
     732
     733    fprintf (file, " </Process>\n");
    558734}
    559735
     
    678854                                  PVOID pv )
    679855{
    680     PTIB ptib = NULL;
    681     PPIB ppib = NULL;
    682    
     856    PROCESSINFO Info = {0};
     857
    683858    /* From the VAC++3 docs:
    684859     *      "The first thing an exception handler should do is check the
     
    696871     */
    697872
    698     if ( pReportRec->fHandlerFlags &
    699          (EH_EXIT_UNWIND | EH_UNWINDING | EH_NESTED_CALL) )
     873    if (pReportRec->fHandlerFlags &
     874        (EH_EXIT_UNWIND | EH_UNWINDING | EH_NESTED_CALL))
    700875        return XCPT_CONTINUE_SEARCH;
    701876
    702     // can it ever fail?...
    703     DosGetInfoBlocks( &ptib, &ppib );
    704        
     877    /* setup the process info structure */
     878    DosGetInfoBlocks (&Info.ptib, &Info.ppib);
     879
    705880    switch (pReportRec->ExceptionNum)
    706881    {
     
    712887        case XCPT_INTEGER_OVERFLOW:
    713888        {
    714             // "real" exceptions:
    715 
     889            /* "real" exceptions: */
     890
     891            APIRET arc = NO_ERROR;
     892            PVOID pBuf = NULL;
     893           
     894            char szFullExeName [CCHMAXPATH] = "";
     895            char szBaseExeName [CCHMAXPATH] = "";
     896           
     897            TIB2 Tib2Orig;
    716898            DATETIME dt;
    717             char szFileName[CCHMAXPATH];
     899
     900            char szFileName [CCHMAXPATH];
    718901            FILE *file = NULL;
    719             char szExeName[CCHMAXPATH] = "unknown";
    720             char szExeBase[CCHMAXPATH];
    721            
    722             DosBeep( 880, 200 );
    723 
    724             if ( ppib )
    725             {
    726                 // get the main module name
    727                 DosQueryModuleName( ppib->pib_hmte, sizeof(szExeName),
    728                                     szExeName );
    729                
    730                 // find the base name (w/o path and extension)
    731                 char *psz = strrchr( szExeName, '\\' );
     902
     903            /* raise this thread's priority to do it fast */
     904            Tib2Orig = *Info.ptib->tib_ptib2;
     905            Info.ptib->tib_ptib2 = &Tib2Orig;
     906            DosSetPriority (PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, 0);
     907
     908            DosBeep (880, 200);
     909
     910            /* query system state */
     911            {
     912                ULONG ulCB = 64 * 1024;
     913                ULONG cTries = 3;
     914                while (-- cTries)
     915                {
     916                    arc = DosAllocMem (&pBuf, ulCB, PAG_WRITE | PAG_COMMIT);
     917                    if (arc == NO_ERROR)
     918                    {
     919                        memset (pBuf, 0, ulCB);
     920                        arc = DosQuerySysState (QS_PROCESS | QS_MTE, 0,
     921                                                Info.ppib->pib_ulpid, 0,
     922                                                pBuf, ulCB);
     923                        if (arc == NO_ERROR)
     924                        {
     925                            QSPTRREC *pPtrRec = (QSPTRREC *) pBuf;
     926                            Info.bHaveSysState = TRUE;
     927                            Info.pProcRec = pPtrRec->pProcRec;
     928                            Info.pLibRec = pPtrRec->pLibRec;
     929                        }
     930                        else if (arc == ERROR_BUFFER_OVERFLOW)
     931                        {
     932                            /* retry with some bigger buffer size */
     933                            DosFreeMem (pBuf);
     934                            pBuf = NULL;
     935                            ulCB *= 2;
     936                            continue;
     937                        }
     938                    }
     939                    break;
     940                }
     941            }
     942       
     943            /* get the main module name */
     944            DosQueryModuleName (Info.ppib->pib_hmte,
     945                                sizeof (szFullExeName), szFullExeName);
     946            {
     947                /* find the base name (w/o path and extension) */
     948                char *psz = strrchr (szFullExeName, '\\');
    732949                if ( psz )
    733950                    ++ psz;
    734951                if ( !psz )
    735                     psz = szExeName;
    736                 strcpy( szExeBase, psz );
    737                 psz = strrchr( szExeBase, '.' );
    738                 if ( psz )
     952                    psz = szFullExeName;
     953                strcpy (szBaseExeName, psz);
     954                psz = strrchr (szBaseExeName, '.');
     955                if (psz)
    739956                    *psz = '\0';
    740             }
    741 
    742             // compose the desired base file name for the log file
    743             // (<datetime>-<exe>)
    744             DosGetDateTime( &dt );
    745             sprintf( szFileName, "%04d%02d%02d%02d%02d%02d-%s",
     957                Info.pszFullName = szFullExeName;
     958                Info.pszBaseName = szBaseExeName;
     959            }
     960           
     961            /* compose the desired base file name for the log file
     962             * (<datetime>-<exe>) */
     963            DosGetDateTime (&dt);
     964            sprintf (szFileName, "%04d%02d%02d%02d%02d%02d-%s",
    746965                     dt.year, dt.month, dt.day,
    747966                     dt.hours, dt.minutes, dt.seconds,
    748                      szExeBase );
     967                     szBaseExeName);
    749968           
    750             // open the log file:
     969            /* open the log file: */
    751970           
    752             // first try the home directory, then the root drive
    753             // (see QDir::homeDirPath())
    754             file = qt_excOpenLogFile( getenv( "HOME" ), szFileName );
    755             if ( file == NULL )
    756             {
    757                 char *pszHomeDrive = getenv( "HOMEDRIVE" );
    758                 char *pszHomePath = getenv( "HOMEPATH" );
    759                 if ( pszHomeDrive && pszHomePath &&
    760                      strlen( pszHomeDrive ) + strlen( pszHomePath ) < CCHMAXPATH )
     971            /* first, try the home directory, then the root drive
     972             * (see QDir::homeDirPath()) */
     973            file = qt_excOpenLogFile (getenv ("HOME"), szFileName);
     974            if (file == NULL)
     975            {
     976                char *pszHomeDrive = getenv ("HOMEDRIVE");
     977                char *pszHomePath = getenv ("HOMEPATH");
     978                if (pszHomeDrive && pszHomePath &&
     979                    strlen (pszHomeDrive) + strlen (pszHomePath) < CCHMAXPATH)
    761980                {
    762                     char szHomePath[CCHMAXPATH];
    763                     strcpy( szHomePath, pszHomeDrive );
    764                     strcat( szHomePath, pszHomePath );
    765                     file = qt_excOpenLogFile( szHomePath, szFileName );
     981                    char szHomePath [CCHMAXPATH];
     982                    strcpy (szHomePath, pszHomeDrive);
     983                    strcat (szHomePath, pszHomePath);
     984                    file = qt_excOpenLogFile (szHomePath, szFileName);
    766985                }
    767986            }
    768             if ( file == NULL )
    769             {
    770                 static char szBootDrive[] = "\0:";
    771                 if ( !szBootDrive[0] )
    772                 {
    773                     ULONG ulBootDrive;
    774                     DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
    775                                      &ulBootDrive, sizeof(ulBootDrive) );
    776                     szBootDrive[0] = (char) ulBootDrive + 'A' - 1;
    777                 }
    778                 file = qt_excOpenLogFile( szBootDrive, szFileName );
    779             }
    780 
    781             if ( file != NULL )
    782             {
    783                 fprintf( file,
    784                         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
    785                         "<!--\n"
    786                         "  A fatal error has occured while running this application.\n"
    787                         "  Please contact the application vendor, describe what happened\n"
    788                         "  and send the contents of this file saved locally as\n"
    789                         "  '%s'.\n"
    790                         "-->\n",
    791                         szFileName );
    792 
    793                 fprintf( file,
     987            if (file == NULL)
     988            {
     989                char szBootDrive[] = "\0:";
     990                ULONG ulBootDrive;
     991                DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE,
     992                                 &ulBootDrive, sizeof(ulBootDrive) );
     993                szBootDrive[0] = (char) ulBootDrive + 'A' - 1;
     994                file = qt_excOpenLogFile (szBootDrive, szFileName);
     995            }
     996
     997            if (file != NULL)
     998            {
     999                fprintf (file,
     1000                         "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
     1001                         "<!--\n"
     1002                         "  A fatal error has occured while running this application.\n"
     1003                         "  Please contact the application vendor, describe what happened\n"
     1004                         "  and send the contents of this file saved locally as\n"
     1005                         "  '%s'.\n"
     1006                         "-->\n",
     1007                         szFileName);
     1008
     1009                fprintf (file,
    7941010                         "<Trap timestamp=\"%04d-%02d-%02dT%02d:%02d:%02d%c%02d:%02d\" "
    7951011                               "version=\"1.0\"\n"
     
    7991015                         dt.hours, dt.minutes, dt.seconds,
    8001016                         (dt.timezone > 0 ? '-' : '+'),
    801                          abs( dt.timezone / 60 ),
    802                          abs( dt.timezone % 60 ),
     1017                         abs (dt.timezone / 60),
     1018                         abs (dt.timezone % 60),
    8031019                         QT_VERSION_STR );
    8041020
    8051021                XcptPvt::file = file;
    8061022               
    807                 // write trap information
    808                 qt_excWriteException( file, szExeName, szExeBase,
    809                                       ppib, ptib, pReportRec, pContextRec );
     1023                /* write trap information */
     1024                qt_excWriteException (file, &Info, pReportRec, pContextRec);
    8101025
    8111026                XcptPvt::file = NULL;
    8121027               
    813                 fprintf( file, "</Trap>\n\n" );
    814                 fclose( file );
     1028                fprintf (file, "</Trap>\n\n");
     1029                fclose (file);
    8151030               
    816                 // attempt to display the created file
     1031                /* attempt to display the created file */
    8171032                {
    8181033                    STARTDATA SData       = {0};
     
    8201035                    ULONG     ulSessID    = 0;
    8211036                   
    822                     SData.Length  = sizeof(STARTDATA);
     1037                    SData.Length  = sizeof (STARTDATA);
    8231038                    SData.PgmName = "E.EXE";
    8241039                    SData.PgmInputs = szFileName;
    8251040                   
    826                     DosStartSession( &SData, &ulSessID, &pid );
     1041                    DosStartSession (&SData, &ulSessID, &pid);
    8271042                }
    8281043            }
    8291044            else
    830                 DosBeep( 220, 200 );
     1045                DosBeep (220, 200);
     1046
     1047            if (pBuf != NULL)
     1048                DosFreeMem (pBuf);
     1049           
     1050            /* reset old priority */
     1051            DosSetPriority (PRTYS_THREAD, (Tib2Orig.tib2_ulpri & 0x0F00) >> 8,
     1052                                          (UCHAR) Tib2Orig.tib2_ulpri,
     1053                                          0);
    8311054        }
    8321055        break;
    8331056    }
    8341057
    835     // we never handle the exception ourselves
    836 
    837     if ( ptib && ptib->tib_ptib2 && ptib->tib_ptib2->tib2_ultid == 1 &&
    838          QtOS2SysXcptMainHandler::libcHandler != NULL )
    839     {
    840         // we are on the main thread and were installed from qt_init() during
    841         // QApplication initialization using a hack; pass control back to the
    842         // LIBC exception handler
    843         return QtOS2SysXcptMainHandler::libcHandler( pReportRec, pRegRec,
    844                                                      pContextRec, pv );
     1058    /* we never handle the exception ourselves */
     1059
     1060    if (Info.ptib->tib_ptib2->tib2_ultid == 1 &&
     1061        QtOS2SysXcptMainHandler::libcHandler != NULL)
     1062    {
     1063        /* we are on the main thread and were installed from qt_init() during
     1064         * QApplication initialization using a hack; pass control back to the
     1065         * LIBC exception handler */
     1066        return QtOS2SysXcptMainHandler::libcHandler (pReportRec, pRegRec,
     1067                                                     pContextRec, pv);
    8451068    }
    8461069   
Note: See TracChangeset for help on using the changeset viewer.