diff --git a/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs index 36b2067c4b..d0e693f100 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs @@ -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 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 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 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 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 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 } 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 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 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 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 if (thisValue != null) { IDebugMemberInfo instMember = (IDebugMemberInfo)thisValue.Type.GetMember(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(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 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 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 DebugType type = objectCreateExpression.CreateType.ResolveType(context.AppDomain); List 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 } 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 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 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 if (op == BinaryOperatorType.Add) { if (left.Type.Is() || right.Type.Is()) { - 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); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionExtensionMethods.cs b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionExtensionMethods.cs index a7cc14f177..ef3b250932 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionExtensionMethods.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionExtensionMethods.cs @@ -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(this M expr, DebugType type) where M: INode diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs index c93bc25bfb..b8893cf977 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/BreakPointsPad.cs @@ -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"); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs index d99cb36996..ec18cca699 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs @@ -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 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 } } - 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(); - using(new PrintTimes("Callstack refresh")) { + } else { + var items = new ObservableCollection(); 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 previousItemIsExternalMethod = true; } - item.Process = process; - return item; } @@ -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; } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs index 7c4944bdea..8d9e919511 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs @@ -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 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; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs index 8e136d5aaf..230a1a6130 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs @@ -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()))); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs index 2a17b59d8c..f14430b083 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs @@ -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); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs index e8436b9173..f44dd79d68 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs @@ -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 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)); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs index 4eb643e42a..6031eb0aa6 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs @@ -34,7 +34,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads panel.Children.Add(localVarList); WindowsDebugger.RefreshingPads += RefreshPad; - WindowsDebugger.RefreshPads(); + RefreshPad(); } /// Always check if Instance is null, might be null if pad is not opened! @@ -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); - } } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs index c8d7721792..f2cdf0cd0d 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads panel.Children.Add(objectGraphControl); WindowsDebugger.RefreshingPads += RefreshPad; - WindowsDebugger.RefreshPads(); + RefreshPad(); } /// Always check if Instance is null, might be null if pad is not opened! @@ -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(); } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs index 036576733d..579fc17aa4 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs @@ -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 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 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 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 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 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 { diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs index 9fd264d3bb..56c6a1ba6d 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs @@ -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 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); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs index ac18188c60..19b5c1dc7f 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs @@ -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 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) { diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchInputBox.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchInputBox.xaml.cs index e2cb564716..bf6688adf1 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchInputBox.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchInputBox.xaml.cs @@ -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); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs index 7872ab5c1e..ced18372ca 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs @@ -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 ProjectService.SolutionLoaded += delegate { LoadSavedNodes(); }; WindowsDebugger.RefreshingPads += RefreshPad; - WindowsDebugger.RefreshPads(); + RefreshPad(); } #region Saved nodes @@ -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 } } - protected void RefreshPad(object sender, DebuggerEventArgs dbg) + protected void RefreshPad() { - Process debuggedProcess = dbg.Process; + Process debuggedProcess = WindowsDebugger.CurrentProcess; ResetPad(null, null); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs index 2da80bea1c..493f39993f 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs @@ -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); } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs index 29f5fcc6b7..95a8e47961 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs @@ -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(); + } + } + + /// + /// 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. + /// + /// + /// 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 + /// + 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 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 RefreshingPads; - - public static void RefreshPads() - { - RefreshPads(new DebuggerEventArgs(CurrentProcess)); - } - - public static void RefreshPads(DebuggerEventArgs e) - { - if (RefreshingPads != null) { - RefreshingPads(null, e); - } - } - /// - 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 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 public bool IsProcessRunning { get { - return IsDebugging && debuggedProcess.IsRunning; + return IsDebugging && CurrentProcess.IsRunning; } } @@ -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 // } 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 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 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 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 public void Detach() { - debugger.Detach(); + CurrentDebugger.Detach(); } public void StartWithoutDebugging(ProcessStartInfo processStartInfo) @@ -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 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 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 /// 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; } /// @@ -436,10 +361,11 @@ namespace ICSharpCode.SharpDevelop.Services /// 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 } } - bool CanEvaluate - { - get { - return debuggedProcess != null && !debuggedProcess.IsRunning && - (debuggedProcess.SelectedStackFrame != null || debuggedProcess.SelectedThread.MostRecentStackFrame != null); - } - } - /// /// 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 { 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 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 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 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 { foreach (BreakpointBookmark bookmark in BookmarkManager.Bookmarks.OfType()) { 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 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 } 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 { 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 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 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 } } - RefreshPads(e); + RefreshPads(); } void debuggedProcess_DebuggingResumed(object sender, DebuggerEventArgs e) @@ -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 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 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 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 } // 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; } diff --git a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs index 2fde840d61..4a9a8064dc 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/TreeModel/ValueNode.cs @@ -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 try { Stopwatch watch = new Stopwatch(); watch.Start(); - + // Do not keep permanent reference Value val = this.getValue(); @@ -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 } 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 /// 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 GetLocalVariables() @@ -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 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)))); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs index ac10dd7d92..3a23dc75fc 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphBuilder.cs @@ -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 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 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 /// Expression to be checked. 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"); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs index c9b642c0e7..5c19b9f8dd 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraph/ObjectGraphProperty.cs @@ -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 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; } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphControl.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphControl.xaml.cs index 074b42de3f..ef83420aef 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphControl.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Graph/ObjectGraphControl.xaml.cs @@ -62,7 +62,7 @@ namespace Debugger.AddIn.Visualizers.Graph public void RefreshView() { - debuggerService.DebuggedProcess.EnqueueWork(Dispatcher, () => Refresh()); + WindowsDebugger.CurrentProcess.EnqueueWork(Dispatcher, () => Refresh()); } void Refresh() diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs index a05d8cb746..3897ae5f9e 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/GridVisualizer/GridVisualizerWindow.xaml.cs @@ -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 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>( @@ -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; } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/AtomicType.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/AtomicType.cs index c029bb0f12..07dabf71b2 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/AtomicType.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/AtomicType.cs @@ -30,7 +30,7 @@ namespace Debugger.AddIn.Visualizers.Utils /// True if expression's type is atomic, False otherwise. public static bool IsOfAtomicType(this Expression expr) { - DebugType typeOfValue = expr.Evaluate(WindowsDebugger.CurrentProcess).Type; + DebugType typeOfValue = expr.Evaluate().Type; return AtomicType.IsAtomic(typeOfValue); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs index 0c89a25c7e..075f8f517f 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Visualizers/Utils/DebuggerHelpers.cs @@ -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 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(); } /// @@ -80,7 +80,7 @@ namespace Debugger.AddIn.Visualizers.Utils /// public static ulong GetObjectAddress(this Expression expr) { - return expr.Evaluate(WindowsDebugger.CurrentProcess).GetObjectAddress(); + return expr.Evaluate().GetObjectAddress(); } /// @@ -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 public static Value EvalPermanentReference(this Expression expr) { - return expr.Evaluate(WindowsDebugger.CurrentProcess).GetPermanentReference(); + return expr.Evaluate().GetPermanentReference(WindowsDebugger.EvalThread); } /// @@ -133,12 +133,12 @@ namespace Debugger.AddIn.Visualizers.Utils /// Evaluating System.Collections.ICollection.Count on targetObject failed. 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; } /// diff --git a/src/AddIns/Debugger/Debugger.Core/Eval.cs b/src/AddIns/Debugger/Debugger.Core/Eval.cs index 86bbe816c0..7dae8165ed 100644 --- a/src/AddIns/Debugger/Debugger.Core/Eval.cs +++ b/src/AddIns/Debugger/Debugger.Core/Eval.cs @@ -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 } } - 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 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; - } /// Evaluation can not be stopped /// Process exited @@ -200,19 +188,19 @@ namespace Debugger } /// Synchronously calls a function and returns its return value - 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 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 (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 } */ - #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 ); } - #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 ); } - #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); diff --git a/src/AddIns/Debugger/Debugger.Core/Exception.cs b/src/AddIns/Debugger/Debugger.Core/Exception.cs index b56a3a765e..6486f4ba3e 100644 --- a/src/AddIns/Debugger/Debugger.Core/Exception.cs +++ b/src/AddIns/Debugger/Debugger.Core/Exception.cs @@ -47,7 +47,7 @@ namespace Debugger /// 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 /// 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 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 ---"); } /// Returs formated stacktrace for the exception /// Getting the stacktrace involves property /// evaluation so GetValueException can be thrown in some cicumstances. - 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(); diff --git a/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs b/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs index 22d24fb18a..82f71006e3 100644 --- a/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs +++ b/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs @@ -26,6 +26,7 @@ namespace Debugger bool raiseEventsOnNextExit; bool isInCallback; + Thread threadToReport; List breakpointsHit = new List(); Exception exceptionThrown; @@ -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 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 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 // 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; diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugConstructorInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugConstructorInfo.cs index 1fd8775669..55b2686fb5 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugConstructorInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugConstructorInfo.cs @@ -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 /// 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"); } /// 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"); } /// diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugFieldInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugFieldInfo.cs index 8ad8cb9cca..33404f1cb7 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugFieldInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugFieldInfo.cs @@ -109,13 +109,13 @@ namespace Debugger.MetaData /// public override object GetValue(object obj) { - return Value.GetFieldValue((Value)obj, this); + throw new NotImplementedException("Use Debugger.Value directly"); } /// 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"); } /// diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs index d73ef5dc20..38a8c9aff0 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs @@ -160,17 +160,7 @@ namespace Debugger.MetaData /// public override object Invoke(object obj, BindingFlags invokeAttr, Binder binder, object[] parameters, CultureInfo culture) { - List args = new List(); - 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"); } /// @@ -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 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; diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugPropertyInfo.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugPropertyInfo.cs index 35b0bc252a..36937d52d6 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugPropertyInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugPropertyInfo.cs @@ -184,21 +184,13 @@ namespace Debugger.MetaData /// public override object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { - List args = new List(); - foreach(object arg in index) { - args.Add((Value)arg); - } - return Value.GetPropertyValue((Value)obj, this, args.ToArray()); + throw new NotImplementedException("Use Debugger.Value directly"); } /// public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture) { - List args = new List(); - 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 { diff --git a/src/AddIns/Debugger/Debugger.Core/NDebugger.cs b/src/AddIns/Debugger/Debugger.Core/NDebugger.cs index 54b3811e39..0858212982 100644 --- a/src/AddIns/Debugger/Debugger.Core/NDebugger.cs +++ b/src/AddIns/Debugger/Debugger.Core/NDebugger.cs @@ -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; - } + /// The process on which the event occured. Can be null. + public Process Process { get; set; } + /// The thread on which the event occured. Can be null if the event was not thread specific. + public Thread Thread { get; set; } + public Breakpoint[] BreakpointsHit { get; set; } + public Exception ExceptionThrown { get; set; } } [Serializable] @@ -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; } } diff --git a/src/AddIns/Debugger/Debugger.Core/Process.cs b/src/AddIns/Debugger/Debugger.Core/Process.cs index 8225577cc0..4ba91fa22e 100644 --- a/src/AddIns/Debugger/Debugger.Core/Process.cs +++ b/src/AddIns/Debugger/Debugger.Core/Process.cs @@ -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 AppDomains { @@ -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 { AssertPaused(); DisableAllSteppers(); - CheckSelectedStackFrames(); - SelectMostRecentStackFrameWithLoadedSymbols(); foreach (var corBreakpoint in tempBreakpoints) { corBreakpoint.Activate(0); @@ -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 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 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 // 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 } #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; - } - } } } diff --git a/src/AddIns/Debugger/Debugger.Core/Thread.cs b/src/AddIns/Debugger/Debugger.Core/Thread.cs index efe20c3999..0d7226a707 100644 --- a/src/AddIns/Debugger/Debugger.Core/Thread.cs +++ b/src/AddIns/Debugger/Debugger.Core/Thread.cs @@ -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 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 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 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 return stackTrace.ToString(); } - public StackFrame SelectedStackFrame { - get { - if (selectedStackFrame != null && selectedStackFrame.IsInvalid) return null; - if (process.IsRunning) return null; - return selectedStackFrame; - } - set { - selectedStackFrame = value; - } - } - /// /// Returns the most recent stack frame (the one that is currently executing). /// Returns null if callstack is empty. /// 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(); diff --git a/src/AddIns/Debugger/Debugger.Core/Value.cs b/src/AddIns/Debugger/Debugger.Core/Value.cs index b80a29adc5..9366cb94ef 100644 --- a/src/AddIns/Debugger/Debugger.Core/Value.cs +++ b/src/AddIns/Debugger/Debugger.Core/Value.cs @@ -113,8 +113,7 @@ namespace Debugger /// Value is valid only until the debuggee is resummed. 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 } // 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 return newValue; } + /// If we are sure it is heap value we do not need eval. [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 return this; } } else { - return this.Box(); + return this.Box(evalThread); } } @@ -242,13 +250,13 @@ namespace Debugger } /// Copy the acutal value from some other Value object - 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 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 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); } /// Returns all elements in the array @@ -409,88 +419,85 @@ namespace Debugger } } - #region Convenience overload methods - /// Get a field or property of an object with a given name. /// Null if not found - public Value GetMemberValue(string name) + public Value GetMemberValue(Thread evalThread, string name) { MemberInfo memberInfo = this.Type.GetMember(name, DebugType.BindingFlagsAllInScope, DebugType.IsFieldOrNonIndexedProperty); if (memberInfo == null) return null; - return GetMemberValue(memberInfo); + return GetMemberValue(evalThread, memberInfo); } /// Get the value of given member. - 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 - /// Get the value of given member. /// null if member is static - 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 - - /// Get the value of given field. - 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 + /// Get the value of given instance field. + public Value GetFieldValue(string name) + { + FieldInfo fieldInfo = this.Type.GetMember(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) + /// Get the value of given field. + 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); } /// Get the value of given field. + /// Thread to use for thread-local storage /// null if field is static - 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 } } - 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 - /// Get the value of the property using the get accessor - 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 - /// Get the value of the property using the get accessor - 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 - - /// Set the value of the property using the set accessor - public Value SetPropertyValue(PropertyInfo propertyInfo, Value newValue) - { - return SetPropertyValue(this, propertyInfo, null, newValue); + return Value.InvokeMethod(evalThread, objectInstance, (DebugMethodInfo)propertyInfo.GetGetMethod(), arguments); } /// Set the value of the property using the set accessor - 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); } /// Set the value of the property using the set accessor - public static Value SetPropertyValue(Value objectInstance, PropertyInfo propertyInfo, Value newValue) - { - return SetPropertyValue(objectInstance, propertyInfo, null, newValue); - } - - #endregion - - /// Set the value of the property using the set accessor - 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 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 - /// Synchronously invoke the method - 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 - /// Synchronously invoke the method - 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 } /// Invoke the ToString() method - 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 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 - /// Asynchronously invoke the method - 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 - /// Asynchronously invoke the method - 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] diff --git a/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs b/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs index 4d0d02dae9..467695b5fd 100644 --- a/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs +++ b/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs @@ -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 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 } 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); diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/AppDomain_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/AppDomain_Tests.cs index d4e4d795ba..9434bc8042 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/AppDomain_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/AppDomain_Tests.cs @@ -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); diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs index 8a94e96371..288d04de36 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs @@ -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}" /> - ControlFlow_MainThreadExit.cs:25,4-25,26 + @@ -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}" /> diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_Stepping.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_Stepping.cs index 3a8fe902f4..1e9c702976 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_Stepping.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_Stepping.cs @@ -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 diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminateRunningProcess.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminateRunningProcess.cs index df7057c981..0707949069 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminateRunningProcess.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_TerminateRunningProcess.cs @@ -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(); } diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs index 0064524447..f96761b388 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs @@ -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 { 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(); diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/DynamicCode.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/DynamicCode.cs index 4b6b172db4..68d88ab56f 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/DynamicCode.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/DynamicCode.cs @@ -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(); } diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs index 2aa62276b7..876fed301f 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ExpressionEvaluator_Tests.cs @@ -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 expressions = new List(); foreach(MemberInfo memberInfo in myClass.Type.GetFieldsAndNonIndexedProperties(DebugType.BindingFlagsAll)) { @@ -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 { // 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 { 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; } diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/Process_MemoryReadWrite.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/Process_MemoryReadWrite.cs index 07b1e83c4d..f7ef425378 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/Process_MemoryReadWrite.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/Process_MemoryReadWrite.cs @@ -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)); diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Callstack.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Callstack.cs index 2a4a877390..7a08d6acac 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Callstack.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Callstack.cs @@ -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(); } diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Lifetime.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Lifetime.cs index 0c51872f68..b6b85829f9 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Lifetime.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_Lifetime.cs @@ -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(); } diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_SetIP.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_SetIP.cs index d53e50ec24..23f9a15278 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_SetIP.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_SetIP.cs @@ -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); diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_VariablesLifetime.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_VariablesLifetime.cs index b008be134c..5041ce0a07 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_VariablesLifetime.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/StackFrame_VariablesLifetime.cs @@ -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 { 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 diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs index 29800cafb6..c8af696246 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs @@ -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 { 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_Tests.cs:14,4-14,40 @@ -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_Tests.cs:16,4-16,40 @@ -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}" /> diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs index 8d9e1c29b2..2021910972 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/Value_Tests.cs @@ -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}));