Browse Source

Removed SelectedThread and SelectedStackFrame from the debugger core. The addin now has to track those.

The thread to be used for evaluation has to be explicitly passed to debugger calls.
newNRvisualizers
David Srbecký 14 years ago
parent
commit
f0ab856167
  1. 63
      src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs
  2. 6
      src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionExtensionMethods.cs
  3. 23
      src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs
  4. 46
      src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs
  5. 38
      src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs
  6. 2
      src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs
  7. 12
      src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs
  8. 11
      src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs
  9. 25
      src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs
  10. 15
      src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs
  11. 29
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs
  12. 3
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs
  13. 54
      src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs
  14. 23
      src/AddIns/Debugger/Debugger.AddIn/Pads/WatchInputBox.xaml.cs
  15. 10
      src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
  16. 5
      src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs
  17. 318
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
  18. 30
      src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs
  19. 13
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs
  20. 4
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs
  21. 2
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphControl.xaml.cs
  22. 10
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs
  23. 2
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/AtomicType.cs
  24. 14
      src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs
  25. 135
      src/AddIns/Debugger/Debugger.Core/Eval.cs
  26. 16
      src/AddIns/Debugger/Debugger.Core/Exception.cs
  27. 13
      src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs
  28. 8
      src/AddIns/Debugger/Debugger.Core/MetaData/DebugConstructorInfo.cs
  29. 4
      src/AddIns/Debugger/Debugger.Core/MetaData/DebugFieldInfo.cs
  30. 18
      src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs
  31. 12
      src/AddIns/Debugger/Debugger.Core/MetaData/DebugPropertyInfo.cs
  32. 17
      src/AddIns/Debugger/Debugger.Core/NDebugger.cs
  33. 95
      src/AddIns/Debugger/Debugger.Core/Process.cs
  34. 38
      src/AddIns/Debugger/Debugger.Core/Thread.cs
  35. 203
      src/AddIns/Debugger/Debugger.Core/Value.cs
  36. 18
      src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs
  37. 8
      src/AddIns/Debugger/Debugger.Tests/Tests/AppDomain_Tests.cs
  38. 8
      src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs
  39. 82
      src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_Stepping.cs
  40. 4
      src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminateRunningProcess.cs
  41. 8
      src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs
  42. 6
      src/AddIns/Debugger/Debugger.Tests/Tests/DynamicCode.cs
  43. 24
      src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs
  44. 4
      src/AddIns/Debugger/Debugger.Tests/Tests/Process_MemoryReadWrite.cs
  45. 10
      src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Callstack.cs
  46. 12
      src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Lifetime.cs
  47. 6
      src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_SetIP.cs
  48. 10
      src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_VariablesLifetime.cs
  49. 15
      src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs
  50. 6
      src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs

63
src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs

@ -6,10 +6,10 @@ using System.Collections; @@ -6,10 +6,10 @@ using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Debugger;
using Debugger.MetaData;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.SharpDevelop.Services;
namespace ICSharpCode.NRefactory.Visitors
{
@ -51,6 +51,10 @@ namespace ICSharpCode.NRefactory.Visitors @@ -51,6 +51,10 @@ namespace ICSharpCode.NRefactory.Visitors
get { return context; }
}
public Thread EvalThread {
get { return this.Context.Thread; }
}
ExpressionEvaluator(StackFrame context)
{
this.context = context;
@ -76,19 +80,12 @@ namespace ICSharpCode.NRefactory.Visitors @@ -76,19 +80,12 @@ namespace ICSharpCode.NRefactory.Visitors
return Evaluate(Parse(code, language), context, data);
}
public static Value Evaluate(INode code, Process context)
{
if (context.SelectedStackFrame == null && context.SelectedThread.MostRecentStackFrame == null)
// This can happen when needed 'dll' is missing. This causes an exception dialog to be shown even before the applicaiton starts
throw new GetValueException("Can not evaluate because the process has no managed stack frames");
return Evaluate(code, context.GetCurrentExecutingFrame());
}
public static Value Evaluate(INode code, StackFrame context, object data = null)
{
if (context == null) throw new ArgumentNullException("context");
if (context.IsInvalid) throw new DebuggerException("The context is no longer valid");
if (context == null)
throw new GetValueException("Invalid stackframe");
if (context.IsInvalid)
throw new DebuggerException("The context is no longer valid");
TypedValue val = new ExpressionEvaluator(context).Evaluate(code, false, data);
if (val == null)
@ -113,7 +110,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -113,7 +110,7 @@ namespace ICSharpCode.NRefactory.Visitors
return astExpression;
}
public static string FormatValue(Value val)
public static string FormatValue(Thread evalThread, Value val)
{
if (val == null) {
return null;
@ -127,7 +124,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -127,7 +124,7 @@ namespace ICSharpCode.NRefactory.Visitors
foreach(Value item in val.GetArrayElements()) {
if (!first) sb.Append(", ");
first = false;
sb.Append(FormatValue(item));
sb.Append(FormatValue(evalThread, item));
}
sb.Append("}");
return sb.ToString();
@ -135,13 +132,13 @@ namespace ICSharpCode.NRefactory.Visitors @@ -135,13 +132,13 @@ namespace ICSharpCode.NRefactory.Visitors
StringBuilder sb = new StringBuilder();
sb.Append(val.Type.Name);
sb.Append(" {");
val = val.GetPermanentReference();
int count = (int)val.GetMemberValue("Count").PrimitiveValue;
val = val.GetPermanentReference(evalThread);
int count = (int)val.GetMemberValue(evalThread, "Count").PrimitiveValue;
for(int i = 0; i < count; i++) {
if (i > 0) sb.Append(", ");
DebugPropertyInfo itemProperty = (DebugPropertyInfo)val.Type.GetProperty("Item");
Value item = val.GetPropertyValue(itemProperty, Eval.CreateValue(val.AppDomain, i));
sb.Append(FormatValue(item));
Value item = val.GetPropertyValue(evalThread, itemProperty, Eval.CreateValue(evalThread, i));
sb.Append(FormatValue(evalThread, item));
}
sb.Append("}");
return sb.ToString();
@ -152,7 +149,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -152,7 +149,7 @@ namespace ICSharpCode.NRefactory.Visitors
} else if (val.Type.IsPrimitive) {
return val.PrimitiveValue.ToString();
} else {
return val.InvokeToString();
return val.InvokeToString(evalThread);
}
}
@ -170,7 +167,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -170,7 +167,7 @@ namespace ICSharpCode.NRefactory.Visitors
try {
val = (TypedValue)expression.AcceptVisitor(this, data);
if (val != null && permRef)
val = new TypedValue(val.Value.GetPermanentReference(), val.Type);
val = new TypedValue(val.Value.GetPermanentReference(this.EvalThread), val.Type);
} catch (NotImplementedException e) {
throw new EvaluateException(expression, "Language feature not implemented: " + e.Message);
} finally {
@ -254,7 +251,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -254,7 +251,7 @@ namespace ICSharpCode.NRefactory.Visitors
TypedValue CreateValue(object primitiveValue)
{
Value val = Eval.CreateValue(context.AppDomain, primitiveValue);
Value val = Eval.CreateValue(this.EvalThread, primitiveValue);
return new TypedValue(val, val.Type);
}
@ -300,7 +297,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -300,7 +297,7 @@ namespace ICSharpCode.NRefactory.Visitors
if (!left.Value.IsReference && left.Type.FullName != right.Type.FullName) {
throw new GetValueException(string.Format("Type {0} expected, {1} seen", left.Type.FullName, right.Type.FullName));
}
left.Value.SetValue(right.Value);
left.Value.SetValue(this.EvalThread, right.Value);
return right;
}
@ -377,14 +374,14 @@ namespace ICSharpCode.NRefactory.Visitors @@ -377,14 +374,14 @@ namespace ICSharpCode.NRefactory.Visitors
if (thisValue != null) {
IDebugMemberInfo instMember = (IDebugMemberInfo)thisValue.Type.GetMember<MemberInfo>(identifier, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, DebugType.IsFieldOrNonIndexedProperty);
if (instMember != null)
return new TypedValue(Value.GetMemberValue(thisValue.Value, (MemberInfo)instMember), instMember.MemberType);
return new TypedValue(Value.GetMemberValue(this.EvalThread, thisValue.Value, (MemberInfo)instMember), instMember.MemberType);
}
// Static class members
foreach(DebugType declaringType in ((DebugType)context.MethodInfo.DeclaringType).GetSelfAndDeclaringTypes()) {
IDebugMemberInfo statMember = (IDebugMemberInfo)declaringType.GetMember<MemberInfo>(identifier, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static, DebugType.IsFieldOrNonIndexedProperty);
if (statMember != null)
return new TypedValue(Value.GetMemberValue(null, (MemberInfo)statMember), statMember.MemberType);
return new TypedValue(Value.GetMemberValue(this.EvalThread, null, (MemberInfo)statMember), statMember.MemberType);
}
throw new GetValueException("Identifier \"" + identifier + "\" not found in this context");
@ -418,7 +415,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -418,7 +415,7 @@ namespace ICSharpCode.NRefactory.Visitors
if (pi == null)
throw new GetValueException("The object does not have an indexer property");
return new TypedValue(
target.Value.GetPropertyValue(pi, GetValues(indexes)),
target.Value.GetPropertyValue(this.EvalThread, pi, GetValues(indexes)),
(DebugType)pi.PropertyType
);
}
@ -456,7 +453,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -456,7 +453,7 @@ namespace ICSharpCode.NRefactory.Visitors
MethodInfo method = targetType.GetMethod(methodName, DebugType.BindingFlagsAllInScope, null, GetTypes(args), null);
if (method == null)
throw new GetValueException("Method " + methodName + " not found");
Value retVal = Value.InvokeMethod(target != null ? target.Value : null, method, GetValues(args));
Value retVal = Value.InvokeMethod(this.EvalThread, target != null ? target.Value : null, method, GetValues(args));
if (retVal == null)
return null;
return new TypedValue(retVal, (DebugType)method.ReturnType);
@ -469,10 +466,10 @@ namespace ICSharpCode.NRefactory.Visitors @@ -469,10 +466,10 @@ namespace ICSharpCode.NRefactory.Visitors
DebugType type = objectCreateExpression.CreateType.ResolveType(context.AppDomain);
List<TypedValue> ctorArgs = EvaluateAll(objectCreateExpression.Parameters);
ConstructorInfo ctor = type.GetConstructor(BindingFlags.Default, null, CallingConventions.Any, GetTypes(ctorArgs), null);
DebugConstructorInfo ctor = (DebugConstructorInfo)type.GetConstructor(BindingFlags.Default, null, CallingConventions.Any, GetTypes(ctorArgs), null);
if (ctor == null)
throw new EvaluateException(objectCreateExpression, "Constructor not found");
Value val = (Value)ctor.Invoke(GetValues(ctorArgs));
Value val = Value.InvokeMethod(this.EvalThread, null, ctor.MethodInfo, GetValues(ctorArgs));
return new TypedValue(val, type);
}
@ -488,14 +485,14 @@ namespace ICSharpCode.NRefactory.Visitors @@ -488,14 +485,14 @@ namespace ICSharpCode.NRefactory.Visitors
} else if (!arrayCreateExpression.ArrayInitializer.IsNull) {
length = arrayCreateExpression.ArrayInitializer.CreateExpressions.Count;
}
Value array = Eval.NewArray((DebugType)type.GetElementType(), (uint)length, null);
Value array = Eval.NewArray(this.EvalThread, (DebugType)type.GetElementType(), (uint)length, null);
if (!arrayCreateExpression.ArrayInitializer.IsNull) {
List<Expression> inits = arrayCreateExpression.ArrayInitializer.CreateExpressions;
if (inits.Count != length)
throw new EvaluateException(arrayCreateExpression, "Incorrect initializer length");
for(int i = 0; i < length; i++) {
TypedValue init = EvaluateAs(inits[i], (DebugType)type.GetElementType());
array.SetArrayElement(new int[] { i }, init.Value);
array.SetArrayElement(this.EvalThread, new int[] { i }, init.Value);
}
}
return new TypedValue(array, type);
@ -522,7 +519,7 @@ namespace ICSharpCode.NRefactory.Visitors @@ -522,7 +519,7 @@ namespace ICSharpCode.NRefactory.Visitors
if (memberInfos.Length == 0)
throw new GetValueException("Member \"" + memberReferenceExpression.MemberName + "\" not found");
return new TypedValue(
Value.GetMemberValue(target != null ? target.Value : null, memberInfos[0]),
Value.GetMemberValue(this.EvalThread, target != null ? target.Value : null, memberInfos[0]),
((IDebugMemberInfo)memberInfos[0]).MemberType
);
}
@ -749,8 +746,8 @@ namespace ICSharpCode.NRefactory.Visitors @@ -749,8 +746,8 @@ namespace ICSharpCode.NRefactory.Visitors
if (op == BinaryOperatorType.Add) {
if (left.Type.Is<string>() || right.Type.Is<string>()) {
string a = left.Value.IsNull ? string.Empty : left.Value.InvokeToString();
string b = right.Value.IsNull ? string.Empty : right.Value.InvokeToString();
string a = left.Value.IsNull ? string.Empty : left.Value.InvokeToString(this.EvalThread);
string b = right.Value.IsNull ? string.Empty : right.Value.InvokeToString(this.EvalThread);
return CreateValue(a + b);
}
}

6
src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionExtensionMethods.cs

