Browse Source

Added windows for breakpoints and callstack

+ fix crash when no MemberReference is found for code mapping
pull/263/head
Ronny Klier 14 years ago
parent
commit
8a5b5547d4
  1. 12
      Debugger/ILSpy.Debugger/Commands/BreakpointCommand.cs
  2. 10
      Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj
  3. 73
      Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml
  4. 99
      Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml.cs
  5. 35
      Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml
  6. 215
      Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml.cs
  7. 55
      ILSpy.SharpDevelop.LGPL/AvalonEdit/IconBarMargin.cs

12
Debugger/ILSpy.Debugger/Commands/BreakpointCommand.cs

@ -9,6 +9,7 @@ using ICSharpCode.ILSpy.AvalonEdit; @@ -9,6 +9,7 @@ using ICSharpCode.ILSpy.AvalonEdit;
using ICSharpCode.ILSpy.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Bookmarks;
using ICSharpCode.ILSpy.Debugger.Services;
using Mono.Cecil;
namespace ICSharpCode.ILSpy.Debugger.Commands
{
@ -27,16 +28,21 @@ namespace ICSharpCode.ILSpy.Debugger.Commands @@ -27,16 +28,21 @@ namespace ICSharpCode.ILSpy.Debugger.Commands
// check if the codemappings exists for this line
var storage = DebugInformation.CodeMappings;
int token = 0;
foreach (var key in storage.Keys) {
var instruction = storage[key].GetInstructionByLineNumber(line, out token);
foreach (var storageEntry in storage) {
var instruction = storageEntry.Value.GetInstructionByLineNumber(line, out token);
if (instruction == null) {
continue;
}
// no bookmark on the line: create a new breakpoint
MemberReference memberReference;
if (!DebugInformation.DecompiledMemberReferences.TryGetValue(storageEntry.Key, out memberReference)) {
continue;
}
DebuggerService.ToggleBreakpointAt(
DebugInformation.DecompiledMemberReferences[key],
memberReference,
line,
instruction.ILInstructionOffset,
DebugInformation.Language);

10
Debugger/ILSpy.Debugger/ILSpy.Debugger.csproj

@ -109,6 +109,14 @@ @@ -109,6 +109,14 @@
<DependentUpon>AttachToProcessWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="UI\BreakpointPanel.xaml.cs" >
<DependentUpon>BreakpointPanel.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="UI\CallStackPanel.xaml.cs" >
<DependentUpon>CallStackPanel.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="UI\DebuggerSettingsPanel.xaml.cs">
<DependentUpon>DebuggerSettingsPanel.xaml</DependentUpon>
<SubType>Code</SubType>
@ -130,6 +138,8 @@ @@ -130,6 +138,8 @@
<Page Include="ToolTips\PinControlsDictionary.xaml" />
<Page Include="ToolTips\VisualizerPicker.xaml" />
<Page Include="UI\AttachToProcessWindow.xaml" />
<Page Include="UI\BreakpointPanel.xaml" />
<Page Include="UI\CallStackPanel.xaml" />
<Page Include="UI\DebuggerSettingsPanel.xaml" />
<Page Include="UI\ExecuteProcessWindow.xaml" />
</ItemGroup>

73
Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml

@ -0,0 +1,73 @@ @@ -0,0 +1,73 @@
<?xml version="1.0" encoding="utf-8"?>
<UserControl
x:Class="ILSpyPlugin.BreakpointPanel" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:bm="clr-namespace:ICSharpCode.ILSpy.Bookmarks">
<Grid>
<ListView
Name="view"
HorizontalContentAlignment="Stretch"
SelectionMode="Single"
MouseDoubleClick="view_MouseDoubleClick"
KeyUp="view_KeyUp">
<ListView.View>
<GridView
AllowsColumnReorder="False">
<GridViewColumn
Header="">
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel
Orientation="Horizontal">
<Image
Width="16"
Height="16"
Margin="1,1,1,1"
Source="{Binding Image}"
HorizontalAlignment="Left" />
<CheckBox
Width="16"
Height="16"
Margin="3,3,3,1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsEnabled="{Binding CanToggle}"
IsChecked="{Binding IsEnabled}" />
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Header="Class">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Text="{Binding MemberReference.DeclaringType.Name}"
Margin="1,1,1,1" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Header="Method">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Text="{Binding MemberReference.Name}"
Margin="1,1,1,1" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Header="Line">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Text="{Binding LineNumber}"
Margin="1,1,1,1"
HorizontalAlignment="Center" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
</UserControl>

99
Debugger/ILSpy.Debugger/UI/BreakpointPanel.xaml.cs

@ -0,0 +1,99 @@ @@ -0,0 +1,99 @@
// 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.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using ICSharpCode.ILSpy;
using ICSharpCode.ILSpy.Bookmarks;
namespace ILSpyPlugin
{
/// <summary>
/// Interaction logic for BreakpointPanel.xaml
/// </summary>
public partial class BreakpointPanel : UserControl, IPane
{
static BreakpointPanel s_instance;
public static BreakpointPanel Instance
{
get {
if (null == s_instance)
{
App.Current.VerifyAccess();
s_instance = new BreakpointPanel();
}
return s_instance;
}
}
private BreakpointPanel()
{
InitializeComponent();
view.ItemsSource = BookmarkManager.Bookmarks;
BookmarkManager.Added += new BookmarkEventHandler(OnAdded);
BookmarkManager.Removed += new BookmarkEventHandler(OnRemoved);
}
public void Show()
{
if (!IsVisible)
MainWindow.Instance.ShowInBottomPane("Breakpoints", this);
}
private void OnAdded(object sender, BookmarkEventArgs e)
{
view.ItemsSource = null;
view.ItemsSource = BookmarkManager.Bookmarks;
}
private void OnRemoved(object sender, BookmarkEventArgs e)
{
view.ItemsSource = null;
view.ItemsSource = BookmarkManager.Bookmarks;
}
public void Closed()
{
}
void view_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (MouseButton.Left != e.ChangedButton)
return;
var selectedItem = view.SelectedItem as BookmarkBase;
if (null == selectedItem)
return;
// TODO: Line should be part of jump target
MainWindow.Instance.JumpToReference(selectedItem.MemberReference);
MainWindow.Instance.TextView.UnfoldAndScroll(selectedItem.LineNumber);
e.Handled = true;
}
void view_KeyUp(object sender, KeyEventArgs e)
{
if (e.Key != Key.Delete)
return;
var selectedItem = view.SelectedItem as BookmarkBase;
if (null == selectedItem)
return;
BookmarkManager.RemoveMark(selectedItem);
e.Handled = true;
}
}
[ExportMainMenuCommand(Menu="_Debugger", Header="Show _Breakpoints", MenuCategory="Others", MenuOrder=8)]
public class BookmarkManagerPanelCommand : SimpleCommand
{
public override void Execute(object parameter)
{
BreakpointPanel.Instance.Show();
}
}
}

35
Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml

@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<UserControl
x:Class="ILSpyPlugin.CallStackPanel" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
>
<Grid>
<ListView
Name="view"
MouseDoubleClick="view_MouseDoubleClick">
<ListView.View>
<GridView>
<GridViewColumn
Header="Module">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Text="{Binding ModuleName}"
Foreground="{Binding FontColor}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
<GridViewColumn
Header="Name">
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock
Text="{Binding Name}"
Foreground="{Binding FontColor}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
</Grid>
</UserControl>

215
Debugger/ILSpy.Debugger/UI/CallStackPanel.xaml.cs

@ -0,0 +1,215 @@ @@ -0,0 +1,215 @@
// 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.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using Debugger;
using ICSharpCode.ILSpy;
using ICSharpCode.ILSpy.Debugger.Models.TreeModel;
using ICSharpCode.ILSpy.Debugger.Services;
using ICSharpCode.ILSpy.XmlDoc;
using Mono.Cecil;
namespace ILSpyPlugin
{
/// <summary>
/// Interaction logic for CallStackPanel.xaml
/// </summary>
public partial class CallStackPanel : UserControl
{
static CallStackPanel s_instance;
IDebugger m_currentDebugger;
Process debuggedProcess;
public static CallStackPanel Instance
{
get {
if (null == s_instance)
{
App.Current.VerifyAccess();
s_instance = new CallStackPanel();
}
return s_instance;
}
}
private CallStackPanel()
{
InitializeComponent();
DebuggerService.DebugStarted += new EventHandler(OnDebugStarted);
DebuggerService.DebugStopped += new EventHandler(OnDebugStopped);
if (DebuggerService.IsDebuggerStarted)
OnDebugStarted(null, EventArgs.Empty);
}
public void Show()
{
if (!IsVisible)
MainWindow.Instance.ShowInBottomPane("Callstack", this);
}
void OnDebugStarted(object sender, EventArgs args)
{
m_currentDebugger = DebuggerService.CurrentDebugger;
m_currentDebugger.IsProcessRunningChanged += new EventHandler(OnProcessRunningChanged);
debuggedProcess = ((WindowsDebugger)m_currentDebugger).DebuggedProcess;
OnProcessRunningChanged(null, EventArgs.Empty);
}
void OnDebugStopped(object sender, EventArgs args)
{
m_currentDebugger.IsProcessRunningChanged -= new EventHandler(OnProcessRunningChanged);
m_currentDebugger = null;
debuggedProcess = null;
}
void OnProcessRunningChanged(object sender, EventArgs args)
{
if (m_currentDebugger.IsProcessRunning)
return;
RefreshPad();
}
void RefreshPad()
{
if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedThread == null) {
view.ItemsSource = null;
return;
}
List<CallStackItem> items = null;
StackFrame activeFrame = null;
try {
Utils.DoEvents(debuggedProcess);
items = CreateItems().ToList();
activeFrame = debuggedProcess.SelectedThread.SelectedStackFrame;
} catch(AbortedBecauseDebuggeeResumedException) {
} catch(System.Exception) {
if (debuggedProcess == null || debuggedProcess.HasExited) {
// Process unexpectedly exited
} else {
throw;
}
}
view.ItemsSource = items;
view.SelectedItem = items != null ? items.FirstOrDefault(item => object.Equals(activeFrame, item.Frame)) : null;
}
IEnumerable<CallStackItem> CreateItems()
{
foreach (StackFrame frame in debuggedProcess.SelectedThread.GetCallstack(100)) {
CallStackItem item;
// show modules names
string moduleName = frame.MethodInfo.DebugModule.ToString();
item = new CallStackItem() {
Name = GetFullName(frame), ModuleName = moduleName
};
item.Frame = frame;
yield return item;
Utils.DoEvents(debuggedProcess);
}
}
internal static string GetFullName(StackFrame frame)
{
// disabled by default, my be switched if options / context menu is added
bool showArgumentNames = false;
bool showArgumentValues = false;
StringBuilder name = new StringBuilder();
name.Append(frame.MethodInfo.DeclaringType.FullName);
name.Append('.');
name.Append(frame.MethodInfo.Name);
if (showArgumentNames || showArgumentValues) {
name.Append("(");
for (int i = 0; i < frame.ArgumentCount; i++) {
string parameterName = null;
string argValue = null;
if (showArgumentNames) {
try {
parameterName = frame.MethodInfo.GetParameters()[i].Name;
} catch { }
if (parameterName == "") parameterName = null;
}
if (showArgumentValues) {
try {
argValue = frame.GetArgumentValue(i).AsString(100);
} catch { }
}
if (parameterName != null && argValue != null) {
name.Append(parameterName);
name.Append("=");
name.Append(argValue);
}
if (parameterName != null && argValue == null) {
name.Append(parameterName);
}
if (parameterName == null && argValue != null) {
name.Append(argValue);
}
if (parameterName == null && argValue == null) {
name.Append("Global.NA");
}
if (i < frame.ArgumentCount - 1) {
name.Append(", ");
}
}
name.Append(")");
}
return name.ToString();
}
void view_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
if (MouseButton.Left != e.ChangedButton)
return;
var selectedItem = view.SelectedItem as CallStackItem;
if (null == selectedItem)
return;
var foundAssembly = MainWindow.Instance.CurrentAssemblyList.OpenAssembly(selectedItem.Frame.MethodInfo.DebugModule.FullPath);
if (null == foundAssembly || null == foundAssembly.AssemblyDefinition)
return;
MemberReference mr = XmlDocKeyProvider.FindMemberByKey(foundAssembly.AssemblyDefinition.MainModule, "M:" + selectedItem.Name);
if (mr == null)
return;
MainWindow.Instance.JumpToReference(mr);
e.Handled = true;
}
}
public class CallStackItem
{
public string Name { get; set; }
public string Language { get; set; }
public StackFrame Frame { get; set; }
public string Line { get; set; }
public string ModuleName { get; set; }
public Brush FontColor {
get { return Brushes.Black; }
}
}
[ExportMainMenuCommand(Menu="_Debugger", Header="Show _Callstack", MenuCategory="Others", MenuOrder=9)]
public class CallstackPanelcommand : SimpleCommand
{
public override void Execute(object parameter)
{
CallStackPanel.Instance.Show();
}
}
}

