Browse Source

Evaluate local vars.

pull/191/merge
Eusebiu Marcu 16 years ago
parent
commit
6e10e6bbe0
  1. 20
      Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs
  2. 2
      Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs
  3. 16
      Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs
  4. 27
      Debugger/ILSpy.Debugger/Models/TreeModel/ChildNodesOfObject.cs
  5. 13
      Debugger/ILSpy.Debugger/Models/TreeModel/ExpressionNode.cs
  6. 2
      Debugger/ILSpy.Debugger/Services/Debugger/DebuggerHelper.cs
  7. 2
      Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
  8. 34
      Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs
  9. 5
      ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs
  10. 7
      ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

20
Debugger/Debugger.Core/MetaData/DebugMethodInfo.cs

@ -343,12 +343,12 @@ namespace Debugger.MetaData
uint token = 0; uint token = 0;
bool success = 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 (Read(code, 0x02, 0x7B) || Read(code, 0x7E)) && // ldarg.0; ldfld || ldsfld
ReadToken(code, ref token) && // <field token> ReadToken(code, ref token) && // <field token>
(Read(code, 0x0A, 0x2B, 0x00, 0x06) || true) && // stloc.0; br.s; offset+00; ldloc.0 || nothing (Read(code, 0x0A, 0x2B, 0x00, 0x06) || true) && // stloc.0; br.s; offset+00; ldloc.0 || nothing
Read(code, 0x2A); // ret Read(code, 0x2A); // ret
if (!success) return; if (!success) return;
if (this.Process.Options.Verbose) { if (this.Process.Options.Verbose) {
@ -427,7 +427,7 @@ namespace Debugger.MetaData
// Look on the method // Look on the method
DebugType.IsDefined( DebugType.IsDefined(
this, this,
false, false,
typeof(System.Diagnostics.DebuggerStepThroughAttribute), typeof(System.Diagnostics.DebuggerStepThroughAttribute),
typeof(System.Diagnostics.DebuggerNonUserCodeAttribute), typeof(System.Diagnostics.DebuggerNonUserCodeAttribute),
typeof(System.Diagnostics.DebuggerHiddenAttribute)) typeof(System.Diagnostics.DebuggerHiddenAttribute))
@ -435,7 +435,7 @@ namespace Debugger.MetaData
// Look on the type // Look on the type
DebugType.IsDefined( DebugType.IsDefined(
declaringType, declaringType,
false, false,
typeof(System.Diagnostics.DebuggerStepThroughAttribute), typeof(System.Diagnostics.DebuggerStepThroughAttribute),
typeof(System.Diagnostics.DebuggerNonUserCodeAttribute), typeof(System.Diagnostics.DebuggerNonUserCodeAttribute),
typeof(System.Diagnostics.DebuggerHiddenAttribute)); 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) public DebugLocalVariableInfo GetLocalVariable(int offset, string name)
{ {
foreach(DebugLocalVariableInfo loc in GetLocalVariables(offset)) { foreach(DebugLocalVariableInfo loc in GetLocalVariables(offset)) {

2
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) 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<Expression>(); var args = new List<Expression>();
foreach(int index in indices) { foreach(int index in indices) {
args.Add(new PrimitiveExpression(index)); args.Add(new PrimitiveExpression(index));

16
Debugger/Debugger.Core/NRefactory/Visitors/ExpressionEvaluator.cs

@ -383,13 +383,23 @@ namespace ICSharpCode.NRefactory.Visitors
} }
} }
// get parameter
DebugParameterInfo par = context.MethodInfo.GetParameter(identifier); DebugParameterInfo par = context.MethodInfo.GetParameter(identifier);
if (par != null) if (par != null)
return new TypedValue(par.GetValue(context), (DebugType)par.ParameterType); return new TypedValue(par.GetValue(context), (DebugType)par.ParameterType);
DebugLocalVariableInfo loc = context.MethodInfo.GetLocalVariable(context.IP, identifier); //get local variables
if (loc != null)
return new TypedValue(loc.GetValue(context), (DebugType)loc.LocalType); // 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 // Instance class members
// Note that the method might be generated instance method that represents anonymous method // Note that the method might be generated instance method that represents anonymous method

27
Debugger/ILSpy.Debugger/Models/TreeModel/ChildNodesOfObject.cs

@ -10,6 +10,7 @@ using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ILSpy.Debugger.Services; using ILSpy.Debugger.Services;
using ILSpy.Debugger.Services.Debugger; using ILSpy.Debugger.Services.Debugger;
using Module = Debugger.Module;
namespace ILSpy.Debugger.Models.TreeModel namespace ILSpy.Debugger.Models.TreeModel
{ {
@ -97,7 +98,12 @@ namespace ILSpy.Debugger.Models.TreeModel
public static IEnumerable<TreeNode> LazyGetItemsOfIList(Expression targetObject) public static IEnumerable<TreeNode> LazyGetItemsOfIList(Expression targetObject)
{ {
// This is needed for expanding IEnumerable<T> // This is needed for expanding IEnumerable<T>
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; int count = 0;
GetValueException error = null; GetValueException error = null;
try { 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");
}
}
} }
} }

13
Debugger/ILSpy.Debugger/Models/TreeModel/ExpressionNode.cs

@ -10,6 +10,7 @@ using System.Windows.Media;
using Debugger; using Debugger;
using Debugger.MetaData; using Debugger.MetaData;
using Decompiler;
using ICSharpCode.NRefactory.Ast; using ICSharpCode.NRefactory.Ast;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ILSpy.Debugger.Services; using ILSpy.Debugger.Services;
@ -148,6 +149,18 @@ namespace ILSpy.Debugger.Models.TreeModel
Value val; Value val;
try { try {
if (expression is IdentifierExpression) {
var frame = WindowsDebugger.DebuggedProcess.SelectedThread.MostRecentStackFrame;
int token = frame.MethodInfo.MetadataToken;
List<ILVariable> 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); val = expression.Evaluate(WindowsDebugger.DebuggedProcess);
} catch (GetValueException e) { } catch (GetValueException e) {
error = e; error = e;

2
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); listType = DebugType.CreateFromType(itemType.AppDomain, typeof(System.Collections.Generic.List<>), itemType);
var iEnumerableType = DebugType.CreateFromType(itemType.AppDomain, typeof(IEnumerable<>), itemType); var iEnumerableType = DebugType.CreateFromType(itemType.AppDomain, typeof(IEnumerable<>), itemType);
// explicitely cast the variable to IEnumerable<T>, where T is itemType // explicitely cast the variable to IEnumerable<T>, 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() { return new ObjectCreateExpression() {
Type = listType.GetTypeReference()/*, Type = listType.GetTypeReference()/*,
Arguments = iEnumerableVariableExplicitCast.ToList() */ Arguments = iEnumerableVariableExplicitCast.ToList() */

2
Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs

@ -12,9 +12,7 @@ using System.Windows.Media;
using Debugger; using Debugger;
using Debugger.Interop.CorPublish; using Debugger.Interop.CorPublish;
using Decompiler;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.Visitors; using ICSharpCode.NRefactory.Visitors;

34
Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs

@ -33,11 +33,11 @@ namespace ILSpy.Debugger.ToolTips
/// <summary> /// <summary>
/// Description of TextEditorListener. /// Description of TextEditorListener.
/// </summary> /// </summary>
public class TextEditorListener : IWeakEventListener public class TextEditorListener : IWeakEventListener
{ {
private static readonly TextEditorListener instance; private static readonly TextEditorListener instance;
static TextEditorListener() static TextEditorListener()
{ {
instance = new TextEditorListener(); instance = new TextEditorListener();
} }
@ -45,7 +45,6 @@ namespace ILSpy.Debugger.ToolTips
private TextEditorListener() { } private TextEditorListener() { }
Popup popup; Popup popup;
ToolTip toolTip;
TextEditor editor; TextEditor editor;
public static TextEditorListener Instance { public static TextEditorListener Instance {
@ -72,9 +71,6 @@ namespace ILSpy.Debugger.ToolTips
void OnMouseDown(MouseEventArgs mouseEventArgs0) void OnMouseDown(MouseEventArgs mouseEventArgs0)
{ {
if (toolTip != null)
toolTip.IsOpen = false;
TryCloseExistingPopup(true); TryCloseExistingPopup(true);
if (popup != null) if (popup != null)
@ -82,14 +78,13 @@ namespace ILSpy.Debugger.ToolTips
} }
void OnMouseHoverStopped(MouseEventArgs e) void OnMouseHoverStopped(MouseEventArgs e)
{ {
if (toolTip != null)
toolTip.IsOpen = false;
} }
void OnMouseHover(MouseEventArgs e) void OnMouseHover(MouseEventArgs e)
{ {
ToolTipRequestEventArgs args = new ToolTipRequestEventArgs(editor); ToolTipRequestEventArgs args = new ToolTipRequestEventArgs(editor);
var pos = editor.GetPositionFromPoint(e.GetPosition(editor)); var pos = editor.GetPositionFromPoint(e.GetPosition(editor));
args.InDocument = pos.HasValue; args.InDocument = pos.HasValue;
@ -118,25 +113,6 @@ namespace ILSpy.Debugger.ToolTips
popup.IsOpen = true; popup.IsOpen = true;
} }
e.Handled = 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 { } else {
// close popup if mouse hovered over empty area // close popup if mouse hovered over empty area

5
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -70,6 +70,11 @@ namespace Decompiler
DeclareVariableInSmallestScope.DeclareVariable(astBlock, AstBuilder.ConvertType(v.Type), v.Name); 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; return astBlock;
} }

7
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -1,7 +1,9 @@
using System; using System;
using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Mono.Cecil; using Mono.Cecil;
using Mono.Cecil.Cil; using Mono.Cecil.Cil;
using Cecil = Mono.Cecil; using Cecil = Mono.Cecil;
@ -10,6 +12,11 @@ namespace Decompiler
{ {
public class ILAstBuilder public class ILAstBuilder
{ {
/// <summary>
///
/// </summary>
public static ConcurrentDictionary<int, List<ILVariable>> MemberLocalVariables = new ConcurrentDictionary<int, List<ILVariable>>();
class StackSlot class StackSlot
{ {
public List<ByteCode> PushedBy; // One of those public List<ByteCode> PushedBy; // One of those

Loading…
Cancel
Save