diff options
Diffstat (limited to 'sal/osl/os2/except.c')
-rw-r--r-- | sal/osl/os2/except.c | 1061 |
1 files changed, 0 insertions, 1061 deletions
diff --git a/sal/osl/os2/except.c b/sal/osl/os2/except.c deleted file mode 100644 index 5683aa21c..000000000 --- a/sal/osl/os2/except.c +++ /dev/null @@ -1,1061 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * (a copy is included in the LICENSE file that accompanied this code). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -/* - *@@sourcefile except.c: - * this file contains powerful exception handlers. - * except.h also defines easy-to-use macros for them. - * - * Usage: All OS/2 programs, PM or text mode. - * - * <B>Introduction</B> - * - * OS/2 exception handlers are a mess to program and, - * if installed wrongly, almost impossible to debug. - * The problem is that for any program that does a bit - * more than showing a message box, using exception - * handlers is a must to avoid system hangs. This - * especially applies to multi-thread programs using - * mutex semaphores (more on that below). The functions - * and macros in here are designed to make that more - * simple. - * - * The macros in except.h automatically insert code for - * properly registering and deregistering the handlers - * in except.c. You should ALWAYS use these macros - * instead of directly registering the handlers to avoid - * accidentally forgetting to deregister them. If you - * forget to deregister an exception handler, this can - * lead to really strange errors (crashes, hangs) which - * are nearly impossible to debug because the thread's - * stack probably got completely messed up. - * - * The general idea of these macros is to define - * TRY / CATCH blocks similar to C++. If an exception - * occurs in the TRY block, execution is transferred to - * the CATCH block. (This works in both C and C++, by the - * way.) - * - * The "OnKill" function that was added with V0.9.0 has - * been removed again with V0.9.7. - * - * The general usage is like this: - * - + int your_protected_func(int ...) - + { - + TRY_LOUD(excptid) // or: TRY_QUIET(excptid) - + { - + char *p = NULL; - + - + .... // the stuff in here is protected by - + // the excHandlerLoud or excHandlerQuiet - + // exception handler - + *p = "A"; - + } - + CATCH(excptid) - + { - + .... // exception occurred: react here - + } END_CATCH(); // always needed! - + } // end of your_func - * - * TRY_LOUD is for installing excHandlerLoud. - * TRY_QUIET is for installing excHandlerQuiet. - * CATCH / END_CATCH are the same for the two. This - * is where the exception handler jumps to if an - * exception occurs. - * The CATCH block is _required_ even if you do nothing - * in there, because the CATCH() macro will deregister - * the handler. - * - * "excptid" can be any C identifier which is not used in - * your current variable scope, e.g. "excpt1". This - * is used for creating an EXCEPTSTRUCT variable of - * that name on the stack. The "excptid"'s in TRY_* and - * CATCH must match, since this is where the macros - * store the exception handler data. - * - * These macros may be nested if you use different - * "excptid"'s for sub-macros. - * - * Inside the TRY and CATCH blocks, you must not use - * "goto" (to a location outside the block) or "return", - * because this will not deregister the handler. - * - * Keep in mind that all the code in the TRY_* block is - * protected by the handler, including all functions that - * get called. So if you enclose your main() code in a - * TRY_* block, your entire application is protected. - * If any subfunction fails, execution is transferred to - * the closest CATCH() that was installed (as with C++ - * try and catch). - * - * <B>Asynchronous exceptions</B> - * - * The exception handlers in this file (which are installed - * with the TRY/CATCH mechanism) only intercept synchronous - * exceptions, most importantly, XCPT_ACCESS_VIOLATION (see - * excHandlerLoud for a list). They do not protect your code - * against asynchronous exceptions. - * - * OS/2 defines asynchronous exceptions to be those that - * can be delayed. With OS/2, there are only three of these: - * - * -- XCPT_PROCESS_TERMINATE - * -- XCPT_ASYNC_PROCESS_TERMINATE - * -- XCPT_SIGNAL (thread 1 only) - * - * To protect yourself against these also, put the section - * in question in a DosEnterMustComplete/DosExitMustComplete - * block as well. - * - * <B>Mutex semaphores</B> - * - * The problem with OS/2 mutex semaphores is that they are - * sometimes not automatically released when a thread terminates. - * If there are several mutexes involved and they are released - * in improper order, you can get zombie threads on exit. - * Even worse, if this happens to a PM thread, this will hang - * the system. - * - * As a result, you should protect any section of code which - * requests a semaphore with the exception handlers. - * - * So _whenever_ you request a mutex semaphore, enclose - * the block with TRY/CATCH in case the code crashes. - * Besides, enclose the TRY/CATCH block in a must-complete - * section, like this: - * - + HMTX hmtx = ... - + - + int your_func(int) - + { - + BOOL fSemOwned = FALSE; - + - + TRY_QUIET(excpt1) // or TRY_LOUD - + { - + if (fSemOwned = !DosRequestMutexSem(hmtx, ...)) - + { ... // work on your protected data - + } - + // mutex gets released below - + } - + CATCH(excpt1) { } END_CATCH(); // always needed! - + - + if (fSemOwned) - + // this gets executed always, even if an exception occurred - + DosReleaseMutexSem(hmtx); - + } // end of your_func - * - * This way your mutex semaphore gets released in every - * possible condition. - * - * <B>Customizing</B> - * - * As opposed to versions before 0.9.0, this code is now - * completely independent of XWorkplace. This file now - * contains "pure" exception handlers only. - * - * However, you can customize these exception handlers by - * calling excRegisterHooks. This is what XWorkplace does now. - * This should be done upon initialization of your application. - * If excRegisterHooks is not called, the following safe - * defaults are used: - * - * -- the trap log file is TRAP.LOG in the root - * directory of your boot drive. - * - * For details on the provided exception handlers, refer - * to excHandlerLoud and excHandlerQuiet. - * - * More useful debug information can be found in the "OS/2 Debugging - * Handbook", which is now available in INF format on the IBM - * DevCon site ("http://service2.boulder.ibm.com/devcon/"). - * This book shows worked examples of how to unwind a stack dump. - * - * This file incorporates code from the following: - * -- Monte Copeland, IBM Boca Ration, Florida, USA (1993) - * -- Roman Stangl, from the Program Commander/2 sources - * (1997-98) - * -- Marc Fiammante, John Currier, Kim Rasmussen, - * Anthony Cruise (EXCEPT3.ZIP package for a generic - * exception handling DLL, available at Hobbes). - * - * If not explicitly stated otherwise, the code has been written - * by me, Ulrich M�ller. - * - * Note: Version numbering in this file relates to XWorkplace version - * numbering. - * - *@@header "helpers\except.h" - */ - -/* - * This file Copyright (C) 1992-99 Ulrich M�ller, - * Monte Copeland, - * Roman Stangl, - * Kim Rasmussen, - * Marc Fiammante, - * John Currier, - * Anthony Cruise. - * This file is part of the "XWorkplace helpers" source package. - * - * 2009-06-15 published under LGPL3 with Ulrich M�ller permission. - * - */ - -#define OS2EMX_PLAIN_CHAR - // this is needed for "os2emx.h"; if this is defined, - // emx will define PSZ as _signed_ char, otherwise - // as unsigned char - -#define INCL_DOSMODULEMGR -#define INCL_DOSEXCEPTIONS -#define INCL_DOSPROCESS -#define INCL_DOSMISC -#define INCL_DOSERRORS -#include <os2.h> - -// C library headers -#include <stdio.h> // needed for except.h -#include <stdlib.h> -#include <time.h> -#include <string.h> -#include <setjmp.h> // needed for except.h -#include <assert.h> // needed for except.h - -#define DONT_REPLACE_MALLOC -#include "helpers\setup.h" // code generation and debugging options - -// headers in /helpers -#include "helpers\dosh.h" // Control Program helper routines -#include "helpers\except.h" // exception handling -#include "helpers\debug.h" // symbol/debug code analysis - -#pragma hdrstop - -/* ****************************************************************** - * - * Global variables - * - ********************************************************************/ - -// hooks to be registered using excRegisterHooks -PFNEXCOPENFILE G_pfnExcOpenFile = 0; -PFNEXCHOOK G_pfnExcHook = 0; -PFNEXCHOOKERROR G_pfnExcHookError = 0; -// beep flag for excHandlerLoud -BOOL G_fBeepOnException = TRUE; - -ULONG G_ulExplainExceptionRunning = 0; - // global flag which is != 0 if some exception handler - // is inside excExplainException, so that XShutdown can - // wait until the trap log is done; - // this is exported thru except.h - // V0.9.13 (2001-06-19) [umoeller] - -/* - *@@category: Helpers\Control program helpers\Exceptions/debugging - * See except.c. - */ - -/* ****************************************************************** - * - * Exception helper routines - * - ********************************************************************/ - -/* - *@@ excDescribePage: - * - */ - -VOID excDescribePage(FILE *file, ULONG ulCheck) -{ - APIRET arc; - ULONG ulCountPages = 1; - ULONG ulFlagsPage = 0; - arc = DosQueryMem((PVOID)ulCheck, &ulCountPages, &ulFlagsPage); - - if (arc == NO_ERROR) - { - fprintf(file, "valid, flags: "); - if (ulFlagsPage & PAG_READ) - fprintf(file, "read "); - if (ulFlagsPage & PAG_WRITE) - fprintf(file, "write "); - if (ulFlagsPage & PAG_EXECUTE) - fprintf(file, "execute "); - if (ulFlagsPage & PAG_GUARD) - fprintf(file, "guard "); - if (ulFlagsPage & PAG_COMMIT) - fprintf(file, "committed "); - if (ulFlagsPage & PAG_SHARED) - fprintf(file, "shared "); - if (ulFlagsPage & PAG_FREE) - fprintf(file, "free "); - if (ulFlagsPage & PAG_BASE) - fprintf(file, "base "); - } - else if (arc == ERROR_INVALID_ADDRESS) - fprintf(file, "invalid"); -} - -/* - *@@ excPrintStackFrame: - * wrapper for dbgPrintStackFrame to format - * output stuff right. - * - *@@added V0.9.2 (2000-03-10) [umoeller] - *@@changed V0.9.12 (2001-05-12) [umoeller]: added seg:ofs to output always - */ - -VOID excPrintStackFrame(FILE *file, // in: output log file - PSZ pszDescription, // in: description for stack frame (should be eight chars) - ULONG ulAddress) // in: address to debug -{ - APIRET arc = NO_ERROR; - HMODULE hmod1 = NULLHANDLE; - CHAR szMod1[2*CCHMAXPATH] = "unknown"; - ULONG ulObject = 0, - ulOffset = 0; - fprintf(file, - " %-8s: %08lX ", - pszDescription, - ulAddress); - arc = DosQueryModFromEIP(&hmod1, - &ulObject, - sizeof(szMod1), szMod1, - &ulOffset, - ulAddress); - - if (arc != NO_ERROR) - { - // error: - fprintf(file, - " %-8s Error: DosQueryModFromEIP returned %lu\n", - szMod1, - arc); - } - else - { - CHAR szFullName[2*CCHMAXPATH]; - - fprintf(file, - " %-8s %02lX:%08lX\n ", - szMod1, - ulObject + 1, // V0.9.12 (2001-05-12) [umoeller] - ulOffset); // V0.9.12 (2001-05-12) [umoeller] - - DosQueryModuleName(hmod1, sizeof(szFullName), szFullName); - dbgPrintStackFrame(file, - szFullName, - ulObject, - ulOffset); - - fprintf(file, "\n"); - - // make a 'tick' sound to let the user know we're still alive - DosBeep(2000, 10); - } -} - -/* - *@@ excDumpStackFrames: - * called from excExplainException to dump the - * thread's stack frames. This calls excPrintStackFrame - * for each stack frame found. - * - *@@added V0.9.4 (2000-06-15) [umoeller] - */ - -VOID excDumpStackFrames(FILE *file, // in: logfile from fopen() - PTIB ptib, - PCONTEXTRECORD pContextRec) // in: excpt info -{ - PULONG pulStackWord = 0; - - fprintf(file, "\n\nStack frames:\n Address Module seg:ofs\n"); - - // first the trapping address itself - excPrintStackFrame(file, - "CS:EIP ", - pContextRec->ctx_RegEip); - - - pulStackWord = (PULONG)pContextRec->ctx_RegEbp; - /* if (pContextRec->ctx_RegEbp < pContextRec->ctx_RegEsp) - pulStackWord = (PULONG)(pContextRec->ctx_RegEbp & 0xFFFFFFF0); - else - pulStackWord = (PULONG)(pContextRec->ctx_RegEsp & 0xFFFFFFF0); */ - - while ( (pulStackWord != 0) - && (pulStackWord < (PULONG)ptib->tib_pstacklimit) - ) - { - CHAR szAddress[20]; - - if (((ULONG)pulStackWord & 0x00000FFF) == 0x00000000) - { - // we're on a page boundary: check access - ULONG ulCountPages = 0x1000; - ULONG ulFlagsPage = 0; - APIRET arc = DosQueryMem((void *)pulStackWord, - &ulCountPages, - &ulFlagsPage); - if ( (arc != NO_ERROR) - || ( (arc == NO_ERROR) - && ( !( ((ulFlagsPage & (PAG_COMMIT|PAG_READ)) - == (PAG_COMMIT|PAG_READ) - ) - ) - ) - ) - ) - { - fprintf(file, "\n %08lX: ", (ULONG)pulStackWord); - fprintf(file, "Page inaccessible"); - pulStackWord += 0x1000; - continue; // for - } - } - - sprintf(szAddress, "%08lX", - (ULONG)pulStackWord); - excPrintStackFrame(file, - szAddress, - *(pulStackWord+1)); - pulStackWord = (PULONG)*(pulStackWord); - - if (pulStackWord == 0) - fprintf(file, "\n pulStackWord == 0"); - else if (pulStackWord >= (PULONG)ptib->tib_pstacklimit) - fprintf(file, "\n pulStackWord >= (PULONG)ptib->tib_pstacklimit"); - } // end while -} - -/* - *@@ excExplainException: - * used by the exception handlers below to write - * LOTS of information about the exception into a logfile. - * - * This calls excPrintStackFrame for each stack frame. - * - *@@changed V0.9.0 [umoeller]: added support for application hook - *@@changed V0.9.0 (99-11-02) [umoeller]: added TID to dump - *@@changed V0.9.2 (2000-03-10) [umoeller]: now using excPrintStackFrame - *@@changed V0.9.3 (2000-05-03) [umoeller]: fixed crashes - *@@changed V0.9.6 (2000-11-06) [umoeller]: added more register dumps - *@@changed V0.9.13 (2001-06-19) [umoeller]: added global flag for whether this is running - *@@changed V0.9.16 (2001-11-02) [pr]: make object display signed - *@@changed V0.9.19 (2002-03-28) [umoeller]: added thread ordinal - */ - -VOID excExplainException(FILE *file, // in: logfile from fopen() - PSZ pszHandlerName, // in: descriptive string - PEXCEPTIONREPORTRECORD pReportRec, // in: excpt info - PCONTEXTRECORD pContextRec) // in: excpt info -{ - ULONG aulBuf[3]; - const char *pcszVersion = "unknown"; - - PTIB ptib = NULL; - PPIB ppib = NULL; - HMODULE hMod1, hMod2; - CHAR szMod1[CCHMAXPATH] = "unknown", - szMod2[CCHMAXPATH] = "unknown"; - ULONG ulObjNum, - ulOffset; - ULONG ul; - - ULONG ulOldPriority = 0x0100; // regular, delta 0 - - // raise global flag for whether this func is running - // V0.9.13 (2001-06-19) [umoeller] - G_ulExplainExceptionRunning++; - - // raise this thread's priority, because this - // might take some time - if (DosGetInfoBlocks(&ptib, &ppib) == NO_ERROR) - if (ptib) - if (ptib->tib_ptib2) - { - ulOldPriority = ptib->tib_ptib2->tib2_ulpri; - DosSetPriority(PRTYS_THREAD, - PRTYC_REGULAR, - PRTYD_MAXIMUM, - 0); // current thread - } - - // make some noise -#ifndef __NOEXCEPTIONBEEPS__ // V0.9.19 (2002-04-17) [umoeller] - if (G_fBeepOnException) - { - DosBeep( 250, 30); - DosBeep( 500, 30); - DosBeep(1000, 30); - DosBeep(2000, 30); - DosBeep(4000, 30); - DosBeep(2000, 30); - DosBeep(1000, 30); - DosBeep( 500, 30); - DosBeep( 250, 30); - } -#endif - - // generic exception info - DosQuerySysInfo(QSV_VERSION_MAJOR, // 11 - QSV_VERSION_MINOR, // 12 - &aulBuf, sizeof(aulBuf)); - // Warp 3 is reported as 20.30 - // Warp 4 is reported as 20.40 - // Aurora is reported as 20.45 - - if (aulBuf[0] == 20) - { - switch (aulBuf[1]) - { - case 30: pcszVersion = "Warp 3"; break; - case 40: pcszVersion = "Warp 4"; break; - case 45: pcszVersion = "WSeB kernel"; break; - } - } - fprintf(file, - "Running OS/2 version: %u.%u (%s)\n", - aulBuf[0], // major - aulBuf[1], - pcszVersion); - - - // generic exception info - fprintf(file, - "\n%s:\n Exception type: %08lX\n Address: %08lX\n Params: ", - pszHandlerName, - pReportRec->ExceptionNum, - (ULONG)pReportRec->ExceptionAddress); - for (ul = 0; ul < pReportRec->cParameters; ul++) - { - fprintf(file, "%08lX ", - pReportRec->ExceptionInfo[ul]); - } - - // now explain the exception in a bit more detail; - // depending on the exception, pReportRec->ExceptionInfo - // contains some useful data - switch (pReportRec->ExceptionNum) - { - case XCPT_ACCESS_VIOLATION: - fprintf(file, "\nXCPT_ACCESS_VIOLATION: "); - if (pReportRec->ExceptionInfo[0] & XCPT_READ_ACCESS) - fprintf(file, "Invalid read access from 0x%04lX:%08lX.\n", - pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]); - else if (pReportRec->ExceptionInfo[0] & XCPT_WRITE_ACCESS) - fprintf(file, "Invalid write access to 0x%04lX:%08lX.\n", - pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]); - else if (pReportRec->ExceptionInfo[0] & XCPT_SPACE_ACCESS) - fprintf(file, "Invalid space access at 0x%04lX.\n", - pReportRec->ExceptionInfo[1]); - else if (pReportRec->ExceptionInfo[0] & XCPT_LIMIT_ACCESS) - fprintf(file, "Invalid limit access occurred.\n"); - else if (pReportRec->ExceptionInfo[0] == XCPT_UNKNOWN_ACCESS) - fprintf(file, "unknown at 0x%04lX:%08lX\n", - pContextRec->ctx_SegDs, pReportRec->ExceptionInfo[1]); - fprintf(file, - "Explanation: An attempt was made to access a memory object which does\n" - " not belong to the current process. Most probable causes\n" - " for this are that an invalid pointer was used, there was\n" - " confusion with administering memory or error conditions \n" - " were not properly checked for.\n"); - break; - - case XCPT_INTEGER_DIVIDE_BY_ZERO: - fprintf(file, "\nXCPT_INTEGER_DIVIDE_BY_ZERO.\n"); - fprintf(file, - "Explanation: An attempt was made to divide an integer value by zero,\n" - " which is not defined.\n"); - break; - - case XCPT_ILLEGAL_INSTRUCTION: - fprintf(file, "\nXCPT_ILLEGAL_INSTRUCTION.\n"); - fprintf(file, - "Explanation: An attempt was made to execute an instruction that\n" - " is not defined on this machine's architecture.\n"); - break; - - case XCPT_PRIVILEGED_INSTRUCTION: - fprintf(file, "\nXCPT_PRIVILEGED_INSTRUCTION.\n"); - fprintf(file, - "Explanation: An attempt was made to execute an instruction that\n" - " is not permitted in the current machine mode or that\n" - " the program had no permission to execute.\n"); - break; - - case XCPT_INTEGER_OVERFLOW: - fprintf(file, "\nXCPT_INTEGER_OVERFLOW.\n"); - fprintf(file, - "Explanation: An integer operation generated a carry-out of the most\n" - " significant bit. This is a sign of an attempt to store\n" - " a value which does not fit into an integer variable.\n"); - break; - - default: - fprintf(file, "\nUnknown OS/2 exception number %d.\n", pReportRec->ExceptionNum); - fprintf(file, "Look this up in the OS/2 header files.\n"); - break; - } - - // V0.9.16 (2001-11-02) [pr]: We already got this info. above - this overwrites the - // original values before the priority change, which is rather confusing. - // if (DosGetInfoBlocks(&ptib, &ppib) == NO_ERROR) - { - /* - * process info: - * - */ - - if ((ptib) && (ppib)) // (99-11-01) [umoeller] - { - if (pContextRec->ContextFlags & CONTEXT_CONTROL) - { - // get the main module - hMod1 = ppib->pib_hmte; - DosQueryModuleName(hMod1, - sizeof(szMod1), - szMod1); - - // get the trapping module - DosQueryModFromEIP(&hMod2, - &ulObjNum, - sizeof(szMod2), - szMod2, - &ulOffset, - pContextRec->ctx_RegEip); - DosQueryModuleName(hMod2, - sizeof(szMod2), - szMod2); - } - - fprintf(file, - "\nProcess information:" - "\n Process ID: 0x%lX" - "\n Process module: 0x%lX (%s)" - "\n Trapping module: 0x%lX (%s)" - "\n Object: %ld\n", // V0.9.16 (2001-11-02) [pr]: make this display signed - ppib->pib_ulpid, - hMod1, szMod1, - hMod2, szMod2, - ulObjNum); - - fprintf(file, - "\nTrapping thread information:" - "\n Thread ID: 0x%lX (%lu)" - "\n Thread slot ID: 0x%lX (%lu)" // added V0.9.19 (2002-03-28) [umoeller] - "\n Priority: 0x%lX\n", - ptib->tib_ptib2->tib2_ultid, ptib->tib_ptib2->tib2_ultid, - ptib->tib_ordinal, ptib->tib_ordinal, - ulOldPriority); - } - else - fprintf(file, "\nProcess information was not available."); - - /* - * now call the hook, if one has been defined, - * so that the application can write additional - * information to the traplog (V0.9.0) - */ - - if (G_pfnExcHook) - G_pfnExcHook(file, ptib, ulOldPriority); // V0.9.16 (2001-12-02) [pr] - - // *** registers - - fprintf(file, "\nRegisters:"); - if (pContextRec->ContextFlags & CONTEXT_INTEGER) - { - // DS the following 4 added V0.9.6 (2000-11-06) [umoeller] - fprintf(file, "\n DS = %08lX ", pContextRec->ctx_SegDs); - excDescribePage(file, pContextRec->ctx_SegDs); - // ES - fprintf(file, "\n ES = %08lX ", pContextRec->ctx_SegEs); - excDescribePage(file, pContextRec->ctx_SegEs); - // FS - fprintf(file, "\n FS = %08lX ", pContextRec->ctx_SegFs); - excDescribePage(file, pContextRec->ctx_SegFs); - // GS - fprintf(file, "\n GS = %08lX ", pContextRec->ctx_SegGs); - excDescribePage(file, pContextRec->ctx_SegGs); - - // EAX - fprintf(file, "\n EAX = %08lX ", pContextRec->ctx_RegEax); - excDescribePage(file, pContextRec->ctx_RegEax); - // EBX - fprintf(file, "\n EBX = %08lX ", pContextRec->ctx_RegEbx); - excDescribePage(file, pContextRec->ctx_RegEbx); - // ECX - fprintf(file, "\n ECX = %08lX ", pContextRec->ctx_RegEcx); - excDescribePage(file, pContextRec->ctx_RegEcx); - // EDX - fprintf(file, "\n EDX = %08lX ", pContextRec->ctx_RegEdx); - excDescribePage(file, pContextRec->ctx_RegEdx); - // ESI - fprintf(file, "\n ESI = %08lX ", pContextRec->ctx_RegEsi); - excDescribePage(file, pContextRec->ctx_RegEsi); - // EDI - fprintf(file, "\n EDI = %08lX ", pContextRec->ctx_RegEdi); - excDescribePage(file, pContextRec->ctx_RegEdi); - fprintf(file, "\n"); - } - else - fprintf(file, " not available\n"); - - if (pContextRec->ContextFlags & CONTEXT_CONTROL) - { - - // *** instruction - - fprintf(file, "Instruction pointer (where exception occurred):\n CS:EIP = %04lX:%08lX ", - pContextRec->ctx_SegCs, - pContextRec->ctx_RegEip); - excDescribePage(file, pContextRec->ctx_RegEip); - - // *** CPU flags - - fprintf(file, "\n EFLAGS = %08lX", pContextRec->ctx_EFlags); - - /* - * stack: - * - */ - - fprintf(file, "\nStack:\n Base: %08lX\n Limit: %08lX", - (ULONG)(ptib ? ptib->tib_pstack : 0), - (ULONG)(ptib ? ptib->tib_pstacklimit : 0)); - fprintf(file, "\n SS:ESP = %04lX:%08lX ", - pContextRec->ctx_SegSs, - pContextRec->ctx_RegEsp); - excDescribePage(file, pContextRec->ctx_RegEsp); - - fprintf(file, "\n EBP = %08lX ", pContextRec->ctx_RegEbp); - excDescribePage(file, pContextRec->ctx_RegEbp); - - /* - * stack dump: - */ - - if (ptib != 0) - { - excDumpStackFrames(file, ptib, pContextRec); - } - } - } - fprintf(file, "\n"); - - // reset old priority - DosSetPriority(PRTYS_THREAD, - (ulOldPriority & 0x0F00) >> 8, - (UCHAR)ulOldPriority, - 0); // current thread - - // lower global flag again V0.9.13 (2001-06-19) [umoeller] - G_ulExplainExceptionRunning--; -} - -/* ****************************************************************** - * - * Exported routines - * - ********************************************************************/ - -/* - *@@ excRegisterHooks: - * this registers hooks which get called for - * exception handlers. You can set any of the - * hooks to NULL for safe defaults (see top of - * except.c for details). You can set none, - * one, or both of the hooks, and you can call - * this function several times. - * - * Both hooks get called whenever an exception - * occurs, so there better be no bugs in these - * routines. ;-) They only get called from - * within excHandlerLoud (because excHandlerQuiet - * writes no trap logs). - * - * The hooks are as follows: - * - * -- pfnExcOpenFileNew gets called to open - * the trap log file. This must return a FILE* - * pointer from fopen(). If this is not defined, - * ?:\TRAP.LOG is used. Use this to specify a - * different file and have some notes written - * into it before the actual exception info. - * - * -- pfnExcHookNew gets called while the trap log - * is being written. At this point, - * the following info has been written into - * the trap log already: - * -- exception type/address block - * -- exception explanation - * -- process information - * - * _After_ the hook, the exception handler - * continues with the "Registers" information - * and stack dump/analysis. - * - * Use this hook to write additional application - * info into the trap log, such as the state - * of your own threads and mutexes. - * - * -- pfnExcHookError gets called when the TRY_* macros - * fail to install an exception handler (when - * DosSetExceptionHandler fails). I've never seen - * this happen. - * - *@@added V0.9.0 [umoeller] - *@@changed V0.9.2 (2000-03-10) [umoeller]: pfnExcHookError added - */ - -VOID excRegisterHooks(PFNEXCOPENFILE pfnExcOpenFileNew, - PFNEXCHOOK pfnExcHookNew, - PFNEXCHOOKERROR pfnExcHookError, - BOOL fBeepOnExceptionNew) -{ - // adjust the global variables - G_pfnExcOpenFile = pfnExcOpenFileNew; - G_pfnExcHook = pfnExcHookNew; - G_pfnExcHookError = pfnExcHookError; - G_fBeepOnException = fBeepOnExceptionNew; -} - -/* - *@@ excHandlerLoud: - * this is the "sophisticated" exception handler; - * which gives forth a loud sequence of beeps thru the - * speaker, writes a trap log and then returns back - * to the thread to continue execution, i.e. the - * default OS/2 exception handler will never get - * called. - * - * This requires a setjmp() call on - * EXCEPTIONREGISTRATIONRECORD2.jmpThread before - * being installed. The TRY_LOUD macro will take - * care of this for you (see except.c). - * - * This intercepts the following exceptions (see - * the OS/2 Control Program Reference for details): - * - * -- XCPT_ACCESS_VIOLATION (traps 0x0d, 0x0e) - * -- XCPT_INTEGER_DIVIDE_BY_ZERO (trap 0) - * -- XCPT_ILLEGAL_INSTRUCTION (trap 6) - * -- XCPT_PRIVILEGED_INSTRUCTION - * -- XCPT_INTEGER_OVERFLOW (trap 4) - * - * For these exceptions, we call the functions in debug.c - * to try to find debug code or SYM file information about - * what source code corresponds to the error. - * - * See excRegisterHooks for the default setup of this. - * - * Note that to get meaningful debugging information - * in this handler's traplog, you need the following: - * - * a) have a MAP file created at link time (/MAP) - * - * b) convert the MAP to a SYM file using MAPSYM - * - * c) put the SYM file in the same directory of - * the module (EXE or DLL). This must have the - * same filestem as the module. - * - * All other exceptions are passed to the next handler - * in the exception handler chain. This might be the - * C/C++ compiler handler or the default OS/2 handler, - * which will probably terminate the process. - * - *@@changed V0.9.0 [umoeller]: added support for thread termination - *@@changed V0.9.2 (2000-03-10) [umoeller]: switched date format to ISO - *@@changed V0.9.19 (2002-05-07) [umoeller]: added EXCEPTIONREPORTRECORD info so that catch block can check that - */ - -ULONG _System excHandlerLoud(PEXCEPTIONREPORTRECORD pReportRec, - PEXCEPTIONREGISTRATIONRECORD2 pRegRec2, - PCONTEXTRECORD pContextRec, - PVOID pv) -{ - /* From the VAC++3 docs: - * "The first thing an exception handler should do is check the - * exception flags. If EH_EXIT_UNWIND is set, meaning - * the thread is ending, the handler tells the operating system - * to pass the exception to the next exception handler. It does the - * same if the EH_UNWINDING flag is set, the flag that indicates - * this exception handler is being removed. - * The EH_NESTED_CALL flag indicates whether the exception - * occurred within an exception handler. If the handler does - * not check this flag, recursive exceptions could occur until - * there is no stack remaining." - * So for all these conditions, we exit immediately. - */ - - if (pReportRec->fHandlerFlags & EH_EXIT_UNWIND) - return (XCPT_CONTINUE_SEARCH); - if (pReportRec->fHandlerFlags & EH_UNWINDING) - return (XCPT_CONTINUE_SEARCH); - if (pReportRec->fHandlerFlags & EH_NESTED_CALL) - return (XCPT_CONTINUE_SEARCH); - - switch (pReportRec->ExceptionNum) - { - case XCPT_ACCESS_VIOLATION: - case XCPT_INTEGER_DIVIDE_BY_ZERO: - case XCPT_ILLEGAL_INSTRUCTION: - case XCPT_PRIVILEGED_INSTRUCTION: - case XCPT_INVALID_LOCK_SEQUENCE: - case XCPT_INTEGER_OVERFLOW: - { - // "real" exceptions: - FILE *file; - - // open traplog file; - if (G_pfnExcOpenFile) - // hook defined for this: call it - file = (*G_pfnExcOpenFile)(); - else - { - CHAR szFileName[100]; - // no hook defined: open some - // default traplog file in root directory of - // boot drive - sprintf(szFileName, "%c:\\trap.log", doshQueryBootDrive()); - file = fopen(szFileName, "a"); - - if (file) - { - DATETIME DT; - DosGetDateTime(&DT); - fprintf(file, - "\nTrap message -- Date: %04d-%02d-%02d, Time: %02d:%02d:%02d\n", - DT.year, DT.month, DT.day, - DT.hours, DT.minutes, DT.seconds); - fprintf(file, "------------------------------------------------\n"); - - } - } - - // write error log - excExplainException(file, - "excHandlerLoud", - pReportRec, - pContextRec); - fclose(file); - - // copy report rec to user buffer - // V0.9.19 (2002-05-07) [umoeller] - memcpy(&pRegRec2->err, - pReportRec, - sizeof(EXCEPTIONREPORTRECORD)); - - // jump back to failing routine - longjmp(pRegRec2->jmpThread, pReportRec->ExceptionNum); - break; } - } - - // not handled - return (XCPT_CONTINUE_SEARCH); -} - -/* - *@@ excHandlerQuiet: - * "quiet" xcpt handler, which simply suppresses exceptions; - * this is useful for certain error-prone functions, where - * exceptions are likely to appear, for example used by - * wpshCheckObject to implement a fail-safe SOM object check. - * - * This does _not_ write an error log and makes _no_ sound. - * This simply jumps back to the trapping thread or - * calls EXCEPTIONREGISTRATIONRECORD2.pfnOnKill. - * - * Other than that, this behaves like excHandlerLoud. - * - * This is best registered thru the TRY_QUIET macro - * (new with V0.84, described in except.c), which - * does the necessary setup. - * - *@@changed V0.9.0 [umoeller]: added support for thread termination - *@@changed V0.9.19 (2002-05-07) [umoeller]: added EXCEPTIONREPORTRECORD info so that catch block can check that - */ - -ULONG _System excHandlerQuiet(PEXCEPTIONREPORTRECORD pReportRec, - PEXCEPTIONREGISTRATIONRECORD2 pRegRec2, - PCONTEXTRECORD pContextRec, - PVOID pv) -{ - if (pReportRec->fHandlerFlags & EH_EXIT_UNWIND) - return (XCPT_CONTINUE_SEARCH); - if (pReportRec->fHandlerFlags & EH_UNWINDING) - return (XCPT_CONTINUE_SEARCH); - if (pReportRec->fHandlerFlags & EH_NESTED_CALL) - return (XCPT_CONTINUE_SEARCH); - - switch (pReportRec->ExceptionNum) - { - case XCPT_ACCESS_VIOLATION: - case XCPT_INTEGER_DIVIDE_BY_ZERO: - case XCPT_ILLEGAL_INSTRUCTION: - case XCPT_PRIVILEGED_INSTRUCTION: - case XCPT_INVALID_LOCK_SEQUENCE: - case XCPT_INTEGER_OVERFLOW: - // write excpt explanation only if the - // resp. debugging #define is set (setup.h) - #ifdef DEBUG_WRITEQUIETEXCPT - { - FILE *file = excOpenTraplogFile(); - excExplainException(file, - "excHandlerQuiet", - pReportRec, - pContextRec); - fclose(file); - } - #endif - - // copy report rec to user buffer - // V0.9.19 (2002-05-07) [umoeller] - memcpy(&pRegRec2->err, - pReportRec, - sizeof(EXCEPTIONREPORTRECORD)); - - // jump back to failing routine - longjmp(pRegRec2->jmpThread, pReportRec->ExceptionNum); - break; - - default: - break; - } - - return (XCPT_CONTINUE_SEARCH); -} - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |