excptwnt.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 512 行 · 第 1/2 页

C
512
字号
    if( context->ContextFlags & CONTEXT_SEGMENTS ) {
        fmt_hex( buff, "DS =0x00000000 ", (void *)context->SegDs );
        fmt_hex( buff, "ES =0x00000000 ", (void *)context->SegEs );
        fmt_hex( buff, "FS =0x00000000 ", (void *)context->SegFs );
        fmt_hex( buff, "GS =0x00000000\n", (void *)context->SegGs );
    }
    WriteFile( NT_STDERR_FILENO, buff, strlen(buff), &written, NULL );
    buff[0] = '\0';
    if( context->ContextFlags & CONTEXT_CONTROL ) {
        sp = (DWORD *)context->Esp;
        fmt_hex( buff, "Stack dump (SS:ESP)\n", 0 );
        for( i = 1; i <= 72; i++) {
            if(( (long)sp & 0x0000FFFF ) == 0 ) {
                fmt_hex( buff, "-stack end\n", 0 );
            } else {
                fmt_hex( buff, "0x00000000 ", GetFromSS( sp ) );
            }
            if(( i % 6 ) == 0 ) {
                fmt_hex( buff, "\n", 0 );
            }
            WriteFile( NT_STDERR_FILENO, buff, strlen( buff ), &written, NULL );
            buff[0] = '\0';
            if(( (long)sp & 0x0000FFFF ) == 0 )
                break;
            sp++;
        }
    }
#endif

    return( EXCEPTION_EXECUTE_HANDLER );
}


void __DefaultExceptionHandler( void )
{
    LPTOP_LEVEL_EXCEPTION_FILTER top_filter;

    // This routine is called whenever a new process begins.
    // Install an exception handler and then check to see if we already
    // have one. If we did, set it back to the previous one. This ensures
    // we always have one set up and permits apps to install their own.

    top_filter = SetUnhandledExceptionFilter( __ReportException );
    if( top_filter != NULL ) {
        SetUnhandledExceptionFilter( top_filter );
    }
}


// Note: this needs to be cdecl for Win32s and Windows 95
//       Windows NT doesn't care if it is cdecl or stdcall

