Пример #1
0
/*
 * ReqProg_kill
 *
 * If it was a task that we attached to (WasStarted), all we do is
 * forgive the last interrupt, and then exit
 *
 * If it was a task we started, we TerminateApp it, and then wait for
 * the task ended notification.  Note:  Task ended isn't quite good enough,
 * since the module isn't unloaded.  However, you may never get the module
 * unloaded notification, if you are debugging the 2nd, 3rd etc instance
 * of an app, since the module is loaded more than once.  BUT, a NEW command
 * from the debugger ends up restarting the app "too fast" - the module isn't
 * deleted yet, and so it ends up running a second instance, even if you
 * really don't have a first instance.  This is the reason for that half
 * second pause - to allow Windows to get on with the unloading of the module,
 * if it is going to.  Ack.
 */
unsigned ReqProg_kill( void )
{
    prog_kill_ret       *ret;

    ret = GetOutPtr( 0 );
    ret->err = 0;
    Out((OUT_LOAD,"KILL: DebugeeTask=%04x, WasStarted=%d",
        DebugeeTask, WasStarted ));
    if( DebugeeTask != NULL ) {
        IntResult.EFlags &= ~TRACE_BIT;
        if( WasStarted ) {
            Out((OUT_LOAD,"Doing Release Debugee"));
            DebuggerWaitForMessage( RELEASE_DEBUGEE, DebugeeTask, RESTART_APP );
        } else {
            TerminateApp( DebugeeTask, NO_UAE_BOX );
            DebuggerWaitForMessage( KILLING_DEBUGEE, NULL, -1 );
            Out((OUT_LOAD,"Task Terminated(not current)"));
            {
                DWORD   a;
                a = GetTickCount();
                while( GetTickCount() < a + 500 ) {
                    Yield();
                }
            }
        }
#if 0
        FiniASynchHook();
#endif
    }
    ExitSoftMode();
    if( WDebug386 ) {
        if( WasInt32 ) {
            WasInt32 = FALSE;
            DoneWithInterrupt( NULL );
        }
    }
    DebugeeTask = NULL;
    ModuleTop = 0;
    CurrentModule = 1;
    FaultHandlerEntered = FALSE;
    PendingTrap = FALSE;
    SaveStdIn = NIL_HANDLE;
    SaveStdOut = NIL_HANDLE;
    Debugging32BitApp = FALSE;
    return( sizeof( *ret ) );
}
Пример #2
0
/*
 * FaultHandler:
 *
 * Handle all faults.
 *
 * When we get a fault, the first thing we do is check if we are using
 * WDEBUG.386.  If we are, we call GetDebugInterruptData in WINT32.DLL
 * to see if the fault was a 32-bit one.  If it was, the structure
 * IntResult will be filled in.
 *
 * We make sure that we are not already handling a fault.  If we
 * are, we punt and give it to the next guy.
 *
 * We disable the hot key for doing CTRL_ALT_F (in WDEBUG.386), to make
 * sure that we are not interrupted while in the debugger!
 *
 * If we get an INT3, and it was NOT a 32-bit fault, we back up IP.
 * (If it was a 32-bit fault, it is communicated as a breakpoint, and
 * we don't need to back up IP). We then check if we were waiting for
 * the breakpoint, and if we were, we write back the original byte.
 *
 * If it was not a 32-bit fault, we call saveState, which copies the
 * correct data into the IntResult structure (this is the structure
 * that we use to access/update the registers, see accregs.c).
 *
 * We then directed yield to the debugger, and go into a message loop
 * for the debuggee.
 *
 * Once the debuggee exits its message loop, we check to see if we
 * need to do a special request (access a segment or do an I/O redirection).
 *
 * If there was no special request, we then reset the app's registers
 * (with restoreState for a 16-bit fault, and DoneWithInterreupt in WINT32.DLL
 * for a 32-bit fault), re-enable the hot key for async stopping,
 * and return to IntHandler to allow it to restart the debuggee.
 */
