/* * doStartTask: * * handle NFY_STARTTASK notification * * If we are waiting for the debuggee to load, then this is the task. * We remember the module and task ID's, and plant a breakpoint at the * starting address of the application. We can do that now, since we * now know the code selector for the segment with the start address. * * Otherwise, we simply record it so that we can notify the debugger * about a loaded module later. */ static BOOL doStartTask( DWORD data ) { char val; TASKENTRY te; te.dwSize = sizeof( te ); TaskFindHandle( &te, TaskAtNotify ); if( DebuggerState == LOADING_DEBUGEE ) { DebugeeModule = te.hModule; DebugeeTask = TaskAtNotify; StopNewTask.loc.segment = HIWORD( data ); ReadMem( StopNewTask.loc.segment, StopNewTask.loc.offset, &StopNewTask.value, 1 ); val = '\xcc'; WriteMem( StopNewTask.loc.segment, StopNewTask.loc.offset, &val, 1 ); ReadMem( StopNewTask.loc.segment, StopNewTask.loc.offset, &val, 1 ); Out((OUT_RUN," wrote breakpoint at %04x:%04lx, oldbyte=%02x(is now %02x)", StopNewTask.loc.segment, StopNewTask.loc.offset, StopNewTask.value, val )); Out((OUT_RUN," StartTask: cs:ip = %Fp", data )); ToDebugger( TASK_LOADED ); } else { AddModuleLoaded( te.hModule, FALSE ); } return( FALSE ); } /* doStartTask */
/* * doOutStr: * * handle a NFY_OUTSTR notification * * We return to the debugger so that it can display the string for the * user to see. */ static BOOL doOutStr( DWORD data ) { char *src; if( DebuggerState != RUNNING_DEBUGEE ) { Out((OUT_ERR,"Debugger was bad! '%s'",OutBuff)); return( 0 ); } src = (LPSTR) data; while( *src ) { if( *src == '\r' || OutPos == (MAX_STR-1) ) { OutBuff[ OutPos++ ] = '\0'; Out((OUT_RUN,"Going to debugger for OUT_STR '%s'",OutBuff)); if( DebugeeTask == NULL ) return( 0 ); ToDebugger( OUT_STR ); } if( *src != '\n' && *src != '\t' ) { OutBuff[ OutPos++ ] = *src; } src++; } return( 0 ); } /* doOutStr */
/* * 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 */