Browse Source

map code for assemblies without symbols

pull/191/merge
Eusebiu Marcu 15 years ago
parent
commit
16d7bcde97
  1. 6
      Debugger/Debugger.Core/Breakpoint.cs
  2. 66
      Debugger/Debugger.Core/SourcecodeSegment.cs
  3. 10
      Debugger/Debugger.Core/StackFrame.cs
  4. 15
      Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs
  5. 4
      Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs
  6. 108
      Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs
  7. 9
      Debugger/ILSpy.Debugger/ToolTips/DebuggerTooltipControl.xaml.cs
  8. 3
      Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs
  9. 16
      ILSpy/MainWindow.xaml.cs

6
Debugger/Debugger.Core/Breakpoint.cs

@ -187,7 +187,8 @@ namespace Debugger @@ -187,7 +187,8 @@ namespace Debugger
internal override bool SetBreakpoint(Module module)
{
SourcecodeSegment segment = SourcecodeSegment.CreateForIL(module, this.Line, (int)MetadataToken, ILOffset);
if (segment == null)
return false;
try {
ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart);
corBreakpoint.Activate(Enabled ? 1 : 0);
@ -197,8 +198,7 @@ namespace Debugger @@ -197,8 +198,7 @@ namespace Debugger
OnSet(new BreakpointEventArgs(this));
return true;
}
catch (COMException) {
} catch {
return false;
}
}

66
Debugger/Debugger.Core/SourcecodeSegment.cs

@ -104,7 +104,7 @@ namespace Debugger @@ -104,7 +104,7 @@ namespace Debugger
yield return symUrl;
yield break;
}
if (Path.IsPathRooted(symUrl)) {
Dictionary<string, object> returned = new Dictionary<string, object>();
@ -212,7 +212,7 @@ namespace Debugger @@ -212,7 +212,7 @@ namespace Debugger
segment.corFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken());
segment.ilStart = (int)sqPoint.Offset;
segment.ilEnd = (int)sqPoint.Offset;
segment.stepRanges = null;
segment.stepRanges = null;
return segment;
}
}
@ -341,27 +341,57 @@ namespace Debugger @@ -341,27 +341,57 @@ namespace Debugger
public override string ToString()
{
return string.Format("{0}:{1},{2}-{3},{4}",
Path.GetFileName(this.Filename ?? string.Empty),
return string.Format("{0}:{1},{2}-{3},{4}",
Path.GetFileName(this.Filename ?? string.Empty),
this.startLine, this.startColumn, this.endLine, this.endColumn);
}
#region ILSpy
public static SourcecodeSegment CreateForIL(Module module, int line, int metadataToken, int iLOffset)
{
SourcecodeSegment segment = new SourcecodeSegment();
segment.module = module;
segment.typename = null;
segment.checkSum = null;
segment.startLine = line;
segment.startColumn = 0;
segment.endLine = line;
segment.endColumn = 0;
segment.corFunction = module.CorModule.GetFunctionFromToken((uint)metadataToken);
segment.ilStart = iLOffset;
segment.ilEnd = iLOffset;
segment.stepRanges = null;
return segment;
try {
SourcecodeSegment segment = new SourcecodeSegment();
segment.module = module;
segment.typename = null;
segment.checkSum = null;
segment.startLine = line;
segment.startColumn = 0;
segment.endLine = line;
segment.endColumn = 0;
segment.corFunction = module.CorModule.GetFunctionFromToken((uint)metadataToken);
segment.ilStart = iLOffset;
segment.ilEnd = iLOffset;
segment.stepRanges = null;
return segment;
} catch {
return null;
}
}
public static SourcecodeSegment ResolveForIL(Module module, ICorDebugFunction corFunction, int line, int offset, int[] ranges)
{
try {
SourcecodeSegment segment = new SourcecodeSegment();
segment.module = module;
segment.typename = null;
segment.checkSum = null;
segment.startLine = line;
segment.startColumn = 0;
segment.endLine = line;
segment.endColumn = 0;
segment.corFunction = corFunction;
segment.ilStart = offset;
segment.ilEnd = offset;
segment.stepRanges = ranges;
return segment;
} catch {
return null;
}
}
#endregion
}
}

