Browse Source

Redesigned debugger evaluation interface

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@728 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 20 years ago
parent
commit
6e62dad949
  1. 4
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj
  2. 3
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/DebuggerEvents/PausedReason.cs
  3. 22
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Internal/ManagedCallback.cs
  4. 16
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/NDebugger.cs
  5. 4
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs
  6. 92
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Eval.cs
  7. 21
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/EvalEventArgs.cs
  8. 58
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/EvalQueue.cs
  9. 108
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/NDebugger-Evals.cs
  10. 12
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PropertyVariable.cs

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

@ -88,9 +88,7 @@
<Compile Include="Src\Threads\ThreadEventArgs.cs" /> <Compile Include="Src\Threads\ThreadEventArgs.cs" />
<Compile Include="Src\Variables\ArrayVariable.cs" /> <Compile Include="Src\Variables\ArrayVariable.cs" />
<Compile Include="Src\Variables\BuiltInVariable.cs" /> <Compile Include="Src\Variables\BuiltInVariable.cs" />
<Compile Include="Src\Variables\Evals\CorDebugEvalEventArgs.cs" />
<Compile Include="Src\Variables\Evals\Eval.cs" /> <Compile Include="Src\Variables\Evals\Eval.cs" />
<Compile Include="Src\Variables\Evals\EvalQueue.cs" />
<Compile Include="Src\Variables\NullRefVariable.cs" /> <Compile Include="Src\Variables\NullRefVariable.cs" />
<Compile Include="Src\Variables\ObjectVariable.cs" /> <Compile Include="Src\Variables\ObjectVariable.cs" />
<Compile Include="Src\Variables\PropertyVariable.cs" /> <Compile Include="Src\Variables\PropertyVariable.cs" />
@ -203,6 +201,8 @@
<Compile Include="Src\Interop\CorDebug\tagSTATSTG.cs" /> <Compile Include="Src\Interop\CorDebug\tagSTATSTG.cs" />
<Compile Include="Src\Interop\MetaData\IMetaDataImport.cs" /> <Compile Include="Src\Interop\MetaData\IMetaDataImport.cs" />
<Compile Include="Src\Interop\MetaData\COR_FIELD_OFFSET.cs" /> <Compile Include="Src\Interop\MetaData\COR_FIELD_OFFSET.cs" />
<Compile Include="Src\Variables\Evals\EvalEventArgs.cs" />
<Compile Include="Src\Variables\Evals\NDebugger-Evals.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Content Include="README.TXT" /> <Content Include="README.TXT" />

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

