public void RunThreaded() { WinDebug.DEBUG_EVENT DbgEvt = new WinDebug.DEBUG_EVENT(); ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_CONTINUE; foreach (IDebuggerGeneralEvents Event in GeneralEvents) { Event.OnDebugStart(); } // Loop until told to stop while (bContinue == true) { // Pause until a debug event notification happens bContinue = WinDebug.NativeMethods.WaitForDebugEvent(out DbgEvt, VsChromium.Core.Win32.Constants.INFINITE); switch (DbgEvt.dwDebugEventCode) { case WinDebug.DEBUG_EVENT_CODE.EXCEPTION_DEBUG_EVENT: HandleException(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.CREATE_THREAD_DEBUG_EVENT: HandleCreateThread(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.CREATE_PROCESS_DEBUG_EVENT: HandleCreateProcess(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.EXIT_THREAD_DEBUG_EVENT: HandleExitThread(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.EXIT_PROCESS_DEBUG_EVENT: HandleExitProcess(DbgEvt); // XX Temporary bContinue = false; break; case WinDebug.DEBUG_EVENT_CODE.LOAD_DLL_DEBUG_EVENT: HandleLoadDll(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.UNLOAD_DLL_DEBUG_EVENT: HandleUnloadDll(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.OUTPUT_DEBUG_STRING_EVENT: HandleOutputDebugString(DbgEvt); break; case WinDebug.DEBUG_EVENT_CODE.RIP_EVENT: // TODO: Handle break; } // TODO: Stop doing this once we raise an exception WinDebug.NativeMethods.ContinueDebugEvent(DbgEvt.dwProcessId, DbgEvt.dwThreadId, ContinueStatus); ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_CONTINUE; } State = RunState.Ended; foreach (IDebuggerGeneralEvents Event in GeneralEvents) { Event.OnDebugEnd(); } }
private void HandleException(WinDebug.DEBUG_EVENT DebugEvent) { var DebugInfo = DebugEvent.Exception; switch ((ExceptionCode)DebugInfo.ExceptionRecord.ExceptionCode) { case ExceptionCode.AccessViolation: { // Ignore all access violation errors. // This will fallback to the debugee (Cxbx) and the exception handling routine. // Should they be unsupported, the debugger "OVERRIDE_EXCEPTION" message is thrown // which means the exception is usually fatal ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_EXCEPTION_NOT_HANDLED; } break; case (ExceptionCode)DebuggerMessages.ReportType.OVERRIDE_EXCEPTION: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Query = DebuggerMessages.GetExceptionHandledQuery(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); bool Handled = false; foreach (IDebuggerExceptionEvents Event in ExceptionEvents) { Handled |= Event.OnAccessViolation(Thread, Query.ExceptionCode, Query.ExceptionAddress); } // Write the reponse to memory Thread.OwningProcess.WriteMemory(Query.ReponseAddr, Handled); } } break; case (ExceptionCode)DebuggerMessages.ReportType.HLECACHE_FILE: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetHLECacheReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); SetupHLECacheProvider(Report.FileName); } } break; case (ExceptionCode)DebuggerMessages.ReportType.KERNEL_PATCH: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetKernelPatchReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); KernelSymbolProvider.AddKernelSymbolFromMessage(Report); } } break; case (ExceptionCode)DebuggerMessages.ReportType.FILE_OPENED: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetFileOpenedReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); foreach (IDebuggerFileEvents Event in FileEvents) { Event.OnFileOpened(Report); } } } break; case (ExceptionCode)DebuggerMessages.ReportType.FILE_READ: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetFileReadReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); foreach (IDebuggerFileEvents Event in FileEvents) { Event.OnFileRead(Report); } } } break; case (ExceptionCode)DebuggerMessages.ReportType.FILE_WRITE: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetFileWriteReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); foreach (IDebuggerFileEvents Event in FileEvents) { Event.OnFileWrite(Report); } } } break; case (ExceptionCode)DebuggerMessages.ReportType.FILE_CLOSED: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetFileClosedReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); if (Report != null) { foreach (IDebuggerFileEvents Event in FileEvents) { Event.OnFileClosed(Report); } } } } break; case (ExceptionCode)DebuggerMessages.ReportType.DEBUGGER_INIT: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetDebuggerInitReport(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); InitParams = Report; foreach (IDebuggerGeneralEvents Event in GeneralEvents) { Event.OnDebugTitleLoaded(InitParams.Title); } } } break; case (ExceptionCode)DebuggerMessages.ReportType.MS_VC_EXCEPTION: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { var Report = DebuggerMessages.GetMSVCThreadName(Thread, DebugInfo.ExceptionRecord.ExceptionInformation); if (Report != null) { // Resolve the ThreadId of an invalid ID to the current thread name if (Report.ThreadId == uint.MaxValue) { Report.ThreadId = (uint)DebugEvent.dwThreadId; } var ResolvedThread = DebugInstance.MainProcess.FindThread(Report.ThreadId); if (ResolvedThread != null) { // Update the resolved thread name ResolvedThread.DebugName = Report.Name; foreach (IDebuggerThreadEvents Event in ThreadEvents) { Event.OnThreadNamed(Thread); } } } } } break; case ExceptionCode.Breakpoint: { var Thread = DebugInstance.MainProcess.FindThread((uint)DebugEvent.dwThreadId); if (Thread != null) { uint BpAddr = (uint)DebugInfo.ExceptionRecord.ExceptionAddress; uint BpCode = DebugInfo.ExceptionRecord.ExceptionCode; bool FirstChance = (DebugInfo.dwFirstChance != 0); bpStall.Reset(); foreach (IDebuggerExceptionEvents Event in ExceptionEvents) { Event.OnBreakpoint(Thread, BpAddr, BpCode, FirstChance); } bpStall.WaitOne(); } } break; case ExceptionCode.SingleStep: // TODO Handle break; default: ContinueStatus = WinDebug.CONTINUE_STATUS.DBG_EXCEPTION_NOT_HANDLED; break; } }