Browse Source

Created classes to keep debugger state. State changes to paused for whole callback

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/branches/2.0@1250 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 20 years ago
parent
commit
610f738f4c
  1. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj
  2. 20
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/DebugeeState.cs
  3. 6
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/DebuggerEvents/PausedReason.cs
  4. 169
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs
  5. 71
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/NDebugger-StateControl.cs
  6. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/NDebugger.cs
  7. 33
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/PauseSession.cs
  8. 12
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs
  9. 20
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs
  10. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Thread.cs
  11. 5
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Eval.cs
  12. 6
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs
  13. 12
      src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/DebuggerTests.cs

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj

@ -368,6 +368,8 @@
<Compile Include="Src\Wrappers\CorDebug\ICorDebugGenericValue.cs" /> <Compile Include="Src\Wrappers\CorDebug\ICorDebugGenericValue.cs" />
<Compile Include="Src\Interop\CorSym\ISymUnmanagedDispose.cs" /> <Compile Include="Src\Interop\CorSym\ISymUnmanagedDispose.cs" />
<Compile Include="Src\Wrappers\CorSym\Autogenerated\ISymUnmanagedDispose.cs" /> <Compile Include="Src\Wrappers\CorSym\Autogenerated\ISymUnmanagedDispose.cs" />
<Compile Include="Src\Debugger\DebugeeState.cs" />
<Compile Include="Src\Debugger\PauseSession.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="README.TXT" /> <Content Include="README.TXT" />

20
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/DebugeeState.cs

@ -0,0 +1,20 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
namespace Debugger
{
/// <summary>
/// Unique identifier of the state of the debugee.
/// Changes when debuggee is stepped, but not when properity is evaluated.
/// </summary>
public class DebugeeState
{
}
}

6
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/DebuggerEvents/PausedReason.cs

@ -9,17 +9,17 @@ namespace Debugger
{ {
public enum PausedReason:int public enum PausedReason:int
{ {
AllEvalsComplete, EvalComplete,
StepComplete, StepComplete,
Breakpoint, Breakpoint,
Break, Break,
ControlCTrap, ControlCTrap,
Exception, Exception,
DebuggerError, DebuggerError,
EvalComplete,
CurrentThreadChanged, CurrentThreadChanged,
CurrentFunctionChanged, CurrentFunctionChanged,
ExceptionIntercepted, ExceptionIntercepted,
SetIP SetIP,
Other
} }
} }

169
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs

