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 @@ -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) && // <field 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 @@ -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 @@ -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 @@ -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)) {

2
Debugger/Debugger.Core/NRefactory/Ast/ExpressionExtensionMethods.cs

@ -74,7 +74,7 @@ namespace ICSharpCode.NRefactory.Ast @@ -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<Expression>();
foreach(int index in indices) {
args.Add(new PrimitiveExpression(index));

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

@ -383,13 +383,23 @@ namespace ICSharpCode.NRefactory.Visitors @@ -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

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

@ -10,6 +10,7 @@ using ICSharpCode.NRefactory.Ast; @@ -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 @@ -97,7 +98,12 @@ namespace ILSpy.Debugger.Models.TreeModel
public static IEnumerable<TreeNode> LazyGetItemsOfIList(Expression targetObject)
{
// 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;
GetValueException error = null;
try {
@ -145,5 +151,24 @@ namespace ILSpy.Debugger.Models.TreeModel @@ -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; @@ -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 @@ -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<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);
} catch (GetValueException e) {
error = e;

2
Debugger/ILSpy.Debugger/Services/Debugger/DebuggerHelper.cs

@ -27,7 +27,7 @@ namespace ILSpy.Debugger.Services.Debugger @@ -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<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() {
Type = listType.GetTypeReference()/*,
Arguments = iEnumerableVariableExplicitCast.ToList() */

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

@ -12,9 +12,7 @@ using System.Windows.Media; @@ -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;

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

@ -33,11 +33,11 @@ namespace ILSpy.Debugger.ToolTips @@ -33,11 +33,11 @@ namespace ILSpy.Debugger.ToolTips
/// <summary>
/// Description of TextEditorListener.
/// </summary>
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 @@ -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 @@ -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 @@ -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 @@ -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

5
ICSharpCode.Decompiler/Ast/AstMethodBodyBuilder.cs

@ -70,6 +70,11 @@ namespace Decompiler @@ -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;
}

7
ICSharpCode.Decompiler/ILAst/ILAstBuilder.cs

@ -1,7 +1,9 @@ @@ -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 @@ -10,6 +12,11 @@ namespace Decompiler
{
public class ILAstBuilder
{
/// <summary>
///
/// </summary>
public static ConcurrentDictionary<int, List<ILVariable>> MemberLocalVariables = new ConcurrentDictionary<int, List<ILVariable>>();
class StackSlot
{
public List<ByteCode> PushedBy; // One of those

Loading…
Cancel
Save