@ -1,4 +1,4 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright> // <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license> // <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/> // <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
@ -9,6 +9,7 @@ namespace Debugger
{ {
public enum PausedReason:int public enum PausedReason:int
{ {
AllEvalsComplete,
StepComplete, StepComplete,
Breakpoint, Breakpoint,
Break, Break,

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

@ -28,8 +28,6 @@ namespace Debugger
Process callingProcess; Process callingProcess;
Thread callingThread; Thread callingThread;
public event EventHandler<CorDebugEvalEventArgs> CorDebugEvalCompleted;
public ManagedCallback(NDebugger debugger) public ManagedCallback(NDebugger debugger)
{ {
this.debugger = debugger; this.debugger = debugger;
@ -196,18 +194,26 @@ namespace Debugger
ExitCallback_Continue(); ExitCallback_Continue();
} }
public void EvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval eval) public void EvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval)
{ {
EnterCallback("EvalComplete", pThread); EnterCallback("EvalComplete", pThread);
if (CorDebugEvalCompleted != null) { // Let the eval know it that the CorEval has finished
CorDebugEvalCompleted(this, new CorDebugEvalEventArgs(debugger, eval)); // this will also remove the eval form PendingEvals collection
Eval eval = debugger.GetEval(corEval);
if (eval != null) {
eval.OnEvalComplete(new EvalEventArgs(debugger, eval));
} }
ExitCallback_Paused(PausedReason.EvalComplete); if (debugger.PendingEvals.Count > 0) {
debugger.SetupNextEvaluation();
ExitCallback_Continue();
} else {
ExitCallback_Paused(PausedReason.AllEvalsComplete);
}
} }
public void DebuggerError(ICorDebugProcess pProcess, int errorHR, uint errorCode) public void DebuggerError(ICorDebugProcess pProcess, int errorHR, uint errorCode)
{ {
EnterCallback("DebuggerError", pProcess); EnterCallback("DebuggerError", pProcess);

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

@ -1,4 +1,4 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright> // <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license> // <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/> // <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
@ -22,17 +22,9 @@ namespace Debugger
ICorDebug corDebug; ICorDebug corDebug;
ManagedCallback managedCallback; ManagedCallback managedCallback;
ManagedCallbackProxy managedCallbackProxy; ManagedCallbackProxy managedCallbackProxy;
ApartmentState requiredApartmentState; ApartmentState requiredApartmentState;
EvalQueue evalQueue;
internal EvalQueue EvalQueue {
get {
return evalQueue;
}
}
public ApartmentState RequiredApartmentState { public ApartmentState RequiredApartmentState {
get { get {
return requiredApartmentState; return requiredApartmentState;
@ -117,8 +109,6 @@ namespace Debugger
currentProcess = null; currentProcess = null;
evalQueue = new EvalQueue(this);
TraceMessage("Reset done"); TraceMessage("Reset done");
corDebug.Terminate(); corDebug.Terminate();

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

@ -1,4 +1,4 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright> // <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license> // <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/> // <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
@ -448,7 +448,7 @@ namespace Debugger
evalArgs = new ICorDebugValue[] {ThisVariable.CorValue}; evalArgs = new ICorDebugValue[] {ThisVariable.CorValue};
} }
Eval eval = new Eval(debugger, evalCorFunction, evalArgs); Eval eval = new Eval(debugger, evalCorFunction, evalArgs);
debugger.EvalQueue.AddEval(eval); debugger.AddEval(eval);
properties.Add(new PropertyVariable(debugger, eval, method.Name.Remove(0, 4))); properties.Add(new PropertyVariable(debugger, eval, method.Name.Remove(0, 4)));
} }
} }

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

@ -1,4 +1,4 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright> // <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license> // <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/> // <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
@ -9,76 +9,86 @@ using System;
using System.Collections; using System.Collections;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Debugger;
using Debugger.Interop.CorDebug; using Debugger.Interop.CorDebug;
using Debugger.Interop.MetaData; using Debugger.Interop.MetaData;
namespace Debugger namespace Debugger
{ {
class Eval /// <summary>
/// This class holds information about function evaluation.
/// </summary>
public class Eval
{ {
NDebugger debugger; NDebugger debugger;
ICorDebugEval corEval; ICorDebugEval corEval;
ICorDebugFunction corFunction; ICorDebugFunction corFunction;
ICorDebugValue[] args; ICorDebugValue[] args;
bool complete = false;
public event EventHandler<DebuggerEventArgs> EvalComplete; bool completed = false;
Variable result;
protected virtual void OnEvalComplete(DebuggerEventArgs e)
{ public event EventHandler<EvalEventArgs> EvalComplete;
if (EvalComplete != null) {
EvalComplete(this, e); /// <summary>
/// True if the evaluation has been completed.
/// </summary>
public bool Completed {
get {
return completed;
}
}
/// <summary>
/// The result of the evaluation if the evaluation is complete and has returned a value. Null otherwise.
/// </summary>
public Variable Result {
get {
if (completed) {
return result;
} else {
return null;
}
}
}
internal ICorDebugEval CorEval {
get {
return corEval;
} }
} }
public Eval(NDebugger debugger, ICorDebugFunction corFunction, ICorDebugValue[] args) internal Eval(NDebugger debugger, ICorDebugFunction corFunction, ICorDebugValue[] args)
{ {
this.debugger = debugger; this.debugger = debugger;
this.corFunction = corFunction; this.corFunction = corFunction;
this.args = args; this.args = args;
debugger.ManagedCallback.CorDebugEvalCompleted += new EventHandler<CorDebugEvalEventArgs>(CorDebugEvalCompletedInManagedCallback);
} }
/// <summary> /// <returns>True is setup was successful</returns>
/// Executes the evaluation and doesn't return until value is evaluated. internal bool SetupEvaluation()
///
///
/// </summary>
public void PerformEval()
{
AsyncPerformEval();
while (!complete) {
System.Windows.Forms.Application.DoEvents();
}
}
/// <summary>
/// Executes the evaluation and resumes debugger.
/// </summary>
public void AsyncPerformEval()
{ {
debugger.AssertPaused(); debugger.AssertPaused();
// TODO: What if this thread is not suitable?
debugger.CurrentThread.CorThread.CreateEval(out corEval); debugger.CurrentThread.CorThread.CreateEval(out corEval);
corEval.CallFunction(corFunction, (uint)args.Length, args); corEval.CallFunction(corFunction, (uint)args.Length, args);
debugger.Continue(); return true;
} }
public ICorDebugValue GetResult() protected internal virtual void OnEvalComplete(EvalEventArgs e)
{ {
completed = true;
ICorDebugValue corValue; ICorDebugValue corValue;
corEval.GetResult(out corValue); corEval.GetResult(out corValue);
return corValue; result = VariableFactory.CreateVariable(debugger, corValue, "eval result");
}
if (EvalComplete != null) {
void CorDebugEvalCompletedInManagedCallback(object sender, CorDebugEvalEventArgs e) EvalComplete(this, e);
{
if (e.CorDebugEval == corEval) {
complete = true;
OnEvalComplete(new DebuggerEventArgs(debugger));
} }
} }
} }

21
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/CorDebugEvalEventArgs.cs → src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/EvalEventArgs.cs

@ -1,4 +1,4 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright> // <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license> // <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/> // <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
@ -6,24 +6,29 @@
// </file> // </file>
using System; using System;
using Debugger.Interop.CorDebug;
namespace Debugger namespace Debugger
{ {
[Serializable] [Serializable]
class CorDebugEvalEventArgs : DebuggerEventArgs public class EvalEventArgs : DebuggerEventArgs
{ {
ICorDebugEval corDebugEval; Eval eval;
public ICorDebugEval CorDebugEval { public Eval Eval {
get { get {
return corDebugEval; return eval;
} }
} }
public CorDebugEvalEventArgs(NDebugger debugger, ICorDebugEval corDebugEval): base(debugger) public Variable Result {
get {
return eval.Result;
}
}
public EvalEventArgs(NDebugger debugger, Eval eval): base(debugger)
{ {
this.corDebugEval = corDebugEval; this.eval = eval;
} }
} }
} }

58
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/EvalQueue.cs

@ -1,58 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections;
using System.Runtime.InteropServices;
using Debugger.Interop.CorDebug;
using Debugger.Interop.MetaData;
namespace Debugger
{
class EvalQueue
{
NDebugger debugger;
ArrayList waitingEvals = new ArrayList();
public event EventHandler<DebuggerEventArgs> AllEvalsComplete;
public EvalQueue(NDebugger debugger)
{
this.debugger = debugger;
}
public void AddEval(Eval eval)
{
waitingEvals.Add(eval);
}
public void PerformAllEvals()
{
while (waitingEvals.Count > 0) {
PerformNextEval();
}
}
public void PerformNextEval()
{
if (waitingEvals.Count == 0) {
throw new DebuggerException("No eval in queue to perform.");
}
Eval eval = (Eval)waitingEvals[0];
waitingEvals.Remove(eval);
eval.PerformEval();
if (waitingEvals.Count == 0) {
if (AllEvalsComplete != null) {
AllEvalsComplete(this, new DebuggerEventArgs(debugger));
}
}
}
}
}

108
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/NDebugger-Evals.cs

@ -0,0 +1,108 @@
// <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
using System.Collections.Generic;
using Debugger.Interop.CorDebug;
namespace Debugger
{
public partial class NDebugger
{
List<Eval> pendingEvalsCollection = new List<Eval>();
public event EventHandler<EvalEventArgs> EvalAdded;
public event EventHandler<EvalEventArgs> EvalCompleted;
public event EventHandler<DebuggerEventArgs> AllEvelsCompleted;
protected virtual void OnEvalAdded(EvalEventArgs e)
{
if (EvalAdded != null) {
EvalAdded(this, e);
}
}
protected virtual void OnEvalCompleted(EvalEventArgs e)
{
if (EvalCompleted != null) {
EvalCompleted(this, e);
}
}
protected virtual void OnAllEvelsCompleted(DebuggerEventArgs e)
{
if (AllEvelsCompleted != null) {
AllEvelsCompleted(this, e);
}
}
public IList<Eval> PendingEvals {
get {
return pendingEvalsCollection.AsReadOnly();
}
}
internal Eval GetEval(ICorDebugEval corEval) {
return pendingEvalsCollection.Find(delegate (Eval eval) {return eval.CorEval == corEval;});
}
/// <summary>
/// Adds eval to a list of pending evals.
/// The evaluation of pending evals should be started by calling StartEvaluation in paused stated.
/// The the debugger will continue until all evals are done and will stop with PausedReason.AllEvalsComplete
/// </summary>
internal Eval AddEval(Eval eval)
{
pendingEvalsCollection.Add(eval);
eval.EvalComplete += EvalComplete;
OnEvalAdded(new EvalEventArgs(this, eval));
return eval;
}
// Removes eval from collection and fires events for the eval
void EvalComplete(object sender, EvalEventArgs e)
{
pendingEvalsCollection.Remove(e.Eval);
OnEvalCompleted(e);
if (pendingEvalsCollection.Count == 0) {
OnAllEvelsCompleted(new DebuggerEventArgs(this));
}
}
// return true if there was eval to setup and it was setup
internal bool SetupNextEvaluation()
{
if (pendingEvalsCollection.Count > 0) {
return pendingEvalsCollection[0].SetupEvaluation();
} else {
return false;
}
}
/// <summary>
/// Starts evaluation of pending evals.
/// </summary>
public bool StartEvaluation()
{
this.AssertPaused();
// TODO: Investigate other threads, are they alowed to run?
if (SetupNextEvaluation()) {
this.Continue();
return true;
} else {
return false;
}
}
}
}

12
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PropertyVariable.cs

@ -1,4 +1,4 @@
// <file> // <file>
// <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright> // <copyright see="prj:///doc/copyright.txt">2002-2005 AlphaSierraPapa</copyright>
// <license see="prj:///doc/license.txt">GNU General Public License</license> // <license see="prj:///doc/license.txt">GNU General Public License</license>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/> // <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
@ -20,7 +20,7 @@ namespace Debugger
internal PropertyVariable(NDebugger debugger, Eval eval, string name):base(debugger, null, name) internal PropertyVariable(NDebugger debugger, Eval eval, string name):base(debugger, null, name)
{ {
this.eval = eval; this.eval = eval;
eval.EvalComplete += new EventHandler<DebuggerEventArgs>(EvalComplete); eval.EvalComplete += new EventHandler<EvalEventArgs>(EvalComplete);
} }
public bool IsEvaluated { public bool IsEvaluated {
@ -71,7 +71,7 @@ namespace Debugger
/// </summary> /// </summary>
public void Evaluate() public void Evaluate()
{ {
eval.PerformEval(); //eval.PerformEval();
} }
/// <summary> /// <summary>
@ -79,12 +79,12 @@ namespace Debugger
/// </summary> /// </summary>
public void AsyncEvaluate() public void AsyncEvaluate()
{ {
eval.AsyncPerformEval(); //eval.AsyncPerformEval();
} }
void EvalComplete(object sender, DebuggerEventArgs args) void EvalComplete(object sender, EvalEventArgs args)
{ {
currentValue = VariableFactory.CreateVariable(debugger, eval.GetResult(), Name); currentValue = VariableFactory.CreateVariable(debugger, eval.Result.CorValue, Name);
OnValueEvaluated(); OnValueEvaluated();
} }

Loading…
Cancel
Save