@ -10,7 +10,7 @@
// Output: \1 - intention \2 - declaration \3 - function name \4-9 parameters // Output: \1 - intention \2 - declaration \3 - function name \4-9 parameters
// Replace with: // Replace with:
// \1\2\n\1{\n\1\tEnterCallback("\3");\n\1\t\n\1\tExitCallback_Continue();\n\1} // \1\2\n\1{\n\1\tEnterCallback(PausedReason.Other, "\3");\n\1\t\n\1\tExitCallback_Continue();\n\1}
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -23,11 +23,6 @@ namespace Debugger
{ {
NDebugger debugger; NDebugger debugger;
bool handlingCallback = false;
Process callingProcess;
Thread callingThread;
public NDebugger Debugger { public NDebugger Debugger {
get { get {
return debugger; return debugger;
@ -39,71 +34,43 @@ namespace Debugger
this.debugger = debugger; this.debugger = debugger;
} }
public bool HandlingCallback { void EnterCallback(PausedReason pausedReason, string name, ICorDebugProcess pProcess)
get {
return handlingCallback;
}
}
// Sets CurrentProcess
void EnterCallback(string name, ICorDebugProcess pProcess)
{
EnterCallback(name);
callingProcess = debugger.GetProcess(pProcess);
callingProcess.IsRunning = false;
}
// Sets CurrentProcess
void EnterCallback(string name, ICorDebugAppDomain pAppDomain)
{ {
EnterCallback(name); debugger.TraceMessage("Callback: " + name);
debugger.AssertRunning();
callingProcess = debugger.GetProcess(pAppDomain.Process); debugger.PauseSession = new PauseSession(pausedReason);
callingProcess.IsRunning = false; debugger.CurrentProcess = debugger.GetProcess(pProcess);
debugger.CurrentProcess.IsRunning = false;
} }
void EnterCallback(string name, ICorDebugThread pThread) void EnterCallback(PausedReason pausedReason, string name, ICorDebugAppDomain pAppDomain)
{ {
EnterCallback(name); EnterCallback(pausedReason, name, pAppDomain.Process);
callingThread = debugger.GetThread(pThread);
callingProcess = callingThread.Process;
callingProcess.IsRunning = false;
} }
void EnterCallback(string name) void EnterCallback(PausedReason pausedReason, string name, ICorDebugThread pThread)
{ {
handlingCallback = true;
debugger.TraceMessage("Callback: " + name); debugger.TraceMessage("Callback: " + name);
// ExitProcess may be called at any time when debuggee is killed // ExitProcess may be called at any time when debuggee is killed
if (name != "ExitProcess") { if (name != "ExitProcess") debugger.AssertRunning();
debugger.AssertRunning(); Thread thread = debugger.GetThread(pThread);
} debugger.PauseSession = new PauseSession(pausedReason);
debugger.CurrentProcess = thread.Process;
debugger.CurrentProcess.IsRunning = false;
debugger.CurrentProcess.CurrentThread = thread;
} }
void ExitCallback_Continue() void ExitCallback_Continue()
{ {
callingProcess.ContinueCallback(); debugger.CurrentProcess.Continue();
callingThread = null;
callingProcess = null;
handlingCallback = false;
} }
void ExitCallback_Paused(PausedReason reason) void ExitCallback_Paused()
{ {
if (callingThread != null) { if (debugger.CurrentThread != null) {
callingThread.DeactivateAllSteppers(); debugger.CurrentThread.DeactivateAllSteppers();
} }
debugger.Pause();
handlingCallback = false;
debugger.Pause(reason, callingProcess, callingThread, null);
callingThread = null;
callingProcess = null;
} }
@ -111,7 +78,7 @@ namespace Debugger
public void StepComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugStepper pStepper, CorDebugStepReason reason) public void StepComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugStepper pStepper, CorDebugStepReason reason)
{ {
EnterCallback("StepComplete (" + reason.ToString() + ")", pThread); EnterCallback(PausedReason.StepComplete, "StepComplete (" + reason.ToString() + ")", pThread);
Stepper stepper = debugger.GetThread(pThread).GetStepper(pStepper); Stepper stepper = debugger.GetThread(pThread).GetStepper(pStepper);
if (stepper != null) { if (stepper != null) {
@ -122,23 +89,23 @@ namespace Debugger
} }
} }
if (!callingThread.LastFunction.HasSymbols) { if (!debugger.CurrentThread.LastFunction.HasSymbols) {
// This should not happen with JMC enabled // This should not happen with JMC enabled
debugger.TraceMessage(" - leaving code without symbols"); debugger.TraceMessage(" - leaving code without symbols");
ExitCallback_Continue(); ExitCallback_Continue();
} else { } else {
ExitCallback_Paused(PausedReason.StepComplete); ExitCallback_Paused();
} }
} }
// Do not pass the pBreakpoint parameter as ICorDebugBreakpoint - marshaling of it fails in .NET 1.1 // Do not pass the pBreakpoint parameter as ICorDebugBreakpoint - marshaling of it fails in .NET 1.1
public void Breakpoint(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, IntPtr pBreakpoint) public void Breakpoint(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, IntPtr pBreakpoint)
{ {
EnterCallback("Breakpoint", pThread); EnterCallback(PausedReason.Breakpoint, "Breakpoint", pThread);
ExitCallback_Paused(PausedReason.Breakpoint); ExitCallback_Paused();
// foreach (Breakpoint b in debugger.Breakpoints) { // foreach (Breakpoint b in debugger.Breakpoints) {
// if (b.Equals(pBreakpoint)) { // if (b.Equals(pBreakpoint)) {
@ -150,23 +117,23 @@ namespace Debugger
public void BreakpointSetError(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugBreakpoint pBreakpoint, uint dwError) public void BreakpointSetError(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugBreakpoint pBreakpoint, uint dwError)
{ {
EnterCallback("BreakpointSetError", pThread); EnterCallback(PausedReason.Other, "BreakpointSetError", pThread);
ExitCallback_Continue(); ExitCallback_Continue();
} }
public unsafe void Break(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread) public unsafe void Break(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread)
{ {
EnterCallback("Break", pThread); EnterCallback(PausedReason.Break, "Break", pThread);
ExitCallback_Paused(PausedReason.Break); ExitCallback_Paused();
} }
public void ControlCTrap(ICorDebugProcess pProcess) public void ControlCTrap(ICorDebugProcess pProcess)
{ {
EnterCallback("ControlCTrap", pProcess); EnterCallback(PausedReason.ControlCTrap, "ControlCTrap", pProcess);
ExitCallback_Paused(PausedReason.ControlCTrap); ExitCallback_Paused();
} }
public unsafe void Exception(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int unhandled) public unsafe void Exception(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int unhandled)
@ -179,7 +146,7 @@ namespace Debugger
Exception2(pAppDomain, pThread, null, 0, (CorDebugExceptionCallbackType)exceptionType, 0); Exception2(pAppDomain, pThread, null, 0, (CorDebugExceptionCallbackType)exceptionType, 0);
} else { } else {
// This callback should be ignored in v2 applications // This callback should be ignored in v2 applications
EnterCallback("Exception", pThread); EnterCallback(PausedReason.Other, "Exception", pThread);
ExitCallback_Continue(); ExitCallback_Continue();
} }
@ -191,14 +158,14 @@ namespace Debugger
public void LogSwitch(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int lLevel, uint ulReason, string pLogSwitchName, string pParentName) public void LogSwitch(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int lLevel, uint ulReason, string pLogSwitchName, string pParentName)
{ {
EnterCallback("LogSwitch", pThread); EnterCallback(PausedReason.Other, "LogSwitch", pThread);
ExitCallback_Continue(); ExitCallback_Continue();
} }
public void LogMessage(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int lLevel, string pLogSwitchName, string pMessage) public void LogMessage(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, int lLevel, string pLogSwitchName, string pMessage)
{ {
EnterCallback("LogMessage", pThread); EnterCallback(PausedReason.Other, "LogMessage", pThread);
debugger.OnLogMessage(pMessage); debugger.OnLogMessage(pMessage);
@ -207,21 +174,21 @@ namespace Debugger
public void EditAndContinueRemap(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pFunction, int fAccurate) public void EditAndContinueRemap(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pFunction, int fAccurate)
{ {
EnterCallback("EditAndContinueRemap", pThread); EnterCallback(PausedReason.Other, "EditAndContinueRemap", pThread);
ExitCallback_Continue(); ExitCallback_Continue();
} }
public void EvalException(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval) public void EvalException(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval)
{ {
EnterCallback("EvalException", pThread); EnterCallback(PausedReason.EvalComplete, "EvalException", pThread);
HandleEvalComplete(pAppDomain, pThread, corEval, true); HandleEvalComplete(pAppDomain, pThread, corEval, true);
} }
public void EvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval) public void EvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval)
{ {
EnterCallback("EvalComplete", pThread); EnterCallback(PausedReason.EvalComplete, "EvalComplete", pThread);
HandleEvalComplete(pAppDomain, pThread, corEval, false); HandleEvalComplete(pAppDomain, pThread, corEval, false);
} }
@ -239,23 +206,23 @@ namespace Debugger
debugger.SetupNextEvaluation(debugger.GetThread(pThread)); debugger.SetupNextEvaluation(debugger.GetThread(pThread));
ExitCallback_Continue(); ExitCallback_Continue();
} else { } else {
ExitCallback_Paused(PausedReason.AllEvalsComplete); ExitCallback_Paused();
} }
} }
public void DebuggerError(ICorDebugProcess pProcess, int errorHR, uint errorCode) public void DebuggerError(ICorDebugProcess pProcess, int errorHR, uint errorCode)
{ {
EnterCallback("DebuggerError", pProcess); EnterCallback(PausedReason.DebuggerError, "DebuggerError", pProcess);
string errorText = String.Format("Debugger error: \nHR = 0x{0:X} \nCode = 0x{1:X}", errorHR, errorCode); string errorText = String.Format("Debugger error: \nHR = 0x{0:X} \nCode = 0x{1:X}", errorHR, errorCode);
System.Windows.Forms.MessageBox.Show(errorText); System.Windows.Forms.MessageBox.Show(errorText);
ExitCallback_Paused(PausedReason.DebuggerError); ExitCallback_Paused();
} }
public void UpdateModuleSymbols(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule, IStream pSymbolStream) public void UpdateModuleSymbols(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule, IStream pSymbolStream)
{ {
EnterCallback("UpdateModuleSymbols", pAppDomain); EnterCallback(PausedReason.Other, "UpdateModuleSymbols", pAppDomain);
ExitCallback_Continue(); ExitCallback_Continue();
} }
@ -266,7 +233,7 @@ namespace Debugger
public void CreateProcess(ICorDebugProcess pProcess) public void CreateProcess(ICorDebugProcess pProcess)
{ {
EnterCallback("CreateProcess", pProcess); EnterCallback(PausedReason.Other, "CreateProcess", pProcess);
// Process is added in NDebugger.Start // Process is added in NDebugger.Start
@ -275,7 +242,7 @@ namespace Debugger
public void CreateAppDomain(ICorDebugProcess pProcess, ICorDebugAppDomain pAppDomain) public void CreateAppDomain(ICorDebugProcess pProcess, ICorDebugAppDomain pAppDomain)
{ {
EnterCallback("CreateAppDomain", pAppDomain); EnterCallback(PausedReason.Other, "CreateAppDomain", pAppDomain);
pAppDomain.Attach(); pAppDomain.Attach();
@ -284,14 +251,14 @@ namespace Debugger
public void LoadAssembly(ICorDebugAppDomain pAppDomain, ICorDebugAssembly pAssembly) public void LoadAssembly(ICorDebugAppDomain pAppDomain, ICorDebugAssembly pAssembly)
{ {
EnterCallback("LoadAssembly", pAppDomain); EnterCallback(PausedReason.Other, "LoadAssembly", pAppDomain);
ExitCallback_Continue(); ExitCallback_Continue();
} }
public unsafe void LoadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule) public unsafe void LoadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule)
{ {
EnterCallback("LoadModule", pAppDomain); EnterCallback(PausedReason.Other, "LoadModule", pAppDomain);
debugger.AddModule(pModule); debugger.AddModule(pModule);
@ -302,14 +269,14 @@ namespace Debugger
{ {
if (pAppDomain != null) { if (pAppDomain != null) {
EnterCallback("NameChange: pAppDomain", pAppDomain); EnterCallback(PausedReason.Other, "NameChange: pAppDomain", pAppDomain);
ExitCallback_Continue(); ExitCallback_Continue();
} }
if (pThread != null) { if (pThread != null) {
EnterCallback("NameChange: pThread", pThread); EnterCallback(PausedReason.Other, "NameChange: pThread", pThread);
Thread thread = debugger.GetThread(pThread); Thread thread = debugger.GetThread(pThread);
thread.HasBeenLoaded = true; thread.HasBeenLoaded = true;
@ -323,7 +290,7 @@ namespace Debugger
{ {
// We can not use pThread since it has not been added yet // We can not use pThread since it has not been added yet
// and we continue from this callback anyway // and we continue from this callback anyway
EnterCallback("CreateThread", pAppDomain); EnterCallback(PausedReason.Other, "CreateThread", pAppDomain);
debugger.AddThread(pThread); debugger.AddThread(pThread);
@ -332,7 +299,7 @@ namespace Debugger
public void LoadClass(ICorDebugAppDomain pAppDomain, ICorDebugClass c) public void LoadClass(ICorDebugAppDomain pAppDomain, ICorDebugClass c)
{ {
EnterCallback("LoadClass", pAppDomain); EnterCallback(PausedReason.Other, "LoadClass", pAppDomain);
ExitCallback_Continue(); ExitCallback_Continue();
} }
@ -343,14 +310,14 @@ namespace Debugger
public void UnloadClass(ICorDebugAppDomain pAppDomain, ICorDebugClass c) public void UnloadClass(ICorDebugAppDomain pAppDomain, ICorDebugClass c)
{ {
EnterCallback("UnloadClass", pAppDomain); EnterCallback(PausedReason.Other, "UnloadClass", pAppDomain);
ExitCallback_Continue(); ExitCallback_Continue();
} }
public void UnloadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule) public void UnloadModule(ICorDebugAppDomain pAppDomain, ICorDebugModule pModule)
{ {
EnterCallback("UnloadModule", pAppDomain); EnterCallback(PausedReason.Other, "UnloadModule", pAppDomain);
debugger.RemoveModule(pModule); debugger.RemoveModule(pModule);
@ -359,14 +326,14 @@ namespace Debugger
public void UnloadAssembly(ICorDebugAppDomain pAppDomain, ICorDebugAssembly pAssembly) public void UnloadAssembly(ICorDebugAppDomain pAppDomain, ICorDebugAssembly pAssembly)
{ {
EnterCallback("UnloadAssembly", pAppDomain); EnterCallback(PausedReason.Other, "UnloadAssembly", pAppDomain);
ExitCallback_Continue(); ExitCallback_Continue();
} }
public void ExitThread(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread) public void ExitThread(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread)
{ {
EnterCallback("ExitThread", pThread); EnterCallback(PausedReason.Other, "ExitThread", pThread);
Thread thread = debugger.GetThread(pThread); Thread thread = debugger.GetThread(pThread);
@ -381,14 +348,14 @@ namespace Debugger
public void ExitAppDomain(ICorDebugProcess pProcess, ICorDebugAppDomain pAppDomain) public void ExitAppDomain(ICorDebugProcess pProcess, ICorDebugAppDomain pAppDomain)
{ {
EnterCallback("ExitAppDomain", pAppDomain); EnterCallback(PausedReason.Other, "ExitAppDomain", pAppDomain);
ExitCallback_Continue(); ExitCallback_Continue();
} }
public void ExitProcess(ICorDebugProcess pProcess) public void ExitProcess(ICorDebugProcess pProcess)
{ {
EnterCallback("ExitProcess", pProcess); EnterCallback(PausedReason.Other, "ExitProcess", pProcess);
Process process = debugger.GetProcess(pProcess); Process process = debugger.GetProcess(pProcess);
@ -406,54 +373,54 @@ namespace Debugger
public void ChangeConnection(ICorDebugProcess pProcess, uint dwConnectionId) public void ChangeConnection(ICorDebugProcess pProcess, uint dwConnectionId)
{ {
EnterCallback("ChangeConnection", pProcess); EnterCallback(PausedReason.Other, "ChangeConnection", pProcess);
ExitCallback_Continue(); ExitCallback_Continue();
} }
public void CreateConnection(ICorDebugProcess pProcess, uint dwConnectionId, IntPtr pConnName) public void CreateConnection(ICorDebugProcess pProcess, uint dwConnectionId, IntPtr pConnName)
{ {
EnterCallback("CreateConnection", pProcess); EnterCallback(PausedReason.Other, "CreateConnection", pProcess);
ExitCallback_Continue(); ExitCallback_Continue();
} }
public void DestroyConnection(ICorDebugProcess pProcess, uint dwConnectionId) public void DestroyConnection(ICorDebugProcess pProcess, uint dwConnectionId)
{ {
EnterCallback("DestroyConnection", pProcess); EnterCallback(PausedReason.Other, "DestroyConnection", pProcess);
ExitCallback_Continue(); ExitCallback_Continue();
} }
public void Exception2(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFrame pFrame, uint nOffset, CorDebugExceptionCallbackType exceptionType, uint dwFlags) public void Exception2(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFrame pFrame, uint nOffset, CorDebugExceptionCallbackType exceptionType, uint dwFlags)
{ {
EnterCallback("Exception2", pThread); EnterCallback(PausedReason.Exception, "Exception2", pThread);
// This callback is also called from Exception(...)!!!! (the .NET 1.1 version) // This callback is also called from Exception(...)!!!! (the .NET 1.1 version)
// Whatch out for the zeros and null! // Whatch out for the zeros and null!
// Exception -> Exception2(pAppDomain, pThread, null, 0, exceptionType, 0); // Exception -> Exception2(pAppDomain, pThread, null, 0, exceptionType, 0);
callingThread.CurrentExceptionType = (ExceptionType)exceptionType; debugger.CurrentThread.CurrentExceptionType = (ExceptionType)exceptionType;
if (ExceptionType.DEBUG_EXCEPTION_UNHANDLED != (ExceptionType)exceptionType) { if (ExceptionType.DEBUG_EXCEPTION_UNHANDLED != (ExceptionType)exceptionType) {
// Handled exception // Handled exception
if (debugger.PauseOnHandledException) { if (debugger.PauseOnHandledException) {
ExitCallback_Paused(PausedReason.Exception); ExitCallback_Paused();
} else { } else {
ExitCallback_Continue(); ExitCallback_Continue();
} }
} else { } else {
// Unhandled exception // Unhandled exception
ExitCallback_Paused(PausedReason.Exception); ExitCallback_Paused();
} }
} }
public void ExceptionUnwind(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, CorDebugExceptionUnwindCallbackType dwEventType, uint dwFlags) public void ExceptionUnwind(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, CorDebugExceptionUnwindCallbackType dwEventType, uint dwFlags)
{ {
EnterCallback("ExceptionUnwind", pThread); EnterCallback(PausedReason.ExceptionIntercepted, "ExceptionUnwind", pThread);
if (dwEventType == CorDebugExceptionUnwindCallbackType.DEBUG_EXCEPTION_INTERCEPTED) { if (dwEventType == CorDebugExceptionUnwindCallbackType.DEBUG_EXCEPTION_INTERCEPTED) {
ExitCallback_Paused(PausedReason.ExceptionIntercepted); ExitCallback_Paused();
} else { } else {
ExitCallback_Continue(); ExitCallback_Continue();
} }
@ -461,14 +428,14 @@ namespace Debugger
public void FunctionRemapComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pFunction) public void FunctionRemapComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pFunction)
{ {
EnterCallback("FunctionRemapComplete", pThread); EnterCallback(PausedReason.Other, "FunctionRemapComplete", pThread);
ExitCallback_Continue(); ExitCallback_Continue();
} }
public void FunctionRemapOpportunity(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pOldFunction, ICorDebugFunction pNewFunction, uint oldILOffset) public void FunctionRemapOpportunity(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugFunction pOldFunction, ICorDebugFunction pNewFunction, uint oldILOffset)
{ {
EnterCallback("FunctionRemapOpportunity", pThread); EnterCallback(PausedReason.Other, "FunctionRemapOpportunity", pThread);
ExitCallback_Continue(); ExitCallback_Continue();
} }
@ -476,9 +443,9 @@ namespace Debugger
public void MDANotification(ICorDebugController c, ICorDebugThread t, ICorDebugMDA mda) public void MDANotification(ICorDebugController c, ICorDebugThread t, ICorDebugMDA mda)
{ {
if (c.Is<ICorDebugAppDomain>()) { if (c.Is<ICorDebugAppDomain>()) {
EnterCallback("MDANotification", c.CastTo<ICorDebugAppDomain>()); EnterCallback(PausedReason.Other, "MDANotification", c.CastTo<ICorDebugAppDomain>());
} else if (c.Is<ICorDebugProcess>()){ } else if (c.Is<ICorDebugProcess>()){
EnterCallback("MDANotification", c.CastTo<ICorDebugProcess>()); EnterCallback(PausedReason.Other, "MDANotification", c.CastTo<ICorDebugProcess>());
} else { } else {
throw new System.Exception("Unknown callback argument"); throw new System.Exception("Unknown callback argument");
} }

71
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/NDebugger-StateControl.cs

@ -18,12 +18,11 @@ namespace Debugger
{ {
public partial class NDebugger public partial class NDebugger
{ {
PausedReason? pausedReason = null;
bool pauseOnHandledException = false; bool pauseOnHandledException = false;
ManualResetEvent pausedHandle = new ManualResetEvent(false); ManualResetEvent pausedHandle = new ManualResetEvent(false);
object sessionID = new object(); PauseSession pauseSession;
object debugeeStateID = new object(); DebugeeState debugeeState;
Process currentProcess; Process currentProcess;
@ -74,10 +73,12 @@ namespace Debugger
if (currentProcess == null) { if (currentProcess == null) {
return null; return null;
} else { } else {
if (currentProcess.IsRunning) return null;
return currentProcess; return currentProcess;
} }
} }
set {
currentProcess = value;
}
} }
public Thread CurrentThread { public Thread CurrentThread {
@ -102,21 +103,21 @@ namespace Debugger
/// <summary> /// <summary>
/// Indentification of the current debugger session. This value changes whenever debugger is continued /// Indentification of the current debugger session. This value changes whenever debugger is continued
/// </summary> /// </summary>
public object SessionID { public PauseSession PauseSession {
get { get {
return sessionID; return pauseSession;
} }
internal set { internal set {
sessionID = value; pauseSession = value;
} }
} }
/// <summary> /// <summary>
/// Indentification of the state of the debugee. This value changes whenever the state of the debugee significatntly changes /// Indentification of the state of the debugee. This value changes whenever the state of the debugee significatntly changes
/// </summary> /// </summary>
public object DebugeeStateID { public DebugeeState DebugeeState {
get { get {
return debugeeStateID; return debugeeState;
} }
} }
@ -136,13 +137,13 @@ namespace Debugger
public bool IsPaused { public bool IsPaused {
get { get {
return (pausedReason != null); return (pauseSession != null);
} }
} }
public bool IsRunning { public bool IsRunning {
get { get {
return (pausedReason == null); return (pauseSession == null);
} }
} }
@ -153,60 +154,28 @@ namespace Debugger
public PausedReason PausedReason { public PausedReason PausedReason {
get { get {
AssertPaused(); AssertPaused();
return (PausedReason)pausedReason; return pauseSession.PausedReason;
} }
} }
internal void Pause(PausedReason reason, Process process, Thread thread, Function function) internal void Pause()
{ {
if (IsPaused) {
throw new DebuggerException("Already paused");
}
if (process == null) {
throw new DebuggerException("Process can not be null");
}
if (thread == null && function != null) {
throw new DebuggerException("Function can not be set without thread");
}
currentProcess = process;
currentProcess.CurrentThread = thread;
if (currentProcess.CurrentThread != null) {
currentProcess.CurrentThread.CurrentFunction = function;
}
pausedReason = reason;
OnDebuggingPaused(); OnDebuggingPaused();
// Debugger state is unknown after calling OnDebuggingPaused (it may be resumed) // Debugger state is unknown after calling OnDebuggingPaused (it may be resumed)
if (IsPaused) { if (IsPaused) {
if (reason != PausedReason.AllEvalsComplete) { if (PausedReason != PausedReason.EvalComplete) {
debugeeStateID = new object(); debugeeState = new DebugeeState();
OnDebuggeeStateChanged(); OnDebuggeeStateChanged();
} }
} }
// This is a good point to autmaticaly evaluate evals from update of variables (if there are any)
if (IsPaused) {
this.StartEvaluation();
}
if (IsPaused) { if (IsPaused) {
pausedHandle.Set(); pausedHandle.Set();
} }
} }
internal void FakePause(PausedReason reason, bool keepCurrentFunction)
{
Process process = CurrentProcess;
Thread thread = CurrentThread;
Function function = CurrentFunction;
Resume();
Pause(reason, process, thread, keepCurrentFunction ? function : null);
}
internal void Resume() internal void Resume()
{ {
if (IsRunning) { if (IsRunning) {
@ -217,14 +186,8 @@ namespace Debugger
pausedHandle.Reset(); pausedHandle.Reset();
pausedReason = null; pauseSession = null;
// Remove all stored functions, they are disponsed between callbacks and they need to be regenerated
foreach(Thread t in Threads) {
t.CurrentFunction = null;
}
// Clear current process
currentProcess = null; currentProcess = null;
} }

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/NDebugger.cs

@ -132,7 +132,7 @@ namespace Debugger
currentProcess = null; currentProcess = null;
pausedHandle.Reset(); pausedHandle.Reset();
pausedReason = null; pauseSession = null;
pendingEvalsCollection.Clear(); pendingEvalsCollection.Clear();

33
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/PauseSession.cs

@ -0,0 +1,33 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// Holds information about the state of paused debugger.
/// Expires when when Continue is called on debugger.
/// </summary>
public class PauseSession
{
PausedReason pausedReason;
public PausedReason PausedReason {
get {
return pausedReason;
}
}
public PauseSession(PausedReason pausedReason)
{
this.pausedReason = pausedReason;
}
}
}

12
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs

@ -23,7 +23,7 @@ namespace Debugger
Module module; Module module;
ICorDebugFunction corFunction; ICorDebugFunction corFunction;
ICorDebugILFrame corILFrame; ICorDebugILFrame corILFrame;
object corILFrameDebuggerSessionID; object corILFramePauseSession;
bool steppedOut; bool steppedOut;
Thread thread; Thread thread;
@ -110,7 +110,7 @@ namespace Debugger
this.chainIndex = chainIndex; this.chainIndex = chainIndex;
this.frameIndex = frameIndex; this.frameIndex = frameIndex;
this.corILFrame = corILFrame; this.corILFrame = corILFrame;
this.corILFrameDebuggerSessionID = debugger.SessionID; this.corILFramePauseSession = debugger.PauseSession;
corFunction = corILFrame.Function; corFunction = corILFrame.Function;
module = debugger.GetModule(corFunction.Module); module = debugger.GetModule(corFunction.Module);
@ -129,9 +129,9 @@ namespace Debugger
internal ICorDebugILFrame CorILFrame { internal ICorDebugILFrame CorILFrame {
get { get {
if (HasExpired) throw new DebuggerException("Function has expired"); if (HasExpired) throw new DebuggerException("Function has expired");
if (corILFrameDebuggerSessionID != debugger.SessionID) { if (corILFramePauseSession != debugger.PauseSession) {
corILFrame = thread.GetFunctionAt(chainIndex, frameIndex).CorILFrame; corILFrame = thread.GetFunctionAt(chainIndex, frameIndex).CorILFrame;
corILFrameDebuggerSessionID = debugger.SessionID; corILFramePauseSession = debugger.PauseSession;
} }
return corILFrame; return corILFrame;
} }
@ -361,8 +361,10 @@ namespace Debugger
if (simulate) { if (simulate) {
CorILFrame.CanSetIP((uint)ilOffset); CorILFrame.CanSetIP((uint)ilOffset);
} else { } else {
// invalidates all frames and chains for the current thread
CorILFrame.SetIP((uint)ilOffset); CorILFrame.SetIP((uint)ilOffset);
debugger.FakePause(PausedReason.SetIP, false); debugger.PauseSession = new PauseSession(PausedReason.SetIP);
debugger.Pause();
} }
} catch { } catch {
return null; return null;

20
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Process.cs

@ -60,7 +60,7 @@ namespace Debugger
{ {
CurrentThread = thread; CurrentThread = thread;
debugger.FakePause(PausedReason.CurrentThreadChanged, false); debugger.Pause();
} }
public IList<Thread> Threads { public IList<Thread> Threads {
@ -123,10 +123,12 @@ namespace Debugger
throw new DebuggerException("Invalid operation"); throw new DebuggerException("Invalid operation");
} }
corProcess.Stop(5000); // TODO: Hardcoded value corProcess.Stop(5000); // TODO: Hardcoded value
isProcessRunning = false; isProcessRunning = false;
debugger.Pause(PausedReason.Break, this, null, null); debugger.PauseSession = new PauseSession(PausedReason.Break);
debugger.CurrentProcess = this;
debugger.Pause();
} }
public void Continue() public void Continue()
@ -137,18 +139,6 @@ namespace Debugger
debugger.Resume(); debugger.Resume();
isProcessRunning = true; isProcessRunning = true;
debugger.SessionID = new object();
corProcess.Continue(0);
}
internal void ContinueCallback()
{
if (isProcessRunning) {
throw new DebuggerException("Invalid operation");
}
isProcessRunning = true;
debugger.SessionID = new object();
corProcess.Continue(0); corProcess.Continue(0);
} }

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Thread.cs

@ -317,7 +317,7 @@ namespace Debugger
{ {
CurrentFunction = function; CurrentFunction = function;
debugger.FakePause(PausedReason.CurrentFunctionChanged, true); debugger.Pause();
} }
public Function LastFunctionWithLoadedSymbols { public Function LastFunctionWithLoadedSymbols {

5
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Eval.cs

@ -24,8 +24,6 @@ namespace Debugger
{ {
NDebugger debugger; NDebugger debugger;
object debugeeStateIDatCreation;
ICorDebugEval corEval; ICorDebugEval corEval;
ICorDebugFunction corFunction; ICorDebugFunction corFunction;
CorValuesGetter getArgs; CorValuesGetter getArgs;
@ -101,7 +99,6 @@ namespace Debugger
this.debugger = debugger; this.debugger = debugger;
this.corFunction = corFunction; this.corFunction = corFunction;
this.getArgs = getArgs; this.getArgs = getArgs;
this.debugeeStateIDatCreation = debugger.DebugeeStateID;
// Schedule the eval for evaluation // Schedule the eval for evaluation
debugger.AddEval(this); debugger.AddEval(this);
@ -115,7 +112,7 @@ namespace Debugger
/// <returns>True is setup was successful</returns> /// <returns>True is setup was successful</returns>
internal bool SetupEvaluation(Thread targetThread) internal bool SetupEvaluation(Thread targetThread)
{ {
if (!debugger.ManagedCallback.HandlingCallback) debugger.AssertPaused(); debugger.AssertPaused();
ICorDebugValue[] args = getArgs(); ICorDebugValue[] args = getArgs();

6
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Value.cs

@ -17,7 +17,7 @@ namespace Debugger
{ {
protected NDebugger debugger; protected NDebugger debugger;
protected ICorDebugValue corValue; protected ICorDebugValue corValue;
object debuggerSessionIDatCreation; object pauseSessionAtCreation;
public event EventHandler<ValueEventArgs> ValueChanged; public event EventHandler<ValueEventArgs> ValueChanged;
@ -38,7 +38,7 @@ namespace Debugger
/// </summary> /// </summary>
public bool IsExpired { public bool IsExpired {
get { get {
return debuggerSessionIDatCreation != debugger.SessionID; return pauseSessionAtCreation != debugger.PauseSession;
} }
} }
@ -106,7 +106,7 @@ namespace Debugger
if (corValue != null) { if (corValue != null) {
this.corValue = DereferenceUnbox(corValue); this.corValue = DereferenceUnbox(corValue);
} }
this.debuggerSessionIDatCreation = debugger.SessionID; this.pauseSessionAtCreation = debugger.PauseSession;
} }
public override string ToString() public override string ToString()

12
src/AddIns/Misc/Debugger/Debugger.Tests/Project/Src/DebuggerTests.cs

@ -527,22 +527,22 @@ namespace Debugger.Tests
Assert.AreEqual(typeof(UnavailableValue), subVars[1].Value.GetType()); Assert.AreEqual(typeof(UnavailableValue), subVars[1].Value.GetType());
debugger.StartEvaluation(); debugger.StartEvaluation();
WaitForPause(PausedReason.AllEvalsComplete, null); WaitForPause(PausedReason.EvalComplete, null);
Assert.AreEqual("private", subVars[1].Value.AsString); Assert.AreEqual("private", subVars[1].Value.AsString);
Assert.AreEqual(typeof(UnavailableValue), subVars[2].Value.GetType()); Assert.AreEqual(typeof(UnavailableValue), subVars[2].Value.GetType());
debugger.StartEvaluation(); debugger.StartEvaluation();
WaitForPause(PausedReason.AllEvalsComplete, null); WaitForPause(PausedReason.EvalComplete, null);
Assert.AreEqual("public", subVars[2].Value.AsString); Assert.AreEqual("public", subVars[2].Value.AsString);
Assert.AreEqual(typeof(UnavailableValue), subVars[3].Value.GetType()); Assert.AreEqual(typeof(UnavailableValue), subVars[3].Value.GetType());
debugger.StartEvaluation(); debugger.StartEvaluation();
WaitForPause(PausedReason.AllEvalsComplete, null); WaitForPause(PausedReason.EvalComplete, null);
Assert.AreEqual(typeof(UnavailableValue), subVars[3].Value.GetType()); Assert.AreEqual(typeof(UnavailableValue), subVars[3].Value.GetType());
Assert.AreEqual(typeof(UnavailableValue), subVars[4].Value.GetType()); Assert.AreEqual(typeof(UnavailableValue), subVars[4].Value.GetType());
debugger.StartEvaluation(); debugger.StartEvaluation();
WaitForPause(PausedReason.AllEvalsComplete, null); WaitForPause(PausedReason.EvalComplete, null);
Assert.AreEqual("static", subVars[4].Value.AsString); Assert.AreEqual("static", subVars[4].Value.AsString);
debugger.Continue(); debugger.Continue();
@ -569,7 +569,7 @@ namespace Debugger.Tests
if (var is PropertyVariable) { if (var is PropertyVariable) {
Assert.AreEqual(typeof(UnavailableValue), var.Value.GetType(), "Variable name: " + var.Name); Assert.AreEqual(typeof(UnavailableValue), var.Value.GetType(), "Variable name: " + var.Name);
debugger.StartEvaluation(); debugger.StartEvaluation();
WaitForPause(PausedReason.AllEvalsComplete, null); WaitForPause(PausedReason.EvalComplete, null);
Assert.AreEqual(false, var.Value.IsExpired, "Variable name: " + var.Name); Assert.AreEqual(false, var.Value.IsExpired, "Variable name: " + var.Name);
Assert.AreNotEqual(null, var.Value.AsString, "Variable name: " + var.Name); Assert.AreNotEqual(null, var.Value.AsString, "Variable name: " + var.Name);
} }
@ -584,7 +584,7 @@ namespace Debugger.Tests
} }
} }
debugger.StartEvaluation(); debugger.StartEvaluation();
WaitForPause(PausedReason.AllEvalsComplete, null); WaitForPause(PausedReason.EvalComplete, null);
debugger.Continue(); debugger.Continue();
debugger.WaitForPrecessExit(); debugger.WaitForPrecessExit();

Loading…
Cancel
Save