55
ILSpy.SharpDevelop.LGPL/AvalonEdit/IconBarMargin.cs

@ -26,8 +26,8 @@ namespace ICSharpCode.ILSpy.AvalonEdit @@ -26,8 +26,8 @@ namespace ICSharpCode.ILSpy.AvalonEdit
public IconBarMargin(IconBarManager manager)
{
BookmarkManager.Added += delegate { InvalidateVisual(); };
BookmarkManager.Removed += delegate { InvalidateVisual(); };
BookmarkManager.Added += new BookmarkEventHandler(OnBookmarkAdded);
BookmarkManager.Removed += new BookmarkEventHandler(OnBookmarkRemoved);
this.manager = manager;
}
@ -242,6 +242,39 @@ namespace ICSharpCode.ILSpy.AvalonEdit @@ -242,6 +242,39 @@ namespace ICSharpCode.ILSpy.AvalonEdit
}
}
public void OnBookmarkAdded(object sender, BookmarkEventArgs args)
{
var breakpoint = args.Bookmark as BreakpointBookmark;
if (null == breakpoint)
return;
var storage = DebugInformation.CodeMappings;
if (storage == null || storage.Count == 0)
return;
var key = breakpoint.MemberReference.MetadataToken.ToInt32();
if (storage.ContainsKey(key))
{
// register to show enabled/disabled state
breakpoint.ImageChanged += delegate { InvalidateVisual(); };
InvalidateVisual();
}
}
public void OnBookmarkRemoved(object sender, BookmarkEventArgs args)
{
var breakpoint = args.Bookmark as BreakpointBookmark;
if (null == breakpoint)
return;
var storage = DebugInformation.CodeMappings;
if (storage == null || storage.Count == 0)
return;
var key = breakpoint.MemberReference.MetadataToken.ToInt32();
if (storage.ContainsKey(key))
{
breakpoint.ImageChanged -= delegate { InvalidateVisual(); };
InvalidateVisual();
}
}
public void SyncBookmarks()
{
var storage = DebugInformation.CodeMappings;
@ -249,7 +282,6 @@ namespace ICSharpCode.ILSpy.AvalonEdit @@ -249,7 +282,6 @@ namespace ICSharpCode.ILSpy.AvalonEdit
return;
//remove existing bookmarks and create new ones
List<BreakpointBookmark> newBookmarks = new List<BreakpointBookmark>();
for (int i = BookmarkManager.Bookmarks.Count - 1; i >= 0; --i) {
var breakpoint = BookmarkManager.Bookmarks[i] as BreakpointBookmark;
if (breakpoint == null)
@ -257,7 +289,12 @@ namespace ICSharpCode.ILSpy.AvalonEdit @@ -257,7 +289,12 @@ namespace ICSharpCode.ILSpy.AvalonEdit
var key = breakpoint.MemberReference.MetadataToken.ToInt32();
if (!storage.ContainsKey(key))
continue;
{
// in case this was visible before
breakpoint.ImageChanged -= delegate { InvalidateVisual(); };
continue;
}
breakpoint.ImageChanged += delegate { InvalidateVisual(); };
var member = DebugInformation.DecompiledMemberReferences[key];
@ -271,17 +308,11 @@ namespace ICSharpCode.ILSpy.AvalonEdit @@ -271,17 +308,11 @@ namespace ICSharpCode.ILSpy.AvalonEdit
breakpoint.Location = new AstLocation(map.SourceCodeLine, 0);
breakpoint.ILRange = map.ILInstructionOffset;
// Why were the breakpoints removed and recreated
// newBookmarks.Add(new BreakpointBookmark(
// member, new AstLocation(map.SourceCodeLine, 0),
// map.ILInstructionOffset, BreakpointAction.Break, DebugInformation.Language));
//
// BookmarkManager.RemoveMark(breakpoint);
// Why were the breakpoints removed and recreated?
// This prevents enable/disable of breakpoints
}
}
newBookmarks.ForEach(m => BookmarkManager.AddMark(m));
SyncCurrentLineBookmark();
}

Loading…
Cancel
Save