/// <summary> /// Loop responsible to wait for debug events. /// Needs to be run in separate thread. /// </summary> private void DebuggerStateLoop() { bool hasClientExited = false; IDebugControl7 loopControl = (IDebugControl7)client; DebugCallbacks eventCallbacks = new DebugCallbacks(client, DebugStatusGo); lock (eventCallbacksReady) { System.Threading.Monitor.Pulse(eventCallbacksReady); } // Default is to start in break mode, wait for release. // DebugStatusGo.WaitOne(); while (!hasClientExited) { loopControl.WaitForEvent(0, UInt32.MaxValue); uint executionStatus = loopControl.GetExecutionStatus(); while (executionStatus == (uint)Defines.DebugStatusBreak) { DebugStatusBreak.Set(); DebugStatusGo.WaitOne(); executionStatus = loopControl.GetExecutionStatus(); } hasClientExited = executionStatus == (uint)Defines.DebugStatusNoDebuggee; } }
/// <summary> /// Initializes a new instance of the <see cref="DebugCallbacks"/> class. /// </summary> /// <param name="control">IDebugControl7 interface.</param> /// <param name="debugStatusGoEvent">Event used to signal when debuggee switches to release state.</param> public DebugCallbacks(IDebugControl7 control, AutoResetEvent debugStatusGoEvent) { // TODO: But the loop should always be running? Why this mess with events? // this.control = control; this.debugStatusGoEvent = debugStatusGoEvent; }
/// <summary> /// Attaches debugger to the already running specified process. /// </summary> /// <param name="processId">The process identifier.</param> /// <param name="attachFlags">The attaching flags.</param> /// <param name="symbolPaths">Array of paths where debugger will look for symbols.</param> public static void AttachToProcess(uint processId, DebugAttach attachFlags = DebugAttach.Noninvasive, params string[] symbolPaths) { IDebugClient debugClient = DebugClient.DebugCreate(); IDebugSymbols5 symbols = (IDebugSymbols5)debugClient; IDebugControl7 control = (IDebugControl7)debugClient; symbols.SetSymbolPathWide(string.Join(";", symbolPaths)); debugClient.AttachProcess(0, processId, attachFlags); control.WaitForEvent(0, uint.MaxValue); InitializeDbgEng(debugClient); }
/// <summary> /// Opens the specified dump file. /// </summary> /// <param name="dumpFile">The dump file.</param> /// <param name="symbolPath">The symbol path.</param> public static IDebugClient OpenDumpFile(string dumpFile, string symbolPath) { IDebugClient client = DebugCreate(); IDebugSymbols5 symbols = (IDebugSymbols5)client; IDebugControl7 control = (IDebugControl7)client; symbols.SetSymbolPathWide(symbolPath); client.OpenDumpFile(dumpFile); control.WaitForEvent(0, uint.MaxValue); symbols.SetSymbolPathWide(symbolPath); control.Execute(0, ".reload -f", 0); return(client); }
private Dumper(string applicationPath, string dumpPath, bool miniDump) { this.dumpPath = dumpPath; this.miniDump = miniDump; // Create debugging client IDebugClient clientBase = DebugClient.DebugCreate(); // Cast to upper clients client = (IDebugClient7)clientBase; control = (IDebugControl7)client; client.SetEventCallbacks(this); client.CreateProcessAndAttach(0, applicationPath, 0x00000002); }
private Dumper(string applicationPath, string dumpPath, bool miniDump) { this.dumpPath = dumpPath; this.miniDump = miniDump; // Create debugging client IDebugClient clientBase = DebugClient.DebugCreate(); // Cast to upper clients client = (IDebugClient7)clientBase; control = (IDebugControl7)client; client.SetEventCallbacks(this); client.CreateProcessAndAttach(0, applicationPath, 0x00000002); }
/// <summary> /// Starts a new process. /// </summary> /// <param name="processPath">Process path.</param> /// <param name="processArguments">Process arguments.</param> /// <param name="symbolPath">Symbol path.</param> /// <param name="debugEngineOptions">Debug engine options.</param> /// <returns></returns> public static IDebugClient OpenProcess(string processPath, string processArguments, string symbolPath, uint debugEngineOptions) { string processCommandLine = processPath + " " + processArguments; IDebugClient client = DebugCreate(); IDebugSymbols5 symbols = (IDebugSymbols5)client; IDebugControl7 control = (IDebugControl7)client; symbols.SetSymbolPathWide(symbolPath); control.SetEngineOptions(debugEngineOptions); client.CreateProcessAndAttach(0, processCommandLine, DebugCreateProcess.DebugOnlyThisProcess, 0, 0); control.WaitForEvent(0, uint.MaxValue); return(client); }
private DebugClient(object client, TaskScheduler scheduler) { _scheduler = scheduler; Client = (IDebugClient5)client; Control = (IDebugControl7)client; DataSpaces = (IDebugDataSpaces4)client; SystemObjects = (IDebugSystemObjects2)client; Symbols = (IDebugSymbols5)client; Advanced = (IDebugAdvanced3)client; Client.SetEventCallbacksWide(this).ThrowIfFailed(); Client.SetOutputCallbacksWide(this).ThrowIfFailed(); Control.AddEngineOptions(DEBUG_ENGOPT.INITIAL_BREAK); }
/// <summary> /// Loop responsible to wait for debug events. /// Needs to be run in separate thread. /// </summary> private void DebuggerStateLoop() { bool hasClientExited = false; IDebugControl7 loopControl = dbgEngDll.Control; debugCallbacks = new DebugCallbacks(loopControl, DebugStatusGo); dbgEngDll.ThreadClient.SetEventCallbacks(debugCallbacks); lock (eventCallbacksReady) { System.Threading.Monitor.Pulse(eventCallbacksReady); } // Default is to start in break mode, wait for the release. // TODO: Needs to be changes with support for non-intrusive debugging. // DebugStatusGo.WaitOne(); while (!hasClientExited) { // Need to check hr return value. // loopControl.WaitForEvent(0, uint.MaxValue); if ((uint)Defines.DebugStatusBreak == loopControl.GetExecutionStatus()) { dbgEngDll.ThreadClient.DispatchCallbacks(200); DebugStatusBreak.Set(); DebugStatusGo.WaitOne(); if (DebuggerLoopExitSignal) { dbgEngDll.ThreadClient.EndSession(DebugEnd.ActiveTerminate); } else { loopControl.Execute(0, "g", 0); } dbgEngDll.ThreadClient.DispatchCallbacks(200); } hasClientExited = loopControl.GetExecutionStatus() == (uint)Defines.DebugStatusNoDebuggee; } }