diff --git a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj index 171d37fd80..dd26d194bf 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj +++ b/src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj @@ -266,7 +266,6 @@ Properties\GlobalAssemblyInfo.cs - diff --git a/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs index 84f5ba51fb..36b2067c4b 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs @@ -355,17 +355,6 @@ namespace ICSharpCode.NRefactory.Visitors { string identifier = identifierExpression.Identifier; - if (identifier == "__exception") { - if (context.Thread.CurrentException != null) { - return new TypedValue( - context.Thread.CurrentException.Value, - DebugType.CreateFromType(context.AppDomain.Mscorlib, typeof(System.Exception)) - ); - } else { - throw new GetValueException("No current exception"); - } - } - DebugParameterInfo par = context.MethodInfo.GetParameter(identifier); if (par != null) return new TypedValue(par.GetValue(context), (DebugType)par.ParameterType); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs b/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs index d8de070030..2525612d69 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs @@ -4,7 +4,7 @@ using System; using System.Drawing; using System.Windows.Forms; - +using System.Xml.Serialization; using Debugger; using ICSharpCode.Core; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs index 0edd6f1f3d..ffd372f674 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs @@ -21,8 +21,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads /// public partial class CallStackPadContent : UserControl { - Process debuggedProcess; - public CallStackPadContent() { InitializeComponent(); @@ -31,6 +29,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads ((GridView)view.View).Columns[0].Width = DebuggingOptions.Instance.ShowModuleNames ? 100d : 0d; ((GridView)view.View).Columns[2].Width = DebuggingOptions.Instance.ShowLineNumbers ? 50d : 0d; + + WindowsDebugger.RefreshingPads += RefreshPad; + WindowsDebugger.RefreshPads(); } ContextMenu CreateMenu() @@ -40,7 +41,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods; extMethodsItem.Click += delegate { extMethodsItem.IsChecked = DebuggingOptions.Instance.ShowExternalMethods = !DebuggingOptions.Instance.ShowExternalMethods; - CallStackPad.InvalidateCallstackPad(); + WindowsDebugger.RefreshPads(); }; MenuItem moduleItem = new MenuItem(); @@ -49,7 +50,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads moduleItem.Click += delegate { moduleItem.IsChecked = DebuggingOptions.Instance.ShowModuleNames = !DebuggingOptions.Instance.ShowModuleNames; ((GridView)view.View).Columns[0].Width = DebuggingOptions.Instance.ShowModuleNames ? 100d : 0d; - CallStackPad.InvalidateCallstackPad(); + WindowsDebugger.RefreshPads(); }; MenuItem argNamesItem = new MenuItem(); @@ -57,7 +58,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames; argNamesItem.Click += delegate { argNamesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentNames = !DebuggingOptions.Instance.ShowArgumentNames; - CallStackPad.InvalidateCallstackPad(); + WindowsDebugger.RefreshPads(); }; MenuItem argValuesItem = new MenuItem(); @@ -65,7 +66,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues; argValuesItem.Click += delegate { argValuesItem.IsChecked = DebuggingOptions.Instance.ShowArgumentValues = !DebuggingOptions.Instance.ShowArgumentValues; - CallStackPad.InvalidateCallstackPad(); + WindowsDebugger.RefreshPads(); }; MenuItem lineItem = new MenuItem(); @@ -74,7 +75,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads lineItem.Click += delegate { lineItem.IsChecked = DebuggingOptions.Instance.ShowLineNumbers = !DebuggingOptions.Instance.ShowLineNumbers; ((GridView)view.View).Columns[2].Width = DebuggingOptions.Instance.ShowLineNumbers ? 50d : 0d; - CallStackPad.InvalidateCallstackPad(); + WindowsDebugger.RefreshPads(); }; return new ContextMenu() { @@ -89,33 +90,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads }; } - public void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= debuggedProcess_Paused; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += debuggedProcess_Paused; - } - CallStackPad.InvalidateCallstackPad(); - } - - void debuggedProcess_Paused(object sender, ProcessEventArgs e) - { - CallStackPad.InvalidateCallstackPad(); - } - void View_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { - if (debuggedProcess == null) + CallStackItem item = view.SelectedItem as CallStackItem; + if (item == null) return; + + Process debuggedProcess = item.Process; + if (debuggedProcess.IsPaused) { - CallStackItem item = view.SelectedItem as CallStackItem; - - if (item == null) - return; - if (item.Frame != null && debuggedProcess.SelectedThread != null) { // check for options - if these options are enabled, selecting the frame should not continue if (!item.Frame.HasSymbols && !debuggedProcess.Options.DecompileCodeWithoutSymbols) { @@ -125,7 +108,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } debuggedProcess.SelectedThread.SelectedStackFrame = item.Frame; debuggedProcess.PauseSession.PausedReason = PausedReason.CurrentFunctionChanged; - debuggedProcess.OnPaused(); // Force refresh of pads - artificial pause + WindowsDebugger.RefreshPads(); } } else { MessageService.ShowMessage("${res:MainWindow.Windows.Debug.CallStack.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.CallStack.FunctionSwitch}"); @@ -140,8 +123,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } } - internal void RefreshPad() + void RefreshPad(object sender, DebuggerEventArgs dbg) { + Process debuggedProcess = dbg.Process; + if (debuggedProcess == null || debuggedProcess.IsRunning || debuggedProcess.SelectedThread == null) { view.ItemsSource = null; return; @@ -155,13 +140,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads debuggedProcess.EnqueueForEach( Dispatcher, debuggedProcess.SelectedThread.GetCallstack(100), - f => items.AddIfNotNull(CreateItem(f, showExternalMethods, ref previousItemIsExternalMethod)) + f => items.AddIfNotNull(CreateItem(debuggedProcess, f, showExternalMethods, ref previousItemIsExternalMethod)) ); } view.ItemsSource = items; } - CallStackItem CreateItem(StackFrame frame, bool showExternalMethods, ref bool previousItemIsExternalMethod) + CallStackItem CreateItem(Process process, StackFrame frame, bool showExternalMethods, ref bool previousItemIsExternalMethod) { CallStackItem item; @@ -196,6 +181,8 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads previousItemIsExternalMethod = true; } + item.Process = process; + return item; } @@ -253,6 +240,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads public class CallStackItem { + public Process Process { get; set; } public string Name { get; set; } public string Language { get; set; } public StackFrame Frame { get; set; } @@ -264,7 +252,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } } - public class CallStackPad : DebuggerPad + public class CallStackPad : AbstractPadContent { CallStackPadContent callStackList; @@ -277,6 +265,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads public CallStackPad() { instance = this; + callStackList = new CallStackPadContent(); } public override object Control { @@ -284,26 +273,5 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads return callStackList; } } - - protected override void InitializeComponents() - { - callStackList = new CallStackPadContent(); - } - - protected override void SelectProcess(Process process) - { - callStackList.SelectProcess(process); - } - - protected override void RefreshPad() - { - callStackList.RefreshPad(); - } - - public static void InvalidateCallstackPad() - { - if (instance != null) - instance.InvalidatePad(); - } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs index ccc20a9464..dbbf5bbab1 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs @@ -10,6 +10,7 @@ using ICSharpCode.Core; using ICSharpCode.Core.WinForms; using ICSharpCode.SharpDevelop.Gui.Pads; using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Services; namespace Debugger.AddIn { @@ -42,7 +43,7 @@ namespace Debugger.AddIn list.WatchItems.Add(text); } - pad.InvalidatePad(); + WindowsDebugger.RefreshPads(); } } } @@ -60,7 +61,8 @@ namespace Debugger.AddIn return; list.WatchItems.Remove(node); - ((WatchPad)this.Owner).InvalidatePad(); + + WindowsDebugger.RefreshPads(); } } } @@ -69,9 +71,7 @@ namespace Debugger.AddIn { public override void Run() { - if (this.Owner is WatchPad) { - ((WatchPad)this.Owner).InvalidatePad(); - } + WindowsDebugger.RefreshPads(); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs index cf257d6b6e..7c4944bdea 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs @@ -45,6 +45,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads string Evaluate(string code) { + Process process = WindowsDebugger.CurrentProcess; if (process == null) { return "No process is being debugged"; } @@ -52,11 +53,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads return "The process is running"; } try { - var debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; - StackFrame frame = debugger.DebuggedProcess.GetCurrentExecutingFrame(); + StackFrame frame = process.GetCurrentExecutingFrame(); if (frame == null) return "No current execution frame"; - object data = debugger.debuggerDecompilerService.GetLocalVariableIndex(frame.MethodInfo.DeclaringType.MetadataToken, + object data = ((WindowsDebugger)DebuggerService.CurrentDebugger).debuggerDecompilerService.GetLocalVariableIndex(frame.MethodInfo.DeclaringType.MetadataToken, frame.MethodInfo.MetadataToken, code); Value val = ExpressionEvaluator.Evaluate(code, SelectedLanguage, frame, data); @@ -66,13 +66,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } } - Process process; - - public Process Process { - get { return process; } - set { process = value; } - } - protected override string Prompt { get { return "> "; @@ -102,32 +95,28 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads public ConsolePad() { WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; - - debugger.ProcessSelected += delegate(object sender, ProcessEventArgs e) { - this.Process = e.Process; - }; - this.Process = debugger.DebuggedProcess; } protected override void AbstractConsolePadTextEntered(object sender, TextCompositionEventArgs e) { - if (this.process == null || this.process.IsRunning) + Process process = WindowsDebugger.CurrentProcess; + if (process == null || process.IsRunning) return; - StackFrame frame = this.process.GetCurrentExecutingFrame(); + StackFrame frame = process.GetCurrentExecutingFrame(); if (frame == null) return; foreach (char ch in e.Text) { if (ch == '.') { - ShowDotCompletion(console.CommandText); + ShowDotCompletion(process, console.CommandText); } } } - void ShowDotCompletion(string currentText) + void ShowDotCompletion(Process process, string currentText) { - StackFrame frame = this.process.GetCurrentExecutingFrame(); + StackFrame frame = process.GetCurrentExecutingFrame(); if (frame == null) return; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs index 3b624fe16b..8e136d5aaf 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs @@ -75,7 +75,7 @@ namespace Debugger.AddIn.Pads.Controls if (!WatchPad.Instance.WatchList.WatchItems.Any(n => text.Name == ((TreeNodeWrapper)n).Node.Name)) WatchPad.Instance.WatchList.WatchItems.Add(node); - WatchPad.Instance.InvalidatePad(); + WindowsDebugger.RefreshPads(); } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs index f382c435f9..ca00a62a5a 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs @@ -13,6 +13,7 @@ using Debugger.AddIn.TreeModel; using ICSharpCode.Core.Presentation; using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui.Pads; +using ICSharpCode.SharpDevelop.Services; using ICSharpCode.TreeView; namespace Debugger.AddIn.Pads.Controls @@ -60,10 +61,7 @@ namespace Debugger.AddIn.Pads.Controls } if (e.Key == Key.Enter || e.Key == Key.Escape) { myList.UnselectAll(); - if (LocalVarPad.Instance != null) - LocalVarPad.Instance.InvalidatePad(); - if (WatchPad.Instance != null) - WatchPad.Instance.InvalidatePad(); + WindowsDebugger.RefreshPads(); } } @@ -77,7 +75,7 @@ namespace Debugger.AddIn.Pads.Controls SelectedNode.Node.Name = cell.CommandText; myList.UnselectAll(); if (WatchType == WatchListType.Watch && WatchPad.Instance != null) { - WatchPad.Instance.InvalidatePad(); + WindowsDebugger.RefreshPads(); } SelectedNode.IsEditing = false; } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs index 60e8147132..2a17b59d8c 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs @@ -65,15 +65,8 @@ namespace Debugger.AddIn.Pads.Controls // get process WindowsDebugger debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; - - debugger.ProcessSelected += delegate(object sender, ProcessEventArgs e) { - this.Process = e.Process; - }; - this.Process = debugger.DebuggedProcess; } - private Process Process { get; set; } - /// /// Gets/sets the command text displayed at the command prompt. /// @@ -150,7 +143,7 @@ namespace Debugger.AddIn.Pads.Controls private void ShowDotCompletion(string currentText) { - var seg = Process.SelectedStackFrame.NextStatement; + var seg = WindowsDebugger.CurrentProcess.SelectedStackFrame.NextStatement; var expressionFinder = ParserService.GetExpressionFinder(seg.Filename); var info = ParserService.GetParseInformation(seg.Filename); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs deleted file mode 100644 index 9e712e5176..0000000000 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs +++ /dev/null @@ -1,85 +0,0 @@ -// 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 System.Windows.Controls; -using Debugger; -using ICSharpCode.SharpDevelop.Debugging; -using ICSharpCode.SharpDevelop.Services; - -namespace ICSharpCode.SharpDevelop.Gui.Pads -{ - public abstract class DebuggerPad : AbstractPadContent - { - protected DockPanel panel; - ToolBar toolbar; - protected WindowsDebugger debugger; - - public override object Control { - get { - return panel; - } - } - - public DebuggerPad() - { - // UI - this.panel = new DockPanel(); - this.toolbar = BuildToolBar(); - - if (this.toolbar != null) { - this.toolbar.SetValue(DockPanel.DockProperty, Dock.Top); - - this.panel.Children.Add(toolbar); - } - - // logic - debugger = (WindowsDebugger)DebuggerService.CurrentDebugger; - - InitializeComponents(); - - debugger.ProcessSelected += delegate(object sender, ProcessEventArgs e) { - SelectProcess(e.Process); - }; - SelectProcess(debugger.DebuggedProcess); - } - - protected virtual void InitializeComponents() - { - - } - - protected virtual void SelectProcess(Process process) - { - - } - - /// - /// Never call this directly. Always use InvalidatePad() - /// - protected virtual void RefreshPad() - { - - } - - bool invalidatePadEnqueued; - - public void InvalidatePad() - { - WorkbenchSingleton.AssertMainThread(); - if (invalidatePadEnqueued || WorkbenchSingleton.Workbench == null) - return; - invalidatePadEnqueued = true; - WorkbenchSingleton.SafeThreadAsyncCall( - delegate { - invalidatePadEnqueued = false; - RefreshPad(); - }); - - } - - protected virtual ToolBar BuildToolBar() - { - return null; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs index b2d39e5b5f..e8436b9173 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs @@ -11,17 +11,23 @@ using Debugger; using Debugger.AddIn.Pads.Controls; using Debugger.AddIn.Pads.ParallelPad; using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Services; namespace ICSharpCode.SharpDevelop.Gui.Pads { - public class LoadedModulesPad : DebuggerPad + public class LoadedModulesPad : AbstractPadContent { + DockPanel panel; ListView loadedModulesList; - Process debuggedProcess; ObservableCollection loadedModules; - protected override void InitializeComponents() + public override object Control { + get { return panel; } + } + + public LoadedModulesPad() { + this.panel = new DockPanel(); loadedModulesList = new ListView(); loadedModules = new ObservableCollection(); loadedModulesList.ItemsSource = loadedModules; @@ -29,6 +35,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads panel.Children.Add(loadedModulesList); RedrawContent(); ResourceService.LanguageChanged += delegate { RedrawContent(); }; + + WindowsDebugger.RefreshingPads += RefreshPad; + WindowsDebugger.RefreshPads(); } public void RedrawContent() @@ -46,49 +55,17 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads new Binding { Path = new PropertyPath("Symbols") }, 130); } - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Modules.Added -= debuggedProcess_ModuleLoaded; - debuggedProcess.Modules.Removed -= debuggedProcess_ModuleUnloaded; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Modules.Added += debuggedProcess_ModuleLoaded; - debuggedProcess.Modules.Removed += debuggedProcess_ModuleUnloaded; - } - InvalidatePad(); - } - - void debuggedProcess_ModuleLoaded(object sender, CollectionItemEventArgs e) - { - AddModule(e.Item); - } - - void debuggedProcess_ModuleUnloaded(object sender, CollectionItemEventArgs e) - { - RemoveModule(e.Item); - } - - protected override void RefreshPad() + void RefreshPad(object sender, DebuggerEventArgs dbg) { + Process debuggedProcess = dbg.Process; + loadedModules.Clear(); if (debuggedProcess != null) { foreach(Module module in debuggedProcess.Modules) { - AddModule(module); + loadedModules.Add(new ModuleModel(module)); } } } - - void AddModule(Module module) - { - loadedModules.Add(new ModuleModel(module)); - } - - void RemoveModule(Module module) - { - loadedModules.RemoveWhere(model => model.Module == module); - } } static class ListViewExtensions diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs index 7d3987e18e..4eb643e42a 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs @@ -3,25 +3,38 @@ using System.Collections.ObjectModel; using System.Linq; +using System.Windows.Controls; using System.Windows.Threading; using Debugger; using Debugger.AddIn.Pads.Controls; using Debugger.AddIn.TreeModel; using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Services; using Exception = System.Exception; using TreeNode = Debugger.AddIn.TreeModel.TreeNode; namespace ICSharpCode.SharpDevelop.Gui.Pads { - public class LocalVarPad : DebuggerPad + public class LocalVarPad : AbstractPadContent { + DockPanel panel; WatchList localVarList; - Process debuggedProcess; static LocalVarPad instance; + public override object Control { + get { return panel; } + } + public LocalVarPad() { + this.panel = new DockPanel(); instance = this; + + localVarList = new WatchList(WatchListType.LocalVar); + panel.Children.Add(localVarList); + + WindowsDebugger.RefreshingPads += RefreshPad; + WindowsDebugger.RefreshPads(); } /// Always check if Instance is null, might be null if pad is not opened! @@ -29,35 +42,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads get { return instance; } } - public Process Process { - get { return debuggedProcess; } - } - - protected override void InitializeComponents() - { - localVarList = new WatchList(WatchListType.LocalVar); - panel.Children.Add(localVarList); - } - - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= debuggedProcess_Paused; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += debuggedProcess_Paused; - } - InvalidatePad(); - } - - void debuggedProcess_Paused(object sender, ProcessEventArgs e) - { - InvalidatePad(); - } - - protected override void RefreshPad() + void RefreshPad(object sender, DebuggerEventArgs dbg) { + Process debuggedProcess = dbg.Process; + if (debuggedProcess == null || debuggedProcess.IsRunning) { localVarList.WatchItems.Clear(); return; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs index afae24227e..7874d6dbd1 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs @@ -7,26 +7,40 @@ using System.Globalization; using System.Text; using System.Text.RegularExpressions; using System.Windows.Controls; - using Debugger; using Debugger.Interop; using ICSharpCode.Core; using ICSharpCode.Core.Presentation; using ICSharpCode.SharpDevelop.Debugging; +using ICSharpCode.SharpDevelop.Services; namespace ICSharpCode.SharpDevelop.Gui.Pads { - public sealed class MemoryPad : DebuggerPad + public sealed class MemoryPad : AbstractPadContent { + DockPanel panel; + ToolBar toolbar; + int currentAddressIndex; ConsoleControl console; int columnsNumber = 16; byte displayByteSize = 1; byte[] memory; - Process debuggedProcess; List> memoryAddresses = new List>(); Dictionary addressesMapping = new Dictionary(); + public override object Control { + get { + return panel; + } + } + + public Process debuggedProcess { + get { + return WindowsDebugger.CurrentProcess; + } + } + /// /// Gets or sets the number of columns in the display /// @@ -61,10 +75,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads public MemoryPad() { + this.panel = new DockPanel(); + this.toolbar = ToolBarService.CreateToolBar(panel, this, "/SharpDevelop/Pads/MemoryPad/ToolBar"); + this.toolbar.SetValue(DockPanel.DockProperty, Dock.Top); + this.panel.Children.Add(toolbar); + this.console = new ConsoleControl(); this.panel.Children.Add(console); this.console.Encoding = Encoding.Default; - RefreshPad(); // exception + Refresh(); this.console.SetReadonly(); DebuggerService.DebugStopped += DebuggerService_DebugStopped; @@ -77,21 +96,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads memory = null; } - protected override ToolBar BuildToolBar() - { - return ToolBarService.CreateToolBar(panel, this, "/SharpDevelop/Pads/MemoryPad/ToolBar"); - } - - protected override void SelectProcess(Process process) - { - if (process == null) - return; - - debuggedProcess = process; - memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses(); - currentAddressIndex = 0; - } - public void JumpToAddress(string address) { try { @@ -135,13 +139,21 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } } - public bool Refresh(bool refreshMemoryAddresses = false) + public bool Refresh(object sender, DebuggerEventArgs dbg) + { + return Refresh(); + } + + public bool Refresh() { + memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses(); + currentAddressIndex = 0; + if (console == null) return false; console.Clear(); - if (debuggedProcess == null || debugger.IsProcessRunning) { + if (debuggedProcess == null || debuggedProcess.IsRunning) { console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NotDebuggingOrProcessRunning")); return false; } @@ -152,9 +164,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads return false; } - if (refreshMemoryAddresses) - memoryAddresses = debuggedProcess.GetVirtualMemoryAddresses(); - if (memoryAddresses.Count == 0) { console.Append(ResourceService.GetString("MainWindow.Windows.Debug.MemoryPad.NoMappings")); return false; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs index 1617201833..c8d7721792 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs @@ -1,6 +1,7 @@ // 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 System.Windows.Controls; using ICSharpCode.Core; using System; using System.Collections.Generic; @@ -8,21 +9,33 @@ using System.Linq; using System.Windows; using Debugger; using Debugger.AddIn.Visualizers.Graph; +using ICSharpCode.SharpDevelop.Services; namespace ICSharpCode.SharpDevelop.Gui.Pads { /// /// Description of ObjectGraphPad. /// - public class ObjectGraphPad : DebuggerPad + public class ObjectGraphPad : AbstractPadContent { - Process debuggedProcess; + DockPanel panel; ObjectGraphControl objectGraphControl; static ObjectGraphPad instance; + public override object Control { + get { return panel; } + } + public ObjectGraphPad() { + this.panel = new DockPanel(); instance = this; + + objectGraphControl = new ObjectGraphControl(); + panel.Children.Add(objectGraphControl); + + WindowsDebugger.RefreshingPads += RefreshPad; + WindowsDebugger.RefreshPads(); } /// Always check if Instance is null, might be null if pad is not opened! @@ -30,15 +43,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads get { return instance; } } - protected override void InitializeComponents() - { - objectGraphControl = new ObjectGraphControl(); - panel.Children.Add(objectGraphControl); - } - - - protected override void RefreshPad() + protected void RefreshPad(object sender, DebuggerEventArgs dbg) { + Process debuggedProcess = dbg.Process; + // BUG: if pad window is undocked and floats standalone, IsVisible == false (so pad won't refresh) // REQUEST: need to refresh when pad becomes visible -> VisibleChanged event? if (!objectGraphControl.IsVisible) @@ -51,22 +59,5 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } this.objectGraphControl.RefreshView(); } - - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= debuggedProcess_Paused; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += debuggedProcess_Paused; - } - InvalidatePad(); - } - - void debuggedProcess_Paused(object sender, ProcessEventArgs e) - { - InvalidatePad(); - } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs index fa8fe1eaab..e7266ebcff 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs @@ -73,7 +73,6 @@ namespace Debugger.AddIn.Pads.ParallelPad if (thread == null) throw new ArgumentNullException("thread"); this.thread = thread; - thread.NameChanged += delegate { RaisePropertyChanged(() => Name); }; } public Thread Thread { @@ -131,13 +130,6 @@ namespace Debugger.AddIn.Pads.ParallelPad if (module == null) throw new ArgumentNullException("module"); this.module = module; - this.module.SymbolsUpdated += delegate { - RaisePropertyChanged(() => Name); - RaisePropertyChanged(() => Address); - RaisePropertyChanged(() => Path); - RaisePropertyChanged(() => Order); - RaisePropertyChanged(() => Symbols); - }; } public Module Module { diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs index 8feecd7c33..036576733d 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs @@ -20,6 +20,7 @@ using ICSharpCode.SharpDevelop.Bookmarks; using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Editor; using ICSharpCode.SharpDevelop.Gui.Pads; +using ICSharpCode.SharpDevelop.Services; namespace ICSharpCode.SharpDevelop.Gui.Pads { @@ -29,43 +30,45 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads Tasks } - public class ParallelStackPad : DebuggerPad + public class ParallelStackPad : AbstractPadContent { + DockPanel panel; + ToolBar toolbar; + DrawSurface surface; - Process debuggedProcess; ParallelStacksGraph graph; List currentThreadStacks = new List(); ParallelStacksView parallelStacksView; StackFrame selectedFrame; bool isMethodView; + public override object Control { + get { return panel; } + } + #region Overrides - protected override void InitializeComponents() + public ParallelStackPad() { + this.panel = new DockPanel(); + this.toolbar = ToolBarService.CreateToolBar(panel, this, "/SharpDevelop/Pads/ParallelStacksPad/ToolBar"); + this.toolbar.SetValue(DockPanel.DockProperty, Dock.Top); + this.panel.Children.Add(toolbar); + surface = new DrawSurface(); panel.Children.Add(surface); - } - - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= OnProcessPaused; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += OnProcessPaused; - } - + + WindowsDebugger.RefreshingPads += RefreshPad; + WindowsDebugger.RefreshPads(); DebuggerService.DebugStarted += OnReset; - DebuggerService.DebugStopped += OnReset; - - InvalidatePad(); + DebuggerService.DebugStopped += OnReset; } - protected override void RefreshPad() + protected void RefreshPad(object sender, DebuggerEventArgs dbg) { + Process debuggedProcess = dbg.Process; + if (debuggedProcess == null || debuggedProcess.IsRunning) { return; } @@ -95,12 +98,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads if (isMethodView) { // build method view for threads - CreateMethodViewStacks(); + CreateMethodViewStacks(debuggedProcess); } else { // normal view - CreateCommonStacks(); + CreateCommonStacks(debuggedProcess); } } @@ -119,11 +122,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads surface.SetGraph(graph); } } - - protected override ToolBar BuildToolBar() - { - return ToolBarService.CreateToolBar(panel, this, "/SharpDevelop/Pads/ParallelStacksPad/ToolBar"); - } #endregion @@ -133,7 +131,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads get { return parallelStacksView; } set { parallelStacksView = value; - InvalidatePad(); + WindowsDebugger.RefreshPads(); } } @@ -141,7 +139,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads get { return isMethodView; } set { isMethodView = value; - InvalidatePad(); + WindowsDebugger.RefreshPads(); } } @@ -163,11 +161,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads BookmarkManager.RemoveAll(b => b is SelectedFrameBookmark); } - void OnProcessPaused(object sender, ProcessEventArgs e) - { - InvalidatePad(); - } - void AddChildren(ThreadStack parent) { if(parent.ThreadStackChildren == null || parent.ThreadStackChildren.Count == 0) @@ -187,7 +180,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } } - void CreateCommonStacks() + void CreateCommonStacks(Process debuggedProcess) { // stack.ItemCollection order // 0 -> top of stack = S.C @@ -369,7 +362,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } } - void CreateMethodViewStacks() + void CreateMethodViewStacks(Process debuggedProcess) { var list = new List, ObservableCollection, List>>(); @@ -439,6 +432,8 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads void CreateThreadStack(Thread thread) { + Process debuggedProcess = thread.Process; + var items = CreateItems(thread); if (items == null || items.Count == 0) return; @@ -465,6 +460,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads int noTasks = 0; var result = new ObservableCollection(); var callstack = thread.GetCallstack(100); + Process debuggedProcess = thread.Process; if (parallelStacksView == ParallelStacksView.Threads) { foreach (StackFrame frame in callstack) { @@ -536,7 +532,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } if (frame.Thread.SelectedStackFrame != null && - frame.Thread.ID == debuggedProcess.SelectedThread.ID && + frame.Thread.ID == WindowsDebugger.CurrentProcess.SelectedThread.ID && frame.Thread.SelectedStackFrame.IP == frame.IP && frame.Thread.SelectedStackFrame.GetMethodName() == frame.GetMethodName()) { model.Image = PresentationResourceService.GetImage("Bookmarks.CurrentLine").Source; @@ -583,7 +579,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads ToggleSelectedFrameBookmark(e.Location); if (isMethodView) - InvalidatePad(); + WindowsDebugger.RefreshPads(); } #endregion diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs index 35d1dd92b8..9fd264d3bb 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs @@ -5,11 +5,11 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Dynamic; +using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; - using ICSharpCode.Core.Presentation; using ICSharpCode.NRefactory; using ICSharpCode.SharpDevelop; @@ -183,7 +183,7 @@ namespace Debugger.AddIn.Pads.ParallelPad if (selectedItem == null) return; - var thread = Process.Threads.Find(t => t.ID == threadId); + var thread = Process.Threads.FirstOrDefault(t => t.ID == threadId); if (thread == null) return; diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs index 5a5f60ab1f..f8e50fb269 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs @@ -9,6 +9,7 @@ using System.Windows.Controls; using Debugger; using Debugger.AddIn.Pads.ParallelPad; using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Services; namespace ICSharpCode.SharpDevelop.Gui.Pads { @@ -48,7 +49,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } bool suspended = item.Thread.Suspended; - if (!debuggedProcess.IsPaused) { + if (WindowsDebugger.CurrentProcess == null || WindowsDebugger.CurrentProcess.IsRunning) { MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotFreezeWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.Freeze}"); return; } @@ -56,7 +57,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads foreach(ThreadModel current in items.OfType()) { current.Thread.Suspended = !suspended; } - InvalidatePad(); + WindowsDebugger.RefreshPads(); }; menu.Items.Add(freezeItem); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs index 2f908ce001..bb779bb64e 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs @@ -20,14 +20,19 @@ using Thread = Debugger.Thread; namespace ICSharpCode.SharpDevelop.Gui.Pads { - public partial class RunningThreadsPad : DebuggerPad + public partial class RunningThreadsPad : AbstractPadContent { + DockPanel panel; ListView runningThreadsList; ObservableCollection runningThreads; - Process debuggedProcess; - protected override void InitializeComponents() + public override object Control { + get { return panel; } + } + + public RunningThreadsPad() { + this.panel = new DockPanel(); runningThreads = new ObservableCollection(); runningThreadsList = new ListView(); runningThreadsList.ContextMenu = CreateContextMenuStrip(); @@ -38,6 +43,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads RedrawContent(); ResourceService.LanguageChanged += delegate { RedrawContent(); }; + + WindowsDebugger.RefreshingPads += RefreshPad; + WindowsDebugger.RefreshPads(); } public void RedrawContent() @@ -60,33 +68,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads 80); } - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= debuggedProcess_Paused; - debuggedProcess.Threads.Added -= debuggedProcess_ThreadStarted; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += debuggedProcess_Paused; - debuggedProcess.Threads.Added += debuggedProcess_ThreadStarted; - } - runningThreads.Clear(); - InvalidatePad(); - } - - void debuggedProcess_Paused(object sender, ProcessEventArgs e) - { - InvalidatePad(); - } - - void debuggedProcess_ThreadStarted(object sender, CollectionItemEventArgs e) - { - AddThread(e.Item); - } - - protected override void RefreshPad() + protected void RefreshPad(object sender, DebuggerEventArgs dbg) { + Process debuggedProcess = dbg.Process; + if (debuggedProcess == null || debuggedProcess.IsRunning) { runningThreads.Clear(); return; @@ -103,10 +88,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads void RunningThreadsListItemActivate(object sender, EventArgs e) { + ThreadModel obj = runningThreadsList.SelectedItems[0] as ThreadModel; + Thread thread = obj.Thread; + Process debuggedProcess = thread.Process; + if (debuggedProcess != null) { if (debuggedProcess.IsPaused) { - ThreadModel obj = runningThreadsList.SelectedItems[0] as ThreadModel; - Thread thread = obj.Thread; // check for options - if these options are enabled, selecting the frame should not continue if ((thread.MostRecentStackFrame == null || !thread.MostRecentStackFrame.HasSymbols) && @@ -120,15 +107,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads debuggedProcess.SelectedThread.SelectedStackFrame = debuggedProcess.SelectedThread.MostRecentStackFrame; if (debuggedProcess.SelectedThread.SelectedStackFrame != null) { debuggedProcess.PauseSession.PausedReason = PausedReason.CurrentThreadChanged; - debuggedProcess.OnPaused(); // Force refresh of pads - artificial pause + WindowsDebugger.RefreshPads(); // Force refresh of pads - artificial pause } else { MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchOnNAFrame}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}"); } - } else { - MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}"); - } + } else { + MessageService.ShowMessage("${res:MainWindow.Windows.Debug.Threads.CannotSwitchWhileRunning}", "${res:MainWindow.Windows.Debug.Threads.ThreadSwitch}"); } } + } void AddThread(Thread thread) { @@ -140,7 +127,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads ThreadModel obj = new ThreadModel(thread); runningThreads.Add(obj); - thread.Exited += (s, e) => RemoveThread(e.Thread); } void RemoveThread(Thread thread) diff --git a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs index 5669593f99..7872ab5c1e 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.Specialized; using System.Linq; using System.Windows; +using System.Windows.Controls; using System.Windows.Data; using System.Windows.Input; using System.Windows.Threading; @@ -20,17 +21,22 @@ using ICSharpCode.NRefactory; using ICSharpCode.NRefactory.Ast; using ICSharpCode.SharpDevelop.Debugging; using ICSharpCode.SharpDevelop.Project; +using ICSharpCode.SharpDevelop.Services; using Exception = System.Exception; namespace ICSharpCode.SharpDevelop.Gui.Pads { - public class WatchPad : DebuggerPad + public class WatchPad : AbstractPadContent { + DockPanel panel; WatchList watchList; - Process debuggedProcess; static WatchPad instance; + public override object Control { + get { return panel; } + } + /// Always check if Instance is null, might be null if pad is not opened! public static WatchPad Instance { get { return instance; } @@ -44,15 +50,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads public WatchPad() { + this.panel = new DockPanel(); + instance = this; - } - - public Process Process { - get { return debuggedProcess; } - } - - protected override void InitializeComponents() - { + watchList = new WatchList(WatchListType.Watch); watchList.ContextMenu = MenuService.CreateContextMenu(this, "/SharpDevelop/Pads/WatchPad/ContextMenu"); @@ -68,6 +69,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads ProjectService.SolutionClosed += delegate { watchList.WatchItems.Clear(); }; ProjectService.ProjectAdded += delegate { LoadSavedNodes(); }; ProjectService.SolutionLoaded += delegate { LoadSavedNodes(); }; + + WindowsDebugger.RefreshingPads += RefreshPad; + WindowsDebugger.RefreshPads(); } #region Saved nodes @@ -167,32 +171,13 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads watchList.WatchItems.Add(nod); } - protected override void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= debuggedProcess_Paused; - debuggedProcess.Exited -= ResetPad; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += debuggedProcess_Paused; - debuggedProcess.Exited += ResetPad; - } - InvalidatePad(); - } - - void debuggedProcess_Paused(object sender, ProcessEventArgs e) - { - InvalidatePad(); - } - - TreeNodeWrapper UpdateNode(TreeNodeWrapper node) + TreeNodeWrapper UpdateNode(TreeNodeWrapper node, Process process) { try { LoggingService.Info("Evaluating: " + (string.IsNullOrEmpty(node.Node.Name) ? "is null or empty!" : node.Node.Name)); //Value val = ExpressionEvaluator.Evaluate(nod.Name, nod.Language, debuggedProcess.SelectedStackFrame); - ValueNode valNode = new ValueNode(null, node.Node.Name, () => debugger.GetExpression(node.Node.Name).Evaluate(debuggedProcess)); + ValueNode valNode = new ValueNode(null, node.Node.Name, () => ((WindowsDebugger)DebuggerService.CurrentDebugger).GetExpression(node.Node.Name).Evaluate(process)); return valNode.ToSharpTreeNode(); } catch (GetValueException) { string error = String.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Watch.InvalidExpression}"), node.Node.Name); @@ -201,8 +186,12 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads } } - protected override void RefreshPad() + protected void RefreshPad(object sender, DebuggerEventArgs dbg) { + Process debuggedProcess = dbg.Process; + + ResetPad(null, null); + if (debuggedProcess == null || debuggedProcess.IsRunning) return; @@ -213,7 +202,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads debuggedProcess.EnqueueForEach( Dispatcher.CurrentDispatcher, nodes, - n => watchList.WatchItems.Add(UpdateNode(n)) + n => watchList.WatchItems.Add(UpdateNode(n, debuggedProcess)) ); } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/DebuggeeExceptionForm.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/DebuggeeExceptionForm.cs index 7411b20d30..36e4fcd32a 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Service/DebuggeeExceptionForm.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Service/DebuggeeExceptionForm.cs @@ -104,7 +104,7 @@ namespace ICSharpCode.SharpDevelop.Services void BtnBreakClick(object sender, EventArgs e) { - if (this.process.SelectedThread.CurrentExceptionIsUnhandled) + if (Exception.IsUnhandled) Close(); else if (((WindowsDebugger)DebuggerService.CurrentDebugger).BreakAndInterceptHandledException(Exception)) Close(); diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs index 29752f614c..2da80bea1c 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs @@ -1,6 +1,7 @@ // 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 System.Linq; using Debugger; using ICSharpCode.Core; using ICSharpCode.SharpDevelop.Debugging; @@ -16,26 +17,11 @@ namespace ICSharpCode.SharpDevelop.Services ITextEditorProvider provider = WorkbenchSingleton.Workbench.ActiveViewContent as ITextEditorProvider; WindowsDebugger winDebugger = DebuggerService.CurrentDebugger as WindowsDebugger; - if (provider == null || winDebugger == null) + if (provider == null || winDebugger.DebuggedProcess == null) return; ITextEditor textEditor = provider.TextEditor; - - Breakpoint breakpoint = winDebugger.DebuggerCore.Breakpoints.Add(textEditor.FileName, null, textEditor.Caret.Line, textEditor.Caret.Column, true); - // Be careful to remove the breakpoint just once - breakpoint.Hit += delegate { - if (breakpoint != null) - breakpoint.Remove(); - breakpoint = null; - }; - winDebugger.DebuggedProcess.Paused += delegate { - if (breakpoint != null) - breakpoint.Remove(); - breakpoint = null; - }; - if (!winDebugger.IsProcessRunning) { - winDebugger.Continue(); - } + winDebugger.DebuggedProcess.RunTo(textEditor.FileName, textEditor.Caret.Line, textEditor.Caret.Column); } } } diff --git a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs index f8bfe43bcc..a5c8362cdc 100644 --- a/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs +++ b/src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs @@ -50,22 +50,9 @@ namespace ICSharpCode.SharpDevelop.Services internal IDebuggerDecompilerService debuggerDecompilerService; - //DynamicTreeDebuggerRow currentTooltipRow; - //Expression currentTooltipExpression; + public NDebugger DebuggerCore { get { return debugger; } } - public event EventHandler ProcessSelected; - - public NDebugger DebuggerCore { - get { - return debugger; - } - } - - public Process DebuggedProcess { - get { - return debuggedProcess; - } - } + public Process DebuggedProcess { get { return debuggedProcess; } } public static Process CurrentProcess { get { @@ -78,19 +65,26 @@ namespace ICSharpCode.SharpDevelop.Services } } - /// - public bool BreakAtBeginning { - get; - set; + public static event EventHandler RefreshingPads; + + public static void RefreshPads() + { + RefreshPads(new DebuggerEventArgs(CurrentProcess)); } - protected virtual void OnProcessSelected(ProcessEventArgs e) + public static void RefreshPads(DebuggerEventArgs e) { - if (ProcessSelected != null) { - ProcessSelected(this, e); + if (RefreshingPads != null) { + RefreshingPads(null, e); } } + /// + public bool BreakAtBeginning { + get; + set; + } + public bool ServiceInitialized { get { return debugger != null; @@ -159,13 +153,13 @@ namespace ICSharpCode.SharpDevelop.Services if (DebugStarting != null) DebugStarting(this, EventArgs.Empty); + UpdateBreakpointLines(); + try { // set the JIT flag for evaluating optimized code Process.DebugMode = DebugModeFlag.Debug; - Process process = debugger.Start(processStartInfo.FileName, - processStartInfo.WorkingDirectory, - processStartInfo.Arguments); - SelectProcess(process); + this.debuggedProcess = debugger.Start(processStartInfo.FileName, processStartInfo.WorkingDirectory, processStartInfo.Arguments, this.BreakAtBeginning); + debugger_ProcessStarted(this.debuggedProcess); } catch (System.Exception e) { // COMException: The request is not supported. (Exception from HRESULT: 0x80070032) // COMException: The application has failed to start because its side-by-side configuration is incorrect. Please see the application event log for more detail. (Exception from HRESULT: 0x800736B1) @@ -176,7 +170,6 @@ namespace ICSharpCode.SharpDevelop.Services if (e is COMException || e is BadImageFormatException || e is UnauthorizedAccessException) { string msg = StringParser.Parse("${res:XML.MainMenu.DebugMenu.Error.CannotStartProcess}"); msg += " " + e.Message; - // TODO: Remove if (e is COMException && ((uint)((COMException)e).ErrorCode == 0x80070032)) { msg += Environment.NewLine + Environment.NewLine; msg += "64-bit debugging is not supported. Please set Project -> Project Options... -> Compiling -> Target CPU to 32bit."; @@ -221,14 +214,15 @@ namespace ICSharpCode.SharpDevelop.Services if (DebugStarting != null) DebugStarting(this, EventArgs.Empty); + UpdateBreakpointLines(); + try { // set the JIT flag for evaluating optimized code Process.DebugMode = DebugModeFlag.Debug; - Process process = debugger.Attach(existingProcess); + this.debuggedProcess = debugger.Attach(existingProcess); + debugger_ProcessStarted(this.debuggedProcess); attached = true; - SelectProcess(process); - - process.Modules.Added += process_Modules_Added; + this.debuggedProcess.ModuleLoaded += process_Modules_Added; } catch (System.Exception e) { // CORDBG_E_DEBUGGER_ALREADY_ATTACHED if (e is COMException || e is UnauthorizedAccessException) { @@ -547,9 +541,6 @@ namespace ICSharpCode.SharpDevelop.Services // init NDebugger debugger = new NDebugger(); debugger.Options = DebuggingOptions.Instance; - debugger.DebuggerTraceMessage += debugger_TraceMessage; - debugger.Processes.Added += debugger_ProcessStarted; - debugger.Processes.Removed += debugger_ProcessExited; DebuggerService.BreakPointAdded += delegate (object sender, BreakpointBookmarkEventArgs e) { AddBreakpoint(e.BreakpointBookmark); @@ -559,18 +550,34 @@ namespace ICSharpCode.SharpDevelop.Services AddBreakpoint(b); } + BookmarkManager.Removed += (sender, e) => { + BreakpointBookmark bm = e.Bookmark as BreakpointBookmark; + if (bm != null) { + Breakpoint bp = bm.InternalBreakpointObject as Breakpoint; + bp.IsEnabled = false; + } + }; + if (Initialize != null) { Initialize(this, null); } } - bool Compare(byte[] a, byte[] b) + void UpdateBreakpointLines() { - if (a.Length != b.Length) return false; - for(int i = 0; i < a.Length; i++) { - if (a[i] != b[i]) return false; + foreach (BreakpointBookmark bookmark in BookmarkManager.Bookmarks.OfType()) { + Breakpoint breakpoint = bookmark.InternalBreakpointObject as Breakpoint; + breakpoint.Line = bookmark.LineNumber; + breakpoint.Column = bookmark.ColumnNumber; + } + } + + void UpdateBreakpointIcons() + { + foreach (BreakpointBookmark bookmark in BookmarkManager.Bookmarks.OfType()) { + Breakpoint breakpoint = bookmark.InternalBreakpointObject as Breakpoint; + bookmark.IsHealthy = (debuggedProcess == null) || breakpoint.IsSet; } - return true; } void AddBreakpoint(BreakpointBookmark bookmark) @@ -598,23 +605,13 @@ namespace ICSharpCode.SharpDevelop.Services int[] ilRanges; int methodToken; if (debuggerDecompilerService.GetILAndTokenByLineNumber(token, dbb.LineNumber, out ilRanges, out methodToken)) { - // create BP - breakpoint = new ILBreakpoint( - debugger, - memberReference.FullName, - dbb.LineNumber, - memberReference.MetadataToken.ToInt32(), - methodToken, - ilRanges[0], - dbb.IsEnabled); - - debugger.Breakpoints.Add(breakpoint); + debugger.AddILBreakpoint(memberReference.FullName, dbb.LineNumber, memberReference.MetadataToken.ToInt32(), methodToken, ilRanges[0], dbb.IsEnabled); } } catch (System.Exception ex) { LoggingService.Error("Error on DecompiledBreakpointBookmark: " + ex.Message); } } else { - breakpoint = debugger.Breakpoints.Add(bookmark.FileName, null, bookmark.LineNumber, 0, bookmark.IsEnabled); + breakpoint = debugger.AddBreakpoint(bookmark.FileName, bookmark.LineNumber, 0, bookmark.IsEnabled); } if (breakpoint == null) { @@ -622,93 +619,9 @@ namespace ICSharpCode.SharpDevelop.Services return; } - MethodInvoker setBookmarkColor = delegate { - if (debugger.Processes.Count == 0) { - bookmark.IsHealthy = true; - bookmark.Tooltip = null; - } else if (!breakpoint.IsSet) { - bookmark.IsHealthy = false; - bookmark.Tooltip = "Breakpoint was not found in any loaded modules"; - } else if (breakpoint.OriginalLocation == null || breakpoint.OriginalLocation.CheckSum == null) { - bookmark.IsHealthy = true; - bookmark.Tooltip = null; - } else { - if (!File.Exists(bookmark.FileName)) - return; - - byte[] fileMD5; - IEditable file = FileService.GetOpenFile(bookmark.FileName) as IEditable; - if (file != null) { - byte[] fileContent = Encoding.UTF8.GetBytesWithPreamble(file.Text); - fileMD5 = new MD5CryptoServiceProvider().ComputeHash(fileContent); - } else { - fileMD5 = new MD5CryptoServiceProvider().ComputeHash(File.ReadAllBytes(bookmark.FileName)); - } - if (Compare(fileMD5, breakpoint.OriginalLocation.CheckSum)) { - bookmark.IsHealthy = true; - bookmark.Tooltip = null; - } else { - bookmark.IsHealthy = false; - bookmark.Tooltip = "Check sum or file does not match to the original"; - } - } - }; - - // event handlers on bookmark and breakpoint don't need deregistration - bookmark.IsEnabledChanged += delegate { - breakpoint.Enabled = bookmark.IsEnabled; - }; - breakpoint.Set += delegate { setBookmarkColor(); }; - - setBookmarkColor(); - - EventHandler> bp_debugger_ProcessStarted = (sender, e) => { - setBookmarkColor(); - // User can change line number by inserting or deleting lines - breakpoint.Line = bookmark.LineNumber; - }; - EventHandler> bp_debugger_ProcessExited = (sender, e) => { - setBookmarkColor(); - }; - - EventHandler bp_debugger_BreakpointHit = - new EventHandler( - delegate(object sender, BreakpointEventArgs e) - { - LoggingService.Debug(bookmark.Action + " " + bookmark.ScriptLanguage + " " + bookmark.Condition); - - switch (bookmark.Action) { - case BreakpointAction.Break: - break; - case BreakpointAction.Condition: - if (Evaluate(bookmark.Condition, bookmark.ScriptLanguage)) - DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAtBecause}") + "\n", bookmark.LineNumber, bookmark.FileName, bookmark.Condition)); - else - this.debuggedProcess.AsyncContinue(); - break; - case BreakpointAction.Trace: - DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAt}") + "\n", bookmark.LineNumber, bookmark.FileName)); - break; - } - }); - - BookmarkEventHandler bp_bookmarkManager_Removed = null; - bp_bookmarkManager_Removed = (sender, e) => { - if (bookmark == e.Bookmark) { - debugger.Breakpoints.Remove(breakpoint); - - // unregister the events - debugger.Processes.Added -= bp_debugger_ProcessStarted; - debugger.Processes.Removed -= bp_debugger_ProcessExited; - breakpoint.Hit -= bp_debugger_BreakpointHit; - BookmarkManager.Removed -= bp_bookmarkManager_Removed; - } - }; - // register the events - debugger.Processes.Added += bp_debugger_ProcessStarted; - debugger.Processes.Removed += bp_debugger_ProcessExited; - breakpoint.Hit += bp_debugger_BreakpointHit; - BookmarkManager.Removed += bp_bookmarkManager_Removed; + bookmark.InternalBreakpointObject = breakpoint; + bookmark.IsHealthy = (debuggedProcess == null) || breakpoint.IsSet; + bookmark.IsEnabledChanged += delegate { breakpoint.IsEnabled = bookmark.IsEnabled; }; } bool Evaluate(string code, string language) @@ -734,113 +647,87 @@ namespace ICSharpCode.SharpDevelop.Services DebuggerService.PrintDebugMessage(e.Message); } - void debugger_TraceMessage(object sender, MessageEventArgs e) - { - LoggingService.Debug("Debugger: " + e.Message); - } - - void debugger_ProcessStarted(object sender, CollectionItemEventArgs e) + void debugger_ProcessStarted(Process process) { - if (debugger.Processes.Count == 1) { - if (DebugStarted != null) { - DebugStarted(this, EventArgs.Empty); - } - } - e.Item.LogMessage += LogMessage; - } - - void debugger_ProcessExited(object sender, CollectionItemEventArgs e) - { - if (debugger.Processes.Count == 0) { - if (DebugStopped != null) { - DebugStopped(this, e); - } - SelectProcess(null); - } else { - SelectProcess(debugger.Processes[0]); + if (DebugStarted != null) { + DebugStarted(this, EventArgs.Empty); } - } - - public void SelectProcess(Process process) - { - if (debuggedProcess != null) { - debuggedProcess.Paused -= debuggedProcess_DebuggingPaused; - debuggedProcess.ExceptionThrown -= debuggedProcess_ExceptionThrown; - debuggedProcess.Resumed -= debuggedProcess_DebuggingResumed; - debuggedProcess.ModulesAdded -= debuggedProcess_ModulesAdded; - } - debuggedProcess = process; - if (debuggedProcess != null) { - debuggedProcess.Paused += debuggedProcess_DebuggingPaused; - debuggedProcess.ExceptionThrown += debuggedProcess_ExceptionThrown; - debuggedProcess.Resumed += debuggedProcess_DebuggingResumed; - debuggedProcess.ModulesAdded += debuggedProcess_ModulesAdded; - - debuggedProcess.BreakAtBeginning = BreakAtBeginning; - } - // reset - BreakAtBeginning = false; - JumpToCurrentLine(); - OnProcessSelected(new ProcessEventArgs(process)); + process.ModuleLoaded += (s, e) => UpdateBreakpointIcons(); + process.ModuleLoaded += (s, e) => RefreshPads(e); + process.ModuleUnloaded += (s, e) => RefreshPads(e); + process.LogMessage += LogMessage; + process.Paused += debuggedProcess_DebuggingPaused; + process.Resumed += debuggedProcess_DebuggingResumed; + process.Exited += (s, e) => debugger_ProcessExited(e.Process); + + UpdateBreakpointIcons(); } - void debuggedProcess_ModulesAdded(object sender, ModuleEventArgs e) + void debugger_ProcessExited(Process process) { - var currentModuleTypes = e.Module.GetNamesOfDefinedTypes(); - foreach (var bookmark in DebuggerService.Breakpoints.OfType()) { - var breakpoint = debugger.Breakpoints.FirstOrDefault( - b => b is ILBreakpoint && b.Line == bookmark.LineNumber && - ((ILBreakpoint)b).MetadataToken == bookmark.MemberReference.MetadataToken.ToInt32()); - if (breakpoint == null) - continue; - // set the breakpoint only if the module contains the type - if (!currentModuleTypes.Contains(breakpoint.TypeName)) - continue; - - breakpoint.SetBreakpoint(e.Module); + if (DebugStopped != null) { + DebugStopped(this, EventArgs.Empty); } + debuggedProcess = null; + UpdateBreakpointIcons(); } - void debuggedProcess_DebuggingPaused(object sender, ProcessEventArgs e) + void debuggedProcess_DebuggingPaused(object sender, DebuggerEventArgs e) { OnIsProcessRunningChanged(EventArgs.Empty); LoggingService.Info("Jump to current line"); JumpToCurrentLine(); - // TODO update tooltip - /*if (currentTooltipRow != null && currentTooltipRow.IsShown) { - using(new PrintTimes("Update tooltip")) { - try { - Utils.DoEvents(debuggedProcess); - AbstractNode updatedNode = ValueNode.Create(currentTooltipExpression); - currentTooltipRow.SetContentRecursive(updatedNode); - } catch (AbortedBecauseDebuggeeResumedException) { - } + if (e.ExceptionThrown != null) { + HandleException(e); + } + + foreach (Breakpoint breakpoint in e.BreakpointsHit) { + var bookmark = BookmarkManager.Bookmarks.OfType().First(bm => bm.InternalBreakpointObject == breakpoint); + + LoggingService.Debug(bookmark.Action + " " + bookmark.ScriptLanguage + " " + bookmark.Condition); + + switch (bookmark.Action) { + case BreakpointAction.Break: + break; + case BreakpointAction.Condition: + if (Evaluate(bookmark.Condition, bookmark.ScriptLanguage)) + DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAtBecause}") + "\n", bookmark.LineNumber, bookmark.FileName, bookmark.Condition)); + else + this.debuggedProcess.AsyncContinue(); + break; + case BreakpointAction.Trace: + DebuggerService.PrintDebugMessage(string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.Conditional.Breakpoints.BreakpointHitAt}") + "\n", bookmark.LineNumber, bookmark.FileName)); + break; } - }*/ + } + + RefreshPads(e); } - void debuggedProcess_DebuggingResumed(object sender, ProcessEventArgs e) + void debuggedProcess_DebuggingResumed(object sender, DebuggerEventArgs e) { OnIsProcessRunningChanged(EventArgs.Empty); DebuggerService.RemoveCurrentLineMarker(); + + RefreshPads(e); } - void debuggedProcess_ExceptionThrown(object sender, ExceptionEventArgs e) + void HandleException(DebuggerEventArgs e) { JumpToCurrentLine(); StringBuilder stacktraceBuilder = new StringBuilder(); - if (e.IsUnhandled) { + if (e.ExceptionThrown.IsUnhandled) { // Need to intercept now so that we can evaluate properties - if (e.Process.SelectedThread.InterceptException(e.Exception)) { - stacktraceBuilder.AppendLine(e.Exception.ToString()); + if (e.Process.SelectedThread.InterceptException(e.ExceptionThrown)) { + stacktraceBuilder.AppendLine(e.ExceptionThrown.ToString()); string stackTrace; try { - stackTrace = e.Exception.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.EndOfInnerException}")); + stackTrace = e.ExceptionThrown.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.EndOfInnerException}")); } catch (GetValueException) { stackTrace = e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}")); } @@ -848,19 +735,19 @@ namespace ICSharpCode.SharpDevelop.Services } else { // For example, happens on stack overflow stacktraceBuilder.AppendLine(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptException}")); - stacktraceBuilder.AppendLine(e.Exception.ToString()); + stacktraceBuilder.AppendLine(e.ExceptionThrown.ToString()); stacktraceBuilder.Append(e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}"))); } } else { - stacktraceBuilder.AppendLine(e.Exception.ToString()); + stacktraceBuilder.AppendLine(e.ExceptionThrown.ToString()); stacktraceBuilder.Append(e.Process.SelectedThread.GetStackTrace(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.Symbols}"), StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.NoSymbols}"))); } - string title = e.IsUnhandled ? StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Unhandled}") : StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Handled}"); - string message = string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Message}"), e.Exception.Type); - Bitmap icon = WinFormsResourceService.GetBitmap(e.IsUnhandled ? "Icons.32x32.Error" : "Icons.32x32.Warning"); + string title = e.ExceptionThrown.IsUnhandled ? StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Unhandled}") : StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Title.Handled}"); + string message = string.Format(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.Message}"), e.ExceptionThrown.Type); + Bitmap icon = WinFormsResourceService.GetBitmap(e.ExceptionThrown.IsUnhandled ? "Icons.32x32.Error" : "Icons.32x32.Warning"); - DebuggeeExceptionForm.Show(debuggedProcess, title, message, stacktraceBuilder.ToString(), icon, e.IsUnhandled, e.Exception); + DebuggeeExceptionForm.Show(debuggedProcess, title, message, stacktraceBuilder.ToString(), icon, e.ExceptionThrown.IsUnhandled, e.ExceptionThrown); } public bool BreakAndInterceptHandledException(Debugger.Exception exception) @@ -961,14 +848,14 @@ namespace ICSharpCode.SharpDevelop.Services return (StopAttachedProcessDialogResult)MessageService.ShowCustomDialog(caption, message, (int)StopAttachedProcessDialogResult.Detach, (int)StopAttachedProcessDialogResult.Cancel, buttonLabels); } - void process_Modules_Added(object sender, CollectionItemEventArgs e) + void process_Modules_Added(object sender, ModuleEventArgs e) { if (ProjectService.OpenSolution == null) return; ProjectService.OpenSolution.Projects - .Where(p => e.Item.Name.IndexOf(p.Name) >= 0) - .ForEach(p => e.Item.LoadSymbolsFromDisk(new []{ Path.GetDirectoryName(p.OutputAssemblyFullPath) })); + .Where(p => e.Module.Name.IndexOf(p.Name) >= 0) + .ForEach(p => e.Module.LoadSymbolsFromDisk(new []{ Path.GetDirectoryName(p.OutputAssemblyFullPath) })); } } } diff --git a/src/AddIns/Debugger/Debugger.Core/AppDomainCollection.cs b/src/AddIns/Debugger/Debugger.Core/AppDomainCollection.cs deleted file mode 100644 index 19c92e40f6..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/AppDomainCollection.cs +++ /dev/null @@ -1,24 +0,0 @@ -// 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 Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class AppDomainCollection: CollectionWithEvents - { - public AppDomainCollection(NDebugger dbgr): base(dbgr) {} - - public AppDomain this[ICorDebugAppDomain corAppDomain] { - get { - foreach(AppDomain a in this) { - if (a.CorAppDomain.Equals(corAppDomain)) { - return a; - } - } - throw new DebuggerException("AppDomain not found"); - } - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs b/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs index bca887514f..56a4924610 100644 --- a/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs +++ b/src/AddIns/Debugger/Debugger.Core/Breakpoint.cs @@ -11,103 +11,43 @@ namespace Debugger { public class Breakpoint: DebuggerObject { - NDebugger debugger; - - string fileName; - byte[] checkSum; - int line; - int column; - bool enabled; - - SourcecodeSegment originalLocation; - + bool enabled; protected List corBreakpoints = new List(); - public event EventHandler Hit; - public event EventHandler Set; - - [Debugger.Tests.Ignore] - public NDebugger Debugger { - get { return debugger; } - protected set { debugger = value; } - } - - public string FileName { - get { return fileName; } - } - - public byte[] CheckSum { - get { return checkSum; } - } - - public int Line { - get { return line; } - set { line = value; } - } + public string FileName { get; private set; } + public int Line { get; set; } + public int Column { get; set; } + public SourcecodeSegment OriginalLocation { get; private set; } - public int Column { - get { return column; } - } - - public bool Enabled { + public bool IsEnabled { get { return enabled; } set { enabled = value; foreach(ICorDebugFunctionBreakpoint corBreakpoint in corBreakpoints) { - corBreakpoint.Activate(enabled ? 1 : 0); + try { + corBreakpoint.Activate(enabled ? 1 : 0); + } catch(COMException e) { + // Sometimes happens, but we had not repro yet. + // 0x80131301: Process was terminated. + if ((uint)e.ErrorCode == 0x80131301) + continue; + throw; + } } } } - public SourcecodeSegment OriginalLocation { - get { return originalLocation; } - } - public bool IsSet { - get { - return corBreakpoints.Count > 0; - } - } - - public string TypeName { - get; protected set; - } - - protected virtual void OnHit(BreakpointEventArgs e) - { - if (Hit != null) { - Hit(this, e); - } - } - - internal void NotifyHit() - { - OnHit(new BreakpointEventArgs(this)); - debugger.Breakpoints.OnHit(this); - } - - protected virtual void OnSet(BreakpointEventArgs e) - { - if (Set != null) { - Set(this, e); - } + get { return corBreakpoints.Count > 0; } } - public Breakpoint() { } + public string TypeName { get; protected set; } - public Breakpoint(NDebugger debugger, ICorDebugFunctionBreakpoint corBreakpoint) + internal Breakpoint(string fileName, int line, int column, bool enabled) { - this.debugger = debugger; - this.corBreakpoints.Add(corBreakpoint); - } - - public Breakpoint(NDebugger debugger, string fileName, byte[] checkSum, int line, int column, bool enabled) - { - this.debugger = debugger; - this.fileName = fileName; - this.checkSum = checkSum; - this.line = line; - this.column = column; + this.FileName = fileName; + this.Line = line; + this.Column = column; this.enabled = enabled; } @@ -119,70 +59,38 @@ namespace Debugger return false; } - internal void Deactivate() - { - foreach(ICorDebugFunctionBreakpoint corBreakpoint in corBreakpoints) { - #if DEBUG - // Get repro - corBreakpoint.Activate(0); - #else - try { - corBreakpoint.Activate(0); - } catch(COMException e) { - // Sometimes happens, but we had not repro yet. - // 0x80131301: Process was terminated. - if ((uint)e.ErrorCode == 0x80131301) - continue; - throw; - } - #endif - } - corBreakpoints.Clear(); - } - - internal void MarkAsDeactivated() + internal void NotifyDebuggerTerminated() { corBreakpoints.Clear(); } public virtual bool SetBreakpoint(Module module) { - if (this.fileName == null) + SourcecodeSegment segment = SourcecodeSegment.Resolve(module, FileName, Line, Column); + if (segment == null) return false; - SourcecodeSegment segment = SourcecodeSegment.Resolve(module, FileName, CheckSum, Line, Column); - if (segment == null) return false; - - originalLocation = segment; + OriginalLocation = segment; ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); corBreakpoint.Activate(enabled ? 1 : 0); corBreakpoints.Add(corBreakpoint); - OnSet(new BreakpointEventArgs(this)); - return true; } - - /// Remove this breakpoint - public void Remove() - { - debugger.Breakpoints.Remove(this); - } } public class ILBreakpoint : Breakpoint { - public ILBreakpoint(NDebugger debugger, string typeName, int line, int metadataToken, int memberToken, int offset, bool enabled) + public ILBreakpoint(string typeName, int line, int metadataToken, int memberToken, int offset, bool enabled) + : base(null, line, 0, enabled) { - this.Debugger = debugger; - this.Line = line; this.TypeName = typeName; this.MetadataToken = metadataToken; this.MemberMetadataToken = memberToken; this.ILOffset = offset; - this.Enabled = enabled; + this.IsEnabled = enabled; } public int MetadataToken { get; private set; } @@ -193,36 +101,23 @@ namespace Debugger public override bool SetBreakpoint(Module module) { + var currentModuleTypes = module.GetNamesOfDefinedTypes(); + // set the breakpoint only if the module contains the type + if (!currentModuleTypes.Contains(this.TypeName)) + return false; + SourcecodeSegment segment = SourcecodeSegment.CreateForIL(module, this.Line, MemberMetadataToken, ILOffset); if (segment == null) return false; try { ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); - corBreakpoint.Activate(Enabled ? 1 : 0); + corBreakpoint.Activate(this.IsEnabled ? 1 : 0); corBreakpoints.Add(corBreakpoint); - OnSet(new BreakpointEventArgs(this)); return true; - } catch - #if DEBUG - (System.Exception) - #endif - { + } catch { return false; } } } - - [Serializable] - public class BreakpointEventArgs : DebuggerEventArgs - { - public Breakpoint Breakpoint { - get; private set; - } - - public BreakpointEventArgs(Breakpoint breakpoint): base(breakpoint.Debugger) - { - this.Breakpoint = breakpoint; - } - } } diff --git a/src/AddIns/Debugger/Debugger.Core/BreakpointCollection.cs b/src/AddIns/Debugger/Debugger.Core/BreakpointCollection.cs deleted file mode 100644 index 0e114f5cd8..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/BreakpointCollection.cs +++ /dev/null @@ -1,102 +0,0 @@ -// 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 Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class BreakpointCollection: CollectionWithEvents - { - public event EventHandler> Hit; - - protected internal void OnHit(Breakpoint item) - { - if (Hit != null) { - Hit(this, new CollectionItemEventArgs(item)); - } - } - - public BreakpointCollection(NDebugger debugger):base(debugger) { } - - internal Breakpoint this[ICorDebugBreakpoint corBreakpoint] { - get { - foreach (Breakpoint breakpoint in this) { - if (breakpoint.IsOwnerOf(corBreakpoint)) { - return breakpoint; - } - } - return null; - } - } - - public new void Add(Breakpoint breakpoint) - { - base.Add(breakpoint); - } - - public Breakpoint Add(string filename, int line) - { - Breakpoint breakpoint = new Breakpoint(this.Debugger, filename, null, line, 0, true); - Add(breakpoint); - return breakpoint; - } - - public Breakpoint Add(string fileName, byte[] checkSum, int line, int column, bool enabled) - { - Breakpoint breakpoint = new Breakpoint(this.Debugger, fileName, checkSum, line, column, enabled); - Add(breakpoint); - return breakpoint; - } - - protected override void OnAdded(Breakpoint breakpoint) - { - foreach(Process process in this.Debugger.Processes) { - foreach(Module module in process.Modules) { - if (breakpoint is ILBreakpoint) { - var currentModuleTypes = module.GetNamesOfDefinedTypes(); - // set the breakpoint only if the module contains the type - if (!currentModuleTypes.Contains(breakpoint.TypeName)) - continue; - } - breakpoint.SetBreakpoint(module); - } - } - - base.OnAdded(breakpoint); - } - - public new void Remove(Breakpoint breakpoint) - { - base.Remove(breakpoint); - } - - protected override void OnRemoved(Breakpoint breakpoint) - { - breakpoint.Deactivate(); - - base.OnRemoved(breakpoint); - } - - internal void SetInModule(Module module) - { - // This is in case that the client modifies the collection as a response to set breakpoint - // NB: If client adds new breakpoint, it will be set directly as a result of his call, not here (because module is already loaded) - List collection = new List(); - collection.AddRange(this); - - var currentModuleTypes = module.GetNamesOfDefinedTypes(); - foreach (Breakpoint b in collection) { - if (b is ILBreakpoint) { - // set the breakpoint only if the module contains the type - if (!currentModuleTypes.Contains(b.TypeName)) - continue; - b.SetBreakpoint(module); - } else { - b.SetBreakpoint(module); - } - } - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/CollectionWithEvents.cs b/src/AddIns/Debugger/Debugger.Core/CollectionWithEvents.cs deleted file mode 100644 index 1a1715f113..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/CollectionWithEvents.cs +++ /dev/null @@ -1,109 +0,0 @@ -// 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; -using System.Collections.Generic; - -namespace Debugger -{ - public class CollectionItemEventArgs : EventArgs - { - T item; - - public T Item { - get { - return item; - } - } - - public CollectionItemEventArgs(T item) - { - this.item = item; - } - } - - /// - /// A collection that fires events when items are added or removed. - /// - public class CollectionWithEvents : IEnumerable - { - NDebugger debugger; - - List list = new List(); - - public event EventHandler> Added; - public event EventHandler> Removed; - - protected virtual void OnAdded(T item) - { - if (Added != null) { - Added(this, new CollectionItemEventArgs(item)); - } - } - - protected virtual void OnRemoved(T item) - { - if (Removed != null) { - Removed(this, new CollectionItemEventArgs(item)); - } - } - - public CollectionWithEvents(NDebugger debugger) - { - this.debugger = debugger; - } - - protected NDebugger Debugger { - get { - return debugger; - } - } - - public int Count { - get { - return list.Count; - } - } - - public T this[int index] { - get { - return list[index]; - } - } - - internal void Add(T item) - { - list.Add(item); - OnAdded(item); - } - - internal void Remove(T item) - { - if (list.Remove(item)) { - OnRemoved(item); - } else { - throw new DebuggerException("Item is not in the collection"); - } - } - - internal void Clear() - { - List oldList = list; - list = new List(); - foreach (T item in oldList) { - OnRemoved(item); - } - } - - IEnumerator IEnumerable.GetEnumerator() - { - return list.GetEnumerator(); - } - - IEnumerator IEnumerable.GetEnumerator() - { - return list.GetEnumerator(); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj b/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj index 3b6c2aa1ea..48ea660c35 100644 --- a/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj +++ b/src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj @@ -64,17 +64,13 @@ - - - - @@ -102,7 +98,6 @@ - @@ -148,8 +143,6 @@ - - @@ -157,7 +150,6 @@ - diff --git a/src/AddIns/Debugger/Debugger.Core/Eval.cs b/src/AddIns/Debugger/Debugger.Core/Eval.cs index 15edd7d898..86bbe816c0 100644 --- a/src/AddIns/Debugger/Debugger.Core/Eval.cs +++ b/src/AddIns/Debugger/Debugger.Core/Eval.cs @@ -120,7 +120,7 @@ namespace Debugger } } - appDomain.Process.ActiveEvals.Add(this); + appDomain.Process.activeEvals.Add(this); if (appDomain.Process.Options.SuspendOtherThreads) { appDomain.Process.AsyncContinue(DebuggeeStateAction.Keep, new Thread[] { thread }, CorDebugThreadState.THREAD_SUSPEND); diff --git a/src/AddIns/Debugger/Debugger.Core/EvalCollection.cs b/src/AddIns/Debugger/Debugger.Core/EvalCollection.cs deleted file mode 100644 index 6004c9dabd..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/EvalCollection.cs +++ /dev/null @@ -1,23 +0,0 @@ -// 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 Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class EvalCollection: CollectionWithEvents - { - public EvalCollection(NDebugger debugger): base(debugger) {} - - internal Eval this[ICorDebugEval corEval] { - get { - foreach(Eval eval in this) { - if (eval.IsCorEval(corEval)) { - return eval; - } - } - throw new DebuggerException("Eval not found for given ICorDebugEval"); - } - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/Exception.cs b/src/AddIns/Debugger/Debugger.Core/Exception.cs index ee75897de2..c7f2f66ec8 100644 --- a/src/AddIns/Debugger/Debugger.Core/Exception.cs +++ b/src/AddIns/Debugger/Debugger.Core/Exception.cs @@ -15,9 +15,16 @@ namespace Debugger get { return exception; } } - public Exception(Value exception) + ExceptionType ExceptionType { get; set; } + + public bool IsUnhandled { + get { return this.ExceptionType == ExceptionType.Unhandled; } + } + + internal Exception(Value exception, ExceptionType exceptionType) { this.exception = exception; + this.ExceptionType = exceptionType; } /// The GetType().FullName of the exception. @@ -42,7 +49,7 @@ namespace Debugger public Exception InnerException { get { Value innerException = exception.GetMemberValue("_innerException"); - return innerException.IsNull ? null : new Exception(innerException); + return innerException.IsNull ? null : new Exception(innerException, this.ExceptionType); } } @@ -92,30 +99,4 @@ namespace Debugger return sb.ToString(); } } - - public class ExceptionEventArgs: ProcessEventArgs - { - readonly Exception exception; - readonly ExceptionType exceptionType; - readonly bool isUnhandled; - - public Exception Exception { - get { return exception; } - } - - public ExceptionType ExceptionType { - get { return exceptionType; } - } - - public bool IsUnhandled { - get { return isUnhandled; } - } - - public ExceptionEventArgs(Process process, Exception exception, ExceptionType exceptionType, bool isUnhandled):base(process) - { - this.exception = exception; - this.exceptionType = exceptionType; - this.isUnhandled = isUnhandled; - } - } } diff --git a/src/AddIns/Debugger/Debugger.Core/ExceptionType.cs b/src/AddIns/Debugger/Debugger.Core/ExceptionType.cs index 287bcf31d1..af23e7b77f 100644 --- a/src/AddIns/Debugger/Debugger.Core/ExceptionType.cs +++ b/src/AddIns/Debugger/Debugger.Core/ExceptionType.cs @@ -3,7 +3,7 @@ namespace Debugger { - public enum ExceptionType + enum ExceptionType { FirstChance = 1, UserFirstChance = 2, diff --git a/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs b/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs index d0076d569d..d7a14d395e 100644 --- a/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs +++ b/src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs @@ -2,6 +2,7 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using Debugger.Interop; @@ -24,6 +25,9 @@ namespace Debugger bool pauseOnNextExit; bool isInCallback = false; + List breakpointsHit = new List(); + Exception exceptionThrown; + [Debugger.Tests.Ignore] public Process Process { get { return process; } @@ -74,7 +78,7 @@ namespace Debugger void EnterCallback(PausedReason pausedReason, string name, ICorDebugThread pThread) { EnterCallback(pausedReason, name, pThread.GetProcess()); - process.SelectedThread = process.Threads[pThread]; + process.SelectedThread = process.GetThread(pThread); } void ExitCallback() @@ -84,8 +88,7 @@ namespace Debugger process.TraceMessage("Process has queued callbacks"); // only process callbacks if no exception occurred - // if no thread is selected CurrentException must be null - if (hasQueuedCallbacks && (process.SelectedThread == null || process.SelectedThread.CurrentException == null)) { + if (hasQueuedCallbacks && exceptionThrown == null) { // Exception has Exception2 queued after it process.AsyncContinue(DebuggeeStateAction.Keep, null, null); } else if (process.Evaluating) { @@ -113,11 +116,15 @@ namespace Debugger // Do not set selected stack frame // Do not raise events } else { + DebuggerEventArgs e = new DebuggerEventArgs(process); + e.BreakpointsHit = breakpointsHit.ToArray(); + e.ExceptionThrown = exceptionThrown; + breakpointsHit.Clear(); + exceptionThrown = null; + // Raise the pause event outside the callback // Warning: Make sure that process in not resumed in the meantime - process.Debugger.MTA2STA.AsyncCall(process.RaisePausedEvents); - - // The event might probably get called out of order when the process is running again + process.Debugger.MTA2STA.AsyncCall(delegate { process.OnPaused(e); }); } } @@ -128,7 +135,7 @@ namespace Debugger { EnterCallback(PausedReason.StepComplete, "StepComplete (" + reason.ToString() + ")", pThread); - Thread thread = process.Threads[pThread]; + Thread thread = process.GetThread(pThread); Stepper stepper = process.GetStepper(pStepper); StackFrame currentStackFrame = process.SelectedThread.MostRecentStackFrame; @@ -169,9 +176,11 @@ namespace Debugger { EnterCallback(PausedReason.Breakpoint, "Breakpoint", pThread); - Breakpoint breakpoint = process.Debugger.Breakpoints[corBreakpoint]; - // The event will be risen outside the callback - process.BreakpointHitEventQueue.Enqueue(breakpoint); + Breakpoint breakpoint = process.Debugger.GetBreakpoint(corBreakpoint); + // Could be tempBreakpoint + if (breakpoint != null) { + breakpointsHit.Add(breakpoint); + } pauseOnNextExit = true; @@ -246,14 +255,14 @@ namespace Debugger public void EvalException(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval) { - EnterCallback(PausedReason.EvalComplete, "EvalException (" + process.ActiveEvals[corEval].Description + ")", pThread); + EnterCallback(PausedReason.EvalComplete, "EvalException (" + process.GetActiveEval(corEval).Description + ")", pThread); HandleEvalComplete(pAppDomain, pThread, corEval, true); } public void EvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval) { - EnterCallback(PausedReason.EvalComplete, "EvalComplete (" + process.ActiveEvals[corEval].Description + ")", pThread); + EnterCallback(PausedReason.EvalComplete, "EvalComplete (" + process.GetActiveEval(corEval).Description + ")", pThread); HandleEvalComplete(pAppDomain, pThread, corEval, false); } @@ -261,9 +270,9 @@ namespace Debugger void HandleEvalComplete(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread, ICorDebugEval corEval, bool exception) { // Let the eval know that the CorEval has finished - Eval eval = process.ActiveEvals[corEval]; + Eval eval = process.GetActiveEval(corEval); eval.NotifyEvaluationComplete(!exception); - process.ActiveEvals.Remove(eval); + process.activeEvals.Remove(eval); pauseOnNextExit = true; ExitCallback(); @@ -299,7 +308,7 @@ namespace Debugger { EnterCallback(PausedReason.Other, "UpdateModuleSymbols", pAppDomain); - Module module = process.Modules[pModule]; + Module module = process.GetModule(pModule); if (module.CorModule is ICorDebugModule3 && module.IsDynamic) { // In .NET 4.0, we use the LoadClass callback to load dynamic modules // because it always works - UpdateModuleSymbols does not. @@ -343,7 +352,7 @@ namespace Debugger EnterCallback(PausedReason.Other, "CreateAppDomain", pAppDomain); pAppDomain.Attach(); - process.AppDomains.Add(new AppDomain(process, pAppDomain)); + process.appDomains.Add(new AppDomain(process, pAppDomain)); ExitCallback(); } @@ -359,8 +368,9 @@ namespace Debugger { EnterCallback(PausedReason.Other, "LoadModule " + pModule.GetName(), pAppDomain); - Module module = new Module(process.AppDomains[pAppDomain], pModule); - process.Modules.Add(module); + Module module = new Module(process.GetAppDomain(pAppDomain), pModule); + process.modules.Add(module); + process.OnModuleLoaded(module); ExitCallback(); } @@ -378,9 +388,6 @@ namespace Debugger EnterCallback(PausedReason.Other, "NameChange: pThread", pThread); - Thread thread = process.Threads[pThread]; - thread.NotifyNameChanged(); - ExitCallback(); } @@ -393,7 +400,7 @@ namespace Debugger EnterCallback(PausedReason.Other, "CreateThread " + pThread.GetID(), pAppDomain); Thread thread = new Thread(process, pThread); - process.Threads.Add(thread); + process.threads.Add(thread); thread.CorThread.SetDebugState(process.NewThreadState); @@ -404,7 +411,7 @@ namespace Debugger { EnterCallback(PausedReason.Other, "LoadClass", pAppDomain); - Module module = process.Modules[c.GetModule()]; + Module module = process.GetModule(c.GetModule()); // Dynamic module has been extended - reload symbols to inlude new class module.LoadSymbolsDynamic(); @@ -427,7 +434,9 @@ namespace Debugger { EnterCallback(PausedReason.Other, "UnloadModule", pAppDomain); - process.Modules.Remove(process.Modules[pModule]); + Module module = process.GetModule(pModule); + process.modules.Remove(module); + process.OnModuleUnloaded(module); ExitCallback(); } @@ -441,11 +450,13 @@ namespace Debugger public void ExitThread(ICorDebugAppDomain pAppDomain, ICorDebugThread pThread) { + Thread thread = process.TryGetThread(pThread); + // ICorDebugThread is still not dead and can be used for some operations - if (process.Threads.Contains(pThread)) { + if (thread != null) { EnterCallback(PausedReason.Other, "ExitThread " + pThread.GetID(), pThread); - process.Threads[pThread].NotifyExited(); + thread.NotifyExited(); } else { EnterCallback(PausedReason.Other, "ExitThread " + pThread.GetID(), process.CorProcess); @@ -466,7 +477,7 @@ namespace Debugger { EnterCallback(PausedReason.Other, "ExitAppDomain", pAppDomain); - process.AppDomains.Remove(process.AppDomains[pAppDomain]); + process.appDomains.Remove(process.GetAppDomain(pAppDomain)); ExitCallback(); } @@ -476,7 +487,7 @@ namespace Debugger // ExitProcess may be called at any time when debuggee is killed process.TraceMessage("Callback: ExitProcess"); - process.NotifyHasExited(); + process.OnExited(); } #endregion @@ -518,11 +529,9 @@ namespace Debugger if (exceptionType == ExceptionType.Unhandled || (pauseOnHandled && exceptionType == ExceptionType.CatchHandlerFound)) { // sanity check: we can only handle one exception after another // TODO : create Exception queue if CLR throws multiple exceptions - Debug.Assert(process.SelectedThread.CurrentException == null); - process.SelectedThread.CurrentException = new Exception(new Value(process.AppDomains[pAppDomain], process.SelectedThread.CorThread.GetCurrentException()).GetPermanentReference()); - process.SelectedThread.CurrentException_DebuggeeState = process.DebuggeeState; - process.SelectedThread.CurrentExceptionType = exceptionType; - process.SelectedThread.CurrentExceptionIsUnhandled = exceptionType == ExceptionType.Unhandled; + Debug.Assert(exceptionThrown == null); + Value value = new Value(process.GetAppDomain(pAppDomain), process.SelectedThread.CorThread.GetCurrentException()).GetPermanentReference(); + exceptionThrown = new Exception(value, exceptionType); pauseOnNextExit = true; } diff --git a/src/AddIns/Debugger/Debugger.Core/ManagedCallbackSwitch.cs b/src/AddIns/Debugger/Debugger.Core/ManagedCallbackSwitch.cs index c7abb50974..968b28cc76 100644 --- a/src/AddIns/Debugger/Debugger.Core/ManagedCallbackSwitch.cs +++ b/src/AddIns/Debugger/Debugger.Core/ManagedCallbackSwitch.cs @@ -73,7 +73,7 @@ namespace Debugger Process process; // We have to wait until the created process is added into the collection lock(debugger.ProcessIsBeingCreatedLock) { - process = debugger.Processes[pProcess]; + process = debugger.GetProcess(pProcess); } // Make *really* sure the process is not dead if (process == null) { diff --git a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs index a152d02dba..4a9afee7a3 100644 --- a/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs +++ b/src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs @@ -1075,7 +1075,7 @@ namespace Debugger.MetaData public static DebugType CreateFromCorClass(AppDomain appDomain, bool? valueType, ICorDebugClass corClass, DebugType[] genericArguments) { - MetaDataImport metaData = appDomain.Process.Modules[corClass.GetModule()].MetaData; + MetaDataImport metaData = appDomain.Process.GetModule(corClass.GetModule()).MetaData; if (valueType == null) { uint superClassToken = metaData.GetTypeDefProps(corClass.GetToken()).SuperClassToken; @@ -1175,7 +1175,7 @@ namespace Debugger.MetaData genericArguments.Add(DebugType.CreateFromCorType(appDomain, t)); } // Get class props - this.module = appDomain.Process.Modules[corType.GetClass().GetModule()]; + this.module = appDomain.Process.GetModule(corType.GetClass().GetModule()); this.classProps = module.MetaData.GetTypeDefProps(corType.GetClass().GetToken()); if (this.DebugModule.AppDomain != appDomain) throw new DebuggerException("The specified AppDomain was inccorect"); diff --git a/src/AddIns/Debugger/Debugger.Core/Module.cs b/src/AddIns/Debugger/Debugger.Core/Module.cs index db6c99dbd8..d6c1704682 100644 --- a/src/AddIns/Debugger/Debugger.Core/Module.cs +++ b/src/AddIns/Debugger/Debugger.Core/Module.cs @@ -29,11 +29,6 @@ namespace Debugger internal Dictionary LoadedDebugTypes = new Dictionary(); - /// - /// Occurs when symbols are loaded or unloaded (for memory modules) - /// - public event EventHandler SymbolsUpdated; - public AppDomain AppDomain { get { return appDomain; } } @@ -222,11 +217,11 @@ namespace Debugger /// /// Load symblos for on-disk module /// - public void LoadSymbolsFromDisk(string[] searchPath) + public void LoadSymbolsFromDisk(string[] symbolsSearchPaths) { if (!IsDynamic && !IsInMemory) { if (symReader == null) { - symReader = metaData.GetSymReader(fullPath, string.Join("; ", searchPath ?? new string[0])); + symReader = metaData.GetSymReader(fullPath, string.Join("; ", symbolsSearchPaths ?? new string[0])); if (symReader != null) { process.TraceMessage("Loaded symbols from disk for " + this.Name); OnSymbolsUpdated(); @@ -280,31 +275,10 @@ namespace Debugger void OnSymbolsUpdated() { - SetBreakpoints(); - ResetJustMyCodeStatus(); - if (SymbolsUpdated != null) { - SymbolsUpdated(this, new ModuleEventArgs(this)); - } - } - - void SetBreakpoints() - { - if (this.HasSymbols) { - // This is in case that the client modifies the collection as a response to set breakpoint - // NB: If client adds new breakpoint, it will be set directly as a result of his call, not here (because module is already loaded) - List collection = new List(); - collection.AddRange(this.Debugger.Breakpoints); - - var currentModuleTypes = this.GetNamesOfDefinedTypes(); - foreach (Breakpoint b in collection) { - if (b is ILBreakpoint) { - // set the breakpoint only if the module contains the type - if (!currentModuleTypes.Contains(b.TypeName)) - continue; - } - b.SetBreakpoint(this); - } + foreach (Breakpoint b in this.Debugger.Breakpoints) { + b.SetBreakpoint(this); } + ResetJustMyCodeStatus(); } void SetJITCompilerFlags() @@ -396,21 +370,4 @@ namespace Debugger return jcf; } } - - [Serializable] - public class ModuleEventArgs : ProcessEventArgs - { - Module module; - - public Module Module { - get { - return module; - } - } - - public ModuleEventArgs(Module module): base(module.Process) - { - this.module = module; - } - } } diff --git a/src/AddIns/Debugger/Debugger.Core/ModuleCollection.cs b/src/AddIns/Debugger/Debugger.Core/ModuleCollection.cs deleted file mode 100644 index d01fd53af5..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/ModuleCollection.cs +++ /dev/null @@ -1,50 +0,0 @@ -// 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 Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class ModuleCollection: CollectionWithEvents - { - public ModuleCollection(NDebugger debugger):base (debugger) {} - - int lastAssignedModuleOrderOfLoading = 0; - - public Module this[string filename] { - get { - foreach(Module module in this) { - if (module.Name == filename) { - return module; - } - } - throw new DebuggerException("Module \"" + filename + "\" is not in collection"); - } - } - - internal Module this[ICorDebugModule corModule] { - get { - foreach(Module module in this) { - if (module.CorModule == corModule) { - return module; - } - } - throw new DebuggerException("Module is not in collection"); - } - } - - protected override void OnAdded(Module module) - { - module.OrderOfLoading = lastAssignedModuleOrderOfLoading; - lastAssignedModuleOrderOfLoading++; - base.OnAdded(module); - } - - protected override void OnRemoved(Module module) - { - base.OnRemoved(module); - module.Dispose(); - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/NDebugger.cs b/src/AddIns/Debugger/Debugger.Core/NDebugger.cs index 61ecb39eb5..2b6603f258 100644 --- a/src/AddIns/Debugger/Debugger.Core/NDebugger.cs +++ b/src/AddIns/Debugger/Debugger.Core/NDebugger.cs @@ -2,6 +2,7 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using System.Collections.Generic; using System.IO; using System.Text; using System.Threading; @@ -17,8 +18,8 @@ namespace Debugger ManagedCallbackSwitch managedCallbackSwitch; ManagedCallbackProxy managedCallbackProxy; - BreakpointCollection breakpoints; - ProcessCollection processes; + internal List breakpoints = new List(); + internal List processes = new List(); MTA2STA mta2sta = new MTA2STA(); @@ -49,19 +50,16 @@ namespace Debugger set { options = value; } } - public BreakpointCollection Breakpoints { - get { return breakpoints; } + public IEnumerable Breakpoints { + get { return this.breakpoints; } } - public ProcessCollection Processes { - get { return processes; } + public IEnumerable Processes { + get { return this.processes; } } public NDebugger() { - processes = new ProcessCollection(this); - breakpoints = new BreakpointCollection(this); - if (ApartmentState.STA == System.Threading.Thread.CurrentThread.GetApartmentState()) { mta2sta.CallMethod = CallMethod.HiddenFormWithTimeout; } else { @@ -69,6 +67,15 @@ namespace Debugger } } + internal Process GetProcess(ICorDebugProcess corProcess) { + foreach (Process process in this.Processes) { + if (process.CorProcess == corProcess) { + return process; + } + } + return null; + } + /// /// Get the .NET version of the process that called this function /// @@ -137,38 +144,57 @@ namespace Debugger internal void TerminateDebugger() { - // Mark breakpints as deactivated - foreach (Breakpoint b in this.Breakpoints) { - b.MarkAsDeactivated(); + foreach(Breakpoint breakpoint in this.Breakpoints) { + breakpoint.NotifyDebuggerTerminated(); } - TraceMessage("Reset done"); - corDebug.Terminate(); - TraceMessage("ICorDebug terminated"); int released = TrackedComObjects.ReleaseAll(); - TraceMessage("Released " + released + " tracked COM objects"); } - /// - /// Internal: Used to debug the debugger library. - /// - public event EventHandler DebuggerTraceMessage; + public Breakpoint AddBreakpoint(string fileName, int line, int column = 0, bool enabled = true) + { + Breakpoint breakpoint = new Breakpoint(fileName, line, column, enabled); + AddBreakpoint(breakpoint); + return breakpoint; + } - protected internal virtual void OnDebuggerTraceMessage(MessageEventArgs e) + public ILBreakpoint AddILBreakpoint(string typeName, int line, int metadataToken, int memberToken, int offset, bool enabled) { - if (DebuggerTraceMessage != null) { - DebuggerTraceMessage(this, e); + ILBreakpoint breakpoint = new ILBreakpoint(typeName, line, metadataToken, memberToken, offset, enabled); + AddBreakpoint(breakpoint); + return breakpoint; + } + + void AddBreakpoint(Breakpoint breakpoint) + { + this.breakpoints.Add(breakpoint); + + foreach (Process process in this.Processes) { + foreach(Module module in process.Modules) { + breakpoint.SetBreakpoint(module); + } + } + } + + internal Breakpoint GetBreakpoint(ICorDebugBreakpoint corBreakpoint) + { + foreach (Breakpoint breakpoint in this.Breakpoints) { + if (breakpoint.IsOwnerOf(corBreakpoint)) { + return breakpoint; + } } + return null; } internal void TraceMessage(string message) { - System.Diagnostics.Debug.WriteLine("Debugger:" + message); - OnDebuggerTraceMessage(new MessageEventArgs(null, message)); + message = "Debugger: " + message; + System.Console.WriteLine(message); + System.Diagnostics.Debug.WriteLine(message); } public void StartWithoutDebugging(System.Diagnostics.ProcessStartInfo psi) @@ -181,39 +207,36 @@ namespace Debugger internal object ProcessIsBeingCreatedLock = new object(); - public Process Start(string filename, string workingDirectory, string arguments) + public Process Start(string filename, string workingDirectory, string arguments, bool breakInMain) { InitDebugger(GetProgramVersion(filename)); lock(ProcessIsBeingCreatedLock) { Process process = Process.CreateProcess(this, filename, workingDirectory, arguments); // Expose a race conditon System.Threading.Thread.Sleep(0); - this.Processes.Add(process); + process.BreakInMain = breakInMain; + this.processes.Add(process); return process; } } - public Process Attach(System.Diagnostics.Process existingProcess) + public Process Attach(System.Diagnostics.Process existingProcess) { string mainModule = existingProcess.MainModule.FileName; InitDebugger(GetProgramVersion(mainModule)); - ICorDebugProcess corDebugProcess = corDebug.DebugActiveProcess((uint)existingProcess.Id, 0); - // TODO: Can we get the acutal working directory? - Process process = new Process(this, corDebugProcess, Path.GetDirectoryName(mainModule)); - this.Processes.Add(process); - return process; + lock(ProcessIsBeingCreatedLock) { + ICorDebugProcess corDebugProcess = corDebug.DebugActiveProcess((uint)existingProcess.Id, 0); + // TODO: Can we get the acutal working directory? + Process process = new Process(this, corDebugProcess, Path.GetDirectoryName(mainModule)); + this.processes.Add(process); + return process; + } } public void Detach() { - // Deactivate breakpoints - foreach (Breakpoint b in this.Breakpoints) { - b.Deactivate(); - } - // Detach all processes. - for (int i = 0; i < this.Processes.Count; ++i) { - Process process = this.Processes[i]; + foreach(Process process in this.Processes) { if (process == null || process.HasExited) continue; process.Detach(); @@ -264,57 +287,49 @@ namespace Debugger } [Serializable] - public class DebuggerEventArgs : EventArgs + public class DebuggerEventArgs: EventArgs { - NDebugger debugger; - - public NDebugger Debugger { - get { - return debugger; - } - } + public Process Process { get; internal set; } + public Breakpoint[] BreakpointsHit { get; internal set; } + public Exception ExceptionThrown { get; internal set; } - public DebuggerEventArgs(NDebugger debugger) + public DebuggerEventArgs(Process process) { - this.debugger = debugger; + this.Process = process; } } [Serializable] - public class MessageEventArgs : ProcessEventArgs + public class ModuleEventArgs: DebuggerEventArgs { - int level; - string message; - string category; - - public int Level { - get { - return level; - } - } + public Module Module { get; private set; } - public string Message { - get { - return message; - } - } - - public string Category { - get { - return category; - } + public ModuleEventArgs(Module module) : base(module.Process) + { + this.Module = module; } + } + + [Serializable] + public class MessageEventArgs : EventArgs + { + public Process Process { get; private set; } + public int Level { get; private set; } + public string Message { get; private set; } + public string Category { get; private set; } - public MessageEventArgs(Process process, string message): this(process, 0, message, String.Empty) + public MessageEventArgs(Process process, string message) { - this.message = message; + this.Process = process; + this.Message = message; } - public MessageEventArgs(Process process, int level, string message, string category): base(process) + public MessageEventArgs(Process process, int level, string message, string category) { - this.level = level; - this.message = message; - this.category = category; + this.Process = process; + this.Level = level; + this.Message = message; + this.Category = category; } } } diff --git a/src/AddIns/Debugger/Debugger.Core/Process.cs b/src/AddIns/Debugger/Debugger.Core/Process.cs index 933ecdb8f4..e00aa2dbdd 100644 --- a/src/AddIns/Debugger/Debugger.Core/Process.cs +++ b/src/AddIns/Debugger/Debugger.Core/Process.cs @@ -42,13 +42,21 @@ namespace Debugger ICorDebugProcess corProcess; ManagedCallback callbackInterface; - EvalCollection activeEvals; - ModuleCollection modules; - ThreadCollection threads; - AppDomainCollection appDomains; + List tempBreakpoints = new List(); + + internal List activeEvals = new List(); + internal List modules = new List(); + internal List threads = new List(); + internal List appDomains = new List(); string workingDirectory; + public event EventHandler LogMessage; + public event EventHandler ModuleLoaded; + public event EventHandler ModuleUnloaded; + public event EventHandler Paused; + public event EventHandler Resumed; + public event EventHandler Exited; public NDebugger Debugger { get { return debugger; } @@ -70,26 +78,19 @@ namespace Debugger get { return callbackInterface; } } - public EvalCollection ActiveEvals { - get { return activeEvals; } - } - internal bool Evaluating { get { return activeEvals.Count > 0; } } - public ModuleCollection Modules { - get { return modules; } + public IEnumerable Modules { + get { return this.modules; } } - public ThreadCollection Threads { - get { return threads; } + public IEnumerable Threads { + get { return this.threads; } } - public Thread SelectedThread { - get { return this.Threads.Selected; } - set { this.Threads.Selected = value; } - } + public Thread SelectedThread { get; set; } public StackFrame SelectedStackFrame { get { @@ -111,12 +112,9 @@ namespace Debugger } } - public bool BreakAtBeginning { - get; - set; - } + internal bool BreakInMain { get; set; } - public AppDomainCollection AppDomains { + public IEnumerable AppDomains { get { return appDomains; } } @@ -139,12 +137,6 @@ namespace Debugger this.workingDirectory = workingDirectory; this.callbackInterface = new ManagedCallback(this); - - activeEvals = new EvalCollection(debugger); - modules = new ModuleCollection(debugger); - modules.Added += OnModulesAdded; - threads = new ThreadCollection(debugger); - appDomains = new AppDomainCollection(debugger); } static unsafe public Process CreateProcess(NDebugger debugger, string filename, string workingDirectory, string arguments) @@ -187,14 +179,10 @@ namespace Debugger return new Process(debugger, outProcess, workingDirectory); } - /// Fired when System.Diagnostics.Trace.WriteLine() is called in debuged process - public event EventHandler LogMessage; - - protected internal virtual void OnLogMessage(MessageEventArgs arg) + internal void OnLogMessage(MessageEventArgs arg) { - TraceMessage ("Debugger event: OnLogMessage"); - if (LogMessage != null) { - LogMessage(this, arg); + if (this.LogMessage != null) { + this.LogMessage(this, arg); } } @@ -202,8 +190,63 @@ namespace Debugger { if (args.Length > 0) message = string.Format(message, args); - System.Diagnostics.Debug.WriteLine("Debugger:" + message); - debugger.OnDebuggerTraceMessage(new MessageEventArgs(this, message)); + this.Debugger.TraceMessage(message); + } + + internal AppDomain GetAppDomain(ICorDebugAppDomain corAppDomain) + { + foreach(AppDomain a in this.AppDomains) { + if (a.CorAppDomain.Equals(corAppDomain)) { + return a; + } + } + throw new DebuggerException("AppDomain not found"); + } + + internal Eval GetActiveEval(ICorDebugEval corEval) + { + foreach(Eval eval in this.activeEvals) { + if (eval.IsCorEval(corEval)) { + return eval; + } + } + throw new DebuggerException("Eval not found for given ICorDebugEval"); + } + + public Module GetModule(string filename) { + foreach(Module module in this.Modules) { + if (module.Name == filename) { + return module; + } + } + throw new DebuggerException("Module \"" + filename + "\" is not in collection"); + } + + internal Module GetModule(ICorDebugModule corModule) { + foreach(Module module in this.Modules) { + if (module.CorModule == corModule) { + return module; + } + } + throw new DebuggerException("Module is not in collection"); + } + + internal Thread GetThread(ICorDebugThread corThread) { + foreach(Thread thread in this.Threads) { + if (thread.CorThread == corThread) { + return thread; + } + } + throw new DebuggerException("Thread is not in collection"); + } + + internal Thread TryGetThread(ICorDebugThread corThread) { + foreach(Thread thread in this.Threads) { + if (thread.CorThread == corThread) { + return thread; + } + } + return null; } /// Read the specified amount of memory at the given memory address @@ -231,34 +274,24 @@ namespace Debugger return written; } - #region Exceptions - - public event EventHandler ExceptionThrown; - - protected internal virtual void OnExceptionThrown(ExceptionEventArgs e) - { - TraceMessage ("Debugger event: OnExceptionThrown()"); - if (ExceptionThrown != null) { - ExceptionThrown(this, e); - } - } - - #endregion - // State control for the process internal bool TerminateCommandIssued = false; - internal Queue BreakpointHitEventQueue = new Queue(); #region Events - public event EventHandler Paused; - public event EventHandler Resumed; - - // HACK: public - public virtual void OnPaused() + internal void OnPaused(DebuggerEventArgs e) { AssertPaused(); + DisableAllSteppers(); + CheckSelectedStackFrames(); + SelectMostRecentStackFrameWithLoadedSymbols(); + + foreach (var corBreakpoint in tempBreakpoints) { + corBreakpoint.Activate(0); + } + tempBreakpoints.Clear(); + // No real purpose - just additional check if (callbackInterface.IsInCallback) throw new DebuggerException("Can not raise event within callback."); TraceMessage ("Debugger event: OnPaused()"); @@ -272,19 +305,19 @@ namespace Debugger TraceMessage ("Skipping OnPaused delegate because process has exited"); break; } - d.DynamicInvoke(this, new ProcessEventArgs(this)); + d.DynamicInvoke(this, e); } } } - protected virtual void OnResumed() + void OnResumed() { AssertRunning(); if (callbackInterface.IsInCallback) throw new DebuggerException("Can not raise event within callback."); TraceMessage ("Debugger event: OnResumed()"); if (Resumed != null) { - Resumed(this, new ProcessEventArgs(this)); + Resumed(this, new DebuggerEventArgs(this)); } } @@ -330,36 +363,6 @@ namespace Debugger } } - /// Sets up the eviroment and raises user events - internal void RaisePausedEvents() - { - AssertPaused(); - DisableAllSteppers(); - CheckSelectedStackFrames(); - SelectMostRecentStackFrameWithLoadedSymbols(); - - // if CurrentException is set an exception has occurred. - if (SelectedThread.CurrentException != null) { - ExceptionEventArgs args = new ExceptionEventArgs(this, this.SelectedThread.CurrentException, this.SelectedThread.CurrentExceptionType, this.SelectedThread.CurrentExceptionIsUnhandled); - OnExceptionThrown(args); - // clear exception, it is being processed by the debugger. - this.SelectedThread.CurrentException = null; - // The event could have resumed or killed the process - if (this.IsRunning || this.TerminateCommandIssued || this.HasExited) return; - } - - while(BreakpointHitEventQueue.Count > 0) { - Breakpoint breakpoint = BreakpointHitEventQueue.Dequeue(); - breakpoint.NotifyHit(); - // The event could have resumed or killed the process - if (this.IsRunning || this.TerminateCommandIssued || this.HasExited) return; - } - - OnPaused(); - // The event could have resumed the process - if (this.IsRunning || this.TerminateCommandIssued || this.HasExited) return; - } - #endregion internal void AssertPaused() @@ -390,26 +393,29 @@ namespace Debugger bool hasExited = false; - public event EventHandler Exited; - public bool HasExited { get { return hasExited; } } - internal void NotifyHasExited() + internal void OnExited() { if(!hasExited) { hasExited = true; if (Exited != null) { - Exited(this, new ProcessEventArgs(this)); + Exited(this, new DebuggerEventArgs(this)); } // Expire pause seesion first if (IsPaused) { NotifyResumed(DebuggeeStateAction.Clear); } - debugger.Processes.Remove(this); + debugger.processes.Remove(this); + + if (debugger.processes.Count == 0) { + // Exit callback and then terminate the debugger + this.Debugger.MTA2STA.AsyncCall( delegate { this.Debugger.TerminateDebugger(); } ); + } } } @@ -420,7 +426,7 @@ namespace Debugger corProcess.Stop(uint.MaxValue); // Infinite; ignored anyway NotifyPaused(PausedReason.ForcedBreak); - RaisePausedEvents(); + OnPaused(new DebuggerEventArgs(this)); } public void Detach() @@ -430,6 +436,11 @@ namespace Debugger NotifyPaused(PausedReason.ForcedBreak); } + // Deactivate breakpoints + foreach (Breakpoint b in this.Debugger.Breakpoints) { + b.IsEnabled = false; + } + // This is necessary for detach foreach(Stepper s in this.Steppers) { if (s.CorStepper.IsActive() == 1) { @@ -441,8 +452,7 @@ namespace Debugger corProcess.Detach(); // modules - foreach(Module m in this.Modules) - { + foreach(Module m in this.Modules) { m.Dispose(); } @@ -451,7 +461,7 @@ namespace Debugger // threads this.threads.Clear(); - NotifyHasExited(); + OnExited(); } public void Continue() @@ -460,9 +470,24 @@ namespace Debugger WaitForPause(); } + public void RunTo(string fileName, int line, int column) + { + foreach(Module module in this.Modules) { + SourcecodeSegment segment = SourcecodeSegment.Resolve(module, fileName, line, column); + if (segment != null) { + ICorDebugFunctionBreakpoint corBreakpoint = segment.CorFunction.GetILCode().CreateBreakpoint((uint)segment.ILStart); + corBreakpoint.Activate(1); + this.tempBreakpoints.Add(corBreakpoint); + } + } + if (this.IsPaused) { + AsyncContinue(); + } + } + internal Thread[] UnsuspendedThreads { get { - List unsuspendedThreads = new List(this.Threads.Count); + List unsuspendedThreads = new List(); foreach(Thread t in this.Threads) { if (!t.Suspended) unsuspendedThreads.Add(t); @@ -657,40 +682,48 @@ namespace Debugger #region Break at begining - private void OnModulesAdded(object sender, CollectionItemEventArgs e) + int lastAssignedModuleOrderOfLoading = 0; + + internal void OnModuleLoaded(Module module) { - if (BreakAtBeginning) { - if (e.Item.SymReader == null) return; // No symbols + module.OrderOfLoading = lastAssignedModuleOrderOfLoading++; + + foreach (Breakpoint b in this.Debugger.Breakpoints) { + b.SetBreakpoint(module); + } + + if (this.BreakInMain) { + if (module.SymReader == null) return; // No symbols try { // create a BP at entry point - uint entryPoint = e.Item.SymReader.GetUserEntryPoint(); + uint entryPoint = module.SymReader.GetUserEntryPoint(); if (entryPoint == 0) return; // no EP - var mainFunction = e.Item.CorModule.GetFunctionFromToken(entryPoint); - var corBreakpoint = mainFunction.CreateBreakpoint(); + var corBreakpoint = module.CorModule.GetFunctionFromToken(entryPoint).CreateBreakpoint(); corBreakpoint.Activate(1); - - // create a SD BP - var breakpoint = new Breakpoint(this.debugger, corBreakpoint); - this.debugger.Breakpoints.Add(breakpoint); - breakpoint.Hit += delegate { - if (breakpoint != null) - breakpoint.Remove(); - breakpoint = null; - }; + this.tempBreakpoints.Add(corBreakpoint); } catch { // the app does not have an entry point - COM exception } - BreakAtBeginning = false; + + this.BreakInMain = false; } - if (ModulesAdded != null) - ModulesAdded(this, new ModuleEventArgs(e.Item)); + if (this.ModuleLoaded != null) { + this.ModuleLoaded(this, new ModuleEventArgs(module)); + } } - #endregion + internal void OnModuleUnloaded(Module module) + { + module.Dispose(); + + if (this.ModuleUnloaded != null) { + this.ModuleUnloaded(this, new ModuleEventArgs(module)); + } + } - public event EventHandler ModulesAdded; + #endregion public StackFrame GetCurrentExecutingFrame() { diff --git a/src/AddIns/Debugger/Debugger.Core/ProcessCollection.cs b/src/AddIns/Debugger/Debugger.Core/ProcessCollection.cs deleted file mode 100644 index b155531926..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/ProcessCollection.cs +++ /dev/null @@ -1,34 +0,0 @@ -// 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 Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class ProcessCollection: CollectionWithEvents - { - public ProcessCollection(NDebugger debugger): base(debugger) {} - - internal Process this[ICorDebugProcess corProcess] { - get { - foreach (Process process in this) { - if (process.CorProcess == corProcess) { - return process; - } - } - return null; - } - } - - protected override void OnRemoved(Process item) - { - base.OnRemoved(item); - - if (this.Count == 0) { - // Exit callback and then terminate the debugger - this.Debugger.MTA2STA.AsyncCall( delegate { this.Debugger.TerminateDebugger(); } ); - } - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/ProcessEventArgs.cs b/src/AddIns/Debugger/Debugger.Core/ProcessEventArgs.cs deleted file mode 100644 index e28f81aa15..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/ProcessEventArgs.cs +++ /dev/null @@ -1,22 +0,0 @@ -// 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; - -namespace Debugger -{ - [Serializable] - public class ProcessEventArgs: DebuggerEventArgs - { - Process process; - - public Process Process { - get { return process; } - } - - public ProcessEventArgs(Process process): base(process == null ? null : process.Debugger) - { - this.process = process; - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Core/Properties/AssemblyInfo.cs b/src/AddIns/Debugger/Debugger.Core/Properties/AssemblyInfo.cs index 6c9f5b87c5..ecd6793867 100644 --- a/src/AddIns/Debugger/Debugger.Core/Properties/AssemblyInfo.cs +++ b/src/AddIns/Debugger/Debugger.Core/Properties/AssemblyInfo.cs @@ -13,5 +13,5 @@ using System.Reflection; [assembly: AssemblyConfiguration("")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] -[assembly: AssemblyCopyright("2005-2008 David Srbecký")] +[assembly: AssemblyCopyright("2005-2012 David Srbecký")] [assembly: AssemblyVersion("4.0.0.0")] diff --git a/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs b/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs index 55b5f92b68..af985081b4 100644 --- a/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs +++ b/src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs @@ -13,68 +13,18 @@ namespace Debugger { public class SourcecodeSegment: DebuggerObject { - Module module; - - string filename; - string typename; - byte[] checkSum; - int startLine; - int startColumn; - int endLine; - int endColumn; - - ICorDebugFunction corFunction; - int ilStart; - int ilEnd; - int[] stepRanges; - - public Module Module { - get { return module; } - } - - public string Filename { - get { return filename; } - } - - public string Typename { - get { return typename; } - } - - public byte[] CheckSum { - get { return checkSum; } - } - - public int StartLine { - get { return startLine; } - } - - public int StartColumn { - get { return startColumn; } - } - - public int EndLine { - get { return endLine; } - } - - public int EndColumn { - get { return endColumn; } - } - - internal ICorDebugFunction CorFunction { - get { return corFunction; } - } - - public int ILStart { - get { return ilStart; } - } - - public int ILEnd { - get { return ilEnd; } - } - - public int[] StepRanges { - get { return stepRanges; } - } + public Module Module { get; private set; } + public string Filename { get; private set; } + public string Typename { get; private set; } + public byte[] CheckSum { get; private set; } + public int StartLine { get; private set; } + public int StartColumn { get; private set; } + public int EndLine { get; private set; } + public int EndColumn { get; private set; } + internal ICorDebugFunction CorFunction { get; private set; } + public int ILStart { get; private set; } + public int ILEnd { get; private set; } + public int[] StepRanges { get; private set; } private SourcecodeSegment() { @@ -150,7 +100,7 @@ namespace Debugger } } - static ISymUnmanagedDocument GetSymDocumentFromFilename(Module module, string filename, byte[] checksum) + static ISymUnmanagedDocument GetSymDocumentFromFilename(Module module, string filename) { if (filename == null) throw new ArgumentNullException("filename"); @@ -174,15 +124,17 @@ namespace Debugger return null; } - public static SourcecodeSegment Resolve(Module module, string fileName, byte[] checkSum, int line, int column) + public static SourcecodeSegment Resolve(Module module, string fileName, int line, int column) { // Do not use ISymUnmanagedReader.GetDocument! It is broken if two files have the same name // Do not use ISymUnmanagedMethod.GetOffset! It sometimes returns negative offset + if (fileName == null) return null; + ISymUnmanagedReader symReader = module.SymReader; if (symReader == null) return null; // No symbols - ISymUnmanagedDocument symDoc = GetSymDocumentFromFilename(module, fileName, checkSum); + ISymUnmanagedDocument symDoc = GetSymDocumentFromFilename(module, fileName); if (symDoc == null) return null; // Document not found ISymUnmanagedMethod symMethod; @@ -202,17 +154,17 @@ namespace Debugger // If the desired breakpoint position is before the end of the sequence point if (line < sqPoint.EndLine || (line == sqPoint.EndLine && column < sqPoint.EndColumn)) { SourcecodeSegment segment = new SourcecodeSegment(); - segment.module = module; - segment.filename = symDoc.GetURL(); - segment.checkSum = symDoc.GetCheckSum(); - segment.startLine = (int)sqPoint.Line; - segment.startColumn = (int)sqPoint.Column; - segment.endLine = (int)sqPoint.EndLine; - segment.endColumn = (int)sqPoint.EndColumn; - segment.corFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken()); - segment.ilStart = (int)sqPoint.Offset; - segment.ilEnd = (int)sqPoint.Offset; - segment.stepRanges = null; + segment.Module = module; + segment.Filename = symDoc.GetURL(); + segment.CheckSum = symDoc.GetCheckSum(); + segment.StartLine = (int)sqPoint.Line; + segment.StartColumn = (int)sqPoint.Column; + segment.EndLine = (int)sqPoint.EndLine; + segment.EndColumn = (int)sqPoint.EndColumn; + segment.CorFunction = module.CorModule.GetFunctionFromToken(symMethod.GetToken()); + segment.ILStart = (int)sqPoint.Offset; + segment.ILEnd = (int)sqPoint.Offset; + segment.StepRanges = null; return segment; } } @@ -300,21 +252,21 @@ namespace Debugger } SourcecodeSegment segment = new SourcecodeSegment(); - segment.module = module; - segment.filename = GetFilenameFromSymDocument(module, sequencePoints[i].Document); - segment.checkSum = sequencePoints[i].Document.GetCheckSum(); - segment.startLine = (int)sequencePoints[i].Line; - segment.startColumn = (int)sequencePoints[i].Column; - segment.endLine = (int)sequencePoints[i].EndLine; - segment.endColumn = (int)sequencePoints[i].EndColumn; - segment.corFunction = corFunction; - segment.ilStart = ilStart; - segment.ilEnd = ilEnd; - segment.stepRanges = stepRanges.ToArray(); + segment.Module = module; + segment.Filename = GetFilenameFromSymDocument(module, sequencePoints[i].Document); + segment.CheckSum = sequencePoints[i].Document.GetCheckSum(); + segment.StartLine = (int)sequencePoints[i].Line; + segment.StartColumn = (int)sequencePoints[i].Column; + segment.EndLine = (int)sequencePoints[i].EndLine; + segment.EndColumn = (int)sequencePoints[i].EndColumn; + segment.CorFunction = corFunction; + segment.ILStart = ilStart; + segment.ILEnd = ilEnd; + segment.StepRanges = stepRanges.ToArray(); // VB.NET sometimes produces temporary files which it then deletes // (eg 17d14f5c-a337-4978-8281-53493378c1071.vb) - string filename = Path.GetFileName(segment.filename); + string filename = Path.GetFileName(segment.Filename); if (filename.Length == 40 && filename.EndsWith(".vb")) { bool guidName = true; foreach(char c in filename.Substring(0, filename.Length - 3)) { @@ -343,7 +295,7 @@ namespace Debugger { return string.Format("{0}:{1},{2}-{3},{4}", Path.GetFileName(this.Filename ?? string.Empty), - this.startLine, this.startColumn, this.endLine, this.endColumn); + this.StartLine, this.StartColumn, this.EndLine, this.EndColumn); } #region Decompiled breakpoint @@ -352,17 +304,17 @@ namespace Debugger { 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; + 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 { @@ -372,19 +324,19 @@ namespace Debugger public static SourcecodeSegment ResolveForIL(Module module, ICorDebugFunction corFunction, int line, int offset, int[] ranges) { - try { + 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 = ranges[1]; - segment.stepRanges = ranges; + 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 = ranges[1]; + segment.StepRanges = ranges; return segment; } catch { diff --git a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs index 7a953b0b91..f0099cfb10 100644 --- a/src/AddIns/Debugger/Debugger.Core/StackFrame.cs +++ b/src/AddIns/Debugger/Debugger.Core/StackFrame.cs @@ -83,14 +83,14 @@ namespace Debugger { this.process = thread.Process; this.thread = thread; - this.appDomain = process.AppDomains[corILFrame.GetFunction().GetClass().GetModule().GetAssembly().GetAppDomain()]; + this.appDomain = process.GetAppDomain(corILFrame.GetFunction().GetClass().GetModule().GetAssembly().GetAppDomain()); this.corILFrame = corILFrame; this.corILFramePauseSession = process.PauseSession; this.corFunction = corILFrame.GetFunction(); this.chainIndex = chainIndex; this.frameIndex = frameIndex; - MetaDataImport metaData = thread.Process.Modules[corFunction.GetClass().GetModule()].MetaData; + MetaDataImport metaData = thread.Process.GetModule(corFunction.GetClass().GetModule()).MetaData; int methodGenArgs = metaData.EnumGenericParams(corFunction.GetToken()).Length; // Class parameters are first, then the method ones List corGenArgs = ((ICorDebugILFrame2)corILFrame).EnumerateTypeParameters().ToList(); @@ -263,7 +263,7 @@ namespace Debugger { process.AssertPaused(); - SourcecodeSegment segment = SourcecodeSegment.Resolve(this.MethodInfo.DebugModule, filename, null, line, column); + SourcecodeSegment segment = SourcecodeSegment.Resolve(this.MethodInfo.DebugModule, filename, line, column); if (segment != null && segment.CorFunction.GetToken() == this.MethodInfo.MetadataToken) { try { @@ -274,7 +274,7 @@ namespace Debugger CorILFrame.SetIP((uint)segment.ILStart); process.NotifyResumed(DebuggeeStateAction.Keep); process.NotifyPaused(PausedReason.SetIP); - process.RaisePausedEvents(); + process.OnPaused(new DebuggerEventArgs(process)); } } catch { return null; diff --git a/src/AddIns/Debugger/Debugger.Core/Stepper.cs b/src/AddIns/Debugger/Debugger.Core/Stepper.cs index c8bb8c8d94..3e36f904a7 100644 --- a/src/AddIns/Debugger/Debugger.Core/Stepper.cs +++ b/src/AddIns/Debugger/Debugger.Core/Stepper.cs @@ -118,7 +118,7 @@ namespace Debugger } [Serializable] - class StepperEventArgs: ProcessEventArgs + class StepperEventArgs: EventArgs { Stepper stepper; CorDebugStepReason reason; @@ -131,7 +131,7 @@ namespace Debugger get { return reason; } } - public StepperEventArgs(Stepper stepper, CorDebugStepReason reason): base(stepper.Process) + public StepperEventArgs(Stepper stepper, CorDebugStepReason reason) { this.stepper = stepper; this.reason = reason; diff --git a/src/AddIns/Debugger/Debugger.Core/Thread.cs b/src/AddIns/Debugger/Debugger.Core/Thread.cs index 9f25b02822..efe20c3999 100644 --- a/src/AddIns/Debugger/Debugger.Core/Thread.cs +++ b/src/AddIns/Debugger/Debugger.Core/Thread.cs @@ -24,14 +24,6 @@ namespace Debugger StackFrame selectedStackFrame; - Exception currentException; - DebuggeeState currentException_DebuggeeState; - ExceptionType currentExceptionType; - bool currentExceptionIsUnhandled; - - public event EventHandler NameChanged; - public event EventHandler Exited; - public Process Process { get { return process; } } @@ -94,15 +86,7 @@ namespace Debugger } this.HasExited = true; - OnExited(new ThreadEventArgs(this)); - process.Threads.Remove(this); - } - - protected virtual void OnExited(ThreadEventArgs e) - { - if (Exited != null) { - Exited(this, e); - } + process.threads.Remove(this); } /// If the thread is not at safe point, it is not posible to evaluate @@ -142,7 +126,7 @@ namespace Debugger process.AssertPaused(); ICorDebugValue corValue = this.CorThread.GetObject(); - return new Value(process.AppDomains[this.CorThread.GetAppDomain()], corValue); + return new Value(process.GetAppDomain(this.CorThread.GetAppDomain()), corValue); } } @@ -160,44 +144,6 @@ namespace Debugger } } - protected virtual void OnNameChanged(ThreadEventArgs e) - { - if (NameChanged != null) { - NameChanged(this, e); - } - } - - internal void NotifyNameChanged() - { - OnNameChanged(new ThreadEventArgs(this)); - } - - public Exception CurrentException { - get { - if (currentException_DebuggeeState == process.DebuggeeState) { - return currentException; - } else { - return null; - } - } - internal set { currentException = value; } - } - - internal DebuggeeState CurrentException_DebuggeeState { - get { return currentException_DebuggeeState; } - set { currentException_DebuggeeState = value; } - } - - public ExceptionType CurrentExceptionType { - get { return currentExceptionType; } - internal set { currentExceptionType = value; } - } - - public bool CurrentExceptionIsUnhandled { - get { return currentExceptionIsUnhandled; } - internal set { currentExceptionIsUnhandled = value; } - } - /// Tryies to intercept the current exception. /// The intercepted expression stays available through the CurrentException property. /// False, if the exception was already intercepted or @@ -220,9 +166,6 @@ namespace Debugger } if (mostRecentUnoptimized == null) return false; - if (exception == null) - exception = currentException; - try { // Interception will expire the CorValue so keep permanent reference exception.MakeValuePermanent(); @@ -380,21 +323,4 @@ namespace Debugger } } } - - [Serializable] - public class ThreadEventArgs : ProcessEventArgs - { - Thread thread; - - public Thread Thread { - get { - return thread; - } - } - - public ThreadEventArgs(Thread thread): base(thread.Process) - { - this.thread = thread; - } - } } diff --git a/src/AddIns/Debugger/Debugger.Core/ThreadCollection.cs b/src/AddIns/Debugger/Debugger.Core/ThreadCollection.cs deleted file mode 100644 index 500b52aa46..0000000000 --- a/src/AddIns/Debugger/Debugger.Core/ThreadCollection.cs +++ /dev/null @@ -1,53 +0,0 @@ -// 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 Debugger.Interop.CorDebug; - -namespace Debugger -{ - public class ThreadCollection: CollectionWithEvents - { - public ThreadCollection(NDebugger debugger): base(debugger) {} - - Thread selected; - - public Thread Selected { - get { return selected; } - set { selected = value; } - } - - public Thread Find(Predicate predicate) - { - if (predicate == null) - return null; - - foreach (var thread in this) - { - if (predicate(thread)) - return thread; - } - - return null; - } - - internal bool Contains(ICorDebugThread corThread) - { - foreach(Thread thread in this) { - if (thread.CorThread == corThread) return true; - } - return false; - } - - internal Thread this[ICorDebugThread corThread] { - get { - foreach(Thread thread in this) { - if (thread.CorThread == corThread) { - return thread; - } - } - throw new DebuggerException("Thread is not in collection"); - } - } - } -} diff --git a/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs b/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs index 9082f28cef..c1bcf1f6f9 100644 --- a/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs +++ b/src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs @@ -196,33 +196,30 @@ namespace Debugger.Tests log = ""; lastLogMessage = null; - process = debugger.Start(exeFilename, Path.GetDirectoryName(exeFilename), testName); + process = debugger.Start(exeFilename, Path.GetDirectoryName(exeFilename), testName, false); process.LogMessage += delegate(object sender, MessageEventArgs e) { log += e.Message; lastLogMessage = e.Message; LogEvent("LogMessage", e.Message.Replace("\r",@"\r").Replace("\n",@"\n")); }; - process.Modules.Added += delegate(object sender, CollectionItemEventArgs e) { - LogEvent("ModuleLoaded", e.Item.Name + (e.Item.HasSymbols ? " (Has symbols)" : " (No symbols)")); + process.ModuleLoaded += delegate(object sender, ModuleEventArgs e) { + LogEvent("ModuleLoaded", e.Module.Name + (e.Module.HasSymbols ? " (Has symbols)" : " (No symbols)")); }; - process.Paused += delegate(object sender, ProcessEventArgs e) { - LogEvent("DebuggingPaused", e.Process.PauseSession.PausedReason.ToString() + " " + e.Process.SelectedStackFrame.NextStatement.ToString()); - }; -// process.DebuggingResumed += delegate(object sender, ProcessEventArgs e) { -// LogEvent("DebuggingResumed", e.Process.PausedReason.ToString()); -// }; - process.ExceptionThrown += delegate(object sender, ExceptionEventArgs e) { - StringBuilder msg = new StringBuilder(); - if (process.SelectedThread.InterceptException(e.Exception)) { - msg.Append(e.Exception.ToString()); - } else { - // For example, happens on stack overflow - msg.Append("Could not intercept: "); - msg.Append(e.Exception.ToString()); + process.Paused += delegate(object sender, DebuggerEventArgs e) { + if (e.ExceptionThrown != null) { + StringBuilder msg = new StringBuilder(); + if (process.SelectedThread.InterceptException(e.ExceptionThrown)) { + msg.Append(e.ExceptionThrown.ToString()); + } else { + // For example, happens on stack overflow + msg.Append("Could not intercept: "); + msg.Append(e.ExceptionThrown.ToString()); + } + LogEvent("ExceptionThrown", msg.ToString()); } - LogEvent("ExceptionThrown", msg.ToString()); + LogEvent("DebuggingPaused", e.Process.PauseSession.PausedReason.ToString() + " " + e.Process.SelectedStackFrame.NextStatement.ToString()); }; - process.Exited += delegate(object sender, EventArgs e) { + process.Exited += delegate(object sender, DebuggerEventArgs e) { LogEvent("ProcessExited", null); }; diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/Breakpoint_Tests.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/Breakpoint_Tests.cs index 0909840898..8c83bdde08 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/Breakpoint_Tests.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/Breakpoint_Tests.cs @@ -28,8 +28,8 @@ namespace Debugger.Tests { [NUnit.Framework.Test] public void Breakpoint_Tests() { - Breakpoint breakpoint1 = debugger.Breakpoints.Add(@"Breakpoint_Tests.cs", 14); - Breakpoint breakpoint2 = debugger.Breakpoints.Add(@"Breakpoint_Tests.cs", 15); + Breakpoint breakpoint1 = debugger.AddBreakpoint(@"Breakpoint_Tests.cs", 14); + Breakpoint breakpoint2 = debugger.AddBreakpoint(@"Breakpoint_Tests.cs", 15); StartTest(); @@ -64,16 +64,16 @@ namespace Debugger.Tests { Break Breakpoint_Tests.cs:12,4-12,40 @@ -89,15 +89,15 @@ namespace Debugger.Tests { diff --git a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs index 7b91fbf995..7121b07e38 100644 --- a/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs +++ b/src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs @@ -60,12 +60,11 @@ namespace Debugger.Tests { ControlFlow_MainThreadExit.exe (Has symbols) Break ControlFlow_MainThreadExit.cs:20,4-20,40 + Capacity="4" + Count="2"> ForcedBreak ControlFlow_MainThreadExit.cs:25,4-25,26 + Capacity="4" + Count="2"> @@ -100,7 +97,6 @@ namespace Debugger.Tests { e) - { - e.Item.Threads.Added += delegate(object sender2, CollectionItemEventArgs f) { - ObjectDump("ThreadStartedEvent", f.Item); - }; - } } } #endif @@ -50,23 +44,23 @@ namespace Debugger.Tests { name="Thread_Tests.cs"> mscorlib.dll (No symbols) - + Thread_Tests.exe (Has symbols) + Break Thread_Tests.cs:12,4-12,40 + - - Thread_Tests.exe (Has symbols) - Break Thread_Tests.cs:13,4-13,40 + RuntimeValue="{System.Threading.Thread}" + SelectedStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()" /> + + Break Thread_Tests.cs:14,4-14,40 - Break Thread_Tests.cs:15,4-15,40 + Break Thread_Tests.cs:16,4-16,40 - - - diff --git a/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs b/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs index 3bdbcc5da4..a19452939c 100644 --- a/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs +++ b/src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs @@ -49,6 +49,8 @@ namespace ICSharpCode.SharpDevelop.Debugging } } + public object InternalBreakpointObject { get; set; } + public virtual bool IsHealthy { get { return isHealthy;