Browse Source

fix stepping into nested types

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
0d904d7358
  1. 2
      Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
  2. 75
      Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
  3. 10
      ICSharpCode.Decompiler/CodeMappings.cs

2
Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs

@ -235,7 +235,7 @@ namespace ILSpy.Debugger.AvalonEdit
uint token; uint token;
var instruction = storage.GetInstructionByTypeAndLine(DebugData.CurrentType.FullName, line, out token); var instruction = storage.GetInstructionByTypeAndLine(DebugData.CurrentType.FullName, line, out token);
if (instruction == null || instruction.ILInstructionOffset.From == 0) { if (instruction == null) {
MessageBox.Show(string.Format("Missing code mappings for {0} at line {1}", DebugData.CurrentType.FullName, line), MessageBox.Show(string.Format("Missing code mappings for {0} at line {1}", DebugData.CurrentType.FullName, line),
"Code mappings", MessageBoxButton.OK, MessageBoxImage.Information); "Code mappings", MessageBoxButton.OK, MessageBoxImage.Information);
return; return;

75
Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs

@ -12,6 +12,7 @@ using System.Windows.Media;
using Debugger; using Debugger;
using Debugger.Interop.CorPublish; using Debugger.Interop.CorPublish;
using Debugger.MetaData;
using ICSharpCode.Decompiler; using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Ast; using ICSharpCode.Decompiler.Ast;
using ICSharpCode.NRefactory; using ICSharpCode.NRefactory;
@ -287,28 +288,49 @@ namespace ILSpy.Debugger.Services
// Stepping: // Stepping:
SourceCodeMapping GetCurrentCodeMapping(out bool isMatch) SourceCodeMapping GetCurrentCodeMapping(out StackFrame frame, out bool isMatch)
{ {
isMatch = false; isMatch = false;
if (CurrentLineBookmark.Instance == null) frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
return null;
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
// get the mapped instruction from the current line marker or the next one // get the mapped instruction from the current line marker or the next one
return CodeMappingsStorage.GetInstructionByTypeAndLine( return CodeMappingsStorage.GetInstructionByTypeTokenAndOffset(
CurrentLineBookmark.Instance.Type.FullName, (uint)frame.MethodInfo.MetadataToken, frame.IP, out isMatch); ((DebugType)frame.MethodInfo.DeclaringType).FullNameWithoutGenericArguments,
(uint)frame.MethodInfo.MetadataToken,
frame.IP, out isMatch);
// int i = debuggedProcess.SelectedThread.Callstack.Count() - 1;
// if (i < 0)
// return null;
//
// while (true) {
// frame = debuggedProcess.SelectedThread.Callstack.ElementAt(i);
//
// // get the mapped instruction from the current line marker or the next one
// var result = CodeMappingsStorage.GetInstructionByTypeTokenAndOffset(
// ((DebugType)frame.MethodInfo.DeclaringType).FullNameWithoutGenericArguments,
// (uint)frame.MethodInfo.MetadataToken,
// frame.IP, out isMatch);
//
// if (result == null) {
// i--;
// if (i < 0)
// return result;
// } else {
// return result;
// }
// }
} }
StackFrame GetStackFrame() StackFrame GetStackFrame()
{ {
bool isMatch; bool isMatch;
var map = GetCurrentCodeMapping(out isMatch); StackFrame frame;
var map = GetCurrentCodeMapping(out frame, out isMatch);
if (map == null) { if (map == null) {
CurrentLineBookmark.Remove();
Continue();
return null; return null;
} else { } else {
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame; //var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
frame.SourceCodeLine = map.SourceCodeLine; frame.SourceCodeLine = map.SourceCodeLine;
frame.ILRanges = map.ToArray(isMatch); frame.ILRanges = map.ToArray(isMatch);
return frame; return frame;
@ -804,8 +826,6 @@ namespace ILSpy.Debugger.Services
public void JumpToCurrentLine() public void JumpToCurrentLine()
{ {
DebuggerService.RemoveCurrentLineMarker();
if (debuggedProcess != null && debuggedProcess.SelectedThread != null) { if (debuggedProcess != null && debuggedProcess.SelectedThread != null) {
// use most recent stack frame because we don't have the symbols // use most recent stack frame because we don't have the symbols
@ -820,6 +840,7 @@ namespace ILSpy.Debugger.Services
TypeDefinition type; TypeDefinition type;
if (CodeMappingsStorage.GetSourceCodeFromMetadataTokenAndOffset(frame.MethodInfo.DeclaringType.FullName, token, ilOffset, out type, out line)) { if (CodeMappingsStorage.GetSourceCodeFromMetadataTokenAndOffset(frame.MethodInfo.DeclaringType.FullName, token, ilOffset, out type, out line)) {
DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(type, line, 0, line, 0); DebuggerService.JumpToCurrentLine(type, line, 0, line, 0);
} else { } else {
// is possible that the type is not decompiled yet, so we must do a decompilation on demand // is possible that the type is not decompiled yet, so we must do a decompilation on demand
@ -830,23 +851,31 @@ namespace ILSpy.Debugger.Services
void DecompileOnDemand(StackFrame frame) void DecompileOnDemand(StackFrame frame)
{ {
var debugType = frame.MethodInfo.DeclaringType; var debugType = (DebugType)frame.MethodInfo.DeclaringType;
uint token = (uint)frame.MethodInfo.MetadataToken; uint token = (uint)frame.MethodInfo.MetadataToken;
int ilOffset = frame.IP; int ilOffset = frame.IP;
string fullName = debugType.Namespace + "." + debugType.Name; string fullName = debugType.FullNameWithoutGenericArguments;
fullName = fullName.Replace("+", "/");
if (DebugData.LoadedAssemblies == null) if (DebugData.LoadedAssemblies == null)
Continue(); Continue();
else { else {
// search for type in the current assembly list // search for type in the current assembly list
TypeDefinition typeDef = null; TypeDefinition typeDef = null;
TypeDefinition nestedTypeDef = null;
foreach (var assembly in DebugData.LoadedAssemblies) { foreach (var assembly in DebugData.LoadedAssemblies) {
foreach (var module in assembly.Modules) { foreach (var module in assembly.Modules) {
foreach (var type in module.Types) { var localType = module.GetType(fullName);
if (type.FullName.Equals(fullName, StringComparison.OrdinalIgnoreCase)) { if (localType != null) {
typeDef = type; if (localType.DeclaringType == null)
break; typeDef = localType;
else {
nestedTypeDef = localType;
typeDef = localType.DeclaringType;
} }
break;
} }
} }
if (typeDef != null) if (typeDef != null)
@ -854,18 +883,20 @@ namespace ILSpy.Debugger.Services
} }
if (typeDef != null) { if (typeDef != null) {
// decompile on demand // decompile on demand
if (!CodeMappingsStorage.ContainsKey(typeDef.FullName)) {
AstBuilder builder = new AstBuilder(new DecompilerContext()); AstBuilder builder = new AstBuilder(new DecompilerContext());
builder.AddType(typeDef); builder.AddType(typeDef);
builder.GenerateCode(new PlainTextOutput()); builder.GenerateCode(new PlainTextOutput());
}
// try jump // try jump
int line; int line;
TypeDefinition type; TypeDefinition type;
if (CodeMappingsStorage.GetSourceCodeFromMetadataTokenAndOffset(typeDef.FullName, token, ilOffset, out type, out line)) { if (CodeMappingsStorage.GetSourceCodeFromMetadataTokenAndOffset((nestedTypeDef ?? typeDef).FullName, token, ilOffset, out type, out line)) {
DebuggerService.JumpToCurrentLine(type, line, 0, line, 0); DebuggerService.RemoveCurrentLineMarker();
DebuggerService.JumpToCurrentLine(typeDef, line, 0, line, 0);
} else { } else {
// continue since we cannot find the debugged type // continue since we cannot find the debugged type
Continue(); StepOver();
} }
} else { } else {
// continue since we cannot find the debugged type // continue since we cannot find the debugged type

10
ICSharpCode.Decompiler/CodeMappings.cs

@ -57,8 +57,9 @@ namespace ICSharpCode.Decompiler
currentList.AddRange(MemberMapping.InvertedList); currentList.AddRange(MemberMapping.InvertedList);
} else { } else {
// if the current list contains the last mapping, add also the last gap // if the current list contains the last mapping, add also the last gap
if (currentList.Count == 1) var lastInverted = MemberMapping.InvertedList.LastOrDefault();
currentList.Add(MemberMapping.InvertedList.LastOrDefault()); if (lastInverted != null && lastInverted.From == currentList[currentList.Count - 1].To)
currentList.Add(lastInverted);
} }
// set the output // set the output
@ -210,13 +211,14 @@ namespace ICSharpCode.Decompiler
return null; return null;
} }
public static SourceCodeMapping GetInstructionByTypeAndLine( public static SourceCodeMapping GetInstructionByTypeTokenAndOffset(
this ConcurrentDictionary<string, List<MemberMapping>> codeMappings, this ConcurrentDictionary<string, List<MemberMapping>> codeMappings,
string typeName, string typeName,
uint token, uint token,
int ilOffset, out bool isMatch) int ilOffset, out bool isMatch)
{ {
isMatch = false; isMatch = false;
typeName = typeName.Replace("+", "/");
if (codeMappings == null) if (codeMappings == null)
throw new ArgumentNullException("CodeMappings storage must be valid!"); throw new ArgumentNullException("CodeMappings storage must be valid!");
@ -278,6 +280,8 @@ namespace ICSharpCode.Decompiler
codeMapping = mapping.MemberCodeMappings.Find(cm => (cm.ILInstructionOffset.From >= ilOffset)); codeMapping = mapping.MemberCodeMappings.Find(cm => (cm.ILInstructionOffset.From >= ilOffset));
if (codeMapping == null) { if (codeMapping == null) {
codeMapping = mapping.MemberCodeMappings.LastOrDefault(); codeMapping = mapping.MemberCodeMappings.LastOrDefault();
if (codeMapping == null)
return false;
} }
} }

Loading…
Cancel
Save