void __loadds __cdecl FaultHandler( volatile fault_frame ff )
{
    restart_opts        rc=CHAIN;
    private_msg         pmsg = FAULT_HIT;
    WORD                sig[2];

    WasInt32 = false;
    if( WDebug386 ) {
        WasInt32 = (bool)GetDebugInterruptData( &IntResult );
        if( WasInt32 ) {
            ff.intf.intnumber = IntResult.InterruptNumber;
            Out((OUT_RUN,"***** 32-bit fault %d, cs:eip=%04x:%08lx *****",
                IntResult.InterruptNumber, IntResult.CS, IntResult.EIP ));
        }
    }
    newStack( 0, 0L );

    /*
     * only one fault at a time
     */
    Out((OUT_RUN,"***** Fault %d, cs:ip=%04x:%04x, ent=%d, state=%d, WasInt32=%d *****",
        ff.intf.intnumber, ff.intf.CS, ff.intf.IP, FaultHandlerEntered,
        (WORD)DebuggerState, WasInt32 ));
    if( FaultHandlerEntered || DebuggerState == ACTIVE ) {
        if( ff.intf.intnumber == WGOD_ASYNCH_STOP_INT ) {
            setRetHow( RESTART_APP );
        } else {
            setRetHow( CHAIN );
        }
        return;
    }
    UseHotKey( 0 );

    ff.ESP = (WORD) ff.ESP;
    ff.intf.oldEBP = (WORD) ff.intf.oldEBP;

    if( ff.intf.intnumber == INT_3 ) {
        if( !WasInt32 ) {
            ff.intf.IP--;
        }
        Out((OUT_ERR,"BP at '(%d) %4.4x:%4.4x %4.4x:%8.8lx'",WasInt32,ff.intf.CS,ff.intf.IP,
        IntResult.CS,IntResult.EIP));
        if( ( WasInt32 && IntResult.CS == DLLLoadCS && IntResult.EIP == DLLLoadIP ) ||
            ( !WasInt32 && ff.intf.CS == DLLLoadCS && ff.intf.IP == DLLLoadIP ) ) {
            Out((OUT_RUN,"Caught DLL Loaded '%4.4x:%4.4x'",DLLLoadCS,DLLLoadIP));
            WriteMem( DLLLoadCS, DLLLoadIP, &DLLLoadSaveByte, 1 );
            ReadMem( IntResult.CS, SIG_OFF, sig, sizeof( DWORD ) );
            if( memcmp( sig, win386sig, 4 ) == 0 ) {
                Out((OUT_RUN,"Zapped sig"));
                WriteMem( IntResult.CS, SIG_OFF, win386sig2, sizeof( DWORD ) );
                pmsg = DLL_LOAD32;
                DLLLoadExpectingInt1 = TRUE;
            } else {
                pmsg = DLL_LOAD;
            }
            DLLLoadCS = 0;
            DLLLoadIP = 0;
        } else if( DebuggerState == WAITING_FOR_BREAKPOINT ) {
            if( (WasInt32 && IntResult.CS == StopNewTask.loc.segment &&
                        IntResult.EIP == StopNewTask.loc.offset ) ||
                (!WasInt32 && ff.intf.CS == StopNewTask.loc.segment &&
                        ff.intf.IP == StopNewTask.loc.offset) ) {
                WriteMem( StopNewTask.loc.segment, StopNewTask.loc.offset,
                            &StopNewTask.value, 1 );
                pmsg = START_BP_HIT;
            }
        }
    } else if( ff.intf.intnumber == 1 && WasInt32 && DLLLoadExpectingInt1 ) {
            // 32-bit dll load from above
        DLLLoadExpectingInt1 = FALSE;
        pmsg = DLL_LOAD;
    } else if( ff.intf.intnumber == WGOD_ASYNCH_STOP_INT ) {
        pmsg = ASYNCH_STOP;
        Out((OUT_RUN,"***** Sending ASYNCH_STOP to debugger"));
    }


    if( !WasInt32 ) {
        saveState( &ff );
    }
    FaultHandlerEntered = true;
    TaskAtFault = GetCurrentTask();

    if( FPUType == X86_NO ) {
        memset( &FPResult, 0, sizeof( FPResult ) );
    } else if( FPUType < X86_387 ) {
        Read8087( &FPResult );
    } else {
        Read387( &FPResult );
    }

    /*
     * switch to debugger
     */
    while( 1 ) {
        if( !ToDebugger( pmsg ) ) break;
        rc = DebugeeWaitForMessage();
        if( rc == RUN_REDIRECT ) {
            ExecuteRedirect();
        } else if( rc == ACCESS_SEGMENT ) {
            AVolatileInt = *(LPINT) MK_FP( SegmentToAccess+1, 0 );
        } else {
            break;
        }
    }
    Out((OUT_RUN,"***** ---> restarting app, rc=%d",rc));

    if( FPUType >= X86_387 ) {
        Write387( &FPResult );
    } else if( FPUType != X86_NO ) {
        Write8087( &FPResult );
    }

    if( !WasInt32 ) {
        restoreState( &ff );
        newStack( IntResult.SS, IntResult.ESP );
    } else {
        WasInt32 = false;
        DoneWithInterrupt( &IntResult );
    }
    TaskAtFault = NULL;

    FaultHandlerEntered = false;
    setRetHow( rc );
    UseHotKey( 1 );

} /* FaultHandler */