@ -4,20 +4,20 @@ @@ -4,20 +4,20 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Debugger;
using Debugger.MetaData;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.PrettyPrinter;
using ICSharpCode.NRefactory.Visitors;
using ICSharpCode.SharpDevelop.Services;
namespace ICSharpCode.NRefactory.Ast
{
public static class ExpressionExtensionMethods
{
public static Value Evaluate(this Expression expression, Process process)
public static Value Evaluate(this Expression expression)
{
return ExpressionEvaluator.Evaluate(expression, process);
return ExpressionEvaluator.Evaluate(expression, WindowsDebugger.CurrentStackFrame);
}
static M SetStaticType<M>(this M expr, DebugType type) where M: INode

23
src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs

@ -17,36 +17,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -17,36 +17,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public class BreakPointsPad : BookmarkPadBase
{
WindowsDebugger debugger;
NDebugger debuggerCore;
public BreakPointsPad()
{
InitializeComponents();
myPanel.Children.Add(CreateToolBar());
CreateColumns();
}
void InitializeComponents()
{
debugger = (WindowsDebugger)DebuggerService.CurrentDebugger;
if (debugger.ServiceInitialized) {
InitializeDebugger();
} else {
debugger.Initialize += delegate {
InitializeDebugger();
};
}
}
public void InitializeDebugger()
{
debuggerCore = debugger.DebuggerCore;
}
protected override ToolBar CreateToolBar()
{
ToolBar toolbar = ToolBarService.CreateToolBar(myPanel, this, "/SharpDevelop/Pads/BreakpointPad/Toolbar");

46
src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs

@ -31,7 +31,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -31,7 +31,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
((GridView)view.View).Columns[2].Width = DebuggingOptions.Instance.ShowLineNumbers ? 50d : 0d;
WindowsDebugger.RefreshingPads += RefreshPad;
WindowsDebugger.RefreshPads();
RefreshPad();
}
ContextMenu CreateMenu()
@ -96,17 +96,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -96,17 +96,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
if (item == null)
return;
Process debuggedProcess = item.Process;
if (debuggedProcess.IsPaused) {
if (item.Frame != null && debuggedProcess.SelectedThread != null) {
if (item.Frame.Process.IsPaused) {
if (item.Frame != null) {
// check for options - if these options are enabled, selecting the frame should not continue
if (!item.Frame.HasSymbols && !debuggedProcess.Options.DecompileCodeWithoutSymbols) {
if (!item.Frame.HasSymbols && !item.Frame.Process.Options.DecompileCodeWithoutSymbols) {
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.CallStack.CannotSwitchWithoutSymbolsOrDecompiledCodeOptions}",
"${res:MainWindow.Windows.Debug.CallStack.FunctionSwitch}");
return;
}
debuggedProcess.SelectedThread.SelectedStackFrame = item.Frame;
WindowsDebugger.CurrentStackFrame = item.Frame;
WindowsDebugger.RefreshPads();
}
} else {
@ -122,30 +120,27 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -122,30 +120,27 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
}
void RefreshPad(object sender, DebuggerEventArgs dbg)
void RefreshPad()
{
Process debuggedProcess = dbg.Process;
if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedThread == null) {
Thread thead = WindowsDebugger.CurrentThread;
if (thead == null) {
view.ItemsSource = null;
return;
}
var items = new ObservableCollection<CallStackItem>();
using(new PrintTimes("Callstack refresh")) {
} else {
var items = new ObservableCollection<CallStackItem>();
bool showExternalMethods = DebuggingOptions.Instance.ShowExternalMethods;
bool previousItemIsExternalMethod = false;
bool previousItemIsExternalMethod = false;
WindowsDebugger.CurrentProcess.EnqueueForEach(
Dispatcher,
thead.GetCallstack(100),
f => items.AddIfNotNull(CreateItem(f, showExternalMethods, ref previousItemIsExternalMethod))
);
debuggedProcess.EnqueueForEach(
Dispatcher,
debuggedProcess.SelectedThread.GetCallstack(100),
f => items.AddIfNotNull(CreateItem(debuggedProcess, f, showExternalMethods, ref previousItemIsExternalMethod))
);
view.ItemsSource = items;
}
view.ItemsSource = items;
}
CallStackItem CreateItem(Process process, StackFrame frame, bool showExternalMethods, ref bool previousItemIsExternalMethod)
CallStackItem CreateItem(StackFrame frame, bool showExternalMethods, ref bool previousItemIsExternalMethod)
{
CallStackItem item;
@ -180,8 +175,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -180,8 +175,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
previousItemIsExternalMethod = true;
}
item.Process = process;
return item;
}
@ -239,7 +232,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -239,7 +232,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
public class CallStackItem
{
public Process Process { get; set; }
public string Name { get; set; }
public string Language { get; set; }
public StackFrame Frame { get; set; }

38
src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs

@ -46,21 +46,21 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -46,21 +46,21 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
string Evaluate(string code)
{
Process process = WindowsDebugger.CurrentProcess;
if (process == null) {
StackFrame frame = WindowsDebugger.CurrentStackFrame;
if (process == null)
return "No process is being debugged";
}
if (process.IsRunning) {
if (process.IsRunning)
return "The process is running";
}
if (frame == null)
return "No current execution frame";
try {
StackFrame frame = process.GetCurrentExecutingFrame();
if (frame == null) return "No current execution frame";
object data = ((WindowsDebugger)DebuggerService.CurrentDebugger).debuggerDecompilerService.GetLocalVariableIndex(frame.MethodInfo.DeclaringType.MetadataToken,
frame.MethodInfo.MetadataToken,
code);
Value val = ExpressionEvaluator.Evaluate(code, SelectedLanguage, frame, data);
return ExpressionEvaluator.FormatValue(val);
return ExpressionEvaluator.FormatValue(WindowsDebugger.EvalThread, val);
} catch (GetValueException e) {
return e.Message;
}
@ -99,27 +99,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -99,27 +99,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
protected override void AbstractConsolePadTextEntered(object sender, TextCompositionEventArgs e)
{
Process process = WindowsDebugger.CurrentProcess;
if (process == null || process.IsRunning)
return;
StackFrame frame = process.GetCurrentExecutingFrame();
if (frame == null)
return;
foreach (char ch in e.Text) {
if (ch == '.') {
ShowDotCompletion(process, console.CommandText);
}
}
StackFrame frame = WindowsDebugger.CurrentStackFrame;
if (e.Text == "." && frame != null)
ShowDotCompletion(frame, console.CommandText);
}
void ShowDotCompletion(Process process, string currentText)
void ShowDotCompletion(StackFrame frame, string currentText)
{
StackFrame frame = process.GetCurrentExecutingFrame();
if (frame == null)
return;
var seg = frame.NextStatement;
if (seg == null)
return;

2
src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs

@ -42,7 +42,7 @@ namespace Debugger.AddIn.Pads.Controls @@ -42,7 +42,7 @@ namespace Debugger.AddIn.Pads.Controls
protected override void LoadChildren()
{
if (this.Node.GetChildren != null) {
var process = ((WindowsDebugger)DebuggerService.CurrentDebugger).DebuggedProcess;
var process = WindowsDebugger.CurrentProcess;
process.EnqueueWork(Dispatcher.CurrentDispatcher, () => Children.AddRange(this.Node.GetChildren().Select(node => node.ToSharpTreeNode())));
}
}

12
src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs

@ -134,16 +134,14 @@ namespace Debugger.AddIn.Pads.Controls @@ -134,16 +134,14 @@ namespace Debugger.AddIn.Pads.Controls
private void consoleControl_TextAreaTextEntered(object sender, TextCompositionEventArgs e)
{
foreach (char ch in e.Text) {
if (ch == '.') {
ShowDotCompletion(console.CommandText);
}
}
StackFrame frame = WindowsDebugger.CurrentStackFrame;
if (e.Text == "." && frame != null)
ShowDotCompletion(frame, console.CommandText);
}
private void ShowDotCompletion(string currentText)
private void ShowDotCompletion(StackFrame frame, string currentText)
{
var seg = WindowsDebugger.CurrentProcess.SelectedStackFrame.NextStatement;
var seg = frame.NextStatement;
var expressionFinder = ParserService.GetExpressionFinder(seg.Filename);
var info = ParserService.GetParseInformation(seg.Filename);

11
src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs

@ -37,7 +37,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -37,7 +37,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
ResourceService.LanguageChanged += delegate { RedrawContent(); };
WindowsDebugger.RefreshingPads += RefreshPad;
WindowsDebugger.RefreshPads();
RefreshPad();
}
public void RedrawContent()
@ -55,13 +55,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -55,13 +55,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
new Binding { Path = new PropertyPath("Symbols") }, 130);
}
void RefreshPad(object sender, DebuggerEventArgs dbg)
void RefreshPad()
{
Process debuggedProcess = dbg.Process;
Process process = WindowsDebugger.CurrentProcess;
loadedModules.Clear();
if (debuggedProcess != null) {
foreach(Module module in debuggedProcess.Modules) {
if (process != null) {
foreach(Module module in process.Modules) {
loadedModules.Add(new ModuleModel(module));
}
}

25
src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -34,7 +34,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
panel.Children.Add(localVarList);
WindowsDebugger.RefreshingPads += RefreshPad;
WindowsDebugger.RefreshPads();
RefreshPad();
}
/// <remarks>Always check if Instance is null, might be null if pad is not opened!</remarks>
@ -42,32 +42,19 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -42,32 +42,19 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
get { return instance; }
}
void RefreshPad(object sender, DebuggerEventArgs dbg)
void RefreshPad()
{
Process debuggedProcess = dbg.Process;
StackFrame frame = WindowsDebugger.CurrentStackFrame;
if (debuggedProcess == null || debuggedProcess.IsRunning) {
if (frame == null) {
localVarList.WatchItems.Clear();
return;
}
LoggingService.Info("Local Variables refresh");
try {
StackFrame frame = debuggedProcess.GetCurrentExecutingFrame();
} else {
localVarList.WatchItems.Clear();
if (frame == null) return;
debuggedProcess.EnqueueForEach(
frame.Process.EnqueueForEach(
Dispatcher.CurrentDispatcher,
ValueNode.GetLocalVariables().ToList(),
n => localVarList.WatchItems.Add(n.ToSharpTreeNode())
);
} catch (Exception ex) {
if (debuggedProcess == null || debuggedProcess.HasExited) {
// Process unexpectedly exited
} else {
MessageService.ShowException(ex);
}
}
}
}

15
src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs

@ -35,7 +35,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -35,7 +35,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
panel.Children.Add(objectGraphControl);
WindowsDebugger.RefreshingPads += RefreshPad;
WindowsDebugger.RefreshPads();
RefreshPad();
}
/// <remarks>Always check if Instance is null, might be null if pad is not opened!</remarks>
@ -43,21 +43,18 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -43,21 +43,18 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
get { return instance; }
}
protected void RefreshPad(object sender, DebuggerEventArgs dbg)
void RefreshPad()
{
Process debuggedProcess = dbg.Process;
// BUG: if pad window is undocked and floats standalone, IsVisible == false (so pad won't refresh)
// REQUEST: need to refresh when pad becomes visible -> VisibleChanged event?
if (!objectGraphControl.IsVisible)
{
if (!objectGraphControl.IsVisible) {
return;
}
if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedStackFrame == null) {
if (WindowsDebugger.CurrentStackFrame == null) {
this.objectGraphControl.Clear();
return;
} else {
this.objectGraphControl.RefreshView();
}
this.objectGraphControl.RefreshView();
}
}
}

29
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs

@ -60,14 +60,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -60,14 +60,14 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
panel.Children.Add(surface);
WindowsDebugger.RefreshingPads += RefreshPad;
WindowsDebugger.RefreshPads();
RefreshPad();
DebuggerService.DebugStarted += OnReset;
DebuggerService.DebugStopped += OnReset;
}
protected void RefreshPad(object sender, DebuggerEventArgs dbg)
protected void RefreshPad()
{
Process debuggedProcess = dbg.Process;
Process debuggedProcess = WindowsDebugger.CurrentProcess;
if (debuggedProcess == null || debuggedProcess.IsRunning) {
return;
@ -304,7 +304,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -304,7 +304,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
commonParent.Process = debuggedProcess;
commonParent.StackSelected += OnThreadStackSelected;
commonParent.FrameSelected += OnFrameSelected;
commonParent.IsSelected = commonParent.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
commonParent.IsSelected = commonParent.ThreadIds.Contains(WindowsDebugger.CurrentThread.ID);
// add new children
foreach (var stack in listOfCurrentStacks) {
if (stack.ItemCollection.Count == 0)
@ -433,6 +433,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -433,6 +433,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
void CreateThreadStack(Thread thread)
{
Process debuggedProcess = thread.Process;
Thread currentThread = WindowsDebugger.CurrentThread;
var items = CreateItems(thread);
if (items == null || items.Count == 0)
@ -445,10 +446,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -445,10 +446,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
threadStack.ItemCollection = items;
threadStack.UpdateThreadIds(parallelStacksView == ParallelStacksView.Tasks, thread.ID);
if (debuggedProcess.SelectedThread != null) {
threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
if (currentThread != null) {
threadStack.IsSelected = threadStack.ThreadIds.Contains(currentThread.ID);
if (selectedFrame == null)
selectedFrame = debuggedProcess.SelectedStackFrame;
selectedFrame = WindowsDebugger.CurrentStackFrame;
}
currentThreadStacks.Add(threadStack);
@ -488,10 +489,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -488,10 +489,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
threadStack.ItemCollection = result.Clone();
threadStack.UpdateThreadIds(true, frame.Thread.ID);
if (debuggedProcess.SelectedThread != null) {
threadStack.IsSelected = threadStack.ThreadIds.Contains(debuggedProcess.SelectedThread.ID);
if (WindowsDebugger.CurrentThread != null) {
threadStack.IsSelected = threadStack.ThreadIds.Contains(WindowsDebugger.CurrentThread.ID);
if (selectedFrame == null)
selectedFrame = debuggedProcess.SelectedStackFrame;
selectedFrame = WindowsDebugger.CurrentStackFrame;
}
currentThreadStacks.Add(threadStack);
@ -531,10 +532,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -531,10 +532,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
lastItemIsExternalMethod = true;
}
if (frame.Thread.SelectedStackFrame != null &&
frame.Thread.ID == WindowsDebugger.CurrentProcess.SelectedThread.ID &&
frame.Thread.SelectedStackFrame.IP == frame.IP &&
frame.Thread.SelectedStackFrame.GetMethodName() == frame.GetMethodName()) {
if (frame.Thread.MostRecentStackFrame != null &&
frame.Thread.ID == WindowsDebugger.CurrentThread.ID &&
frame.Thread.MostRecentStackFrame.IP == frame.IP &&
frame.Thread.MostRecentStackFrame.GetMethodName() == frame.GetMethodName()) {
model.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source;
model.IsRunningStackFrame = true;
} else {

3
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs

@ -14,6 +14,7 @@ using ICSharpCode.Core.Presentation; @@ -14,6 +14,7 @@ using ICSharpCode.Core.Presentation;
using ICSharpCode.NRefactory;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Gui.Pads;
using ICSharpCode.SharpDevelop.Services;
namespace Debugger.AddIn.Pads.ParallelPad
{
@ -233,7 +234,7 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -233,7 +234,7 @@ namespace Debugger.AddIn.Pads.ParallelPad
foreach (var id in ThreadIds) {
MenuItem m = new MenuItem();
m.IsCheckable = true;
m.IsChecked = id == Process.SelectedThread.ID;
m.IsChecked = id == WindowsDebugger.CurrentThread.ID;
m.Click += delegate(object sender, RoutedEventArgs e) {
var menuItem = e.OriginalSource as MenuItem;
SelectFrame((uint)menuItem.Tag, item);

54
src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs

@ -45,7 +45,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -45,7 +45,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
ResourceService.LanguageChanged += delegate { RedrawContent(); };
WindowsDebugger.RefreshingPads += RefreshPad;
WindowsDebugger.RefreshPads();
RefreshPad();
}
public void RedrawContent()
@ -68,53 +68,35 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -68,53 +68,35 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
80);
}
protected void RefreshPad(object sender, DebuggerEventArgs dbg)
protected void RefreshPad()
{
Process debuggedProcess = dbg.Process;
Process process = WindowsDebugger.CurrentProcess;
if (debuggedProcess == null || debuggedProcess.IsRunning) {
if (process == null || process.IsRunning) {
runningThreads.Clear();
return;
} else {
process.EnqueueForEach(
Dispatcher.CurrentDispatcher,
process.Threads.ToList(),
t => AddThread(t)
);
}
LoggingService.Info("Threads refresh");
debuggedProcess.EnqueueForEach(
Dispatcher.CurrentDispatcher,
debuggedProcess.Threads.ToList(),
t => AddThread(t)
);
}
void RunningThreadsListItemActivate(object sender, EventArgs e)
{
ThreadModel obj = runningThreadsList.SelectedItems[0] as ThreadModel;
Thread thread = obj.Thread;
Process debuggedProcess = thread.Process;
if (debuggedProcess != null) {
if (debuggedProcess.IsPaused) {
// check for options - if these options are enabled, selecting the frame should not continue
if ((thread.MostRecentStackFrame == null || !thread.MostRecentStackFrame.HasSymbols) &&
!DebuggingOptions.Instance.DecompileCodeWithoutSymbols) {
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchWithoutDecompiledCodeOptions}",
"${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}");
return;
}
debuggedProcess.SelectedThread = thread;
debuggedProcess.SelectedThread.SelectedStackFrame = debuggedProcess.SelectedThread.MostRecentStackFrame;
if (debuggedProcess.SelectedThread.SelectedStackFrame != null) {
WindowsDebugger.RefreshPads();
} else {
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchOnNAFrame}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}");
}
} else {
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}");
if (WindowsDebugger.CurrentProcess != null) {
if (WindowsDebugger.CurrentProcess.IsPaused) {
WindowsDebugger.CurrentThread = obj.Thread;
WindowsDebugger.RefreshPads();
// TODO: Jump to current line
} else {
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}");
}
}
}
}
void AddThread(Thread thread)
{

23
src/AddIns/Debugger/Debugger.AddIn/Pads/WatchInputBox.xaml.cs

@ -50,31 +50,18 @@ namespace Debugger.AddIn.Pads @@ -50,31 +50,18 @@ namespace Debugger.AddIn.Pads
language = "C#";
console.SetHighlighting("C#");
}
// get process
this.Process = ((WindowsDebugger)DebuggerService.CurrentDebugger).DebuggedProcess;
}
private Process Process { get; set; }
protected override void AbstractConsolePadTextEntered(object sender, TextCompositionEventArgs e)
{
if (this.Process == null || this.Process.IsRunning)
return;
if (this.Process.SelectedStackFrame == null || this.Process.SelectedStackFrame.NextStatement == null)
return;
foreach (char ch in e.Text) {
if (ch == '.') {
ShowDotCompletion(console.CommandText);
}
}
StackFrame frame = WindowsDebugger.CurrentStackFrame;
if (e.Text == "." && frame != null)
ShowDotCompletion(frame, console.CommandText);
}
private void ShowDotCompletion(string currentText)
private void ShowDotCompletion(StackFrame frame, string currentText)
{
var seg = Process.SelectedStackFrame.NextStatement;
var seg = frame.NextStatement;
var expressionFinder = ParserService.GetExpressionFinder(seg.Filename);
var info = ParserService.GetParseInformation(seg.Filename);

10
src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs

@ -19,6 +19,7 @@ using ICSharpCode.Core; @@ -19,6 +19,7 @@ using ICSharpCode.Core;
using ICSharpCode.Core.Presentation;
using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.Visitors;
using ICSharpCode.SharpDevelop.Debugging;
using ICSharpCode.SharpDevelop.Project;
using ICSharpCode.SharpDevelop.Services;
@ -71,7 +72,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -71,7 +72,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
ProjectService.SolutionLoaded += delegate { LoadSavedNodes(); };
WindowsDebugger.RefreshingPads += RefreshPad;
WindowsDebugger.RefreshPads();
RefreshPad();
}
#region Saved nodes
@ -176,8 +177,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -176,8 +177,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
try {
LoggingService.Info("Evaluating: " + (string.IsNullOrEmpty(node.Node.Name) ? "is null or empty!" : node.Node.Name));
//Value val = ExpressionEvaluator.Evaluate(nod.Name, nod.Language, debuggedProcess.SelectedStackFrame);
ValueNode valNode = new ValueNode(null, node.Node.Name, () => ((WindowsDebugger)DebuggerService.CurrentDebugger).GetExpression(node.Node.Name).Evaluate(process));
ValueNode valNode = new ValueNode(null, node.Node.Name, () => ExpressionEvaluator.Evaluate(node.Node.Name, SupportedLanguage.CSharp, WindowsDebugger.CurrentStackFrame));
return valNode.ToSharpTreeNode();
} catch (GetValueException) {
string error = String.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Watch.InvalidExpression}"), node.Node.Name);
@ -186,9 +186,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -186,9 +186,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
}
protected void RefreshPad(object sender, DebuggerEventArgs dbg)
protected void RefreshPad()
{
Process debuggedProcess = dbg.Process;
Process debuggedProcess = WindowsDebugger.CurrentProcess;
ResetPad(null, null);

5
src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs

@ -15,13 +15,12 @@ namespace ICSharpCode.SharpDevelop.Services @@ -15,13 +15,12 @@ namespace ICSharpCode.SharpDevelop.Services
public override void Run()
{
ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider;
WindowsDebugger winDebugger = DebuggerService.CurrentDebugger as WindowsDebugger;
if (provider == null || winDebugger.DebuggedProcess == null)
if (provider == null || WindowsDebugger.CurrentProcess == null)
return;
ITextEditor textEditor = provider.TextEditor;
winDebugger.DebuggedProcess.RunTo(textEditor.FileName, textEditor.Caret.Line, textEditor.Caret.Column);
WindowsDebugger.CurrentProcess.RunTo(textEditor.FileName, textEditor.Caret.Line, textEditor.Caret.Column);
}
}
}

318
src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs

@ -28,12 +28,50 @@ using ICSharpCode.SharpDevelop.Gui.OptionPanels; @@ -28,12 +28,50 @@ using ICSharpCode.SharpDevelop.Gui.OptionPanels;
using ICSharpCode.SharpDevelop.Project;
using Mono.Cecil;
using Process = Debugger.Process;
using StackFrame = Debugger.StackFrame;
using TreeNode = Debugger.AddIn.TreeModel.TreeNode;
namespace ICSharpCode.SharpDevelop.Services
{
public class WindowsDebugger : IDebugger
{
public static NDebugger CurrentDebugger { get; private set; }
public static Process CurrentProcess { get; private set; }
public static Thread CurrentThread { get; set; }
public static StackFrame CurrentStackFrame { get; set; }
public static Action RefreshingPads;
public static void RefreshPads()
{
if (RefreshingPads != null) {
RefreshingPads();
}
}
/// <summary>
/// Gets the thread which should be used for all evaluations.
/// For the time being, it is the selected thread, but we might
/// want to have a dedicated evaluation thread in the future.
/// </summary>
/// <remarks>
/// This exists for two reasons:
/// 1) So that the addin has explicit control over evaluations rather than the core
/// 2) The need to pass this to calls is a reminder that they might do evaluation
/// </remarks>
public static Thread EvalThread {
get {
if (CurrentProcess == null)
throw new GetValueException("Debugger is not running");
if (CurrentProcess.IsRunning)
throw new GetValueException("Process is not paused");
if (CurrentThread == null)
throw new GetValueException("No thread selected");
return CurrentThread;
}
}
enum StopAttachedProcessDialogResult {
Detach = 0,
Terminate = 1,
@ -42,53 +80,15 @@ namespace ICSharpCode.SharpDevelop.Services @@ -42,53 +80,15 @@ namespace ICSharpCode.SharpDevelop.Services
bool attached;
NDebugger debugger;
ICorPublish corPublish;
Process debuggedProcess;
internal IDebuggerDecompilerService debuggerDecompilerService;
public NDebugger DebuggerCore { get { return debugger; } }
public Process DebuggedProcess { get { return debuggedProcess; } }
public static Process CurrentProcess {
get {
WindowsDebugger dbgr = DebuggerService.CurrentDebugger as WindowsDebugger;
if (dbgr != null && dbgr.DebuggedProcess != null) {
return dbgr.DebuggedProcess;
} else {
return null;
}
}
}
public static event EventHandler<DebuggerEventArgs> RefreshingPads;
public static void RefreshPads()
{
RefreshPads(new DebuggerEventArgs(CurrentProcess));
}
public static void RefreshPads(DebuggerEventArgs e)
{
if (RefreshingPads != null) {
RefreshingPads(null, e);
}
}
/// <inheritdoc/>
public bool BreakAtBeginning {
get;
set;
}
public bool BreakAtBeginning { get; set; }
public bool ServiceInitialized {
get {
return debugger != null;
}
get { return CurrentDebugger != null; }
}
public WindowsDebugger()
@ -100,13 +100,13 @@ namespace ICSharpCode.SharpDevelop.Services @@ -100,13 +100,13 @@ namespace ICSharpCode.SharpDevelop.Services
string errorDebugging = "${res:XML.MainMenu.DebugMenu.Error.Debugging}";
string errorNotDebugging = "${res:XML.MainMenu.DebugMenu.Error.NotDebugging}";
string errorProcessRunning = "${res:XML.MainMenu.DebugMenu.Error.ProcessRunning}";
string errorProcessPaused = "${res:XML.MainMenu.DebugMenu.Error.ProcessPaused}";
string errorCannotStepNoActiveFunction = "${res:MainWindow.Windows.Debug.Threads.CannotStepNoActiveFunction}";
// string errorProcessRunning = "${res:XML.MainMenu.DebugMenu.Error.ProcessRunning}";
// string errorProcessPaused = "${res:XML.MainMenu.DebugMenu.Error.ProcessPaused}";
// string errorCannotStepNoActiveFunction = "${res:MainWindow.Windows.Debug.Threads.CannotStepNoActiveFunction}";
public bool IsDebugging {
get {
return ServiceInitialized && debuggedProcess != null;
return ServiceInitialized && CurrentProcess != null;
}
}
@ -118,7 +118,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -118,7 +118,7 @@ namespace ICSharpCode.SharpDevelop.Services
public bool IsProcessRunning {
get {
return IsDebugging && debuggedProcess.IsRunning;
return IsDebugging && CurrentProcess.IsRunning;
}
}
@ -137,7 +137,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -137,7 +137,7 @@ namespace ICSharpCode.SharpDevelop.Services
InitializeService();
}
string version = debugger.GetProgramVersion(processStartInfo.FileName);
string version = CurrentDebugger.GetProgramVersion(processStartInfo.FileName);
if (version.StartsWith("v1.0")) {
MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.Net10NotSupported}");
@ -146,7 +146,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -146,7 +146,7 @@ namespace ICSharpCode.SharpDevelop.Services
// } else if (string.IsNullOrEmpty(version)) {
// // Not a managed assembly
// MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.BadAssembly}");
} else if (debugger.IsKernelDebuggerEnabled) {
} else if (CurrentDebugger.IsKernelDebuggerEnabled) {
MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.KernelDebuggerEnabled}");
} else {
attached = false;
@ -158,8 +158,8 @@ namespace ICSharpCode.SharpDevelop.Services @@ -158,8 +158,8 @@ namespace ICSharpCode.SharpDevelop.Services
try {
// set the JIT flag for evaluating optimized code
Process.DebugMode = DebugModeFlag.Debug;
this.debuggedProcess = debugger.Start(processStartInfo.FileName, processStartInfo.WorkingDirectory, processStartInfo.Arguments, this.BreakAtBeginning);
debugger_ProcessStarted(this.debuggedProcess);
CurrentProcess = CurrentDebugger.Start(processStartInfo.FileName, processStartInfo.WorkingDirectory, processStartInfo.Arguments, this.BreakAtBeginning);
debugger_ProcessStarted();
} catch (System.Exception e) {
// COMException: The request is not supported. (Exception from HRESULT: 0x80070032)
// COMException: The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log for more detail. (Exception from HRESULT: 0x800736B1)
@ -207,7 +207,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -207,7 +207,7 @@ namespace ICSharpCode.SharpDevelop.Services
InitializeService();
}
string version = debugger.GetProgramVersion(existingProcess.MainModule.FileName);
string version = CurrentDebugger.GetProgramVersion(existingProcess.MainModule.FileName);
if (version.StartsWith("v1.0")) {
MessageService.ShowMessage("${res:XML.MainMenu.DebugMenu.Error.Net10NotSupported}");
} else {
@ -219,10 +219,10 @@ namespace ICSharpCode.SharpDevelop.Services @@ -219,10 +219,10 @@ namespace ICSharpCode.SharpDevelop.Services
try {
// set the JIT flag for evaluating optimized code
Process.DebugMode = DebugModeFlag.Debug;
this.debuggedProcess = debugger.Attach(existingProcess);
debugger_ProcessStarted(this.debuggedProcess);
CurrentProcess = CurrentDebugger.Attach(existingProcess);
debugger_ProcessStarted();
attached = true;
this.debuggedProcess.ModuleLoaded += process_Modules_Added;
CurrentProcess.ModuleLoaded += process_Modules_Added;
} catch (System.Exception e) {
// CORDBG_E_DEBUGGER_ALREADY_ATTACHED
if (e is COMException || e is UnauthorizedAccessException) {
@ -240,7 +240,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -240,7 +240,7 @@ namespace ICSharpCode.SharpDevelop.Services
public void Detach()
{
debugger.Detach();
CurrentDebugger.Detach();
}
public void StartWithoutDebugging(ProcessStartInfo processStartInfo)
@ -258,7 +258,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -258,7 +258,7 @@ namespace ICSharpCode.SharpDevelop.Services
StopAttachedProcessDialogResult result = ShowStopAttachedProcessDialog();
switch (result) {
case StopAttachedProcessDialogResult.Terminate:
debuggedProcess.Terminate();
CurrentProcess.Terminate();
attached = false;
break;
case StopAttachedProcessDialogResult.Detach:
@ -267,46 +267,32 @@ namespace ICSharpCode.SharpDevelop.Services @@ -267,46 +267,32 @@ namespace ICSharpCode.SharpDevelop.Services
break;
}
} else {
debuggedProcess.Terminate();
CurrentProcess.Terminate();
}
}
// ExecutionControl:
public void Break()
{
if (!IsDebugging) {
MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.Break}");
return;
if (CurrentProcess != null && CurrentProcess.IsRunning) {
CurrentProcess.Break();
}
if (!IsProcessRunning) {
MessageService.ShowMessage(errorProcessPaused, "${res:XML.MainMenu.DebugMenu.Break}");
return;
}
debuggedProcess.Break();
}
public void Continue()
{
if (!IsDebugging) {
MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.Continue}");
return;
}
if (IsProcessRunning) {
MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.Continue}");
return;
if (CurrentProcess != null && CurrentProcess.IsPaused) {
CurrentProcess.AsyncContinue();
}
debuggedProcess.AsyncContinue();
}
// Stepping:
// TODO - What is this?
Debugger.StackFrame GetStackFrame()
{
bool isMatch = false;
int line = -1;
int[] ilRange = null;
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
var frame = CurrentStackFrame;
int typeToken = frame.MethodInfo.DeclaringType.MetadataToken;
int methodToken = frame.MethodInfo.MetadataToken;
@ -324,76 +310,22 @@ namespace ICSharpCode.SharpDevelop.Services @@ -324,76 +310,22 @@ namespace ICSharpCode.SharpDevelop.Services
public void StepInto()
{
if (!IsDebugging) {
MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepInto}");
return;
}
if (debuggedProcess.IsRunning) {
MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.StepInto}");
return;
}
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
if (frame == null) {
MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepInto}");
} else {
if (!frame.HasSymbols) {
// get frame info from external code mappings
frame = GetStackFrame();
}
frame.AsyncStepInto();
if (CurrentStackFrame != null) {
CurrentStackFrame.AsyncStepInto();
}
}
public void StepOver()
{
if (!IsDebugging) {
MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepOver}");
return;
}
if (debuggedProcess.IsRunning) {
MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.StepOver}");
return;
}
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
if (frame == null) {
MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepOver}");
} else {
if (!frame.HasSymbols) {
// get frame info from external code mappings
frame = GetStackFrame();
}
frame.AsyncStepOver();
if (CurrentStackFrame != null) {
CurrentStackFrame.AsyncStepOver();
}
}
public void StepOut()
{
if (!IsDebugging) {
MessageService.ShowMessage(errorNotDebugging, "${res:XML.MainMenu.DebugMenu.StepOut}");
return;
}
if (debuggedProcess.IsRunning) {
MessageService.ShowMessage(errorProcessRunning, "${res:XML.MainMenu.DebugMenu.StepOut}");
return;
}
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
if (frame == null) {
MessageService.ShowMessage(errorCannotStepNoActiveFunction, "${res:XML.MainMenu.DebugMenu.StepInto}");
} else {
if (!frame.HasSymbols) {
// get frame info from external code mappings
frame = GetStackFrame();
}
frame.AsyncStepOut();
if (CurrentStackFrame != null) {
CurrentStackFrame.AsyncStepOut();
}
}
@ -416,18 +348,11 @@ namespace ICSharpCode.SharpDevelop.Services @@ -416,18 +348,11 @@ namespace ICSharpCode.SharpDevelop.Services
/// </summary>
public Value GetValueFromName(string variableName)
{
if (!CanEvaluate) {
return null;
if (CurrentStackFrame != null) {
object data = debuggerDecompilerService.GetLocalVariableIndex(CurrentStackFrame.MethodInfo.DeclaringType.MetadataToken, CurrentStackFrame.MethodInfo.MetadataToken, variableName);
return ExpressionEvaluator.Evaluate(variableName, SupportedLanguage.CSharp, CurrentStackFrame, data);
}
var frame = debuggedProcess.GetCurrentExecutingFrame();
if (frame == null)
return null;
object data = debuggerDecompilerService.GetLocalVariableIndex(frame.MethodInfo.DeclaringType.MetadataToken,
frame.MethodInfo.MetadataToken,
variableName);
// evaluate expression
return ExpressionEvaluator.Evaluate(variableName, SupportedLanguage.CSharp, frame, data);
return null;
}
/// <summary>
@ -436,10 +361,11 @@ namespace ICSharpCode.SharpDevelop.Services @@ -436,10 +361,11 @@ namespace ICSharpCode.SharpDevelop.Services
/// </summary>
public Expression GetExpression(string variableName)
{
if (!CanEvaluate) {
if (CurrentStackFrame != null) {
return ExpressionEvaluator.ParseExpression(variableName, SupportedLanguage.CSharp);
} else {
throw new GetValueException("Cannot evaluate now - debugged process is either null or running or has no selected stack frame");
}
return ExpressionEvaluator.ParseExpression(variableName, SupportedLanguage.CSharp);
}
public bool IsManaged(int processId)
@ -469,14 +395,6 @@ namespace ICSharpCode.SharpDevelop.Services @@ -469,14 +395,6 @@ namespace ICSharpCode.SharpDevelop.Services
}
}
bool CanEvaluate
{
get {
return debuggedProcess != null && !debuggedProcess.IsRunning &&
(debuggedProcess.SelectedStackFrame != null || debuggedProcess.SelectedThread.MostRecentStackFrame != null);
}
}
/// <summary>
/// Gets the tooltip control that shows the value of given variable.
/// Return null if no tooltip is available.
@ -485,7 +403,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -485,7 +403,7 @@ namespace ICSharpCode.SharpDevelop.Services
{
try {
var tooltipExpression = GetExpression(variableName);
var valueNode = new ValueNode("Icons.16x16.Local", variableName, () => tooltipExpression.Evaluate(this.DebuggedProcess));
var valueNode = new ValueNode("Icons.16x16.Local", variableName, () => tooltipExpression.Evaluate());
return new DebuggerTooltipControl(new TreeNode[] { valueNode });
} catch (System.Exception ex) {
LoggingService.Error("Error on GetTooltipControl: " + ex.Message);
@ -496,7 +414,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -496,7 +414,7 @@ namespace ICSharpCode.SharpDevelop.Services
public Debugger.AddIn.TreeModel.TreeNode GetNode(string variable, string currentImageName = null)
{
try {
return new ValueNode(currentImageName ?? "Icons.16x16.Local", variable, () => GetExpression(variable).Evaluate(this.DebuggedProcess));
return new ValueNode(currentImageName ?? "Icons.16x16.Local", variable, () => GetExpression(variable).Evaluate());
} catch (GetValueException) {
return null;
}
@ -504,8 +422,8 @@ namespace ICSharpCode.SharpDevelop.Services @@ -504,8 +422,8 @@ namespace ICSharpCode.SharpDevelop.Services
public bool SetInstructionPointer(string filename, int line, int column, bool dryRun)
{
if (debuggedProcess != null && debuggedProcess.IsPaused && debuggedProcess.SelectedStackFrame != null) {
SourcecodeSegment seg = debuggedProcess.SelectedStackFrame.SetIP(filename, line, column, dryRun);
if (CurrentStackFrame != null) {
SourcecodeSegment seg = CurrentStackFrame.SetIP(filename, line, column, dryRun);
WindowsDebugger.RefreshPads();
JumpToCurrentLine();
return seg != null;
@ -531,8 +449,8 @@ namespace ICSharpCode.SharpDevelop.Services @@ -531,8 +449,8 @@ namespace ICSharpCode.SharpDevelop.Services
debuggerDecompilerService = items[0];
// init NDebugger
debugger = new NDebugger();
debugger.Options = DebuggingOptions.Instance;
CurrentDebugger = new NDebugger();
CurrentDebugger.Options = DebuggingOptions.Instance;
DebuggerService.BreakPointAdded += delegate (object sender, BreakpointBookmarkEventArgs e) {
AddBreakpoint(e.BreakpointBookmark);
@ -568,7 +486,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -568,7 +486,7 @@ namespace ICSharpCode.SharpDevelop.Services
{
foreach (BreakpointBookmark bookmark in BookmarkManager.Bookmarks.OfType<BreakpointBookmark>()) {
Breakpoint breakpoint = bookmark.InternalBreakpointObject as Breakpoint;
bookmark.IsHealthy = (debuggedProcess == null) || breakpoint.IsSet;
bookmark.IsHealthy = (CurrentProcess == null) || breakpoint.IsSet;
}
}
@ -597,13 +515,13 @@ namespace ICSharpCode.SharpDevelop.Services @@ -597,13 +515,13 @@ namespace ICSharpCode.SharpDevelop.Services
int[] ilRanges;
int methodToken;
if (debuggerDecompilerService.GetILAndTokenByLineNumber(token, dbb.LineNumber, out ilRanges, out methodToken)) {
debugger.AddILBreakpoint(memberReference.FullName, dbb.LineNumber, memberReference.MetadataToken.ToInt32(), methodToken, ilRanges[0], dbb.IsEnabled);
CurrentDebugger.AddILBreakpoint(memberReference.FullName, dbb.LineNumber, memberReference.MetadataToken.ToInt32(), methodToken, ilRanges[0], dbb.IsEnabled);
}
} catch (System.Exception ex) {
LoggingService.Error("Error on DecompiledBreakpointBookmark: " + ex.Message);
}
} else {
breakpoint = debugger.AddBreakpoint(bookmark.FileName, bookmark.LineNumber, 0, bookmark.IsEnabled);
breakpoint = CurrentDebugger.AddBreakpoint(bookmark.FileName, bookmark.LineNumber, 0, bookmark.IsEnabled);
}
if (breakpoint == null) {
@ -612,7 +530,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -612,7 +530,7 @@ namespace ICSharpCode.SharpDevelop.Services
}
bookmark.InternalBreakpointObject = breakpoint;
bookmark.IsHealthy = (debuggedProcess == null) || breakpoint.IsSet;
bookmark.IsHealthy = (CurrentProcess == null) || breakpoint.IsSet;
bookmark.IsEnabledChanged += delegate { breakpoint.IsEnabled = bookmark.IsEnabled; };
}
@ -620,7 +538,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -620,7 +538,7 @@ namespace ICSharpCode.SharpDevelop.Services
{
try {
SupportedLanguage supportedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), language, true);
Value val = ExpressionEvaluator.Evaluate(code, supportedLanguage, debuggedProcess.SelectedStackFrame);
Value val = ExpressionEvaluator.Evaluate(code, supportedLanguage, CurrentStackFrame);
if (val != null && val.Type.IsPrimitive && val.PrimitiveValue is bool)
return (bool)val.PrimitiveValue;
@ -639,36 +557,45 @@ namespace ICSharpCode.SharpDevelop.Services @@ -639,36 +557,45 @@ namespace ICSharpCode.SharpDevelop.Services
DebuggerService.PrintDebugMessage(e.Message);
}
void debugger_ProcessStarted(Process process)
void debugger_ProcessStarted()
{
if (DebugStarted != null) {
DebugStarted(this, EventArgs.Empty);
}
process.ModuleLoaded += (s, e) => UpdateBreakpointIcons();
process.ModuleLoaded += (s, e) => RefreshPads(e);
process.ModuleUnloaded += (s, e) => RefreshPads(e);
process.LogMessage += LogMessage;
process.Paused += debuggedProcess_DebuggingPaused;
process.Resumed += debuggedProcess_DebuggingResumed;
process.Exited += (s, e) => debugger_ProcessExited(e.Process);
CurrentProcess.ModuleLoaded += (s, e) => UpdateBreakpointIcons();
CurrentProcess.ModuleLoaded += (s, e) => RefreshPads();
CurrentProcess.ModuleUnloaded += (s, e) => RefreshPads();
CurrentProcess.LogMessage += LogMessage;
CurrentProcess.Paused += debuggedProcess_DebuggingPaused;
CurrentProcess.Resumed += debuggedProcess_DebuggingResumed;
CurrentProcess.Exited += (s, e) => debugger_ProcessExited();
UpdateBreakpointIcons();
}
void debugger_ProcessExited(Process process)
void debugger_ProcessExited()
{
if (DebugStopped != null) {
DebugStopped(this, EventArgs.Empty);
}
debuggedProcess = null;
CurrentProcess = null;
CurrentThread = null;
CurrentStackFrame = null;
UpdateBreakpointIcons();
RefreshPads();
}
void debuggedProcess_DebuggingPaused(object sender, DebuggerEventArgs e)
{
OnIsProcessRunningChanged(EventArgs.Empty);
CurrentProcess = e.Process;
CurrentThread = e.Thread;
CurrentStackFrame = CurrentThread.MostRecentUserStackFrame;
LoggingService.Info("Jump to current line");
JumpToCurrentLine();
@ -688,7 +615,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -688,7 +615,7 @@ namespace ICSharpCode.SharpDevelop.Services
if (Evaluate(bookmark.Condition, bookmark.ScriptLanguage))
DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAtBecause}") + "\n", bookmark.LineNumber, bookmark.FileName, bookmark.Condition));
else
this.debuggedProcess.AsyncContinue();
CurrentProcess.AsyncContinue();
break;
case BreakpointAction.Trace:
DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAt}") + "\n", bookmark.LineNumber, bookmark.FileName));
@ -696,7 +623,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -696,7 +623,7 @@ namespace ICSharpCode.SharpDevelop.Services
}
}
RefreshPads(e);
RefreshPads();
}
void debuggedProcess_DebuggingResumed(object sender, DebuggerEventArgs e)
@ -704,7 +631,10 @@ namespace ICSharpCode.SharpDevelop.Services @@ -704,7 +631,10 @@ namespace ICSharpCode.SharpDevelop.Services
OnIsProcessRunningChanged(EventArgs.Empty);
DebuggerService.RemoveCurrentLineMarker();
RefreshPads(e);
CurrentThread = null;
CurrentStackFrame = null;
RefreshPads();
}
void HandleException(DebuggerEventArgs e)
@ -715,36 +645,36 @@ namespace ICSharpCode.SharpDevelop.Services @@ -715,36 +645,36 @@ namespace ICSharpCode.SharpDevelop.Services
if (e.ExceptionThrown.IsUnhandled) {
// Need to intercept now so that we can evaluate properties
if (e.Process.SelectedThread.InterceptException(e.ExceptionThrown)) {
if (e.Thread.InterceptException(e.ExceptionThrown)) {
stacktraceBuilder.AppendLine(e.ExceptionThrown.ToString());
string stackTrace;
try {
stackTrace = e.ExceptionThrown.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.EndOfInnerException}"));
stackTrace = e.ExceptionThrown.GetStackTrace(e.Thread, StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.EndOfInnerException}"));
} catch (GetValueException) {
stackTrace = e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}"));
stackTrace = e.Thread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}"));
}
stacktraceBuilder.Append(stackTrace);
} else {
// For example, happens on stack overflow
stacktraceBuilder.AppendLine(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptException}"));
stacktraceBuilder.AppendLine(e.ExceptionThrown.ToString());
stacktraceBuilder.Append(e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}")));
stacktraceBuilder.Append(e.Thread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}")));
}
} else {
stacktraceBuilder.AppendLine(e.ExceptionThrown.ToString());
stacktraceBuilder.Append(e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}")));
stacktraceBuilder.Append(e.Thread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}")));
}
string title = e.ExceptionThrown.IsUnhandled ? StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Unhandled}") : StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Handled}");
string message = string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Message}"), e.ExceptionThrown.Type);
Bitmap icon = WinFormsResourceService.GetBitmap(e.ExceptionThrown.IsUnhandled ? "Icons.32x32.Error" : "Icons.32x32.Warning");
DebuggeeExceptionForm.Show(debuggedProcess, title, message, stacktraceBuilder.ToString(), icon, e.ExceptionThrown.IsUnhandled, e.ExceptionThrown);
DebuggeeExceptionForm.Show(e.Process, title, message, stacktraceBuilder.ToString(), icon, e.ExceptionThrown.IsUnhandled, e.ExceptionThrown);
}
public bool BreakAndInterceptHandledException(Debugger.Exception exception)
{
if (!debuggedProcess.SelectedThread.InterceptException(exception)) {
if (!CurrentThread.InterceptException(exception)) {
MessageService.ShowError("${res:MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptHandledException}");
return false;
}
@ -754,16 +684,16 @@ namespace ICSharpCode.SharpDevelop.Services @@ -754,16 +684,16 @@ namespace ICSharpCode.SharpDevelop.Services
public void JumpToCurrentLine()
{
if (debuggedProcess == null || debuggedProcess.SelectedThread == null)
if (CurrentThread == null)
return;
WorkbenchSingleton.MainWindow.Activate();
// if (debuggedProcess.IsSelectedFrameForced()) {
if (debuggedProcess.SelectedStackFrame != null && debuggedProcess.SelectedStackFrame.HasSymbols) {
if (CurrentThread != null && CurrentStackFrame.HasSymbols) {
JumpToSourceCode();
} else {
JumpToDecompiledCode(debuggedProcess.SelectedStackFrame);
JumpToDecompiledCode(CurrentStackFrame);
}
// } else {
// var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
@ -779,10 +709,10 @@ namespace ICSharpCode.SharpDevelop.Services @@ -779,10 +709,10 @@ namespace ICSharpCode.SharpDevelop.Services
void JumpToSourceCode()
{
if (debuggedProcess == null || debuggedProcess.SelectedThread == null)
if (CurrentProcess == null || CurrentStackFrame == null)
return;
SourcecodeSegment nextStatement = debuggedProcess.NextStatement;
SourcecodeSegment nextStatement = CurrentStackFrame.NextStatement;
if (nextStatement != null) {
DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn);
@ -802,7 +732,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -802,7 +732,7 @@ namespace ICSharpCode.SharpDevelop.Services
}
// check for options - if these options are enabled, debugging decompiled code should not continue
if (!debuggedProcess.Options.DecompileCodeWithoutSymbols) {
if (!CurrentProcess.Options.DecompileCodeWithoutSymbols) {
LoggingService.Info("Decompiled code debugging is disabled!");
return;
}

30
src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs

@ -70,7 +70,7 @@ namespace Debugger.AddIn.TreeModel @@ -70,7 +70,7 @@ namespace Debugger.AddIn.TreeModel
{
Stopwatch watch = new Stopwatch();
watch.Start();
cachedValue = this.getValue().GetPermanentReference();
cachedValue = this.getValue().GetPermanentReference(WindowsDebugger.EvalThread);
cachedValueProcess = cachedValue.Process;
cachedValueDebuggeeState = cachedValue.Process.DebuggeeState;
LoggingService.InfoFormatted("Evaluated node '{0}' in {1} ms (result cached for future use)", this.Name, watch.ElapsedMilliseconds);
@ -101,7 +101,7 @@ namespace Debugger.AddIn.TreeModel @@ -101,7 +101,7 @@ namespace Debugger.AddIn.TreeModel
try {
Stopwatch watch = new Stopwatch();
watch.Start();
// Do not keep permanent reference
Value val = this.getValue();
@ -117,7 +117,7 @@ namespace Debugger.AddIn.TreeModel @@ -117,7 +117,7 @@ namespace Debugger.AddIn.TreeModel
}
} else if (val.Type.IsClass || val.Type.IsValueType) {
if (val.Type.FullNameWithoutGenericArguments == typeof(List<>).FullName) {
if ((int)val.GetMemberValue("_size").PrimitiveValue > 0)
if ((int)val.GetFieldValue("_size").PrimitiveValue > 0)
this.GetChildren = () => GetIListChildren(this.GetValue);
} else {
this.GetChildren = () => GetObjectChildren(val.Type);
@ -148,11 +148,11 @@ namespace Debugger.AddIn.TreeModel @@ -148,11 +148,11 @@ namespace Debugger.AddIn.TreeModel
} else if (val.Type.IsPointer) {
fullValue = String.Format("0x{0:X}", val.PointerAddress);
} else if (val.Type.FullName == typeof(string).FullName) {
fullValue = '"' + val.InvokeToString().Replace("\n", "\\n").Replace("\t", "\\t").Replace("\r", "\\r").Replace("\0", "\\0").Replace("\b", "\\b").Replace("\a", "\\a").Replace("\f", "\\f").Replace("\v", "\\v").Replace("\"", "\\\"") + '"';
fullValue = '"' + val.InvokeToString(WindowsDebugger.EvalThread).Replace("\n", "\\n").Replace("\t", "\\t").Replace("\r", "\\r").Replace("\0", "\\0").Replace("\b", "\\b").Replace("\a", "\\a").Replace("\f", "\\f").Replace("\v", "\\v").Replace("\"", "\\\"") + '"';
} else if (val.Type.FullName == typeof(char).FullName) {
fullValue = "'" + val.InvokeToString().Replace("\n", "\\n").Replace("\t", "\\t").Replace("\r", "\\r").Replace("\0", "\\0").Replace("\b", "\\b").Replace("\a", "\\a").Replace("\f", "\\f").Replace("\v", "\\v").Replace("\"", "\\\"") + "'";
fullValue = "'" + val.InvokeToString(WindowsDebugger.EvalThread).Replace("\n", "\\n").Replace("\t", "\\t").Replace("\r", "\\r").Replace("\0", "\\0").Replace("\b", "\\b").Replace("\a", "\\a").Replace("\f", "\\f").Replace("\v", "\\v").Replace("\"", "\\\"") + "'";
} else if ((val.Type.IsClass || val.Type.IsValueType)) {
fullValue = val.InvokeToString();
fullValue = val.InvokeToString(WindowsDebugger.EvalThread);
} else {
fullValue = val.AsString();
}
@ -259,16 +259,14 @@ namespace Debugger.AddIn.TreeModel @@ -259,16 +259,14 @@ namespace Debugger.AddIn.TreeModel
/// </summary>
static StackFrame GetCurrentStackFrame()
{
var debugger = DebuggerService.CurrentDebugger as WindowsDebugger;
if (debugger == null || debugger.DebuggedProcess == null)
if (WindowsDebugger.CurrentProcess == null)
throw new GetValueException("Debugger is not running");
if (debugger.DebuggedProcess.IsRunning)
if (WindowsDebugger.CurrentProcess.IsRunning)
throw new GetValueException("Process is not paused");
if (debugger.DebuggedProcess.SelectedStackFrame == null)
if (WindowsDebugger.CurrentStackFrame == null)
throw new GetValueException("No stack frame selected");
return debugger.DebuggedProcess.SelectedStackFrame;
return WindowsDebugger.CurrentStackFrame;
}
public static IEnumerable<TreeNode> GetLocalVariables()
@ -371,7 +369,7 @@ namespace Debugger.AddIn.TreeModel @@ -371,7 +369,7 @@ namespace Debugger.AddIn.TreeModel
foreach(MemberInfo memberInfo in members.OrderBy(m => m.Name)) {
var memberInfoCopy = memberInfo;
string imageName = GetImageForMember((IDebugMemberInfo)memberInfo);
yield return new ValueNode(imageName, memberInfo.Name, () => GetValue().GetMemberValue(memberInfoCopy));
yield return new ValueNode(imageName, memberInfo.Name, () => GetValue().GetMemberValue(WindowsDebugger.EvalThread, memberInfoCopy));
}
}
@ -383,18 +381,18 @@ namespace Debugger.AddIn.TreeModel @@ -383,18 +381,18 @@ namespace Debugger.AddIn.TreeModel
try {
// TODO: We want new list on reeval
// We need the list to survive generation of index via Eval
list = getValue().GetPermanentReference();
list = getValue().GetPermanentReference(WindowsDebugger.EvalThread);
DebugType iListType = (DebugType)list.Type.GetInterface(typeof(IList).FullName);
itemProp = iListType.GetProperty("Item");
// Do not get string representation since it can be printed in hex
count = (int)list.GetPropertyValue(iListType.GetProperty("Count")).PrimitiveValue;
count = (int)list.GetPropertyValue(WindowsDebugger.EvalThread, iListType.GetProperty("Count")).PrimitiveValue;
} catch (GetValueException e) {
return new [] { new TreeNode(null, "(error)", e.Message, string.Empty, null) };
}
if (count == 0) {
return new [] { new TreeNode("(empty)", null) };
} else {
return Enumerable.Range(0, count).Select(i => new ValueNode("Icons.16x16.Field", "[" + i + "]", () => list.GetPropertyValue(itemProp, Eval.CreateValue(list.AppDomain, i))));
return Enumerable.Range(0, count).Select(i => new ValueNode("Icons.16x16.Field", "[" + i + "]", () => list.GetPropertyValue(WindowsDebugger.EvalThread, itemProp, Eval.CreateValue(WindowsDebugger.EvalThread, i))));
}
}

13
src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs

@ -85,17 +85,16 @@ namespace Debugger.AddIn.Visualizers.Graph @@ -85,17 +85,16 @@ namespace Debugger.AddIn.Visualizers.Graph
throw new DebuggerVisualizerException("Please specify an expression.");
}
var debuggedProcess = this.debuggerService.DebuggedProcess;
if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedStackFrame == null) {
if (WindowsDebugger.CurrentStackFrame == null) {
throw new DebuggerVisualizerException("Please use the visualizer when debugging.");
}
var rootExpression = ExpressionEvaluator.ParseExpression(expression, SupportedLanguage.CSharp);
Value rootValue = rootExpression.Evaluate(debuggedProcess);
Value rootValue = rootExpression.Evaluate();
if (rootValue.IsNull) {
throw new DebuggerVisualizerException(expression + " is null.");
}
return buildGraphForValue(rootValue.GetPermanentReference(), rootExpression, expandedNodes);
return buildGraphForValue(rootValue.GetPermanentReference(WindowsDebugger.EvalThread), rootExpression, expandedNodes);
}
private ObjectGraph buildGraphForValue(Value rootValue, Expression rootExpression, ExpandedExpressions expandedNodes)
@ -261,7 +260,7 @@ namespace Debugger.AddIn.Visualizers.Graph @@ -261,7 +260,7 @@ namespace Debugger.AddIn.Visualizers.Graph
if (expandedNodes.IsExpanded(complexProperty.Expression))
{
// if expanded, evaluate this property
Value memberValue = complexProperty.Expression.Evaluate(this.debuggerService.DebuggedProcess);
Value memberValue = complexProperty.Expression.Evaluate();
if (memberValue.IsNull)
{
continue;
@ -269,7 +268,7 @@ namespace Debugger.AddIn.Visualizers.Graph @@ -269,7 +268,7 @@ namespace Debugger.AddIn.Visualizers.Graph
else
{
// if property value is not null, create neighbor
memberValue = memberValue.GetPermanentReference();
memberValue = memberValue.GetPermanentReference(WindowsDebugger.EvalThread);
bool createdNew;
// get existing node (loop) or create new
@ -362,7 +361,7 @@ namespace Debugger.AddIn.Visualizers.Graph @@ -362,7 +361,7 @@ namespace Debugger.AddIn.Visualizers.Graph
/// <param name="expr">Expression to be checked.</param>
private void checkIsOfSupportedType(Expression expr)
{
DebugType typeOfValue = expr.Evaluate(debuggerService.DebuggedProcess).Type;
DebugType typeOfValue = expr.Evaluate().Type;
if (typeOfValue.IsArray)
{
throw new DebuggerVisualizerException("Arrays are not supported yet");

4
src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs

@ -39,7 +39,7 @@ namespace Debugger.AddIn.Visualizers.Graph @@ -39,7 +39,7 @@ namespace Debugger.AddIn.Visualizers.Graph
if (this.Expression == null) throw new DebuggerVisualizerException("Cannot evaluate property with missing Expression");
Value debuggerVal;
try {
debuggerVal = this.Expression.Evaluate(WindowsDebugger.CurrentProcess);
debuggerVal = this.Expression.Evaluate();
} catch (System.Exception ex) {
this.Value = "Exception: " + ex.Message;
this.IsEvaluated = true;
@ -49,7 +49,7 @@ namespace Debugger.AddIn.Visualizers.Graph @@ -49,7 +49,7 @@ namespace Debugger.AddIn.Visualizers.Graph
this.IsAtomic = debuggerVal.Type.IsAtomic();
this.IsNull = debuggerVal.IsNull;
// null and complex properties will show empty string
this.Value = debuggerVal.IsNull || (!this.IsAtomic) ? string.Empty : debuggerVal.InvokeToString();
this.Value = debuggerVal.IsNull || (!this.IsAtomic) ? string.Empty : debuggerVal.InvokeToString(WindowsDebugger.EvalThread);
this.IsEvaluated = true;
}
}

2
src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphControl.xaml.cs

@ -62,7 +62,7 @@ namespace Debugger.AddIn.Visualizers.Graph @@ -62,7 +62,7 @@ namespace Debugger.AddIn.Visualizers.Graph
public void RefreshView()
{
debuggerService.DebuggedProcess.EnqueueWork(Dispatcher, () => Refresh());
WindowsDebugger.CurrentProcess.EnqueueWork(Dispatcher, () => Refresh());
}
void Refresh()

10
src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs

@ -6,12 +6,12 @@ using System.Reflection; @@ -6,12 +6,12 @@ using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using Debugger.AddIn.Visualizers.PresentationBindings;
using Debugger.AddIn.Visualizers.Utils;
using Debugger.MetaData;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop;
using ICSharpCode.SharpDevelop.Services;
namespace Debugger.AddIn.Visualizers.GridVisualizer
{
@ -54,11 +54,11 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -54,11 +54,11 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
return;
}
}
shownValue = shownValue.GetPermanentReference();
shownValue = shownValue.GetPermanentReference(WindowsDebugger.EvalThread);
MemberInfo[] members = itemType.GetFieldsAndNonIndexedProperties(BindingFlags.Public | BindingFlags.Instance);
PropertyInfo itemGetter = iListType.GetProperty("Item");
int rowCount = (int)shownValue.GetPropertyValue(iListType.GetProperty("Count")).PrimitiveValue;
int rowCount = (int)shownValue.GetPropertyValue(WindowsDebugger.EvalThread, iListType.GetProperty("Count")).PrimitiveValue;
int columnCount = members.Length + 1;
var rowCollection = new VirtualizingCollection<VirtualizingCollection<string>>(
@ -69,8 +69,8 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer @@ -69,8 +69,8 @@ namespace Debugger.AddIn.Visualizers.GridVisualizer
if (columnIndex == members.Length)
return "[" + rowIndex + "]";
try {
var rowValue = shownValue.GetPropertyValue(itemGetter, Eval.CreateValue(shownValue.AppDomain, rowIndex));
return rowValue.GetMemberValue(members[columnIndex]).InvokeToString();
var rowValue = shownValue.GetPropertyValue(WindowsDebugger.EvalThread, itemGetter, Eval.CreateValue(WindowsDebugger.EvalThread, rowIndex));
return rowValue.GetMemberValue(WindowsDebugger.EvalThread, members[columnIndex]).InvokeToString(WindowsDebugger.EvalThread);
} catch (GetValueException e) {
return "Exception: " + e.Message;
}

2
src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/AtomicType.cs

@ -30,7 +30,7 @@ namespace Debugger.AddIn.Visualizers.Utils @@ -30,7 +30,7 @@ namespace Debugger.AddIn.Visualizers.Utils
/// <returns>True if expression's type is atomic, False otherwise.</returns>
public static bool IsOfAtomicType(this Expression expr)
{
DebugType typeOfValue = expr.Evaluate(WindowsDebugger.CurrentProcess).Type;
DebugType typeOfValue = expr.Evaluate().Type;
return AtomicType.IsAtomic(typeOfValue);
}
}

14
src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs

@ -41,12 +41,12 @@ namespace Debugger.AddIn.Visualizers.Utils @@ -41,12 +41,12 @@ namespace Debugger.AddIn.Visualizers.Utils
throw new GetValueException("Value is not IEnumeralbe");
DebugType listType = DebugType.CreateFromType(iEnumerableValue.AppDomain, typeof(System.Collections.Generic.List<>), itemType);
ConstructorInfo ctor = listType.GetConstructor(BindingFlags.Default, null, CallingConventions.Any, new System.Type[] { iEnumerableType }, null);
DebugConstructorInfo ctor = (DebugConstructorInfo)listType.GetConstructor(BindingFlags.Default, null, CallingConventions.Any, new System.Type[] { iEnumerableType }, null);
if (ctor == null)
throw new DebuggerException("List<T> constructor not found");
// Keep reference since we do not want to keep reenumerating it
return ((Value)ctor.Invoke(new object[] { iEnumerableValue })).GetPermanentReference();
return Value.InvokeMethod(WindowsDebugger.EvalThread, null, ctor.MethodInfo, new Value[] { iEnumerableValue }).GetPermanentReferenceOfHeapValue();
}
/// <summary>
@ -80,7 +80,7 @@ namespace Debugger.AddIn.Visualizers.Utils @@ -80,7 +80,7 @@ namespace Debugger.AddIn.Visualizers.Utils
/// </summary>
public static ulong GetObjectAddress(this Expression expr)
{
return expr.Evaluate(WindowsDebugger.CurrentProcess).GetObjectAddress();
return expr.Evaluate().GetObjectAddress();
}
/// <summary>
@ -102,7 +102,7 @@ namespace Debugger.AddIn.Visualizers.Utils @@ -102,7 +102,7 @@ namespace Debugger.AddIn.Visualizers.Utils
throw new DebuggerException("Cannot obtain method System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode");
}
}
Value defaultHashCode = Eval.InvokeMethod(DebuggerHelpers.hashCodeMethod, null, new Value[]{value});
Value defaultHashCode = Eval.InvokeMethod(WindowsDebugger.EvalThread, DebuggerHelpers.hashCodeMethod, null, new Value[]{value});
//MethodInfo method = value.Type.GetMember("GetHashCode", BindingFlags.Method | BindingFlags.IncludeSuperType) as MethodInfo;
//string hashCode = value.InvokeMethod(method, null).AsString;
@ -124,7 +124,7 @@ namespace Debugger.AddIn.Visualizers.Utils @@ -124,7 +124,7 @@ namespace Debugger.AddIn.Visualizers.Utils
public static Value EvalPermanentReference(this Expression expr)
{
return expr.Evaluate(WindowsDebugger.CurrentProcess).GetPermanentReference();
return expr.Evaluate().GetPermanentReference(WindowsDebugger.EvalThread);
}
/// <summary>
@ -133,12 +133,12 @@ namespace Debugger.AddIn.Visualizers.Utils @@ -133,12 +133,12 @@ namespace Debugger.AddIn.Visualizers.Utils
/// <exception cref="GetValueException">Evaluating System.Collections.ICollection.Count on targetObject failed.</exception>
public static int GetIListCount(this Expression targetObject)
{
Value list = targetObject.Evaluate(WindowsDebugger.CurrentProcess);
Value list = targetObject.Evaluate();
var iCollectionType = list.Type.GetInterface(typeof(System.Collections.ICollection).FullName);
if (iCollectionType == null)
throw new GetValueException("Object does not implement System.Collections.ICollection");
// Do not get string representation since it can be printed in hex
return (int)list.GetPropertyValue(iCollectionType.GetProperty("Count")).PrimitiveValue;
return (int)list.GetPropertyValue(WindowsDebugger.EvalThread, iCollectionType.GetProperty("Count")).PrimitiveValue;
}
/// <summary>

135
src/AddIns/Debugger/Debugger.Core/Eval.cs

@ -46,11 +46,11 @@ namespace Debugger @@ -46,11 +46,11 @@ namespace Debugger
get { return description; }
}
public ICorDebugEval CorEval {
internal ICorDebugEval CorEval {
get { return corEval; }
}
public ICorDebugEval2 CorEval2 {
internal ICorDebugEval2 CorEval2 {
get { return (ICorDebugEval2)corEval; }
}
@ -81,14 +81,25 @@ namespace Debugger @@ -81,14 +81,25 @@ namespace Debugger
}
}
Eval(AppDomain appDomain, string description, EvalStarter evalStarter)
Eval(Thread evalThread, string description, EvalStarter evalStarter)
{
this.appDomain = appDomain;
if (evalThread == null)
throw new DebuggerException("No evaluation thread was provided");
this.appDomain = evalThread.AppDomain;
this.process = appDomain.Process;
this.description = description;
this.state = EvalState.Evaluating;
this.thread = GetEvaluationThread(appDomain);
this.corEval = thread.CorThread.CreateEval();
this.thread = evalThread;
if (evalThread.Suspended)
throw new GetValueException("Can not evaluate because thread is suspended");
if (evalThread.IsInNativeCode)
throw new GetValueException("Can not evaluate because thread is in native code");
if (!evalThread.IsAtSafePoint)
throw new GetValueException("Can not evaluate because thread is not at safe point");
this.corEval = evalThread.CorThread.CreateEval();
try {
evalStarter(this);
@ -123,34 +134,11 @@ namespace Debugger @@ -123,34 +134,11 @@ namespace Debugger
appDomain.Process.activeEvals.Add(this);
if (appDomain.Process.Options.SuspendOtherThreads) {
appDomain.Process.AsyncContinue(DebuggeeStateAction.Keep, new Thread[] { thread }, CorDebugThreadState.THREAD_SUSPEND);
appDomain.Process.AsyncContinue(DebuggeeStateAction.Keep, new Thread[] { evalThread }, CorDebugThreadState.THREAD_SUSPEND);
} else {
appDomain.Process.AsyncContinue(DebuggeeStateAction.Keep, this.Process.UnsuspendedThreads, CorDebugThreadState.THREAD_RUN);
}
}
static Thread GetEvaluationThread(AppDomain appDomain)
{
appDomain.Process.AssertPaused();
Thread st = appDomain.Process.SelectedThread;
if (st != null && !st.Suspended && !st.IsInNativeCode && st.IsAtSafePoint && st.CorThread.GetAppDomain().GetID() == appDomain.ID) {
return st;
}
foreach(Thread t in appDomain.Process.Threads) {
if (!t.Suspended && !t.IsInNativeCode && t.IsAtSafePoint && t.CorThread.GetAppDomain().GetID() == appDomain.ID) {
return t;
}
}
throw new GetValueException("No suitable thread for evaluation");
}
internal bool IsCorEval(ICorDebugEval corEval)
{
return this.corEval == corEval;
}
/// <exception cref="DebuggerException">Evaluation can not be stopped</exception>
/// <exception cref="GetValueException">Process exited</exception>
@ -200,19 +188,19 @@ namespace Debugger @@ -200,19 +188,19 @@ namespace Debugger
}
/// <summary> Synchronously calls a function and returns its return value </summary>
public static Value InvokeMethod(DebugMethodInfo method, Value thisValue, Value[] args)
public static Value InvokeMethod(Thread evalThread, DebugMethodInfo method, Value thisValue, Value[] args)
{
if (method.BackingField != null) {
method.Process.TraceMessage("Using backing field for " + method.FullName);
return Value.GetMemberValue(thisValue, method.BackingField, args);
return Value.GetMemberValue(evalThread, thisValue, method.BackingField, args);
}
return AsyncInvokeMethod(method, thisValue, args).WaitForResult();
return AsyncInvokeMethod(evalThread, method, thisValue, args).WaitForResult();
}
public static Eval AsyncInvokeMethod(DebugMethodInfo method, Value thisValue, Value[] args)
public static Eval AsyncInvokeMethod(Thread evalThread, DebugMethodInfo method, Value thisValue, Value[] args)
{
return new Eval(
method.AppDomain,
evalThread,
"Function call: " + method.FullName,
delegate(Eval eval) {
MethodInvokeStarter(eval, method, thisValue, args);
@ -251,14 +239,16 @@ namespace Debugger @@ -251,14 +239,16 @@ namespace Debugger
if (paramType.IsPrimitive && args[i].Type != paramType) {
object oldPrimVal = arg.PrimitiveValue;
object newPrimVal = Convert.ChangeType(oldPrimVal, paramType.PrimitiveType);
arg = CreateValue(method.AppDomain, newPrimVal);
// Eval - TODO: Is this dangerous?
arg = CreateValue(eval.thread, newPrimVal);
}
// It is importatnt to pass the parameted in the correct form (boxed/unboxed)
if (paramType.IsValueType) {
corArgs.Add(arg.CorGenericValue);
} else {
if (args[i].Type.IsValueType) {
corArgs.Add(arg.Box().CorValue);
// Eval - TODO: Is this dangerous?
corArgs.Add(arg.Box(eval.thread).CorValue);
} else {
corArgs.Add(arg.CorValue);
}
@ -272,22 +262,21 @@ namespace Debugger @@ -272,22 +262,21 @@ namespace Debugger
(uint)corArgs.Count, corArgs.ToArray()
);
}
public static Value CreateValue(AppDomain appDomain, object value)
public static Value CreateValue(Thread evalThread, object value)
{
if (value == null) {
ICorDebugClass corClass = appDomain.ObjectType.CorType.GetClass();
Thread thread = GetEvaluationThread(appDomain);
ICorDebugEval corEval = thread.CorThread.CreateEval();
ICorDebugClass corClass = evalThread.AppDomain.ObjectType.CorType.GetClass();
ICorDebugEval corEval = evalThread.CorThread.CreateEval();
ICorDebugValue corValue = corEval.CreateValue((uint)CorElementType.CLASS, corClass);
return new Value(appDomain, corValue);
return new Value(evalThread.AppDomain, corValue);
} else if (value is string) {
return Eval.NewString(appDomain, (string)value);
return Eval.NewString(evalThread, (string)value);
} else {
if (!value.GetType().IsPrimitive)
throw new DebuggerException("Value must be primitve type. Seen " + value.GetType());
Value val = Eval.NewObjectNoConstructor(DebugType.CreateFromType(appDomain.Mscorlib, value.GetType()));
val.PrimitiveValue = value;
Value val = Eval.NewObjectNoConstructor(evalThread, DebugType.CreateFromType(evalThread.AppDomain.Mscorlib, value.GetType()));
val.SetPrimitiveValue(evalThread, value);
return val;
}
}
@ -318,19 +307,15 @@ namespace Debugger @@ -318,19 +307,15 @@ namespace Debugger
}
*/
#region Convenience methods
public static Value NewString(AppDomain appDomain, string textToCreate)
public static Value NewString(Thread evalThread, string textToCreate)
{
return AsyncNewString(appDomain, textToCreate).WaitForResult();
return AsyncNewString(evalThread, textToCreate).WaitForResult();
}
#endregion
public static Eval AsyncNewString(AppDomain appDomain, string textToCreate)
public static Eval AsyncNewString(Thread evalThread, string textToCreate)
{
return new Eval(
appDomain,
evalThread,
"New string: " + textToCreate,
delegate(Eval eval) {
eval.CorEval2.NewStringWithLength(textToCreate, (uint)textToCreate.Length);
@ -338,20 +323,16 @@ namespace Debugger @@ -338,20 +323,16 @@ namespace Debugger
);
}
#region Convenience methods
public static Value NewArray(DebugType type, uint length, uint? lowerBound)
public static Value NewArray(Thread evalThread, DebugType type, uint length, uint? lowerBound)
{
return AsyncNewArray(type, length, lowerBound).WaitForResult();
return AsyncNewArray(evalThread, type, length, lowerBound).WaitForResult();
}
#endregion
public static Eval AsyncNewArray(DebugType type, uint length, uint? lowerBound)
public static Eval AsyncNewArray(Thread evalThread, DebugType type, uint length, uint? lowerBound)
{
lowerBound = lowerBound ?? 0;
return new Eval(
type.AppDomain,
evalThread,
"New array: " + type + "[" + length + "]",
delegate(Eval eval) {
// Multi-dimensional arrays not supported in .NET 2.0
@ -360,43 +341,37 @@ namespace Debugger @@ -360,43 +341,37 @@ namespace Debugger
);
}
#region Convenience methods
public static Value NewObject(DebugMethodInfo constructor, Value[] constructorArguments)
public static Value NewObject(Thread evalThread, DebugMethodInfo constructor, Value[] constructorArguments)
{
return AsyncNewObject(constructor, constructorArguments).WaitForResult();
return AsyncNewObject(evalThread, constructor, constructorArguments).WaitForResult();
}
#endregion
public static Eval AsyncNewObject(DebugMethodInfo constructor, Value[] constructorArguments)
public static Eval AsyncNewObject(Thread evalThread, DebugMethodInfo constructor, Value[] constructorArguments)
{
ICorDebugValue[] constructorArgsCorDebug = ValuesAsCorDebug(constructorArguments);
return new Eval(
constructor.AppDomain,
evalThread,
"New object: " + constructor.FullName,
delegate(Eval eval) {
eval.CorEval2.NewParameterizedObject(
constructor.CorFunction,
(uint)constructor.DeclaringType.GetGenericArguments().Length, ((DebugType)constructor.DeclaringType).GenericArgumentsAsCorDebugType,
(uint)constructorArgsCorDebug.Length, constructorArgsCorDebug);
(uint)constructor.DeclaringType.GetGenericArguments().Length,
((DebugType)constructor.DeclaringType).GenericArgumentsAsCorDebugType,
(uint)constructorArgsCorDebug.Length,
constructorArgsCorDebug);
}
);
}
#region Convenience methods
public static Value NewObjectNoConstructor(DebugType debugType)
public static Value NewObjectNoConstructor(Thread evalThread, DebugType debugType)
{
return AsyncNewObjectNoConstructor(debugType).WaitForResult();
return AsyncNewObjectNoConstructor(evalThread, debugType).WaitForResult();
}
#endregion
public static Eval AsyncNewObjectNoConstructor(DebugType debugType)
public static Eval AsyncNewObjectNoConstructor(Thread evalThread, DebugType debugType)
{
return new Eval(
debugType.AppDomain,
evalThread,
"New object: " + debugType.FullName,
delegate(Eval eval) {
eval.CorEval2.NewParameterizedObjectNoConstructor(debugType.CorType.GetClass(), (uint)debugType.GetGenericArguments().Length, debugType.GenericArgumentsAsCorDebugType);

16
src/AddIns/Debugger/Debugger.Core/Exception.cs

@ -47,7 +47,7 @@ namespace Debugger @@ -47,7 +47,7 @@ namespace Debugger
/// <seealso cref="System.Exception" />
public string Message {
get {
Value message = exception.GetMemberValue("_message");
Value message = exception.GetFieldValue("_message");
return message.IsNull ? string.Empty : message.AsString();
}
}
@ -56,14 +56,14 @@ namespace Debugger @@ -56,14 +56,14 @@ namespace Debugger
/// <seealso cref="System.Exception" />
public Exception InnerException {
get {
Value innerException = exception.GetMemberValue("_innerException");
Value innerException = exception.GetFieldValue("_innerException");
return innerException.IsNull ? null : new Exception(innerException, this.ExceptionType);
}
}
public void MakeValuePermanent()
{
exception = exception.GetPermanentReference();
exception = exception.GetPermanentReferenceOfHeapValue();
}
public override string ToString()
@ -81,25 +81,25 @@ namespace Debugger @@ -81,25 +81,25 @@ namespace Debugger
return sb.ToString();
}
public string GetStackTrace()
public string GetStackTrace(Thread evalThread)
{
return GetStackTrace("--- End of inner exception stack trace ---");
return GetStackTrace(evalThread, "--- End of inner exception stack trace ---");
}
/// <summary> Returs formated stacktrace for the exception </summary>
/// <exception cref="GetValueException"> Getting the stacktrace involves property
/// evaluation so GetValueException can be thrown in some cicumstances. </exception>
public string GetStackTrace(string endOfInnerExceptionFormat)
public string GetStackTrace(Thread evalThread, string endOfInnerExceptionFormat)
{
StringBuilder sb = new StringBuilder();
if (this.InnerException != null) {
sb.Append(this.InnerException.GetStackTrace(endOfInnerExceptionFormat));
sb.Append(this.InnerException.GetStackTrace(evalThread, endOfInnerExceptionFormat));
sb.Append(" ");
sb.Append(endOfInnerExceptionFormat);
sb.AppendLine();
}
// Note that evaluation is not possible after a stackoverflow exception
Value stackTrace = exception.GetMemberValue("StackTrace");
Value stackTrace = exception.GetMemberValue(evalThread, "StackTrace");
if (!stackTrace.IsNull) {
sb.Append(stackTrace.AsString());
sb.AppendLine();

13
src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs

@ -26,6 +26,7 @@ namespace Debugger @@ -26,6 +26,7 @@ namespace Debugger
bool raiseEventsOnNextExit;
bool isInCallback;
Thread threadToReport;
List<Breakpoint> breakpointsHit = new List<Breakpoint>();
Exception exceptionThrown;
@ -76,7 +77,7 @@ namespace Debugger @@ -76,7 +77,7 @@ namespace Debugger
void EnterCallback(string name, ICorDebugThread pThread)
{
EnterCallback(name, pThread.GetProcess());
process.SelectedThread = process.GetThread(pThread);
threadToReport = process.GetThread(pThread);
}
void ExitCallback()
@ -96,11 +97,13 @@ namespace Debugger @@ -96,11 +97,13 @@ namespace Debugger
process.TraceMessage("Callback exit: Paused");
process.DisableAllSteppers();
process.CheckSelectedStackFrames();
if (raiseEventsOnNextExit) {
DebuggerEventArgs e = new DebuggerEventArgs(process);
DebuggerEventArgs e = new DebuggerEventArgs();
e.Process = process;
e.Thread = threadToReport;
e.BreakpointsHit = breakpointsHit.ToArray();
e.ExceptionThrown = exceptionThrown;
threadToReport = null;
breakpointsHit.Clear();
exceptionThrown = null;
@ -127,7 +130,7 @@ namespace Debugger @@ -127,7 +130,7 @@ namespace Debugger
Thread thread = process.GetThread(pThread);
Stepper stepper = process.GetStepper(pStepper);
StackFrame currentStackFrame = process.SelectedThread.MostRecentStackFrame;
StackFrame currentStackFrame = thread.MostRecentStackFrame;
process.TraceMessage(" - stopped at {0} because of {1}", currentStackFrame.MethodInfo.FullName, stepper.ToString());
process.Steppers.Remove(stepper);
@ -524,7 +527,7 @@ namespace Debugger @@ -524,7 +527,7 @@ namespace Debugger
// sanity check: we can only handle one exception after another
// TODO : create Exception queue if CLR throws multiple exceptions
Debug.Assert(exceptionThrown == null);
Value value = new Value(process.GetAppDomain(pAppDomain), process.SelectedThread.CorThread.GetCurrentException()).GetPermanentReference();
Value value = new Value(process.GetAppDomain(pAppDomain), pThread.GetCurrentException()).GetPermanentReferenceOfHeapValue();
exceptionThrown = new Exception(value, exceptionType);
pauseOnNextExit = true;

8
src/AddIns/Debugger/Debugger.Core/MetaData/DebugConstructorInfo.cs

@ -19,6 +19,10 @@ namespace Debugger.MetaData @@ -19,6 +19,10 @@ namespace Debugger.MetaData
{
DebugMethodInfo methodInfo;
public DebugMethodInfo MethodInfo {
get { return methodInfo; }
}
internal DebugConstructorInfo(DebugMethodInfo methodInfo)
{
this.methodInfo = methodInfo;
@ -109,13 +113,13 @@ namespace Debugger.MetaData @@ -109,13 +113,13 @@ namespace Debugger.MetaData
/// <inheritdoc/>
public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
{
return methodInfo.Invoke(null, invokeAttr, binder, parameters, culture);
throw new NotImplementedException("Use Debugger.Value directly");
}
/// <inheritdoc/>
public override object Invoke(BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
{
return methodInfo.Invoke(null, invokeAttr, binder, parameters, culture);
throw new NotImplementedException("Use Debugger.Value directly");
}
/// <inheritdoc/>

4
src/AddIns/Debugger/Debugger.Core/MetaData/DebugFieldInfo.cs

@ -109,13 +109,13 @@ namespace Debugger.MetaData @@ -109,13 +109,13 @@ namespace Debugger.MetaData
/// <inheritdoc/>
public override object GetValue(object obj)
{
return Value.GetFieldValue((Value)obj, this);
throw new NotImplementedException("Use Debugger.Value directly");
}
/// <inheritdoc/>
public override void SetValue(object obj, object value, System.Reflection.BindingFlags invokeAttr, Binder binder, CultureInfo culture)
{
Value.SetFieldValue((Value)obj, this, (Value)value);
throw new NotImplementedException("Use Debugger.Value directly");
}
/// <inheritdoc/>

18
src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs

@ -160,17 +160,7 @@ namespace Debugger.MetaData @@ -160,17 +160,7 @@ namespace Debugger.MetaData
/// <inheritdoc/>
public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture)
{
List<Value> args = new List<Value>();
foreach(object arg in parameters) {
args.Add((Value)arg);
}
if (this.IsSpecialName && this.Name == ".ctor") {
if (obj != null)
throw new GetValueException("'obj' must be null for constructor call");
return Eval.NewObject(this, args.ToArray());
} else {
return Eval.InvokeMethod(this, (Value)obj, args.ToArray());
}
throw new NotImplementedException("Use Debugger.Value directly");
}
/// <inheritdoc/>
@ -568,7 +558,8 @@ namespace Debugger.MetaData @@ -568,7 +558,8 @@ namespace Debugger.MetaData
localVariables,
0, int.MaxValue,
delegate(StackFrame context) {
return context.GetThisValue().GetFieldValue(fieldInfoCopy);
// TODO: Use eval thread
return context.GetThisValue().GetFieldValue(context.Thread, fieldInfoCopy);
},
(DebugType)fieldInfo.FieldType
);
@ -608,7 +599,8 @@ namespace Debugger.MetaData @@ -608,7 +599,8 @@ namespace Debugger.MetaData
scopeEndOffset,
(DebugType)fieldInfo.FieldType,
delegate(StackFrame context) {
return getCaptureClass(context).GetFieldValue(fieldInfoCopy);
// TODO: Use eval thread
return getCaptureClass(context).GetFieldValue(context.Thread, fieldInfoCopy);
}
);
locVar.IsCaptured = true;

12
src/AddIns/Debugger/Debugger.Core/MetaData/DebugPropertyInfo.cs

@ -184,21 +184,13 @@ namespace Debugger.MetaData @@ -184,21 +184,13 @@ namespace Debugger.MetaData
/// <inheritdoc/>
public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
{
List<Value> args = new List<Value>();
foreach(object arg in index) {
args.Add((Value)arg);
}
return Value.GetPropertyValue((Value)obj, this, args.ToArray());
throw new NotImplementedException("Use Debugger.Value directly");
}
/// <inheritdoc/>
public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture)
{
List<Value> args = new List<Value>();
foreach(object arg in index) {
args.Add((Value)arg);
}
Value.SetPropertyValue((Value)obj, this, args.ToArray(), (Value)value);
throw new NotImplementedException("Use Debugger.Value directly");
}
public bool IsPublic {

17
src/AddIns/Debugger/Debugger.Core/NDebugger.cs

@ -297,14 +297,12 @@ namespace Debugger @@ -297,14 +297,12 @@ namespace Debugger
[Serializable]
public class DebuggerEventArgs: EventArgs
{
public Process Process { get; internal set; }
public Breakpoint[] BreakpointsHit { get; internal set; }
public Exception ExceptionThrown { get; internal set; }
public DebuggerEventArgs(Process process)
{
this.Process = process;
}
/// <summary> The process on which the event occured. Can be null. </summary>
public Process Process { get; set; }
/// <summary> The thread on which the event occured. Can be null if the event was not thread specific. </summary>
public Thread Thread { get; set; }
public Breakpoint[] BreakpointsHit { get; set; }
public Exception ExceptionThrown { get; set; }
}
[Serializable]
@ -312,8 +310,9 @@ namespace Debugger @@ -312,8 +310,9 @@ namespace Debugger
{
public Module Module { get; private set; }
public ModuleEventArgs(Module module) : base(module.Process)
public ModuleEventArgs(Module module)
{
this.Process = module.Process;
this.Module = module;
}
}

95
src/AddIns/Debugger/Debugger.Core/Process.cs

@ -90,28 +90,6 @@ namespace Debugger @@ -90,28 +90,6 @@ namespace Debugger
get { return this.threads; }
}
public Thread SelectedThread { get; set; }
public StackFrame SelectedStackFrame {
get {
if (SelectedThread == null) {
return null;
} else {
return SelectedThread.SelectedStackFrame;
}
}
}
public SourcecodeSegment NextStatement {
get {
if (SelectedStackFrame == null || IsRunning) {
return null;
} else {
return SelectedStackFrame.NextStatement;
}
}
}
internal bool BreakInMain { get; set; }
public IEnumerable<AppDomain> AppDomains {
@ -206,7 +184,7 @@ namespace Debugger @@ -206,7 +184,7 @@ namespace Debugger
internal Eval GetActiveEval(ICorDebugEval corEval)
{
foreach(Eval eval in this.activeEvals) {
if (eval.IsCorEval(corEval)) {
if (eval.CorEval == corEval) {
return eval;
}
}
@ -284,8 +262,6 @@ namespace Debugger @@ -284,8 +262,6 @@ namespace Debugger
{
AssertPaused();
DisableAllSteppers();
CheckSelectedStackFrames();
SelectMostRecentStackFrameWithLoadedSymbols();
foreach (var corBreakpoint in tempBreakpoints) {
corBreakpoint.Activate(0);
@ -317,7 +293,7 @@ namespace Debugger @@ -317,7 +293,7 @@ namespace Debugger
throw new DebuggerException("Can not raise event within callback.");
TraceMessage ("Debugger event: OnResumed()");
if (Resumed != null) {
Resumed(this, new DebuggerEventArgs(this));
Resumed(this, new DebuggerEventArgs() { Process = this });
}
}
@ -406,7 +382,7 @@ namespace Debugger @@ -406,7 +382,7 @@ namespace Debugger
if(!hasExited) {
hasExited = true;
if (Exited != null) {
Exited(this, new DebuggerEventArgs(this));
Exited(this, new DebuggerEventArgs() { Process = this });
}
// Expire pause seesion first
if (IsPaused) {
@ -428,7 +404,7 @@ namespace Debugger @@ -428,7 +404,7 @@ namespace Debugger
corProcess.Stop(uint.MaxValue); // Infinite; ignored anyway
NotifyPaused();
OnPaused(new DebuggerEventArgs(this));
OnPaused(new DebuggerEventArgs() { Process = this });
}
public void Detach()
@ -580,50 +556,6 @@ namespace Debugger @@ -580,50 +556,6 @@ namespace Debugger
// This is done once ExitProcess callback is received
}
void SelectSomeThread()
{
if (this.SelectedThread != null && !this.SelectedThread.IsInValidState) {
this.SelectedThread = null;
}
if (this.SelectedThread == null) {
foreach(Thread thread in this.Threads) {
if (thread.IsInValidState) {
this.SelectedThread = thread;
break;
}
}
}
}
internal void CheckSelectedStackFrames()
{
foreach(Thread thread in this.Threads) {
if (thread.IsInValidState) {
if (thread.SelectedStackFrame != null && thread.SelectedStackFrame.IsInvalid) {
thread.SelectedStackFrame = null;
}
} else {
thread.SelectedStackFrame = null;
}
}
}
internal void SelectMostRecentStackFrameWithLoadedSymbols()
{
SelectSomeThread();
if (this.SelectedThread != null) {
this.SelectedThread.SelectedStackFrame = null;
foreach (StackFrame stackFrame in this.SelectedThread.Callstack) {
if (stackFrame.HasSymbols) {
if (this.Options.StepOverDebuggerAttributes && stackFrame.MethodInfo.IsNonUserCode)
continue;
this.SelectedThread.SelectedStackFrame = stackFrame;
break;
}
}
}
}
internal Stepper GetStepper(ICorDebugStepper corStepper)
{
foreach(Stepper stepper in this.Steppers) {
@ -726,24 +658,5 @@ namespace Debugger @@ -726,24 +658,5 @@ namespace Debugger
}
#endregion
public StackFrame GetCurrentExecutingFrame()
{
if (IsRunning || SelectedThread == null)
return null;
if (SelectedStackFrame != null) {
if (SelectedThread.MostRecentStackFrame != null) {
if (SelectedStackFrame.HasSymbols && SelectedThread.MostRecentStackFrame.HasSymbols)
return SelectedStackFrame;
else
return SelectedThread.MostRecentStackFrame;
} else {
return SelectedThread.MostRecentStackFrame;
}
} else {
return SelectedThread.MostRecentStackFrame;
}
}
}
}

38
src/AddIns/Debugger/Debugger.Core/Thread.cs

@ -22,11 +22,13 @@ namespace Debugger @@ -22,11 +22,13 @@ namespace Debugger
Stepper currentStepIn;
StackFrame selectedStackFrame;
public Process Process {
get { return process; }
}
public AppDomain AppDomain {
get { return process.GetAppDomain(this.corThread.GetAppDomain()); }
}
[Debugger.Tests.Ignore]
public uint ID {
@ -81,9 +83,6 @@ namespace Debugger @@ -81,9 +83,6 @@ namespace Debugger
if (this.HasExited) throw new DebuggerException("Already exited");
process.TraceMessage("Thread " + this.ID + " exited");
if (process.SelectedThread == this) {
process.SelectedThread = null;
}
this.HasExited = true;
process.threads.Remove(this);
@ -113,7 +112,7 @@ namespace Debugger @@ -113,7 +112,7 @@ namespace Debugger
Value runTimeValue = RuntimeValue;
if (runTimeValue.IsNull) return ThreadPriority.Normal;
return (ThreadPriority)(int)runTimeValue.GetMemberValue("m_Priority").PrimitiveValue;
return (ThreadPriority)(int)runTimeValue.GetFieldValue("m_Priority").PrimitiveValue;
}
}
@ -138,7 +137,7 @@ namespace Debugger @@ -138,7 +137,7 @@ namespace Debugger
if (!IsInValidState) return string.Empty;
Value runtimeValue = RuntimeValue;
if (runtimeValue.IsNull) return string.Empty;
Value runtimeName = runtimeValue.GetMemberValue("m_Name");
Value runtimeName = runtimeValue.GetFieldValue("m_Name");
if (runtimeName.IsNull) return string.Empty;
return runtimeName.AsString(100);
}
@ -288,30 +287,31 @@ namespace Debugger @@ -288,30 +287,31 @@ namespace Debugger
return stackTrace.ToString();
}
public StackFrame SelectedStackFrame {
get {
if (selectedStackFrame != null && selectedStackFrame.IsInvalid) return null;
if (process.IsRunning) return null;
return selectedStackFrame;
}
set {
selectedStackFrame = value;
}
}
/// <summary>
/// Returns the most recent stack frame (the one that is currently executing).
/// Returns null if callstack is empty.
/// </summary>
public StackFrame MostRecentStackFrame {
get {
foreach(StackFrame stackFrame in Callstack) {
foreach(StackFrame stackFrame in this.Callstack) {
return stackFrame;
}
return null;
}
}
[Debugger.Tests.Ignore]
public StackFrame MostRecentUserStackFrame {
get {
foreach (StackFrame stackFrame in this.Callstack) {
if (!stackFrame.MethodInfo.StepOver) {
return stackFrame;
}
}
return null;
}
}
public bool IsInNativeCode {
get {
process.AssertPaused();

203
src/AddIns/Debugger/Debugger.Core/Value.cs

@ -113,8 +113,7 @@ namespace Debugger @@ -113,8 +113,7 @@ namespace Debugger
/// Value is valid only until the debuggee is resummed. </summary>
public bool IsInvalid {
get {
return corValue_pauseSession != this.Process.PauseSession &&
!(corValue is ICorDebugHandleValue);
return corValue_pauseSession != this.Process.PauseSession && !(corValue is ICorDebugHandleValue);
}
}
@ -193,11 +192,11 @@ namespace Debugger @@ -193,11 +192,11 @@ namespace Debugger
}
// Box value type
public Value Box()
public Value Box(Thread evalThread)
{
byte[] rawValue = this.CorGenericValue.GetRawValue();
// The type must not be a primive type (always true in current design)
ICorDebugReferenceValue corRefValue = Eval.NewObjectNoConstructor(this.Type).CorReferenceValue;
ICorDebugReferenceValue corRefValue = Eval.NewObjectNoConstructor(evalThread, this.Type).CorReferenceValue;
// Make the reference to box permanent
corRefValue = ((ICorDebugHeapValue2)corRefValue.Dereference()).CreateHandle(CorDebugHandleType.HANDLE_STRONG);
// Create new value
@ -207,8 +206,17 @@ namespace Debugger @@ -207,8 +206,17 @@ namespace Debugger
return newValue;
}
/// <remarks> If we are sure it is heap value we do not need eval. </remarks>
[Debugger.Tests.Ignore]
public Value GetPermanentReference()
public Value GetPermanentReferenceOfHeapValue()
{
if (this.CorValue is ICorDebugReferenceValue) {
return GetPermanentReference(null);
}
throw new DebuggerException("Value is not a heap value");
}
public Value GetPermanentReference(Thread evalThread)
{
if (this.CorValue is ICorDebugHandleValue) {
return this;
@ -224,7 +232,7 @@ namespace Debugger @@ -224,7 +232,7 @@ namespace Debugger
return this;
}
} else {
return this.Box();
return this.Box(evalThread);
}
}
@ -242,13 +250,13 @@ namespace Debugger @@ -242,13 +250,13 @@ namespace Debugger
}
/// <summary> Copy the acutal value from some other Value object </summary>
public void SetValue(Value newValue)
public void SetValue(Thread evalThread, Value newValue)
{
ICorDebugValue newCorValue = newValue.CorValue;
if (this.CorValue is ICorDebugReferenceValue) {
if (!(newCorValue is ICorDebugReferenceValue))
newCorValue = newValue.Box().CorValue;
newCorValue = newValue.Box(evalThread).CorValue;
((ICorDebugReferenceValue)this.CorValue).SetValue(((ICorDebugReferenceValue)newCorValue).GetValue());
} else {
this.CorGenericValue.SetRawValue(newValue.CorGenericValue.GetRawValue());
@ -273,22 +281,24 @@ namespace Debugger @@ -273,22 +281,24 @@ namespace Debugger
return CorGenericValue.GetValue(this.Type.PrimitiveType);
}
}
set {
if (this.Type.FullName == typeof(string).FullName) {
this.SetValue(Eval.NewString(this.AppDomain, value.ToString()));
} else {
if (this.Type.PrimitiveType == null)
throw new DebuggerException("Value is not a primitive type");
if (value == null)
throw new DebuggerException("Can not set primitive value to null");
object newValue;
try {
newValue = Convert.ChangeType(value, this.Type.PrimitiveType);
} catch {
throw new NotSupportedException("Can not convert " + value.GetType().ToString() + " to " + this.Type.PrimitiveType.ToString());
}
CorGenericValue.SetValue(newValue);
}
public void SetPrimitiveValue(Thread evalThread, object value)
{
if (this.Type.FullName == typeof(string).FullName) {
this.SetValue(evalThread, Eval.NewString(evalThread, value.ToString()));
} else {
if (this.Type.PrimitiveType == null)
throw new DebuggerException("Value is not a primitive type");
if (value == null)
throw new DebuggerException("Can not set primitive value to null");
object newValue;
try {
newValue = Convert.ChangeType(value, this.Type.PrimitiveType);
} catch {
throw new NotSupportedException("Can not convert " + value.GetType().ToString() + " to " + this.Type.PrimitiveType.ToString());
}
CorGenericValue.SetValue(newValue);
}
}
@ -370,10 +380,10 @@ namespace Debugger @@ -370,10 +380,10 @@ namespace Debugger
return CorArrayValue.GetElement(indices);
}
public void SetArrayElement(int[] elementIndices, Value newVal)
public void SetArrayElement(Thread evalThread, int[] elementIndices, Value newVal)
{
Value elem = GetArrayElement(elementIndices);
elem.SetValue(newVal);
elem.SetValue(evalThread, newVal);
}
/// <summary> Returns all elements in the array </summary>
@ -409,88 +419,85 @@ namespace Debugger @@ -409,88 +419,85 @@ namespace Debugger
}
}
#region Convenience overload methods
/// <summary> Get a field or property of an object with a given name. </summary>
/// <returns> Null if not found </returns>
public Value GetMemberValue(string name)
public Value GetMemberValue(Thread evalThread, string name)
{
MemberInfo memberInfo = this.Type.GetMember<MemberInfo>(name, DebugType.BindingFlagsAllInScope, DebugType.IsFieldOrNonIndexedProperty);
if (memberInfo == null)
return null;
return GetMemberValue(memberInfo);
return GetMemberValue(evalThread, memberInfo);
}
/// <summary> Get the value of given member. </summary>
public Value GetMemberValue(MemberInfo memberInfo, params Value[] arguments)
public Value GetMemberValue(Thread evalThread, MemberInfo memberInfo, params Value[] arguments)
{
return GetMemberValue(this, memberInfo, arguments);
return GetMemberValue(evalThread, this, memberInfo, arguments);
}
#endregion
/// <summary> Get the value of given member. </summary>
/// <param name="objectInstance">null if member is static</param>
public static Value GetMemberValue(Value objectInstance, MemberInfo memberInfo, params Value[] arguments)
public static Value GetMemberValue(Thread evalThread, Value objectInstance, MemberInfo memberInfo, params Value[] arguments)
{
if (memberInfo is FieldInfo) {
if (arguments.Length > 0)
throw new GetValueException("Arguments can not be used for a field");
return GetFieldValue(objectInstance, (FieldInfo)memberInfo);
return GetFieldValue(evalThread, objectInstance, (FieldInfo)memberInfo);
} else if (memberInfo is PropertyInfo) {
return GetPropertyValue(objectInstance, (PropertyInfo)memberInfo, arguments);
return GetPropertyValue(evalThread, objectInstance, (PropertyInfo)memberInfo, arguments);
} else if (memberInfo is MethodInfo) {
return InvokeMethod(objectInstance, (MethodInfo)memberInfo, arguments);
return InvokeMethod(evalThread, objectInstance, (MethodInfo)memberInfo, arguments);
}
throw new DebuggerException("Unknown member type: " + memberInfo.GetType());
}
#region Convenience overload methods
/// <summary> Get the value of given field. </summary>
public Value GetFieldValue(FieldInfo fieldInfo)
public static void SetFieldValue(Thread evalThread, Value objectInstance, FieldInfo fieldInfo, Value newValue)
{
return Value.GetFieldValue(this, fieldInfo);
Value val = GetFieldValue(evalThread, objectInstance, fieldInfo);
if (!fieldInfo.FieldType.IsAssignableFrom(newValue.Type))
throw new GetValueException("Can not assign {0} to {1}", newValue.Type.FullName, fieldInfo.FieldType.FullName);
val.SetValue(evalThread, newValue);
}
#endregion
/// <summary> Get the value of given instance field. </summary>
public Value GetFieldValue(string name)
{
FieldInfo fieldInfo = this.Type.GetMember<FieldInfo>(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null);
if (fieldInfo == null)
throw new DebuggerException("Field '{0}' not found", name);
return new Value(this.AppDomain, GetFieldCorValue(null, this, fieldInfo));
}
public static void SetFieldValue(Value objectInstance, FieldInfo fieldInfo, Value newValue)
/// <summary> Get the value of given field. </summary>
public Value GetFieldValue(Thread evalThread, FieldInfo fieldInfo)
{
Value val = GetFieldValue(objectInstance, fieldInfo);
if (!fieldInfo.FieldType.IsAssignableFrom(newValue.Type))
throw new GetValueException("Can not assign {0} to {1}", newValue.Type.FullName, fieldInfo.FieldType.FullName);
val.SetValue(newValue);
return Value.GetFieldValue(evalThread, this, fieldInfo);
}
/// <summary> Get the value of given field. </summary>
/// <param name="thread"> Thread to use for thread-local storage </param>
/// <param name="objectInstance">null if field is static</param>
public static Value GetFieldValue(Value objectInstance, FieldInfo fieldInfo)
public static Value GetFieldValue(Thread evalThread, Value objectInstance, FieldInfo fieldInfo)
{
CheckObject(objectInstance, fieldInfo);
if (fieldInfo.IsStatic && fieldInfo.IsLiteral) {
return GetLiteralValue((DebugFieldInfo)fieldInfo);
return GetLiteralValue(evalThread, (DebugFieldInfo)fieldInfo);
} else {
return new Value(
((DebugFieldInfo)fieldInfo).AppDomain,
GetFieldCorValue(objectInstance, fieldInfo)
GetFieldCorValue(evalThread, objectInstance, fieldInfo)
);
}
}
static ICorDebugValue GetFieldCorValue(Value objectInstance, FieldInfo fieldInfo)
static ICorDebugValue GetFieldCorValue(Thread contextThread, Value objectInstance, FieldInfo fieldInfo)
{
Process process = ((DebugFieldInfo)fieldInfo).Process;
// Current frame is used to resolve context specific static values (eg. ThreadStatic)
ICorDebugFrame curFrame = null;
if (process.IsPaused &&
process.SelectedThread != null &&
process.SelectedThread.MostRecentStackFrame != null &&
process.SelectedThread.MostRecentStackFrame.CorILFrame != null)
{
curFrame = process.SelectedThread.MostRecentStackFrame.CorILFrame;
if (contextThread != null && contextThread.MostRecentStackFrame != null && contextThread.MostRecentStackFrame.CorILFrame != null) {
curFrame = contextThread.MostRecentStackFrame.CorILFrame;
}
try {
@ -504,76 +511,54 @@ namespace Debugger @@ -504,76 +511,54 @@ namespace Debugger
}
}
static Value GetLiteralValue(DebugFieldInfo fieldInfo)
static Value GetLiteralValue(Thread evalThread, DebugFieldInfo fieldInfo)
{
CorElementType corElemType = (CorElementType)fieldInfo.FieldProps.ConstantType;
if (corElemType == CorElementType.CLASS) {
// Only null literals are allowed
return Eval.CreateValue(fieldInfo.AppDomain, null);
return Eval.CreateValue(evalThread, null);
} else if (corElemType == CorElementType.STRING) {
string str = Marshal.PtrToStringUni(fieldInfo.FieldProps.ConstantPtr, (int)fieldInfo.FieldProps.ConstantStringLength);
return Eval.CreateValue(fieldInfo.AppDomain, str);
return Eval.CreateValue(evalThread, str);
} else {
DebugType type = DebugType.CreateFromType(fieldInfo.AppDomain.Mscorlib, DebugType.CorElementTypeToManagedType(corElemType));
if (fieldInfo.FieldType.IsEnum && fieldInfo.FieldType.GetEnumUnderlyingType() == type) {
Value val = Eval.NewObjectNoConstructor((DebugType)fieldInfo.FieldType);
Value backingField = val.GetMemberValue("value__");
Value val = Eval.NewObjectNoConstructor(evalThread, (DebugType)fieldInfo.FieldType);
Value backingField = val.GetMemberValue(evalThread, "value__");
backingField.CorGenericValue.SetValue(fieldInfo.FieldProps.ConstantPtr);
return val;
} else {
Value val = Eval.NewObjectNoConstructor(type);
Value val = Eval.NewObjectNoConstructor(evalThread, type);
val.CorGenericValue.SetValue(fieldInfo.FieldProps.ConstantPtr);
return val;
}
}
}
#region Convenience overload methods
/// <summary> Get the value of the property using the get accessor </summary>
public Value GetPropertyValue(PropertyInfo propertyInfo, params Value[] arguments)
public Value GetPropertyValue(Thread evalThread, PropertyInfo propertyInfo, params Value[] arguments)
{
return GetPropertyValue(this, propertyInfo, arguments);
return GetPropertyValue(evalThread, this, propertyInfo, arguments);
}
#endregion
/// <summary> Get the value of the property using the get accessor </summary>
public static Value GetPropertyValue(Value objectInstance, PropertyInfo propertyInfo, params Value[] arguments)
public static Value GetPropertyValue(Thread evalThread, Value objectInstance, PropertyInfo propertyInfo, params Value[] arguments)
{
CheckObject(objectInstance, propertyInfo);
if (propertyInfo.GetGetMethod() == null) throw new GetValueException("Property does not have a get method");
Value val = Value.InvokeMethod(objectInstance, (DebugMethodInfo)propertyInfo.GetGetMethod(), arguments);
return val;
}
#region Convenience overload methods
/// <summary> Set the value of the property using the set accessor </summary>
public Value SetPropertyValue(PropertyInfo propertyInfo, Value newValue)
{
return SetPropertyValue(this, propertyInfo, null, newValue);
return Value.InvokeMethod(evalThread, objectInstance, (DebugMethodInfo)propertyInfo.GetGetMethod(), arguments);
}
/// <summary> Set the value of the property using the set accessor </summary>
public Value SetPropertyValue(PropertyInfo propertyInfo, Value[] arguments, Value newValue)
public Value SetPropertyValue(Thread evalThread, PropertyInfo propertyInfo, Value[] arguments, Value newValue)
{
return SetPropertyValue(this, propertyInfo, arguments, newValue);
return SetPropertyValue(evalThread, this, propertyInfo, arguments, newValue);
}
/// <summary> Set the value of the property using the set accessor </summary>
public static Value SetPropertyValue(Value objectInstance, PropertyInfo propertyInfo, Value newValue)
{
return SetPropertyValue(objectInstance, propertyInfo, null, newValue);
}
#endregion
/// <summary> Set the value of the property using the set accessor </summary>
public static Value SetPropertyValue(Value objectInstance, PropertyInfo propertyInfo, Value[] arguments, Value newValue)
public static Value SetPropertyValue(Thread evalThread, Value objectInstance, PropertyInfo propertyInfo, Value[] arguments, Value newValue)
{
CheckObject(objectInstance, propertyInfo);
@ -585,25 +570,22 @@ namespace Debugger @@ -585,25 +570,22 @@ namespace Debugger
allParams[0] = newValue;
arguments.CopyTo(allParams, 1);
return Value.InvokeMethod(objectInstance, (DebugMethodInfo)propertyInfo.GetSetMethod(), allParams);
return Value.InvokeMethod(evalThread, objectInstance, (DebugMethodInfo)propertyInfo.GetSetMethod(), allParams);
}
#region Convenience overload methods
/// <summary> Synchronously invoke the method </summary>
public Value InvokeMethod(MethodInfo methodInfo, params Value[] arguments)
public Value InvokeMethod(Thread evalThread, MethodInfo methodInfo, params Value[] arguments)
{
return InvokeMethod(this, methodInfo, arguments);
return InvokeMethod(evalThread, this, methodInfo, arguments);
}
#endregion
/// <summary> Synchronously invoke the method </summary>
public static Value InvokeMethod(Value objectInstance, MethodInfo methodInfo, params Value[] arguments)
public static Value InvokeMethod(Thread evalThread, Value objectInstance, MethodInfo methodInfo, params Value[] arguments)
{
CheckObject(objectInstance, methodInfo);
return Eval.InvokeMethod(
evalThread,
(DebugMethodInfo)methodInfo,
methodInfo.IsStatic ? null : objectInstance,
arguments ?? new Value[0]
@ -611,7 +593,7 @@ namespace Debugger @@ -611,7 +593,7 @@ namespace Debugger
}
/// <summary> Invoke the ToString() method </summary>
public string InvokeToString(int maxLength = int.MaxValue)
public string InvokeToString(Thread evalThread, int maxLength = int.MaxValue)
{
if (this.IsNull) return AsString(maxLength);
if (this.Type.IsPrimitive) return AsString(maxLength);
@ -619,25 +601,22 @@ namespace Debugger @@ -619,25 +601,22 @@ namespace Debugger
if (this.Type.IsPointer) return "0x" + this.PointerAddress.ToString("X");
// if (!IsObject) // Can invoke on primitives
DebugMethodInfo methodInfo = (DebugMethodInfo)this.AppDomain.ObjectType.GetMethod("ToString", new DebugType[] {});
return Eval.InvokeMethod(methodInfo, this, new Value[] {}).AsString(maxLength);
return Eval.InvokeMethod(evalThread, methodInfo, this, new Value[] {}).AsString(maxLength);
}
#region Convenience overload methods
/// <summary> Asynchronously invoke the method </summary>
public Eval AsyncInvokeMethod(MethodInfo methodInfo, params Value[] arguments)
public Eval AsyncInvokeMethod(Thread evalThread, MethodInfo methodInfo, params Value[] arguments)
{
return AsyncInvokeMethod(this, methodInfo, arguments);
return AsyncInvokeMethod(evalThread, this, methodInfo, arguments);
}
#endregion
/// <summary> Asynchronously invoke the method </summary>
public static Eval AsyncInvokeMethod(Value objectInstance, MethodInfo methodInfo, params Value[] arguments)
public static Eval AsyncInvokeMethod(Thread evalThread, Value objectInstance, MethodInfo methodInfo, params Value[] arguments)
{
CheckObject(objectInstance, methodInfo);
return Eval.AsyncInvokeMethod(
evalThread,
(DebugMethodInfo)methodInfo,
methodInfo.IsStatic ? null : objectInstance,
arguments ?? new Value[0]

18
src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs

@ -31,11 +31,9 @@ namespace Debugger.Tests @@ -31,11 +31,9 @@ namespace Debugger.Tests
protected XmlElement snapshotNode;
protected int shapshotID;
public StackFrame SelectedStackFrame {
get {
return process.SelectedStackFrame;
}
}
public Thread CurrentThread { get; private set; }
public StackFrame CurrentStackFrame { get; private set; }
public Thread EvalThread { get { return this.CurrentThread; } }
public void Continue()
{
@ -206,9 +204,15 @@ namespace Debugger.Tests @@ -206,9 +204,15 @@ namespace Debugger.Tests
LogEvent("ModuleLoaded", e.Module.Name + (e.Module.HasSymbols ? " (Has symbols)" : " (No symbols)"));
};
process.Paused += delegate(object sender, DebuggerEventArgs e) {
this.CurrentThread = e.Thread;
if (e.Thread != null && e.Thread.IsInValidState) {
this.CurrentStackFrame = e.Thread.MostRecentStackFrame;
} else {
this.CurrentStackFrame = null;
}
if (e.ExceptionThrown != null) {
StringBuilder msg = new StringBuilder();
if (process.SelectedThread.InterceptException(e.ExceptionThrown)) {
if (CurrentThread.InterceptException(e.ExceptionThrown)) {
msg.Append(e.ExceptionThrown.ToString());
} else {
// For example, happens on stack overflow
@ -217,7 +221,7 @@ namespace Debugger.Tests @@ -217,7 +221,7 @@ namespace Debugger.Tests
}
LogEvent("ExceptionThrown", msg.ToString());
}
LogEvent("Paused", e.Process.SelectedStackFrame.NextStatement.ToString());
LogEvent("Paused", CurrentStackFrame != null ? CurrentStackFrame.NextStatement.ToString() : string.Empty);
};
process.Exited += delegate(object sender, DebuggerEventArgs e) {
LogEvent("Exited", null);

8
src/AddIns/Debugger/Debugger.Tests/Tests/AppDomain_Tests.cs

@ -39,12 +39,12 @@ namespace Debugger.Tests { @@ -39,12 +39,12 @@ namespace Debugger.Tests {
{
StartTest();
DebugType type1 = process.SelectedStackFrame.GetLocalVariableValue("one").Type;
DebugType type1b = process.SelectedStackFrame.GetLocalVariableValue("one").Type;
DebugType type1 = this.CurrentStackFrame.GetLocalVariableValue("one").Type;
DebugType type1b = this.CurrentStackFrame.GetLocalVariableValue("one").Type;
ObjectDump("SameDomainEqual", type1 == type1b);
process.Continue();
ObjectDump("AppDomainName", process.SelectedStackFrame.GetLocalVariableValue("appDomainName").AsString());
DebugType type2 = process.SelectedStackFrame.GetLocalVariableValue("two").Type;
ObjectDump("AppDomainName", this.CurrentStackFrame.GetLocalVariableValue("appDomainName").AsString());
DebugType type2 = this.CurrentStackFrame.GetLocalVariableValue("two").Type;
ObjectDump("OtherDomainEqual", type1 == type2);
ObjectDump("AppDomainsEqual", type1.AppDomain == type2.AppDomain);
ObjectDump("AppDomainIDsEqual", type1.AppDomain.ID == type2.AppDomain.ID);

8
src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs

@ -70,8 +70,7 @@ namespace Debugger.Tests { @@ -70,8 +70,7 @@ namespace Debugger.Tests {
MostRecentStackFrame="static System.Void Debugger.Tests.ControlFlow_MainThreadExit.Main()"
Name=""
Priority="Normal"
RuntimeValue="{System.Threading.Thread}"
SelectedStackFrame="static System.Void Debugger.Tests.ControlFlow_MainThreadExit.Main()" />
RuntimeValue="{System.Threading.Thread}" />
</Item>
<Item>
<Thread
@ -84,7 +83,7 @@ namespace Debugger.Tests { @@ -84,7 +83,7 @@ namespace Debugger.Tests {
RuntimeValue="{System.Threading.Thread}" />
</Item>
</ThreadsBeforeExit>
<Paused>ControlFlow_MainThreadExit.cs:25,4-25,26</Paused>
<Paused></Paused>
<ThreadsAfterExit
Capacity="4"
Count="2">
@ -102,8 +101,7 @@ namespace Debugger.Tests { @@ -102,8 +101,7 @@ namespace Debugger.Tests {
MostRecentStackFrame="static Boolean System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle waitableSafeHandle, System.Int64 millisecondsTimeout, System.Boolean hasThreadAffinity, System.Boolean exitContext)"
Name="Worker thread"
Priority="Normal"
RuntimeValue="{System.Threading.Thread}"
SelectedStackFrame="static System.Void Debugger.Tests.ControlFlow_MainThreadExit.WaitForALongTime()" />
RuntimeValue="{System.Threading.Thread}" />
</Item>
</ThreadsAfterExit>
<Exited />

82
src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_Stepping.cs

@ -119,69 +119,69 @@ namespace Debugger.Tests { @@ -119,69 +119,69 @@ namespace Debugger.Tests {
{
StartTest();
SourcecodeSegment start = process.SelectedStackFrame.NextStatement;
SourcecodeSegment start = this.CurrentStackFrame.NextStatement;
foreach (bool jmcEnabled in new bool[] {true, true, false}) {
ObjectDump("Log", "Starting run with JMC=" + jmcEnabled.ToString());
process.SelectedStackFrame.SetIP(start.Filename, start.StartLine + 1, start.StartColumn, false);
this.CurrentStackFrame.SetIP(start.Filename, start.StartLine + 1, start.StartColumn, false);
process.Options.EnableJustMyCode = jmcEnabled;
process.Options.StepOverSingleLineProperties = true;
process.Options.StepOverFieldAccessProperties = true;
process.SelectedStackFrame.StepInto(); // 42.ToString()
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepInto(); // 42.ToString()
Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name);
if (jmcEnabled) {
process.SelectedStackFrame.StepInto(); // StepRoot
Assert.AreEqual("StepRight", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepInto(); // StepRoot
Assert.AreEqual("StepRight", this.CurrentStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepOut();
this.CurrentStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name);
} else {
process.SelectedStackFrame.StepInto(); // StepRoot
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepInto(); // StepRoot
Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name);
}
process.SelectedStackFrame.StepInto(); // Generated default constructor
Assert.AreEqual("Target", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepInto(); // Generated default constructor
Assert.AreEqual("Target", this.CurrentStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepOut();
this.CurrentStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto(); // ShortProperty
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepInto(); // ShortProperty
Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto(); // FieldProperty
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepInto(); // FieldProperty
Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto(); // CatchExcpetion
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepInto(); // CatchExcpetion
Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name);
if (jmcEnabled) {
process.SelectedStackFrame.StepInto(); // ZigZag1
process.SelectedStackFrame.StepOver();
process.SelectedStackFrame.StepOver();
Assert.AreEqual("ZigZag2", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepInto();
Assert.AreEqual("ZigZag2", process.SelectedStackFrame.MethodInfo.Name);
Assert.AreEqual(3, process.SelectedStackFrame.NextStatement.StartColumn);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepInto(); // ZigZag1
this.CurrentStackFrame.StepOver();
this.CurrentStackFrame.StepOver();
Assert.AreEqual("ZigZag2", this.CurrentStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepInto();
Assert.AreEqual("ZigZag2", this.CurrentStackFrame.MethodInfo.Name);
Assert.AreEqual(3, this.CurrentStackFrame.NextStatement.StartColumn);
this.CurrentStackFrame.StepOut();
this.CurrentStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name);
} else {
process.SelectedStackFrame.StepInto(); // ZigZag1
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepInto(); // ZigZag1
Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name);
}
process.SelectedStackFrame.StepInto(); // MyEvent
Assert.AreEqual("Event2", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
Assert.AreEqual("Event4", process.SelectedStackFrame.MethodInfo.Name);
process.SelectedStackFrame.StepOut();
process.SelectedStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", process.SelectedStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepInto(); // MyEvent
Assert.AreEqual("Event2", this.CurrentStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepOut();
Assert.AreEqual("Event4", this.CurrentStackFrame.MethodInfo.Name);
this.CurrentStackFrame.StepOut();
this.CurrentStackFrame.StepOver(); // Finish the step out
Assert.AreEqual("Main", this.CurrentStackFrame.MethodInfo.Name);
}
// Restore default state

4
src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminateRunningProcess.cs

@ -30,11 +30,11 @@ namespace Debugger.Tests { @@ -30,11 +30,11 @@ namespace Debugger.Tests {
{
for(int i = 0; i < 2; i++) {
StartTest();
process.SelectedStackFrame.StepOver();
this.CurrentStackFrame.StepOver();
process.Paused += delegate {
Assert.Fail("Should not have received any callbacks after Terminate");
};
process.SelectedStackFrame.AsyncStepOver();
this.CurrentStackFrame.AsyncStepOver();
ObjectDump("Log", "Calling terminate");
process.Terminate();
}

8
src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs

@ -213,7 +213,7 @@ namespace Debugger.Tests { @@ -213,7 +213,7 @@ namespace Debugger.Tests {
{
ObjectDump(
msg,
SelectedStackFrame.MethodInfo.GetLocalVariables(SelectedStackFrame.IP).Select(v => new LocalVariable() { Name = v.Name, Type = v.LocalType, Value = v.GetValue(process.SelectedStackFrame)})
this.CurrentStackFrame.MethodInfo.GetLocalVariables(this.CurrentStackFrame.IP).Select(v => new LocalVariable() { Name = v.Name, Type = v.LocalType, Value = v.GetValue(this.CurrentStackFrame)})
);
}
@ -234,9 +234,9 @@ namespace Debugger.Tests { @@ -234,9 +234,9 @@ namespace Debugger.Tests {
ObjectDump("DefinedTypes", process.GetModule("DebugType_Tests.exe").GetNamesOfDefinedTypes());
ObjectDump("DefinedTypes", process.GetModule("DebugType_Tests.exe").GetDefinedTypes());
ObjectDump("Members", process.SelectedStackFrame.GetLocalVariableValue("members").Type.GetMembers(DebugType.BindingFlagsAllDeclared));
ObjectDump("Access-Members", process.SelectedStackFrame.GetLocalVariableValue("access").Type.GetMembers());
ObjectDump("MyInterfaceImpl-Members", process.SelectedStackFrame.GetLocalVariableValue("myInterfaceImpl").Type.GetMembers());
ObjectDump("Members", this.CurrentStackFrame.GetLocalVariableValue("members").Type.GetMembers(DebugType.BindingFlagsAllDeclared));
ObjectDump("Access-Members", this.CurrentStackFrame.GetLocalVariableValue("access").Type.GetMembers());
ObjectDump("MyInterfaceImpl-Members", this.CurrentStackFrame.GetLocalVariableValue("myInterfaceImpl").Type.GetMembers());
DumpLocalVariables();
EndTest();

6
src/AddIns/Debugger/Debugger.Tests/Tests/DynamicCode.cs

@ -56,9 +56,9 @@ namespace Debugger.Tests { @@ -56,9 +56,9 @@ namespace Debugger.Tests {
{
StartTest();
process.SelectedStackFrame.StepOver();
process.SelectedStackFrame.StepInto();
Assert.AreEqual("Source.txt", process.SelectedStackFrame.NextStatement.Filename);
this.CurrentStackFrame.StepOver();
this.CurrentStackFrame.StepInto();
Assert.AreEqual("Source.txt", this.CurrentStackFrame.NextStatement.Filename);
EndTest();
}

24
src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs

@ -205,15 +205,15 @@ namespace Debugger.Tests { @@ -205,15 +205,15 @@ namespace Debugger.Tests {
public void ExpressionEvaluator_Tests()
{
StartTest();
process.SelectedStackFrame.StepOver();
process.SelectedStackFrame.StepOver(); // Start worker thread
this.CurrentStackFrame.StepOver();
this.CurrentStackFrame.StepOver(); // Start worker thread
EvalAll(expressionsInput);
// Test member hiding / overloading
Value myClass = SelectedStackFrame.GetLocalVariableValue("myClass").GetPermanentReference();
Expression myClassExpr = SelectedStackFrame.MethodInfo.GetLocalVariable(SelectedStackFrame.IP, "myClass").GetExpression();
Value myClass = this.CurrentStackFrame.GetLocalVariableValue("myClass").GetPermanentReference(this.EvalThread);
Expression myClassExpr = this.CurrentStackFrame.MethodInfo.GetLocalVariable(this.CurrentStackFrame.IP, "myClass").GetExpression();
List<Expression> expressions = new List<Expression>();
foreach(MemberInfo memberInfo in myClass.Type.GetFieldsAndNonIndexedProperties(DebugType.BindingFlagsAll)) {
@ -245,12 +245,12 @@ namespace Debugger.Tests { @@ -245,12 +245,12 @@ namespace Debugger.Tests {
// Test type round tripping
foreach(DebugLocalVariableInfo locVar in process.SelectedStackFrame.MethodInfo.GetLocalVariables()) {
foreach(DebugLocalVariableInfo locVar in this.CurrentStackFrame.MethodInfo.GetLocalVariables()) {
if (locVar.Name.StartsWith("complexType")) {
TypeReference complexTypeRef = locVar.LocalType.GetTypeReference();
string code = "typeof(" + complexTypeRef.PrettyPrint() + ")";
TypeOfExpression complexTypeRefRT = (TypeOfExpression)ExpressionEvaluator.Parse(code, SupportedLanguage.CSharp);
DebugType type = complexTypeRefRT.TypeReference.ResolveType(process.SelectedStackFrame.AppDomain);
DebugType type = complexTypeRefRT.TypeReference.ResolveType(this.CurrentStackFrame.AppDomain);
string status = locVar.LocalType.FullName == type.FullName ? "ok" : "fail";
ObjectDumpToString("TypeResulution", string.Format(" {0} = {1} ({2})", code, type.FullName, status));
}
@ -258,15 +258,15 @@ namespace Debugger.Tests { @@ -258,15 +258,15 @@ namespace Debugger.Tests {
// Type equality
DebugLocalVariableInfo loc = SelectedStackFrame.MethodInfo.GetLocalVariable(SelectedStackFrame.IP, "list");
DebugLocalVariableInfo loc = this.CurrentStackFrame.MethodInfo.GetLocalVariable(this.CurrentStackFrame.IP, "list");
Type locType = loc.LocalType;
Type valType = loc.GetValue(SelectedStackFrame).Type;
Type valType = loc.GetValue(this.CurrentStackFrame).Type;
ObjectDump("TypesIdentitcal", object.ReferenceEquals(locType, valType));
ObjectDump("TypesEqual", locType == valType);
ObjectDump("WorkerThreadMoved", process.SelectedStackFrame.GetThisValue().GetMemberValue("WorkerThreadMoved").AsString());
ObjectDump("WorkerThreadMoved", this.CurrentStackFrame.GetThisValue().GetMemberValue(this.EvalThread, "WorkerThreadMoved").AsString());
process.Continue();
ObjectDump("WorkerThreadMoved", process.SelectedStackFrame.GetThisValue().GetMemberValue("WorkerThreadMoved").AsString());
ObjectDump("WorkerThreadMoved", this.CurrentStackFrame.GetThisValue().GetMemberValue(this.EvalThread, "WorkerThreadMoved").AsString());
EndTest();
}
@ -286,8 +286,8 @@ namespace Debugger.Tests { @@ -286,8 +286,8 @@ namespace Debugger.Tests {
restultFmted = null;
} else {
try {
Value result = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.Evaluate(expr, SupportedLanguage.CSharp, process.SelectedStackFrame);
restultFmted = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.FormatValue(result);
Value result = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.Evaluate(expr, SupportedLanguage.CSharp, this.CurrentStackFrame);
restultFmted = ICSharpCode.NRefactory.Visitors.ExpressionEvaluator.FormatValue(this.EvalThread, result);
} catch (GetValueException e) {
restultFmted = e.Message;
}

4
src/AddIns/Debugger/Debugger.Tests/Tests/Process_MemoryReadWrite.cs

@ -26,8 +26,8 @@ namespace Debugger.Tests { @@ -26,8 +26,8 @@ namespace Debugger.Tests {
{
StartTest();
ulong addrHello = process.SelectedStackFrame.GetLocalVariableValue("hello").Address;
ulong addrWorld = process.SelectedStackFrame.GetLocalVariableValue("world").Address;
ulong addrHello = this.CurrentStackFrame.GetLocalVariableValue("hello").Address;
ulong addrWorld = this.CurrentStackFrame.GetLocalVariableValue("world").Address;
addrHello = DeRef(process.ReadMemory(addrHello, 4));
addrWorld = DeRef(process.ReadMemory(addrWorld, 4));

10
src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Callstack.cs

@ -33,11 +33,11 @@ namespace Debugger.Tests { @@ -33,11 +33,11 @@ namespace Debugger.Tests {
{
StartTest();
ObjectDump("Callstack", process.SelectedThread.GetCallstack());
process.SelectedStackFrame.StepOut();
ObjectDump("Callstack", process.SelectedThread.GetCallstack());
process.SelectedStackFrame.StepOut();
ObjectDump("Callstack", process.SelectedThread.GetCallstack());
ObjectDump("Callstack", this.CurrentThread.GetCallstack());
this.CurrentStackFrame.StepOut();
ObjectDump("Callstack", this.CurrentThread.GetCallstack());
this.CurrentStackFrame.StepOut();
ObjectDump("Callstack", this.CurrentThread.GetCallstack());
EndTest();
}

12
src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Lifetime.cs

@ -36,21 +36,21 @@ namespace Debugger.Tests { @@ -36,21 +36,21 @@ namespace Debugger.Tests {
{
StartTest();
StackFrame stackFrame = process.SelectedStackFrame;
ObjectDump("SelectedStackFrame", process.SelectedStackFrame);
StackFrame stackFrame = this.CurrentStackFrame;
ObjectDump("SelectedStackFrame", this.CurrentStackFrame);
process.Continue(); // Go to the SubFunction
ObjectDump("Old StackFrame", stackFrame);
ObjectDump("SelectedStackFrame", process.SelectedStackFrame);
ObjectDump("SelectedStackFrame", this.CurrentStackFrame);
process.Continue(); // Go back to Function
ObjectDump("Old StackFrame", stackFrame);
ObjectDump("SelectedStackFrame", process.SelectedStackFrame);
ObjectDump("SelectedStackFrame", this.CurrentStackFrame);
process.Continue(); // Setp out of function
ObjectDump("Main", process.SelectedStackFrame);
ObjectDump("Main", this.CurrentStackFrame);
ObjectDump("Old StackFrame", stackFrame);
ObjectDump("SelectedStackFrame", process.SelectedStackFrame);
ObjectDump("SelectedStackFrame", this.CurrentStackFrame);
EndTest();
}

6
src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_SetIP.cs

@ -26,9 +26,9 @@ namespace Debugger.Tests { @@ -26,9 +26,9 @@ namespace Debugger.Tests {
{
StartTest();
Assert.IsNotNull(process.SelectedStackFrame.SetIP("StackFrame_SetIP.cs", 12, 0, true));
Assert.IsNull(process.SelectedStackFrame.SetIP("StackFrame_SetIP.cs", 100, 0, true));
process.SelectedStackFrame.SetIP("StackFrame_SetIP.cs", 12, 0, false);
Assert.IsNotNull(this.CurrentStackFrame.SetIP("StackFrame_SetIP.cs", 12, 0, true));
Assert.IsNull(this.CurrentStackFrame.SetIP("StackFrame_SetIP.cs", 100, 0, true));
this.CurrentStackFrame.SetIP("StackFrame_SetIP.cs", 12, 0, false);
process.Continue();
Assert.AreEqual("1\r\n1\r\n", log);

10
src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_VariablesLifetime.cs

@ -46,15 +46,15 @@ namespace Debugger.Tests { @@ -46,15 +46,15 @@ namespace Debugger.Tests {
StartTest(); // 1 - Enter program
argument = process.SelectedStackFrame.GetArgumentValue(0);
local = process.SelectedStackFrame.GetLocalVariableValue("local");
@class = process.SelectedStackFrame.GetThisValue().GetMemberValue("class");
argument = this.CurrentStackFrame.GetArgumentValue(0);
local = this.CurrentStackFrame.GetLocalVariableValue("local");
@class = this.CurrentStackFrame.GetThisValue().GetMemberValue(this.EvalThread, "class");
ObjectDump("argument", argument);
ObjectDump("local", local);
ObjectDump("@class", @class);
process.Continue(); // 2 - Go to the SubFunction
localInSubFunction = process.SelectedStackFrame.GetLocalVariableValue("localInSubFunction");
localInSubFunction = this.CurrentStackFrame.GetLocalVariableValue("localInSubFunction");
ObjectDump("argument", argument);
ObjectDump("local", local);
ObjectDump("@class", @class);
@ -71,7 +71,7 @@ namespace Debugger.Tests { @@ -71,7 +71,7 @@ namespace Debugger.Tests {
ObjectDump("local", local);
ObjectDump("@class", @class);
ObjectDump("localInSubFunction", @localInSubFunction);
localInSubFunction = process.SelectedStackFrame.GetLocalVariableValue("localInSubFunction");
localInSubFunction = this.CurrentStackFrame.GetLocalVariableValue("localInSubFunction");
ObjectDump("localInSubFunction(new)", @localInSubFunction);
process.Continue(); // 5 - Setp out of both functions

15
src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs

@ -26,11 +26,11 @@ namespace Debugger.Tests { @@ -26,11 +26,11 @@ namespace Debugger.Tests {
public void Thread_Tests()
{
StartTest();
ObjectDump("Thread", process.SelectedThread);
ObjectDump("Thread", this.CurrentThread);
process.Continue();
ObjectDump("Thread", process.SelectedThread);
ObjectDump("Thread", this.CurrentThread);
process.Continue();
ObjectDump("Thread", process.SelectedThread);
ObjectDump("Thread", this.CurrentThread);
EndTest();
}
}
@ -54,8 +54,7 @@ namespace Debugger.Tests { @@ -54,8 +54,7 @@ namespace Debugger.Tests {
MostRecentStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()"
Name=""
Priority="Normal"
RuntimeValue="{System.Threading.Thread}"
SelectedStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()" />
RuntimeValue="{System.Threading.Thread}" />
</Thread>
<Paused>Thread_Tests.cs:14,4-14,40</Paused>
<Thread>
@ -66,8 +65,7 @@ namespace Debugger.Tests { @@ -66,8 +65,7 @@ namespace Debugger.Tests {
MostRecentStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()"
Name=""
Priority="AboveNormal"
RuntimeValue="{System.Threading.Thread}"
SelectedStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()" />
RuntimeValue="{System.Threading.Thread}" />
</Thread>
<Paused>Thread_Tests.cs:16,4-16,40</Paused>
<Thread>
@ -78,8 +76,7 @@ namespace Debugger.Tests { @@ -78,8 +76,7 @@ namespace Debugger.Tests {
MostRecentStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()"
Name="ThreadName"
Priority="AboveNormal"
RuntimeValue="{System.Threading.Thread}"
SelectedStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()" />
RuntimeValue="{System.Threading.Thread}" />
</Thread>
<Exited />
</Test>

6
src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs

@ -40,11 +40,11 @@ namespace Debugger.Tests { @@ -40,11 +40,11 @@ namespace Debugger.Tests {
DumpLocalVariables();
Value array = process.SelectedStackFrame.GetLocalVariableValue("array").GetPermanentReference();
ObjectDump("array.Length", array.GetMemberValue("Length"));
Value array = this.CurrentStackFrame.GetLocalVariableValue("array").GetPermanentReference(this.EvalThread);
ObjectDump("array.Length", array.GetMemberValue(this.EvalThread, "Length"));
ObjectDump("array", array);
Value lbArray = process.SelectedStackFrame.GetLocalVariableValue("lbArray").GetPermanentReference();
Value lbArray = this.CurrentStackFrame.GetLocalVariableValue("lbArray").GetPermanentReference(this.EvalThread);
ObjectDump("lbArray", lbArray);
ObjectDump("lbArray-10-20", lbArray.GetArrayElement(new int[] {10, 20}));

Loading…
Cancel
Save