int __cdecl __ExceptionFilter( LPEXCEPTION_RECORD ex,
                               LPVOID establisher_frame,
                               LPCONTEXT context,
                               LPVOID dispatch_context )
{
    int          sig;
    int          fpe;
#if defined( _M_IX86 )
    char        *eip;
    status_word  sw;
    DWORD        tw;
#endif
    EXCEPTION_POINTERS rec;
    LONG         rv;

    /*
     * unused parms
     */
    dispatch_context  = dispatch_context;
    establisher_frame = establisher_frame;

    /*
     * Test some conditions we can immediately resolve.
     */
    if( ex->ExceptionFlags & UNWINDING )
        return( ExceptionContinueSearch );

    /*
     * Lets see what caused the exception.
     */
    switch( ex->ExceptionCode ) {
#if defined( _M_IX86 )
    case STATUS_FLOAT_STACK_CHECK:
        if( context->FloatSave.StatusWord & SW_C1 ) {
            fpe = FPE_STACKOVERFLOW;
        } else {
            fpe = FPE_STACKUNDERFLOW;
        }
        break;
#elif defined( __AXP__ )
        // no alpha specific floating point exceptions
#elif defined( __PPC__ )
        // no ppc specific floating point exceptions
#else
#error *** Platform Not Supported ***
#endif

    case STATUS_FLOAT_DENORMAL_OPERAND:
        fpe = FPE_DENORMAL;
        break;
    case STATUS_FLOAT_DIVIDE_BY_ZERO:
        fpe = FPE_ZERODIVIDE;
        break;
    case STATUS_FLOAT_INEXACT_RESULT:
        fpe = FPE_INEXACT;
        break;
    case STATUS_FLOAT_OVERFLOW:
        fpe = FPE_OVERFLOW;
        break;
    case STATUS_FLOAT_UNDERFLOW:
        fpe = FPE_UNDERFLOW;
        break;
    case STATUS_FLOAT_INVALID_OPERATION:
        fpe = FPE_INVALID;
#if defined( _M_IX86 )
        eip = (unsigned char *)context->FloatSave.ErrorOffset;

        if( *(unsigned short *)eip == 0xfad9 ) {        // caused by "fsqrt"
            fpe = FPE_SQRTNEG;
        } else if( *(unsigned short *)eip == 0xf1d9 ) { // caused by "fyl2x"
            fpe = FPE_LOGERR;
        } else if( *(unsigned short *)eip == 0xf8d9 ) { // caused by "fprem"
            fpe = FPE_MODERR;
        } else if( *(unsigned short *)eip == 0xf5d9 ) { // caused by "fprem1"
            fpe = FPE_MODERR;
        } else {
            if(( eip[0] == 0xdb ) || ( eip[0] == 0xdf )) {
                if(( eip[1] & 0x30 ) == 0x10 ) {        // caused by "fist(p)"
                    fpe = FPE_IOVERFLOW;
                }
            }
            if( !( eip[0] & 0x01 ) ) {
                if(( eip[1] & 0x30 ) == 0x30 ) {        // "fdiv" or "fidiv"
                    tw    = context->FloatSave.TagWord & 0x0000ffff;
                    sw.sw = context->FloatSave.StatusWord & 0x0000ffff;

                    if((( tw >> (sw.b.st << 1) ) & 0x01 ) == 0x01 ) {
                        fpe = FPE_ZERODIVIDE;
                    }
                }
            }
        }
#endif
        break;
    default:
        fpe = -1;
        break;
    }

    /*
     * If fpe != -1 then we have an identified floating point exception.
     * If there is a handler, invoke it.
     */
    if( fpe != -1 ) {
        __ExceptionHandled = 1;
        _ClearFPE();

        if( __sigfpe_handler( fpe ) != -1 ) {
            if( __ExceptionHandled ) {
#if defined( _M_IX86 )
                context->FloatSave.StatusWord &=
                    ~( SW_BUSY | SW_XCPT_FLAGS | SW_IREQ );
#elif defined( __AXP__ )
                ((unsigned long *)&context->Fpcr)[1] &=
                    ~(FPCR_SUMMARY_BIT | FPCR_XCPT_FLAGS);
#elif defined( __PPC__ )
                // Can we do something here?
#else
#error *** Platform Not Supported ***
#endif
                return( ExceptionContinueExecution );
            }
        }
    } else if( __raise_func ) {
        /*
         * If the signal handling code is linked in then we need to see if the
         * user has installed a signal handler.
         */
        __sig_func  func;

        for( sig = 1; sig <= __SIGLAST; sig++ ) {
            func = __oscode_check_func( sig, ex->ExceptionCode );
            if( func != NULL ) {
                if(( func == SIG_IGN ) || ( func == SIG_DFL ) || ( func == SIG_ERR )) {
                    break;
                }
                __ExceptionHandled = 1;
                (*__raise_func)( sig );
                if( __ExceptionHandled ) { // User has fixed up state
                    return( ExceptionContinueExecution );
                }
            }
        }
    }

    rec.ExceptionRecord = ex;
    rec.ContextRecord   = context;

    __ReportInvoked = 0;    // indicate our own last-chance handler has not run

    // Call __ReportException or an application-installed handler.
    // NOTE: if running under a debugger, the handler will NOT be called
    //       and it returns EXCEPTION_CONTINUE_SEARCH
    //
    // Possible rv values:
    //   -1 => EXCEPTION_CONTINUE_EXECUTION
    //    0 => EXCEPTION_CONTINUE_SEARCH
    //   +1 => EXCEPTION_EXECUTE_HANDLER
    //

    rv = UnhandledExceptionFilter( &rec );
    if( rv == EXCEPTION_EXECUTE_HANDLER ) {
        ExitProcess( -1 );
    } else if( rv == EXCEPTION_CONTINUE_EXECUTION ) {
        return( ExceptionContinueExecution );
    }
    return( ExceptionContinueSearch );
}


void __NewExceptionFilter( REGISTRATION_RECORD *rr )
{
    // This routine is called whenever a new process/thread begins.

    __XCPTHANDLER = rr;
#if defined( __386__ )
    rr->RegistrationRecordPrev = (LPVOID)GetFromFS( 0 );
    rr->RegistrationRecordFilter = __ExceptionFilter;
    PutToFS( (DWORD)rr, 0 );
#elif defined( __AXP__ )
    // __ExceptionFilter() installed in __NTMain()'s pdata
#elif defined( __PPC__ )
    // No idea yet.
#endif

}

void __DoneExceptionFilter( void )
{
#if defined( __386__ )
    REGISTRATION_RECORD *rr;
    rr = __XCPTHANDLER;
    if( rr ) {
        PutToFS( (DWORD)rr->RegistrationRecordPrev, 0 );
    }
#elif defined( __AXP__ )
    // Nothing to do
#elif defined( __PPC__ )
    // No idea yet.
#endif

    __XCPTHANDLER = NULL;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?