Permalink
Browse files

evaluate local variables (not only parameters) for decompiled code.

  • Loading branch information...
1 parent de36dc4 commit 6701792f3914c72b43112fcfa5fb3c2431d21327 @eusebiu eusebiu committed Jul 29, 2011
View
6 src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs
@@ -53,7 +53,11 @@ string Evaluate(string code)
}
try {
var context = !process.IsInExternalCode ? process.SelectedStackFrame : process.SelectedThread.MostRecentStackFrame;
- Value val = ExpressionEvaluator.Evaluate(code, SelectedLanguage, context);
+ var debugger = (WindowsDebugger)DebuggerService.CurrentDebugger;
+ object data = debugger.debuggerDecompilerService.GetLocalVariableIndex(context.MethodInfo.DeclaringType.MetadataToken,
+ context.MethodInfo.MetadataToken,
+ code);
+ Value val = ExpressionEvaluator.Evaluate(code, SelectedLanguage, context, data);
return ExpressionEvaluator.FormatValue(val);
} catch (GetValueException e) {
return e.Message;
View
48 src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
@@ -50,6 +50,8 @@ enum StopAttachedProcessDialogResult {
Process debuggedProcess;
ProcessMonitor monitor;
+ internal IDebuggerDecompilerService debuggerDecompilerService;
+
//DynamicTreeDebuggerRow currentTooltipRow;
//Expression currentTooltipExpression;
@@ -470,8 +472,7 @@ Debugger.StackFrame GetStackFrame()
int methodToken = frame.MethodInfo.MetadataToken;
// get the mapped instruction from the current line marker or the next one
- var decompilerService = GetDecompilerService();
- if (!decompilerService.GetILAndLineNumber(typeToken, methodToken, frame.IP, out ilRange, out line, out isMatch)){
+ if (!debuggerDecompilerService.GetILAndLineNumber(typeToken, methodToken, frame.IP, out ilRange, out line, out isMatch)){
frame.SourceCodeLine = 0;
frame.ILRanges = new [] { 0, 1 };
} else {
@@ -581,10 +582,12 @@ public Value GetValueFromName(string variableName)
}
var stackFrame = !debuggedProcess.IsInExternalCode ? debuggedProcess.SelectedStackFrame : debuggedProcess.SelectedThread.MostRecentStackFrame;
-
try {
+ object data = debuggerDecompilerService.GetLocalVariableIndex(stackFrame.MethodInfo.DeclaringType.MetadataToken,
+ stackFrame.MethodInfo.MetadataToken,
+ variableName);
// evaluate expression
- return ExpressionEvaluator.Evaluate(variableName, SupportedLanguage.CSharp, stackFrame);
+ return ExpressionEvaluator.Evaluate(variableName, SupportedLanguage.CSharp, stackFrame, data);
} catch {
throw;
}
@@ -713,10 +716,14 @@ public void InitializeService()
new RemotingConfigurationHelpper(path).Configure();
}
- debugger = new NDebugger();
-
- debugger.Options = DebuggingOptions.Instance;
+ // get decompiler service
+ var items = AddInTree.BuildItems<IDebuggerDecompilerService>("/SharpDevelop/Services/DebuggerDecompilerService", null, false);
+ if (items.Count > 0)
+ debuggerDecompilerService = items[0];
+ // init NDebugger
+ debugger = new NDebugger();
+ debugger.Options = DebuggingOptions.Instance;
debugger.DebuggerTraceMessage += debugger_TraceMessage;
debugger.Processes.Added += debugger_ProcessStarted;
debugger.Processes.Removed += debugger_ProcessExited;
@@ -750,15 +757,14 @@ void AddBreakpoint(BreakpointBookmark bookmark)
if (bookmark is DecompiledBreakpointBookmark) {
var dbb = (DecompiledBreakpointBookmark)bookmark;
var memberReference = dbb.MemberReference;
- var decompilerService = GetDecompilerService();
int token = memberReference.MetadataToken.ToInt32();
- if (!decompilerService.CheckMappings(token))
- decompilerService.DecompileOnDemand(memberReference as TypeDefinition);
+ if (!debuggerDecompilerService.CheckMappings(token))
+ debuggerDecompilerService.DecompileOnDemand(memberReference as TypeDefinition);
int[] ilRanges;
int methodToken;
- if (decompilerService.GetILAndTokenByLineNumber(token, dbb.LineNumber, out ilRanges, out methodToken)) {
+ if (debuggerDecompilerService.GetILAndTokenByLineNumber(token, dbb.LineNumber, out ilRanges, out methodToken)) {
dbb.ILFrom = ilRanges[0];
dbb.ILTo = ilRanges[1];
// create BP
@@ -1032,6 +1038,10 @@ public void JumpToCurrentLine()
DebuggerService.JumpToCurrentLine(nextStatement.Filename, nextStatement.StartLine, nextStatement.StartColumn, nextStatement.EndLine, nextStatement.EndColumn);
}
} else {
+ if (debuggerDecompilerService == null) {
+ LoggingService.Warn("No IDebuggerDecompilerService found!");
+ return;
+ }
// use most recent stack frame because we don't have the symbols
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
if (frame == null)
@@ -1042,12 +1052,11 @@ public void JumpToCurrentLine()
int methodToken = frame.MethodInfo.MetadataToken;
int ilOffset = frame.IP;
- var decompilerService = GetDecompilerService();
int[] ilRanges = null;
int line = -1;
bool isMatch = false;
- if (decompilerService.GetILAndLineNumber(typeToken, methodToken, ilOffset, out ilRanges, out line, out isMatch)) {
- DebuggerService.DebugStepInformation = null; // we do not need to step into/out
+ if (debuggerDecompilerService.GetILAndLineNumber(typeToken, methodToken, ilOffset, out ilRanges, out line, out isMatch)) {
+ debuggerDecompilerService.DebugStepInformation = null; // we do not need to step into/out
// update marker
var debugType = (DebugType)frame.MethodInfo.DeclaringType;
@@ -1077,19 +1086,10 @@ void StepIntoUnknownFrame(Debugger.StackFrame frame, int token, int ilOffset)
{
var debugType = (DebugType)frame.MethodInfo.DeclaringType;
string fullName = debugType.FullNameWithoutGenericArguments;
- DebuggerService.DebugStepInformation = Tuple.Create(token, ilOffset);
+ debuggerDecompilerService.DebugStepInformation = Tuple.Create(token, ilOffset);
NavigationService.NavigateTo(debugType.DebugModule.FullPath, debugType.FullNameWithoutGenericArguments, string.Empty);
}
- IDebuggerDecompilerService GetDecompilerService()
- {
- var items = AddInTree.BuildItems<IDebuggerDecompilerService>("/SharpDevelop/Services/DebuggerDecompilerService", null, false);
- if (items.Count == 0)
- return null;
-
- return items[0];
- }
-
StopAttachedProcessDialogResult ShowStopAttachedProcessDialog()
{
string caption = StringParser.Parse("${res:XML.MainMenu.DebugMenu.Stop}");
View
12 src/AddIns/Debugger/Debugger.AddIn/TreeModel/ExpressionNode.cs
@@ -157,6 +157,18 @@ void EvaluateExpression()
Value val;
try {
var process = WindowsDebugger.DebuggedProcess;
+ var context = !process.IsInExternalCode ? process.SelectedStackFrame : process.SelectedThread.MostRecentStackFrame;
+ var debugger = (WindowsDebugger)DebuggerService.CurrentDebugger;
+ object data = debugger.debuggerDecompilerService.GetLocalVariableIndex(context.MethodInfo.DeclaringType.MetadataToken,
+ context.MethodInfo.MetadataToken,
+ Name);
+
+ if (expression is MemberReferenceExpression) {
+ var memberExpression = (MemberReferenceExpression)expression;
+ memberExpression.TargetObject.UserData = data;
+ } else {
+ expression.UserData = data;
+ }
// evaluate expression
val = expression.Evaluate(process);
} catch (GetValueException e) {
View
32 src/AddIns/Debugger/Debugger.AddIn/TreeModel/StackFrameNode.cs
@@ -1,10 +1,13 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the BSD license (for details please see \src\AddIns\Debugger\Debugger.AddIn\license.txt)
-using Debugger.MetaData;
using System.Collections.Generic;
+using Debugger.MetaData;
+using ICSharpCode.NRefactory;
using ICSharpCode.NRefactory.Ast;
+using ICSharpCode.NRefactory.Visitors;
using ICSharpCode.SharpDevelop.Debugging;
+using ICSharpCode.SharpDevelop.Services;
namespace Debugger.AddIn.TreeModel
{
@@ -33,12 +36,27 @@ IEnumerable<TreeNode> LazyGetChildNodes()
expression.ImageName = imageName;
yield return expression;
}
- foreach(DebugLocalVariableInfo locVar in stackFrame.MethodInfo.GetLocalVariables(this.StackFrame.IP)) {
- string imageName;
- var image = ExpressionNode.GetImageForLocalVariable(out imageName);
- var expression = new ExpressionNode(image, locVar.Name, locVar.GetExpression());
- expression.ImageName = imageName;
- yield return expression;
+ if (this.stackFrame.HasSymbols) {
+ foreach(DebugLocalVariableInfo locVar in stackFrame.MethodInfo.GetLocalVariables(this.StackFrame.IP)) {
+ string imageName;
+ var image = ExpressionNode.GetImageForLocalVariable(out imageName);
+ var expression = new ExpressionNode(image, locVar.Name, locVar.GetExpression());
+ expression.ImageName = imageName;
+ yield return expression;
+ }
+ } else {
+ WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger;
+ if (debugger.debuggerDecompilerService != null) {
+ int typeToken = this.stackFrame.MethodInfo.DeclaringType.MetadataToken;
+ int methodToken = this.stackFrame.MethodInfo.MetadataToken;
+ foreach (var localVar in debugger.debuggerDecompilerService.GetLocalVariables(typeToken, methodToken)) {
+ string imageName;
+ var image = ExpressionNode.GetImageForLocalVariable(out imageName);
+ var expression = new ExpressionNode(image, localVar, ExpressionEvaluator.ParseExpression(localVar, SupportedLanguage.CSharp));
+ expression.ImageName = imageName;
+ yield return expression;
+ }
+ }
}
if (stackFrame.Thread.CurrentException != null) {
yield return new ExpressionNode(null, "__exception", new IdentifierExpression("__exception"));
View
52 src/AddIns/DisplayBindings/ILSpyAddIn/DebuggerDecompilerService.cs
@@ -2,16 +2,18 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Concurrent;
+using System.Collections.Generic;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast;
+using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.SharpDevelop.Debugging;
using Mono.Cecil;
namespace ICSharpCode.ILSpyAddIn
{
/// <summary>
- /// Description of DebuggerDecompilerService.
+ /// Stores the decompilation information.
/// </summary>
public class DebuggerDecompilerService : IDebuggerDecompilerService
{
@@ -20,12 +22,21 @@ static DebuggerDecompilerService()
DebugInformation = new ConcurrentDictionary<int, DecompileInformation>();
}
+ internal static IDebuggerDecompilerService Instance { get; private set; }
+
/// <summary>
/// Gets or sets the external debug information.
/// <summary>This constains the code mappings and local variables.</summary>
/// </summary>
internal static ConcurrentDictionary<int, DecompileInformation> DebugInformation { get; private set; }
+ public DebuggerDecompilerService()
+ {
+ Instance = this;
+ }
+
+ public Tuple<int, int> DebugStepInformation { get; set; }
+
public bool CheckMappings(int typeToken)
{
DecompileInformation data = null;
@@ -116,5 +127,44 @@ public bool GetILAndLineNumber(int typeToken, int memberToken, int ilOffset, out
return false;
}
+
+ public IEnumerable<string> GetLocalVariables(int typeToken, int memberToken)
+ {
+ if (DebugInformation == null || !DebugInformation.ContainsKey(typeToken))
+ yield break;
+
+ var externalData = DebugInformation[typeToken];
+ IEnumerable<ILVariable> list;
+
+ if (externalData.LocalVariables.TryGetValue(memberToken, out list)) {
+ foreach (var local in list) {
+ if (local.IsParameter)
+ continue;
+ if (string.IsNullOrEmpty(local.Name))
+ continue;
+ yield return local.Name;
+ }
+ }
+ }
+
+ public object GetLocalVariableIndex(int typeToken, int memberToken, string name)
+ {
+ if (DebugInformation == null || !DebugInformation.ContainsKey(typeToken))
+ return null;
+
+ var externalData = DebugInformation[typeToken];
+ IEnumerable<ILVariable> list;
+
+ if (externalData.LocalVariables.TryGetValue(memberToken, out list)) {
+ foreach (var local in list) {
+ if (local.IsParameter)
+ continue;
+ if (local.Name == name)
+ return new[] { local.OriginalVariable.Index };
+ }
+ }
+
+ return null;
+ }
}
}
View
6 src/AddIns/DisplayBindings/ILSpyAddIn/ViewContent/DecompiledViewContent.cs
@@ -222,13 +222,13 @@ void UpdateDebuggingUI()
int typeToken = MemberReference.MetadataToken.ToInt32();
if (!DebuggerDecompilerService.DebugInformation.ContainsKey(typeToken))
return;
- if (DebuggerService.DebugStepInformation == null)
+ if (DebuggerDecompilerService.Instance == null || DebuggerDecompilerService.Instance.DebugStepInformation == null)
return;
// get debugging information
DecompileInformation debugInformation = (DecompileInformation)DebuggerDecompilerService.DebugInformation[typeToken];
- int token = DebuggerService.DebugStepInformation.Item1;
- int ilOffset = DebuggerService.DebugStepInformation.Item2;
+ int token = DebuggerDecompilerService.Instance.DebugStepInformation.Item1;
+ int ilOffset = DebuggerDecompilerService.Instance.DebugStepInformation.Item2;
int line;
MemberReference member;
if (debugInformation.CodeMappings == null || !debugInformation.CodeMappings.ContainsKey(token))
View
24 src/Main/Base/Project/Src/Services/Debugger/DebuggerService.cs
@@ -102,15 +102,6 @@ static IDebugger GetCompatibleDebugger()
get { return debuggerStarted; }
}
- #region Debug third party code
-
- /// <summary>
- /// Gets or sets the current token and IL offset. Used for step in/out.
- /// </summary>
- public static Tuple<int, int> DebugStepInformation { get; set; }
-
- #endregion
-
public static event EventHandler DebugStarting;
public static event EventHandler DebugStarted;
public static event EventHandler DebugStopped;
@@ -461,6 +452,11 @@ public void HandleToolTipRequest(ToolTipRequestEventArgs e)
public interface IDebuggerDecompilerService
{
/// <summary>
+ /// Gets or sets the current method token and IL offset. Used for step in/out.
+ /// </summary>
+ Tuple<int, int> DebugStepInformation { get; set; }
+
+ /// <summary>
/// Checks the code mappings.
/// </summary>
bool CheckMappings(int typeToken);
@@ -479,5 +475,15 @@ public interface IDebuggerDecompilerService
/// Gets the ILRange and source code line number.
/// </summary>
bool GetILAndLineNumber(int typeToken, int memberToken, int ilOffset, out int[] ilRange, out int line, out bool isMatch);
+
+ /// <summary>
+ /// Gets the local variables of a type and a member.
+ /// </summary>
+ IEnumerable<string> GetLocalVariables(int typeToken, int memberToken);
+
+ /// <summary>
+ /// Gets the local variable index.
+ /// </summary>
+ object GetLocalVariableIndex(int typeToken, int memberToken, string name);
}
}

0 comments on commit 6701792

Please sign in to comment.