From 6e10e6bbe046c563a4d3c5990199ae40e8e454b3 Mon Sep 17 00:00:00 2001 From: Eusebiu Marcu Date: Sun, 27 Feb 2011 01:16:53 +0200 Subject: [PATCH] Evaluate local vars. --- .../Debugger.Core/MetaData/DebugMethodInfo.cs | 20 ++++++++--- .../Ast/ExpressionExtensionMethods.cs | 2 +- .../Visitors/ExpressionEvaluator.cs | 16 +++++++-- .../Models/TreeModel/ChildNodesOfObject.cs | 27 ++++++++++++++- .../Models/TreeModel/ExpressionNode.cs | 13 +++++++ .../Services/Debugger/DebuggerHelper.cs | 2 +- .../Services/Debugger/WindowsDebugger.cs | 2 -- .../ToolTips/TextEditorListener.cs | 34 +++---------------- .../Ast/AstMethodBodyBuilder.cs | 5 +++ ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs | 7 ++++ 10 files changed, 87 insertions(+), 41 deletions(-) diff --git a/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs b/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs index f1bc327d7..778427006 100644 --- a/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs +++ b/Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs @@ -343,12 +343,12 @@ namespace Debugger.MetaData uint token = 0; bool success = - (Read(code, 0x00) || true) && // nop || nothing + (Read(code, 0x00) || true) && // nop || nothing (Read(code, 0x02, 0x7B) || Read(code, 0x7E)) && // ldarg.0; ldfld || ldsfld ReadToken(code, ref token) && // (Read(code, 0x0A, 0x2B, 0x00, 0x06) || true) && // stloc.0; br.s; offset+00; ldloc.0 || nothing Read(code, 0x2A); // ret - + if (!success) return; if (this.Process.Options.Verbose) { @@ -427,7 +427,7 @@ namespace Debugger.MetaData // Look on the method DebugType.IsDefined( this, - false, + false, typeof(System.Diagnostics.DebuggerStepThroughAttribute), typeof(System.Diagnostics.DebuggerNonUserCodeAttribute), typeof(System.Diagnostics.DebuggerHiddenAttribute)) @@ -435,7 +435,7 @@ namespace Debugger.MetaData // Look on the type DebugType.IsDefined( declaringType, - false, + false, typeof(System.Diagnostics.DebuggerStepThroughAttribute), typeof(System.Diagnostics.DebuggerNonUserCodeAttribute), typeof(System.Diagnostics.DebuggerHiddenAttribute)); @@ -464,6 +464,18 @@ namespace Debugger.MetaData } } + public static Value GetLocalVariableValue(StackFrame context, int varIndex) + { + ICorDebugValue corVal; + try { + corVal = context.CorILFrame.GetLocalVariable((uint)varIndex); + } catch (COMException e) { + if ((uint)e.ErrorCode == 0x80131304) throw new GetValueException("Unavailable in optimized code"); + throw; + } + return new Value(context.AppDomain, corVal); + } + public DebugLocalVariableInfo GetLocalVariable(int offset, string name) { foreach(DebugLocalVariableInfo loc in GetLocalVariables(offset)) { diff --git a/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs b/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs index 423989ca4..9a7c325d9 100644 --- a/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs +++ b/Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs @@ -74,7 +74,7 @@ namespace ICSharpCode.NRefactory.Ast public static IndexerExpression AppendIndexer(this Expression expression, params int[] indices) { - IndexerExpression indexerExpr = new IndexerExpression() { Target = Parenthesize(expression) }; + IndexerExpression indexerExpr = new IndexerExpression() { Target = expression.Clone().Parenthesize() }; var args = new List(); foreach(int index in indices) { args.Add(new PrimitiveExpression(index)); diff --git a/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs b/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs index 60af5f785..e2cf5dc6b 100644 --- a/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs +++ b/Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs @@ -383,13 +383,23 @@ namespace ICSharpCode.NRefactory.Visitors } } + // get parameter DebugParameterInfo par = context.MethodInfo.GetParameter(identifier); if (par != null) return new TypedValue(par.GetValue(context), (DebugType)par.ParameterType); - DebugLocalVariableInfo loc = context.MethodInfo.GetLocalVariable(context.IP, identifier); - if (loc != null) - return new TypedValue(loc.GetValue(context), (DebugType)loc.LocalType); + //get local variables + +// DebugLocalVariableInfo loc = context.MethodInfo.GetLocalVariable(context.IP, identifier); +// if (loc != null) +// return new TypedValue(loc.GetValue(context), (DebugType)loc.LocalType); + + object localIndex = identifierExpression.Annotation(typeof(int[])); + + if (localIndex != null) { + Value localValue = DebugMethodInfo.GetLocalVariableValue(context, ((int[])localIndex)[0]); + return new TypedValue(localValue, localValue.Type); + } // Instance class members // Note that the method might be generated instance method that represents anonymous method diff --git a/Debugger/ILSpy.Debugger/Models/TreeModel/ChildNodesOfObject.cs b/Debugger/ILSpy.Debugger/Models/TreeModel/ChildNodesOfObject.cs index fe651ba12..1080b4d57 100644 --- a/Debugger/ILSpy.Debugger/Models/TreeModel/ChildNodesOfObject.cs +++ b/Debugger/ILSpy.Debugger/Models/TreeModel/ChildNodesOfObject.cs @@ -10,6 +10,7 @@ using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.CSharp; using ILSpy.Debugger.Services; using ILSpy.Debugger.Services.Debugger; +using Module = Debugger.Module; namespace ILSpy.Debugger.Models.TreeModel { @@ -97,7 +98,12 @@ namespace ILSpy.Debugger.Models.TreeModel public static IEnumerable LazyGetItemsOfIList(Expression targetObject) { // This is needed for expanding IEnumerable - targetObject = new CastExpression() { Expression = targetObject, Type = new SimpleType() { Identifier = typeof(IList).FullName } }; + + var type = new SimpleType() { Identifier = typeof(IList).FullName }; + type.AddAnnotation(DebugType.CreateFromType(Mscorlib, typeof(IList))); + + targetObject = new CastExpression() { Expression = targetObject.Clone(), Type = type }; + int count = 0; GetValueException error = null; try { @@ -145,5 +151,24 @@ namespace ILSpy.Debugger.Models.TreeModel } } } + + static Module mscorlib; + + public static Module Mscorlib { + get { + if (mscorlib != null) return mscorlib; + foreach (var appDomain in WindowsDebugger.CurrentProcess.AppDomains) { + foreach(Module m in appDomain.Process.Modules) { + if (m.Name == "mscorlib.dll" && + m.AppDomain == appDomain) { + mscorlib = m; + return mscorlib; + } + } + } + + throw new DebuggerException("Mscorlib not loaded"); + } + } } } diff --git a/Debugger/ILSpy.Debugger/Models/TreeModel/ExpressionNode.cs b/Debugger/ILSpy.Debugger/Models/TreeModel/ExpressionNode.cs index 0628155a3..4107b7ada 100644 --- a/Debugger/ILSpy.Debugger/Models/TreeModel/ExpressionNode.cs +++ b/Debugger/ILSpy.Debugger/Models/TreeModel/ExpressionNode.cs @@ -10,6 +10,7 @@ using System.Windows.Media; using Debugger; using Debugger.MetaData; +using Decompiler; using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.CSharp; using ILSpy.Debugger.Services; @@ -148,6 +149,18 @@ namespace ILSpy.Debugger.Models.TreeModel Value val; try { + if (expression is IdentifierExpression) { + var frame = WindowsDebugger.DebuggedProcess.SelectedThread.MostRecentStackFrame; + int token = frame.MethodInfo.MetadataToken; + List list; + if (ILAstBuilder.MemberLocalVariables.TryGetValue(token, out list)) { + var variable = list.Find(v => v.Name == Name); + if (variable != null) { + expression.AddAnnotation(new int[] { variable.OriginalVariable.Index }); + } + } + } + val = expression.Evaluate(WindowsDebugger.DebuggedProcess); } catch (GetValueException e) { error = e; diff --git a/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerHelper.cs b/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerHelper.cs index e763ad0b3..4beadd3a2 100644 --- a/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerHelper.cs +++ b/Debugger/ILSpy.Debugger/Services/Debugger/DebuggerHelper.cs @@ -27,7 +27,7 @@ namespace ILSpy.Debugger.Services.Debugger listType = DebugType.CreateFromType(itemType.AppDomain, typeof(System.Collections.Generic.List<>), itemType); var iEnumerableType = DebugType.CreateFromType(itemType.AppDomain, typeof(IEnumerable<>), itemType); // explicitely cast the variable to IEnumerable, where T is itemType - Expression iEnumerableVariableExplicitCast = new CastExpression { Expression = iEnumerableVariable , Type = iEnumerableType.GetTypeReference() }; + Expression iEnumerableVariableExplicitCast = new CastExpression { Expression = iEnumerableVariable.Clone() , Type = iEnumerableType.GetTypeReference() }; return new ObjectCreateExpression() { Type = listType.GetTypeReference()/*, Arguments = iEnumerableVariableExplicitCast.ToList() */ diff --git a/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs b/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs index dcb13b172..3dd4253fd 100644 --- a/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs +++ b/Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs @@ -12,9 +12,7 @@ using System.Windows.Media; using Debugger; using Debugger.Interop.CorPublish; -using Decompiler; using ICSharpCode.Decompiler; -using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.Visitors; diff --git a/Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs b/Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs index 10fc927f0..400cbc902 100644 --- a/Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs +++ b/Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs @@ -33,11 +33,11 @@ namespace ILSpy.Debugger.ToolTips /// /// Description of TextEditorListener. /// - public class TextEditorListener : IWeakEventListener + public class TextEditorListener : IWeakEventListener { private static readonly TextEditorListener instance; - static TextEditorListener() + static TextEditorListener() { instance = new TextEditorListener(); } @@ -45,7 +45,6 @@ namespace ILSpy.Debugger.ToolTips private TextEditorListener() { } Popup popup; - ToolTip toolTip; TextEditor editor; public static TextEditorListener Instance { @@ -72,9 +71,6 @@ namespace ILSpy.Debugger.ToolTips void OnMouseDown(MouseEventArgs mouseEventArgs0) { - if (toolTip != null) - toolTip.IsOpen = false; - TryCloseExistingPopup(true); if (popup != null) @@ -82,14 +78,13 @@ namespace ILSpy.Debugger.ToolTips } void OnMouseHoverStopped(MouseEventArgs e) - { - if (toolTip != null) - toolTip.IsOpen = false; + { + } void OnMouseHover(MouseEventArgs e) { - ToolTipRequestEventArgs args = new ToolTipRequestEventArgs(editor); + ToolTipRequestEventArgs args = new ToolTipRequestEventArgs(editor); var pos = editor.GetPositionFromPoint(e.GetPosition(editor)); args.InDocument = pos.HasValue; @@ -118,25 +113,6 @@ namespace ILSpy.Debugger.ToolTips popup.IsOpen = true; } e.Handled = true; - } else { - if (toolTip == null) { - toolTip = new ToolTip(); - toolTip.Closed += delegate { toolTip = null; }; - } - toolTip.PlacementTarget = editor; // required for property inheritance - - if(args.ContentToShow is string) { - toolTip.Content = new TextBlock - { - Text = (args.ContentToShow as string), - TextWrapping = TextWrapping.Wrap - }; - } - else - toolTip.Content = args.ContentToShow; - - toolTip.IsOpen = true; - e.Handled = true; } } else { // close popup if mouse hovered over empty area diff --git a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs index d08c4972a..dd79dd2e2 100644 --- a/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs +++ b/ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs @@ -70,6 +70,11 @@ namespace Decompiler DeclareVariableInSmallestScope.DeclareVariable(astBlock, AstBuilder.ConvertType(v.Type), v.Name); } + // store the variables - used for debugger + int token = methodDef.MetadataToken.ToInt32(); + ILAstBuilder.MemberLocalVariables.AddOrUpdate( + token, astBuilder.Variables, (key, oldValue) => astBuilder.Variables); + return astBlock; } diff --git a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs index 51656fc1a..09a82bad9 100644 --- a/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs +++ b/ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs @@ -1,7 +1,9 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; + using Mono.Cecil; using Mono.Cecil.Cil; using Cecil = Mono.Cecil; @@ -10,6 +12,11 @@ namespace Decompiler { public class ILAstBuilder { + /// + /// + /// + public static ConcurrentDictionary> MemberLocalVariables = new ConcurrentDictionary>(); + class StackSlot { public List PushedBy; // One of those