10
Debugger/Debugger.Core/StackFrame.cs

@ -139,9 +139,13 @@ namespace Debugger @@ -139,9 +139,13 @@ namespace Debugger
}
}
public int[] ILRanges { get; set; }
public int SourceCodeLine { get; set; }
SourcecodeSegment GetSegmentForOffet(int offset)
{
return SourcecodeSegment.Resolve(this.MethodInfo.DebugModule, corFunction, offset);
return SourcecodeSegment.ResolveForIL(this.MethodInfo.DebugModule, corFunction, SourceCodeLine, offset, ILRanges);
}
/// <summary> Step into next instruction </summary>
@ -187,10 +191,6 @@ namespace Debugger @@ -187,10 +191,6 @@ namespace Debugger
void AsyncStep(bool stepIn)
{
if (this.MethodInfo.DebugModule.HasSymbols == false) {
throw new DebuggerException("Unable to step. No symbols loaded.");
}
SourcecodeSegment nextSt = NextStatement;
if (nextSt == null) {
throw new DebuggerException("Unable to step. Next statement not aviable");

15
Debugger/ILSpy.Debugger/AvalonEdit/IconBarMargin.cs

@ -25,6 +25,7 @@ using System.Windows.Media; @@ -25,6 +25,7 @@ using System.Windows.Media;
using ICSharpCode.AvalonEdit.Editing;
using ICSharpCode.AvalonEdit.Rendering;
using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Decompiler;
using ILSpy.Debugger.Bookmarks;
using ILSpy.Debugger.Services;
using Mono.Cecil;
@ -237,15 +238,27 @@ namespace ILSpy.Debugger.AvalonEdit @@ -237,15 +238,27 @@ namespace ILSpy.Debugger.AvalonEdit
BookmarkBase bm = GetBookmarkFromLine(line);
if (bm != null) {
bm.MouseUp(e);
if (bm.CanToggle) {
BookmarkManager.RemoveMark(bm);
InvalidateVisual();
}
InvalidateVisual();
if (e.Handled)
return;
}
if (e.ChangedButton == MouseButton.Left) {
if (CurrentType != null) {
// check if the codemappings exists for this line
var storage = CodeMappings.GetStorage(DebuggerService.CurrentDebugger.Language);
uint token;
if (storage.GetInstructionByTypeAndLine(CurrentType.FullName, line, out token) == null) {
MessageBox.Show(string.Format("Missing code mappings for {0} at line {1}", CurrentType.FullName, line),
"Code mappings", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}
// no bookmark on the line: create a new breakpoint
DebuggerService.ToggleBreakpointAt(
CurrentType.FullName,

4
Debugger/ILSpy.Debugger/Bookmarks/CurrentLineBookmark.cs

@ -13,6 +13,10 @@ namespace ILSpy.Debugger.Bookmarks @@ -13,6 +13,10 @@ namespace ILSpy.Debugger.Bookmarks
{
static CurrentLineBookmark instance;
public static CurrentLineBookmark Instance {
get { return instance; }
}
static int startLine;
static int startColumn;
static int endLine;

108
Debugger/ILSpy.Debugger/Services/Debugger/WindowsDebugger.cs

@ -1,8 +1,10 @@ @@ -1,8 +1,10 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// 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 System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
@ -45,6 +47,12 @@ namespace ILSpy.Debugger.Services @@ -45,6 +47,12 @@ namespace ILSpy.Debugger.Services
//DynamicTreeDebuggerRow currentTooltipRow;
//Expression currentTooltipExpression;
private ConcurrentDictionary<string, List<MethodMapping>> CodeMappingsStorage {
get {
return CodeMappings.GetStorage(Language);
}
}
public event EventHandler<ProcessEventArgs> ProcessSelected;
public NDebugger DebuggerCore {
@ -274,16 +282,43 @@ namespace ILSpy.Debugger.Services @@ -274,16 +282,43 @@ namespace ILSpy.Debugger.Services
// Stepping:
SourceCodeMapping GetNextCodeMapping()
{
uint token;
var instruction = CodeMappingsStorage.GetInstructionByTypeAndLine(
CurrentLineBookmark.Instance.TypeName,
CurrentLineBookmark.Instance.LineNumber, out token);
var val = CodeMappingsStorage[CurrentLineBookmark.Instance.TypeName];
var mapping = val.Find(m => m.MetadataToken == token);
return mapping.MethodCodeMappings.FirstOrDefault(s => s.ILInstructionOffset.From <= instruction.ILInstructionOffset.To);
}
public void StepInto()
{
if (!IsDebugging) {
MessageBox.Show(errorNotDebugging, "StepInto");
return;
}
if (debuggedProcess.SelectedStackFrame == null || debuggedProcess.IsRunning) {
// use most recent stack frame because we don't have the symbols
if (debuggedProcess.SelectedThread == null ||
debuggedProcess.SelectedThread.MostRecentStackFrame == null ||
debuggedProcess.IsRunning) {
MessageBox.Show(errorCannotStepNoActiveFunction, "StepInto");
} else {
debuggedProcess.SelectedStackFrame.AsyncStepInto();
var map = GetNextCodeMapping();
if (map == null) {
CurrentLineBookmark.Remove();
Continue();
} else {
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
frame.SourceCodeLine = map.SourceCodeLine;
frame.ILRanges = (new List<int> { map.ILInstructionOffset.From, map.ILInstructionOffset.To }).ToArray();
frame.AsyncStepInto();
}
}
}
@ -292,11 +327,24 @@ namespace ILSpy.Debugger.Services @@ -292,11 +327,24 @@ namespace ILSpy.Debugger.Services
if (!IsDebugging) {
MessageBox.Show(errorNotDebugging, "StepOver");
return;
}
if (debuggedProcess.SelectedStackFrame == null || debuggedProcess.IsRunning) {
// use most recent stack frame because we don't have the symbols
if (debuggedProcess.SelectedThread == null ||
debuggedProcess.SelectedThread.MostRecentStackFrame == null ||
debuggedProcess.IsRunning) {
MessageBox.Show(errorCannotStepNoActiveFunction, "StepOver");
} else {
debuggedProcess.SelectedStackFrame.AsyncStepOver();
var map = GetNextCodeMapping();
if (map == null) {
CurrentLineBookmark.Remove();
Continue();
} else {
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
frame.SourceCodeLine = map.SourceCodeLine;
frame.ILRanges = (new List<int> { map.ILInstructionOffset.From, map.ILInstructionOffset.To }).ToArray();
frame.AsyncStepOver();
}
}
}
@ -306,10 +354,23 @@ namespace ILSpy.Debugger.Services @@ -306,10 +354,23 @@ namespace ILSpy.Debugger.Services
MessageBox.Show(errorNotDebugging, "StepOut");
return;
}
if (debuggedProcess.SelectedStackFrame == null || debuggedProcess.IsRunning) {
// use most recent stack frame because we don't have the symbols
if (debuggedProcess.SelectedThread == null ||
debuggedProcess.SelectedThread.MostRecentStackFrame == null ||
debuggedProcess.IsRunning) {
MessageBox.Show(errorCannotStepNoActiveFunction, "StepOut");
} else {
debuggedProcess.SelectedStackFrame.AsyncStepOut();
var map = GetNextCodeMapping();
if (map == null) {
CurrentLineBookmark.Remove();
Continue();
} else {
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
frame.SourceCodeLine = map.SourceCodeLine;
frame.ILRanges = (new List<int> { map.ILInstructionOffset.From, map.ILInstructionOffset.To }).ToArray();
frame.AsyncStepOut();
}
}
}
@ -335,7 +396,7 @@ namespace ILSpy.Debugger.Services @@ -335,7 +396,7 @@ namespace ILSpy.Debugger.Services
if (!CanEvaluate) {
return null;
}
return ExpressionEvaluator.Evaluate(variableName, SupportedLanguage.CSharp, debuggedProcess.SelectedStackFrame);
return ExpressionEvaluator.Evaluate(variableName, SupportedLanguage.CSharp, debuggedProcess.SelectedThread.MostRecentStackFrame);
}
/// <summary>
@ -381,7 +442,10 @@ namespace ILSpy.Debugger.Services @@ -381,7 +442,10 @@ namespace ILSpy.Debugger.Services
public bool CanEvaluate
{
get {
return debuggedProcess != null && !debuggedProcess.IsRunning && debuggedProcess.SelectedStackFrame != null;
return debuggedProcess != null &&
!debuggedProcess.IsRunning &&
debuggedProcess.SelectedThread != null &&
debuggedProcess.SelectedThread.MostRecentStackFrame != null;
}
}
@ -429,8 +493,9 @@ namespace ILSpy.Debugger.Services @@ -429,8 +493,9 @@ namespace ILSpy.Debugger.Services
public bool CanSetInstructionPointer(string filename, int line, int column)
{
if (debuggedProcess != null && debuggedProcess.IsPaused && debuggedProcess.SelectedStackFrame != null) {
SourcecodeSegment seg = debuggedProcess.SelectedStackFrame.CanSetIP(filename, line, column);
if (debuggedProcess != null && debuggedProcess.IsPaused &&
debuggedProcess.SelectedThread != null && debuggedProcess.SelectedThread.MostRecentStackFrame != null) {
SourcecodeSegment seg = debuggedProcess.SelectedThread.MostRecentStackFrame.CanSetIP(filename, line, column);
return seg != null;
} else {
return false;
@ -440,7 +505,7 @@ namespace ILSpy.Debugger.Services @@ -440,7 +505,7 @@ namespace ILSpy.Debugger.Services
public bool SetInstructionPointer(string filename, int line, int column)
{
if (CanSetInstructionPointer(filename, line, column)) {
SourcecodeSegment seg = debuggedProcess.SelectedStackFrame.SetIP(filename, line, column);
SourcecodeSegment seg = debuggedProcess.SelectedThread.MostRecentStackFrame.SetIP(filename, line, column);
return seg != null;
} else {
return false;
@ -498,12 +563,10 @@ namespace ILSpy.Debugger.Services @@ -498,12 +563,10 @@ namespace ILSpy.Debugger.Services
{
Breakpoint breakpoint = null;
var storage = CodeMappings.GetStorage(Language);
if (Language == bookmark.Language) {
uint token;
SourceCodeMapping map =
storage.GetInstructionByTypeAndLine(
CodeMappingsStorage.GetInstructionByTypeAndLine(
bookmark.TypeName, bookmark.LineNumber, out token);
if (map != null) {
@ -613,7 +676,7 @@ namespace ILSpy.Debugger.Services @@ -613,7 +676,7 @@ namespace ILSpy.Debugger.Services
{
try {
SupportedLanguage supportedLanguage = (SupportedLanguage)Enum.Parse(typeof(SupportedLanguage), language, true);
Value val = ExpressionEvaluator.Evaluate(code, supportedLanguage, debuggedProcess.SelectedStackFrame);
Value val = ExpressionEvaluator.Evaluate(code, supportedLanguage, debuggedProcess.SelectedThread.MostRecentStackFrame);
if (val != null && val.Type.IsPrimitive && val.PrimitiveValue is bool)
return (bool)val.PrimitiveValue;
@ -746,14 +809,19 @@ namespace ILSpy.Debugger.Services @@ -746,14 +809,19 @@ namespace ILSpy.Debugger.Services
{
DebuggerService.RemoveCurrentLineMarker();
if (debuggedProcess != null && debuggedProcess.SelectedStackFrame != null) {
var storage = CodeMappings.GetStorage(Language);
if (debuggedProcess != null && debuggedProcess.SelectedThread != null) {
// use most recent stack frame because we don't have the symbols
var frame = debuggedProcess.SelectedThread.MostRecentStackFrame;
if (frame == null)
return;
uint token = (uint)debuggedProcess.SelectedStackFrame.MethodInfo.MetadataToken;
int ilOffset = debuggedProcess.SelectedStackFrame.IP;
uint token = (uint)frame.MethodInfo.MetadataToken;
int ilOffset = frame.IP;
int line;
string typeName;
storage.GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out typeName, out line);
CodeMappingsStorage.GetSourceCodeFromMetadataTokenAndOffset(token, ilOffset, out typeName, out line);
if (typeName != null)
DebuggerService.JumpToCurrentLine(typeName, line, 0, line, 0);
}

9
Debugger/ILSpy.Debugger/ToolTips/DebuggerTooltipControl.xaml.cs

@ -227,17 +227,26 @@ namespace ILSpy.Debugger.Tooltips @@ -227,17 +227,26 @@ namespace ILSpy.Debugger.Tooltips
private void handleScroll(object sender, ScrollChangedEventArgs e)
{
if (this.lazyGrid == null)
return;
btnUp.IsEnabled = !this.lazyGrid.IsScrolledToStart;
btnDown.IsEnabled = !this.lazyGrid.IsScrolledToEnd;
}
void BtnUp_Click(object sender, RoutedEventArgs e)
{
if (this.lazyGrid == null)
return;
this.lazyGrid.ScrollViewer.ScrollUp(1);
}
void BtnDown_Click(object sender, RoutedEventArgs e)
{
if (this.lazyGrid == null)
return;
this.lazyGrid.ScrollViewer.ScrollDown(1);
}

3
Debugger/ILSpy.Debugger/ToolTips/TextEditorListener.cs

@ -76,6 +76,9 @@ namespace ILSpy.Debugger.ToolTips @@ -76,6 +76,9 @@ namespace ILSpy.Debugger.ToolTips
toolTip.IsOpen = false;
TryCloseExistingPopup(true);
if (popup != null)
popup.IsOpen = false;
}
void OnMouseHoverStopped(MouseEventArgs e)

16
ILSpy/MainWindow.xaml.cs

@ -298,10 +298,6 @@ namespace ICSharpCode.ILSpy @@ -298,10 +298,6 @@ namespace ICSharpCode.ILSpy
}
}
#endregion
#region Debugger commands
void RefreshCommandExecuted(object sender, ExecutedRoutedEventArgs e)
{
if (!DebuggerService.CurrentDebugger.IsDebugging) {
@ -312,6 +308,10 @@ namespace ICSharpCode.ILSpy @@ -312,6 +308,10 @@ namespace ICSharpCode.ILSpy
}
}
#endregion
#region Debugger commands
void AttachToProcessExecuted(object sender, ExecutedRoutedEventArgs e)
{
if (!DebuggerService.CurrentDebugger.IsDebugging) {
@ -335,7 +335,7 @@ namespace ICSharpCode.ILSpy @@ -335,7 +335,7 @@ namespace ICSharpCode.ILSpy
void DetachFromProcessExecuted(object sender, ExecutedRoutedEventArgs e)
{
if (DebuggerService.CurrentDebugger.IsDebugging){
if (DebuggerService.CurrentDebugger.IsDebugging && !DebuggerService.CurrentDebugger.IsProcessRunning){
DebuggerService.CurrentDebugger.Detach();
EnableDebuggerUI(true);
@ -351,19 +351,19 @@ namespace ICSharpCode.ILSpy @@ -351,19 +351,19 @@ namespace ICSharpCode.ILSpy
void StepIntoExecuted(object sender, ExecutedRoutedEventArgs e)
{
if (DebuggerService.CurrentDebugger.IsDebugging)
if (DebuggerService.CurrentDebugger.IsDebugging && !DebuggerService.CurrentDebugger.IsProcessRunning)
DebuggerService.CurrentDebugger.StepInto();
}
void StepOverExecuted(object sender, ExecutedRoutedEventArgs e)
{
if (DebuggerService.CurrentDebugger.IsDebugging)
if (DebuggerService.CurrentDebugger.IsDebugging && !DebuggerService.CurrentDebugger.IsProcessRunning)
DebuggerService.CurrentDebugger.StepOver();
}
void StepOutExecuted(object sender, ExecutedRoutedEventArgs e)
{
if (DebuggerService.CurrentDebugger.IsDebugging)
if (DebuggerService.CurrentDebugger.IsDebugging && !DebuggerService.CurrentDebugger.IsProcessRunning)
DebuggerService.CurrentDebugger.StepOut();
}

Loading…
Cancel
Save