/* * 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 ) ); }
/* * 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 */