Browse Source

Removed several debugger events. Refactored event handling in the debugger addin.

newNRvisualizers
David Srbecký 14 years ago
parent
commit
0d4cd64ae6
  1. 1
      src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj
  2. 11
      src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs
  3. 2
      src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs
  4. 80
      src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs
  5. 10
      src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs
  6. 29
      src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs
  7. 2
      src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs
  8. 8
      src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs
  9. 9
      src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs
  10. 85
      src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs
  11. 55
      src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs
  12. 48
      src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs
  13. 57
      src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs
  14. 45
      src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs
  15. 8
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs
  16. 70
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs
  17. 4
      src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs
  18. 5
      src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs
  19. 58
      src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs
  20. 55
      src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs
  21. 2
      src/AddIns/Debugger/Debugger.AddIn/Service/DebuggeeExceptionForm.cs
  22. 20
      src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs
  23. 333
      src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs
  24. 24
      src/AddIns/Debugger/Debugger.Core/AppDomainCollection.cs
  25. 175
      src/AddIns/Debugger/Debugger.Core/Breakpoint.cs
  26. 102
      src/AddIns/Debugger/Debugger.Core/BreakpointCollection.cs
  27. 109
      src/AddIns/Debugger/Debugger.Core/CollectionWithEvents.cs
  28. 8
      src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj
  29. 2
      src/AddIns/Debugger/Debugger.Core/Eval.cs
  30. 23
      src/AddIns/Debugger/Debugger.Core/EvalCollection.cs
  31. 37
      src/AddIns/Debugger/Debugger.Core/Exception.cs
  32. 2
      src/AddIns/Debugger/Debugger.Core/ExceptionType.cs
  33. 75
      src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs
  34. 2
      src/AddIns/Debugger/Debugger.Core/ManagedCallbackSwitch.cs
  35. 4
      src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs
  36. 53
      src/AddIns/Debugger/Debugger.Core/Module.cs
  37. 50
      src/AddIns/Debugger/Debugger.Core/ModuleCollection.cs
  38. 167
      src/AddIns/Debugger/Debugger.Core/NDebugger.cs
  39. 271
      src/AddIns/Debugger/Debugger.Core/Process.cs
  40. 34
      src/AddIns/Debugger/Debugger.Core/ProcessCollection.cs
  41. 22
      src/AddIns/Debugger/Debugger.Core/ProcessEventArgs.cs
  42. 2
      src/AddIns/Debugger/Debugger.Core/Properties/AssemblyInfo.cs
  43. 176
      src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs
  44. 8
      src/AddIns/Debugger/Debugger.Core/StackFrame.cs
  45. 4
      src/AddIns/Debugger/Debugger.Core/Stepper.cs
  46. 78
      src/AddIns/Debugger/Debugger.Core/Thread.cs
  47. 53
      src/AddIns/Debugger/Debugger.Core/ThreadCollection.cs
  48. 35
      src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs
  49. 12
      src/AddIns/Debugger/Debugger.Tests/Tests/Breakpoint_Tests.cs
  50. 12
      src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs
  51. 4
      src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs
  52. 44
      src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs
  53. 2
      src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs

1
src/AddIns/Debugger/Debugger.AddIn/Debugger.AddIn.csproj

@ -266,7 +266,6 @@ @@ -266,7 +266,6 @@
<Compile Include="..\..\..\Main\GlobalAssemblyInfo.cs">
<Link>Properties\GlobalAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Pads\DebuggerPad.cs" />
<Compile Include="Pads\RunningThreadsPad.Menu.cs" />
<Compile Include="TreeModel\ValueNode.cs" />
<Compile Include="TreeModel\Utils.cs" />

11
src/AddIns/Debugger/Debugger.AddIn/NRefactory/ExpressionEvaluator.cs

@ -355,17 +355,6 @@ namespace ICSharpCode.NRefactory.Visitors @@ -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);

2
src/AddIns/Debugger/Debugger.AddIn/Options/DebuggingOptions.cs

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Xml.Serialization;
using Debugger;
using ICSharpCode.Core;

80
src/AddIns/Debugger/Debugger.AddIn/Pads/CallStackPad.xaml.cs

@ -21,8 +21,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -21,8 +21,6 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
/// </summary>
public partial class CallStackPadContent : UserControl
{
Process debuggedProcess;
public CallStackPadContent()
{
InitializeComponent();
@ -31,6 +29,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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();
}
}
}

10
src/AddIns/Debugger/Debugger.AddIn/Pads/Commands/WatchPadCommands.cs

@ -10,6 +10,7 @@ using ICSharpCode.Core; @@ -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 @@ -42,7 +43,7 @@ namespace Debugger.AddIn
list.WatchItems.Add(text);
}
pad.InvalidatePad();
WindowsDebugger.RefreshPads();
}
}
}
@ -60,7 +61,8 @@ namespace Debugger.AddIn @@ -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 @@ -69,9 +71,7 @@ namespace Debugger.AddIn
{
public override void Run()
{
if (this.Owner is WatchPad) {
((WatchPad)this.Owner).InvalidatePad();
}
WindowsDebugger.RefreshPads();
}
}

29
src/AddIns/Debugger/Debugger.AddIn/Pads/ConsolePad.cs

@ -45,6 +45,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -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 @@ -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 @@ -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 @@ -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;

2
src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/TreeNodeWrapper.cs

@ -75,7 +75,7 @@ namespace Debugger.AddIn.Pads.Controls @@ -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();
}
}
}

8
src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchList.xaml.cs

@ -13,6 +13,7 @@ using Debugger.AddIn.TreeModel; @@ -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 @@ -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 @@ -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;
}

9
src/AddIns/Debugger/Debugger.AddIn/Pads/Controls/WatchListAutoCompleteCell.cs

@ -65,15 +65,8 @@ namespace Debugger.AddIn.Pads.Controls @@ -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; }
/// <summary>
/// Gets/sets the command text displayed at the command prompt.
/// </summary>
@ -150,7 +143,7 @@ namespace Debugger.AddIn.Pads.Controls @@ -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);

85
src/AddIns/Debugger/Debugger.AddIn/Pads/DebuggerPad.cs

@ -1,85 +0,0 @@ @@ -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)
{
}
/// <summary>
/// Never call this directly. Always use InvalidatePad()
/// </summary>
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;
}
}
}

55
src/AddIns/Debugger/Debugger.AddIn/Pads/LoadedModulesPad.cs

@ -11,17 +11,23 @@ using Debugger; @@ -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<ModuleModel> loadedModules;
protected override void InitializeComponents()
public override object Control {
get { return panel; }
}
public LoadedModulesPad()
{
this.panel = new DockPanel();
loadedModulesList = new ListView();
loadedModules = new ObservableCollection<ModuleModel>();
loadedModulesList.ItemsSource = loadedModules;
@ -29,6 +35,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -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 @@ -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<Module> e)
{
AddModule(e.Item);
}
void debuggedProcess_ModuleUnloaded(object sender, CollectionItemEventArgs<Module> 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

48
src/AddIns/Debugger/Debugger.AddIn/Pads/LocalVarPad.cs

@ -3,25 +3,38 @@ @@ -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();
}
/// <remarks>Always check if Instance is null, might be null if pad is not opened!</remarks>
@ -29,35 +42,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -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;

57
src/AddIns/Debugger/Debugger.AddIn/Pads/MemoryPad.cs

@ -7,26 +7,40 @@ using System.Globalization; @@ -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<Tuple<long, long>> memoryAddresses = new List<Tuple<long, long>>();
Dictionary<long, int> addressesMapping = new Dictionary<long, int>();
public override object Control {
get {
return panel;
}
}
public Process debuggedProcess {
get {
return WindowsDebugger.CurrentProcess;
}
}
/// <summary>
/// Gets or sets the number of columns in the display
/// </summary>
@ -61,10 +75,15 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -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 @@ -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 @@ -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 @@ -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;

45
src/AddIns/Debugger/Debugger.AddIn/Pads/ObjectGraphPad.cs

@ -1,6 +1,7 @@ @@ -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; @@ -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
{
/// <summary>
/// Description of ObjectGraphPad.
/// </summary>
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();
}
/// <remarks>Always check if Instance is null, might be null if pad is not opened!</remarks>
@ -30,15 +43,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -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 @@ -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();
}
}
}

8
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackFrameModel.cs

@ -73,7 +73,6 @@ namespace Debugger.AddIn.Pads.ParallelPad @@ -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 @@ -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 {

70
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ParallelStackPad.cs

@ -20,6 +20,7 @@ using ICSharpCode.SharpDevelop.Bookmarks; @@ -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 @@ -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<ThreadStack> currentThreadStacks = new List<ThreadStack>();
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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -369,7 +362,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
}
}
void CreateMethodViewStacks()
void CreateMethodViewStacks(Process debuggedProcess)
{
var list = new List<Tuple<ObservableCollection<ParallelStackFrameModel>, ObservableCollection<ParallelStackFrameModel>, List<uint>>>();
@ -439,6 +432,8 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -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 @@ -465,6 +460,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
int noTasks = 0;
var result = new ObservableCollection<ParallelStackFrameModel>();
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 @@ -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 @@ -583,7 +579,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
ToggleSelectedFrameBookmark(e.Location);
if (isMethodView)
InvalidatePad();
WindowsDebugger.RefreshPads();
}
#endregion

4
src/AddIns/Debugger/Debugger.AddIn/Pads/ParallelPad/ThreadStack.xaml.cs

@ -5,11 +5,11 @@ using System; @@ -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 @@ -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;

5
src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.Menu.cs

@ -9,6 +9,7 @@ using System.Windows.Controls; @@ -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 @@ -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 @@ -56,7 +57,7 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads
foreach(ThreadModel current in items.OfType<ThreadModel>()) {
current.Thread.Suspended = !suspended;
}
InvalidatePad();
WindowsDebugger.RefreshPads();
};
menu.Items.Add(freezeItem);

58
src/AddIns/Debugger/Debugger.AddIn/Pads/RunningThreadsPad.cs

@ -20,14 +20,19 @@ using Thread = Debugger.Thread; @@ -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<ThreadModel> runningThreads;
Process debuggedProcess;
protected override void InitializeComponents()
public override object Control {
get { return panel; }
}
public RunningThreadsPad()
{
this.panel = new DockPanel();
runningThreads = new ObservableCollection<ThreadModel>();
runningThreadsList = new ListView();
runningThreadsList.ContextMenu = CreateContextMenuStrip();
@ -38,6 +43,9 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -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 @@ -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<Thread> 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 @@ -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 @@ -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 @@ -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)

55
src/AddIns/Debugger/Debugger.AddIn/Pads/WatchPad.cs

@ -6,6 +6,7 @@ using System.Collections.Generic; @@ -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; @@ -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; }
}
/// <remarks>Always check if Instance is null, might be null if pad is not opened!</remarks>
public static WatchPad Instance {
get { return instance; }
@ -44,15 +50,10 @@ namespace ICSharpCode.SharpDevelop.Gui.Pads @@ -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 @@ -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 @@ -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 @@ -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 @@ -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))
);
}
}

2
src/AddIns/Debugger/Debugger.AddIn/Service/DebuggeeExceptionForm.cs

@ -104,7 +104,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -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();

20
src/AddIns/Debugger/Debugger.AddIn/Service/RunToCursorCommand.cs

@ -1,6 +1,7 @@ @@ -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 @@ -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);
}
}
}

333
src/AddIns/Debugger/Debugger.AddIn/Service/WindowsDebugger.cs

@ -50,22 +50,9 @@ namespace ICSharpCode.SharpDevelop.Services @@ -50,22 +50,9 @@ namespace ICSharpCode.SharpDevelop.Services
internal IDebuggerDecompilerService debuggerDecompilerService;
//DynamicTreeDebuggerRow currentTooltipRow;
//Expression currentTooltipExpression;
public NDebugger DebuggerCore { get { return debugger; } }
public event EventHandler<ProcessEventArgs> 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 @@ -78,19 +65,26 @@ namespace ICSharpCode.SharpDevelop.Services
}
}
/// <inheritdoc/>
public bool BreakAtBeginning {
get;
set;
public static event EventHandler<DebuggerEventArgs> 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);
}
}
/// <inheritdoc/>
public bool BreakAtBeginning {
get;
set;
}
public bool ServiceInitialized {
get {
return debugger != null;
@ -159,13 +153,13 @@ namespace ICSharpCode.SharpDevelop.Services @@ -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 @@ -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 @@ -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 @@ -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 @@ -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<BreakpointBookmark>()) {
Breakpoint breakpoint = bookmark.InternalBreakpointObject as Breakpoint;
breakpoint.Line = bookmark.LineNumber;
breakpoint.Column = bookmark.ColumnNumber;
}
}
void UpdateBreakpointIcons()
{
foreach (BreakpointBookmark bookmark in BookmarkManager.Bookmarks.OfType<BreakpointBookmark>()) {
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 @@ -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 @@ -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<CollectionItemEventArgs<Process>> bp_debugger_ProcessStarted = (sender, e) => {
setBookmarkColor();
// User can change line number by inserting or deleting lines
breakpoint.Line = bookmark.LineNumber;
};
EventHandler<CollectionItemEventArgs<Process>> bp_debugger_ProcessExited = (sender, e) => {
setBookmarkColor();
};
EventHandler<BreakpointEventArgs> bp_debugger_BreakpointHit =
new EventHandler<BreakpointEventArgs>(
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 @@ -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<Process> 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<Process> 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<DecompiledBreakpointBookmark>()) {
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<BreakpointBookmark>().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 @@ -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 @@ -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<Module> 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) }));
}
}
}

24
src/AddIns/Debugger/Debugger.Core/AppDomainCollection.cs

@ -1,24 +0,0 @@ @@ -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<AppDomain>
{
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");
}
}
}
}

175
src/AddIns/Debugger/Debugger.Core/Breakpoint.cs

@ -11,103 +11,43 @@ namespace Debugger @@ -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<ICorDebugFunctionBreakpoint> corBreakpoints = new List<ICorDebugFunctionBreakpoint>();
public event EventHandler<BreakpointEventArgs> Hit;
public event EventHandler<BreakpointEventArgs> 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 @@ -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;
}
/// <summary> Remove this breakpoint </summary>
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 @@ -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;
}
}
}

102
src/AddIns/Debugger/Debugger.Core/BreakpointCollection.cs

@ -1,102 +0,0 @@ @@ -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<Breakpoint>
{
public event EventHandler<CollectionItemEventArgs<Breakpoint>> Hit;
protected internal void OnHit(Breakpoint item)
{
if (Hit != null) {
Hit(this, new CollectionItemEventArgs<Breakpoint>(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<Breakpoint> collection = new List<Breakpoint>();
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);
}
}
}
}
}

109
src/AddIns/Debugger/Debugger.Core/CollectionWithEvents.cs

@ -1,109 +0,0 @@ @@ -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<T> : EventArgs
{
T item;
public T Item {
get {
return item;
}
}
public CollectionItemEventArgs(T item)
{
this.item = item;
}
}
/// <summary>
/// A collection that fires events when items are added or removed.
/// </summary>
public class CollectionWithEvents<T> : IEnumerable<T>
{
NDebugger debugger;
List<T> list = new List<T>();
public event EventHandler<CollectionItemEventArgs<T>> Added;
public event EventHandler<CollectionItemEventArgs<T>> Removed;
protected virtual void OnAdded(T item)
{
if (Added != null) {
Added(this, new CollectionItemEventArgs<T>(item));
}
}
protected virtual void OnRemoved(T item)
{
if (Removed != null) {
Removed(this, new CollectionItemEventArgs<T>(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<T> oldList = list;
list = new List<T>();
foreach (T item in oldList) {
OnRemoved(item);
}
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return list.GetEnumerator();
}
}
}

8
src/AddIns/Debugger/Debugger.Core/Debugger.Core.csproj

@ -64,17 +64,13 @@ @@ -64,17 +64,13 @@
<Compile Include="MetaData\DebugConstructorInfo.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="AppDomain.cs" />
<Compile Include="AppDomainCollection.cs" />
<Compile Include="ArrayDimension.cs" />
<Compile Include="ArrayDimensions.cs" />
<Compile Include="Breakpoint.cs" />
<Compile Include="BreakpointCollection.cs" />
<Compile Include="CollectionWithEvents.cs" />
<Compile Include="DebuggeeState.cs" />
<Compile Include="DebuggerException.cs" />
<Compile Include="DebuggerObject.cs" />
<Compile Include="Eval.cs" />
<Compile Include="EvalCollection.cs" />
<Compile Include="Exception.cs" />
<Compile Include="ExceptionType.cs" />
<Compile Include="GetValueException.cs" />
@ -102,7 +98,6 @@ @@ -102,7 +98,6 @@
<Compile Include="MetaData\IDebugMemberInfo.cs" />
<Compile Include="MetaData\IOverloadable.cs" />
<Compile Include="Module.cs" />
<Compile Include="ModuleCollection.cs" />
<Compile Include="Mono.Cecil\Mono.Cecil.Binary\ImageFormatException.cs" />
<Compile Include="Mono.Cecil\Mono.Cecil.Metadata\CodedIndex.cs" />
<Compile Include="Mono.Cecil\Mono.Cecil.Metadata\ElementType.cs" />
@ -148,8 +143,6 @@ @@ -148,8 +143,6 @@
<Compile Include="PausedReason.cs" />
<Compile Include="PauseSession.cs" />
<Compile Include="Process.cs" />
<Compile Include="ProcessCollection.cs" />
<Compile Include="ProcessEventArgs.cs" />
<Compile Include="SourcecodeSegment.cs" />
<Compile Include="StackFrame.cs" />
<Compile Include="Stepper.cs" />
@ -157,7 +150,6 @@ @@ -157,7 +150,6 @@
<Compile Include="Tests\IgnoreAttribute.cs" />
<Compile Include="Tests\IgnoreOnExceptionAttribute.cs" />
<Compile Include="Thread.cs" />
<Compile Include="ThreadCollection.cs" />
<Compile Include="Value.cs" />
<None Include="Stepping.txt" />
</ItemGroup>

2
src/AddIns/Debugger/Debugger.Core/Eval.cs

@ -120,7 +120,7 @@ namespace Debugger @@ -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);

23
src/AddIns/Debugger/Debugger.Core/EvalCollection.cs

@ -1,23 +0,0 @@ @@ -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<Eval>
{
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");
}
}
}
}

37
src/AddIns/Debugger/Debugger.Core/Exception.cs

@ -15,9 +15,16 @@ namespace Debugger @@ -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;
}
/// <summary> The <c>GetType().FullName</c> of the exception. </summary>
@ -42,7 +49,7 @@ namespace Debugger @@ -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 @@ -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;
}
}
}

2
src/AddIns/Debugger/Debugger.Core/ExceptionType.cs

@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
namespace Debugger
{
public enum ExceptionType
enum ExceptionType
{
FirstChance = 1,
UserFirstChance = 2,

75
src/AddIns/Debugger/Debugger.Core/ManagedCallback.cs

@ -2,6 +2,7 @@ @@ -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 @@ -24,6 +25,9 @@ namespace Debugger
bool pauseOnNextExit;
bool isInCallback = false;
List<Breakpoint> breakpointsHit = new List<Breakpoint>();
Exception exceptionThrown;
[Debugger.Tests.Ignore]
public Process Process {
get { return process; }
@ -74,7 +78,7 @@ namespace Debugger @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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;
}

2
src/AddIns/Debugger/Debugger.Core/ManagedCallbackSwitch.cs

@ -73,7 +73,7 @@ namespace Debugger @@ -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) {

4
src/AddIns/Debugger/Debugger.Core/MetaData/DebugType.cs

@ -1075,7 +1075,7 @@ namespace Debugger.MetaData @@ -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 @@ -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");

53
src/AddIns/Debugger/Debugger.Core/Module.cs

@ -29,11 +29,6 @@ namespace Debugger @@ -29,11 +29,6 @@ namespace Debugger
internal Dictionary<string, DebugType> LoadedDebugTypes = new Dictionary<string, DebugType>();
/// <summary>
/// Occurs when symbols are loaded or unloaded (for memory modules)
/// </summary>
public event EventHandler<ModuleEventArgs> SymbolsUpdated;
public AppDomain AppDomain {
get { return appDomain; }
}
@ -222,11 +217,11 @@ namespace Debugger @@ -222,11 +217,11 @@ namespace Debugger
/// <summary>
/// Load symblos for on-disk module
/// </summary>
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 @@ -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<Breakpoint> collection = new List<Breakpoint>();
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 @@ -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;
}
}
}

50
src/AddIns/Debugger/Debugger.Core/ModuleCollection.cs

@ -1,50 +0,0 @@ @@ -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<Module>
{
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();
}
}
}

167
src/AddIns/Debugger/Debugger.Core/NDebugger.cs

@ -2,6 +2,7 @@ @@ -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 @@ -17,8 +18,8 @@ namespace Debugger
ManagedCallbackSwitch managedCallbackSwitch;
ManagedCallbackProxy managedCallbackProxy;
BreakpointCollection breakpoints;
ProcessCollection processes;
internal List<Breakpoint> breakpoints = new List<Breakpoint>();
internal List<Process> processes = new List<Process>();
MTA2STA mta2sta = new MTA2STA();
@ -49,19 +50,16 @@ namespace Debugger @@ -49,19 +50,16 @@ namespace Debugger
set { options = value; }
}
public BreakpointCollection Breakpoints {
get { return breakpoints; }
public IEnumerable<Breakpoint> Breakpoints {
get { return this.breakpoints; }
}
public ProcessCollection Processes {
get { return processes; }
public IEnumerable<Process> 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 @@ -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;
}
/// <summary>
/// Get the .NET version of the process that called this function
/// </summary>
@ -137,38 +144,57 @@ namespace Debugger @@ -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");
}
/// <summary>
/// Internal: Used to debug the debugger library.
/// </summary>
public event EventHandler<MessageEventArgs> 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 @@ -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 @@ -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;
}
}
}

271
src/AddIns/Debugger/Debugger.Core/Process.cs

@ -42,13 +42,21 @@ namespace Debugger @@ -42,13 +42,21 @@ namespace Debugger
ICorDebugProcess corProcess;
ManagedCallback callbackInterface;
EvalCollection activeEvals;
ModuleCollection modules;
ThreadCollection threads;
AppDomainCollection appDomains;
List<ICorDebugFunctionBreakpoint> tempBreakpoints = new List<ICorDebugFunctionBreakpoint>();
internal List<Eval> activeEvals = new List<Eval>();
internal List<Module> modules = new List<Module>();
internal List<Thread> threads = new List<Thread>();
internal List<AppDomain> appDomains = new List<AppDomain>();
string workingDirectory;
public event EventHandler<MessageEventArgs> LogMessage;
public event EventHandler<ModuleEventArgs> ModuleLoaded;
public event EventHandler<ModuleEventArgs> ModuleUnloaded;
public event EventHandler<DebuggerEventArgs> Paused;
public event EventHandler<DebuggerEventArgs> Resumed;
public event EventHandler<DebuggerEventArgs> Exited;
public NDebugger Debugger {
get { return debugger; }
@ -70,26 +78,19 @@ namespace 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<Module> Modules {
get { return this.modules; }
}
public ThreadCollection Threads {
get { return threads; }
public IEnumerable<Thread> 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 @@ -111,12 +112,9 @@ namespace Debugger
}
}
public bool BreakAtBeginning {
get;
set;
}
internal bool BreakInMain { get; set; }
public AppDomainCollection AppDomains {
public IEnumerable<AppDomain> AppDomains {
get { return appDomains; }
}
@ -139,12 +137,6 @@ namespace Debugger @@ -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 @@ -187,14 +179,10 @@ namespace Debugger
return new Process(debugger, outProcess, workingDirectory);
}
/// <summary> Fired when System.Diagnostics.Trace.WriteLine() is called in debuged process </summary>
public event EventHandler<MessageEventArgs> 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 @@ -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;
}
/// <summary> Read the specified amount of memory at the given memory address </summary>
@ -231,34 +274,24 @@ namespace Debugger @@ -231,34 +274,24 @@ namespace Debugger
return written;
}
#region Exceptions
public event EventHandler<ExceptionEventArgs> 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<Breakpoint> BreakpointHitEventQueue = new Queue<Breakpoint>();
#region Events
public event EventHandler<ProcessEventArgs> Paused;
public event EventHandler<ProcessEventArgs> 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 @@ -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 @@ -330,36 +363,6 @@ namespace Debugger
}
}
/// <summary> Sets up the eviroment and raises user events </summary>
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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -451,7 +461,7 @@ namespace Debugger
// threads
this.threads.Clear();
NotifyHasExited();
OnExited();
}
public void Continue()
@ -460,9 +470,24 @@ namespace Debugger @@ -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<Thread> unsuspendedThreads = new List<Thread>(this.Threads.Count);
List<Thread> unsuspendedThreads = new List<Thread>();
foreach(Thread t in this.Threads) {
if (!t.Suspended)
unsuspendedThreads.Add(t);
@ -657,40 +682,48 @@ namespace Debugger @@ -657,40 +682,48 @@ namespace Debugger
#region Break at begining
private void OnModulesAdded(object sender, CollectionItemEventArgs<Module> 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<ModuleEventArgs> ModulesAdded;
#endregion
public StackFrame GetCurrentExecutingFrame()
{

34
src/AddIns/Debugger/Debugger.Core/ProcessCollection.cs

@ -1,34 +0,0 @@ @@ -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<Process>
{
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(); } );
}
}
}
}

22
src/AddIns/Debugger/Debugger.Core/ProcessEventArgs.cs

@ -1,22 +0,0 @@ @@ -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;
}
}
}

2
src/AddIns/Debugger/Debugger.Core/Properties/AssemblyInfo.cs

@ -13,5 +13,5 @@ using System.Reflection; @@ -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")]

176
src/AddIns/Debugger/Debugger.Core/SourcecodeSegment.cs

@ -13,68 +13,18 @@ namespace Debugger @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 {

8
src/AddIns/Debugger/Debugger.Core/StackFrame.cs

@ -83,14 +83,14 @@ namespace Debugger @@ -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<ICorDebugType> corGenArgs = ((ICorDebugILFrame2)corILFrame).EnumerateTypeParameters().ToList();
@ -263,7 +263,7 @@ namespace Debugger @@ -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 @@ -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;

4
src/AddIns/Debugger/Debugger.Core/Stepper.cs

@ -118,7 +118,7 @@ namespace Debugger @@ -118,7 +118,7 @@ namespace Debugger
}
[Serializable]
class StepperEventArgs: ProcessEventArgs
class StepperEventArgs: EventArgs
{
Stepper stepper;
CorDebugStepReason reason;
@ -131,7 +131,7 @@ namespace Debugger @@ -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;

78
src/AddIns/Debugger/Debugger.Core/Thread.cs

@ -24,14 +24,6 @@ namespace Debugger @@ -24,14 +24,6 @@ namespace Debugger
StackFrame selectedStackFrame;
Exception currentException;
DebuggeeState currentException_DebuggeeState;
ExceptionType currentExceptionType;
bool currentExceptionIsUnhandled;
public event EventHandler<ThreadEventArgs> NameChanged;
public event EventHandler<ThreadEventArgs> Exited;
public Process Process {
get { return process; }
}
@ -94,15 +86,7 @@ namespace Debugger @@ -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);
}
/// <summary> If the thread is not at safe point, it is not posible to evaluate
@ -142,7 +126,7 @@ namespace Debugger @@ -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 @@ -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; }
}
/// <summary> Tryies to intercept the current exception.
/// The intercepted expression stays available through the CurrentException property. </summary>
/// <returns> False, if the exception was already intercepted or
@ -220,9 +166,6 @@ namespace Debugger @@ -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 @@ -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;
}
}
}

53
src/AddIns/Debugger/Debugger.Core/ThreadCollection.cs

@ -1,53 +0,0 @@ @@ -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<Thread>
{
public ThreadCollection(NDebugger debugger): base(debugger) {}
Thread selected;
public Thread Selected {
get { return selected; }
set { selected = value; }
}
public Thread Find(Predicate<Thread> 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");
}
}
}
}

35
src/AddIns/Debugger/Debugger.Tests/DebuggerTestsBase.cs

@ -196,33 +196,30 @@ namespace Debugger.Tests @@ -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<Module> 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);
};

12
src/AddIns/Debugger/Debugger.Tests/Tests/Breakpoint_Tests.cs

@ -28,8 +28,8 @@ namespace Debugger.Tests { @@ -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 { @@ -64,16 +64,16 @@ namespace Debugger.Tests {
<DebuggingPaused>Break Breakpoint_Tests.cs:12,4-12,40</DebuggingPaused>
<Breakpoint1>
<Breakpoint
Enabled="True"
FileName="Breakpoint_Tests.cs"
IsEnabled="True"
IsSet="True"
Line="14"
OriginalLocation="Breakpoint_Tests.cs:14,4-14,49" />
</Breakpoint1>
<Breakpoint2>
<Breakpoint
Enabled="True"
FileName="Breakpoint_Tests.cs"
IsEnabled="True"
IsSet="True"
Line="15"
OriginalLocation="Breakpoint_Tests.cs:16,4-16,49" />
@ -89,15 +89,15 @@ namespace Debugger.Tests { @@ -89,15 +89,15 @@ namespace Debugger.Tests {
<ProcessExited />
<Breakpoint1>
<Breakpoint
Enabled="True"
FileName="Breakpoint_Tests.cs"
IsEnabled="True"
Line="14"
OriginalLocation="Breakpoint_Tests.cs:14,4-14,49" />
</Breakpoint1>
<Breakpoint2>
<Breakpoint
Enabled="True"
FileName="Breakpoint_Tests.cs"
IsEnabled="True"
Line="15"
OriginalLocation="Breakpoint_Tests.cs:16,4-16,49" />
</Breakpoint2>

12
src/AddIns/Debugger/Debugger.Tests/Tests/ControlFlow_MainThreadExit.cs

@ -60,12 +60,11 @@ namespace Debugger.Tests { @@ -60,12 +60,11 @@ namespace Debugger.Tests {
<ModuleLoaded>ControlFlow_MainThreadExit.exe (Has symbols)</ModuleLoaded>
<DebuggingPaused>Break ControlFlow_MainThreadExit.cs:20,4-20,40</DebuggingPaused>
<ThreadsBeforeExit
Count="2"
Selected="Thread Name = Suspended = False">
Capacity="4"
Count="2">
<Item>
<Thread
Callstack="{static System.Void Debugger.Tests.ControlFlow_MainThreadExit.Main()}"
CurrentExceptionType="0"
IsAtSafePoint="True"
IsInValidState="True"
MostRecentStackFrame="static System.Void Debugger.Tests.ControlFlow_MainThreadExit.Main()"
@ -77,7 +76,6 @@ namespace Debugger.Tests { @@ -77,7 +76,6 @@ namespace Debugger.Tests {
<Item>
<Thread
Callstack="{static Boolean System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle waitableSafeHandle, System.Int64 millisecondsTimeout, System.Boolean hasThreadAffinity, System.Boolean exitContext), Boolean System.Threading.WaitHandle.WaitOne(System.Int32 millisecondsTimeout, System.Boolean exitContext), Boolean System.Threading.WaitHandle.WaitOne(), static System.Void Debugger.Tests.ControlFlow_MainThreadExit.WaitForALongTime(), static System.Void System.Threading.ThreadHelper.ThreadStart_Context(System.Object state), static System.Void System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean ignoreSyncCtx), static System.Void System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state), System.Void System.Threading.ThreadHelper.ThreadStart()}"
CurrentExceptionType="0"
IsAtSafePoint="True"
IsInValidState="True"
MostRecentStackFrame="static Boolean System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle waitableSafeHandle, System.Int64 millisecondsTimeout, System.Boolean hasThreadAffinity, System.Boolean exitContext)"
@ -88,11 +86,10 @@ namespace Debugger.Tests { @@ -88,11 +86,10 @@ namespace Debugger.Tests {
</ThreadsBeforeExit>
<DebuggingPaused>ForcedBreak ControlFlow_MainThreadExit.cs:25,4-25,26</DebuggingPaused>
<ThreadsAfterExit
Count="2"
Selected="Thread Name = Worker thread Suspended = False">
Capacity="4"
Count="2">
<Item>
<Thread
CurrentExceptionType="0"
Name=""
Priority="Normal"
RuntimeValue="{Exception: The state of the thread is invalid. (Exception from HRESULT: 0x8013132D)}" />
@ -100,7 +97,6 @@ namespace Debugger.Tests { @@ -100,7 +97,6 @@ namespace Debugger.Tests {
<Item>
<Thread
Callstack="{static Boolean System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle waitableSafeHandle, System.Int64 millisecondsTimeout, System.Boolean hasThreadAffinity, System.Boolean exitContext), Boolean System.Threading.WaitHandle.WaitOne(System.Int32 millisecondsTimeout, System.Boolean exitContext), Boolean System.Threading.WaitHandle.WaitOne(), static System.Void Debugger.Tests.ControlFlow_MainThreadExit.WaitForALongTime(), static System.Void System.Threading.ThreadHelper.ThreadStart_Context(System.Object state), static System.Void System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean ignoreSyncCtx), static System.Void System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state), System.Void System.Threading.ThreadHelper.ThreadStart()}"
CurrentExceptionType="0"
IsAtSafePoint="True"
IsInValidState="True"
MostRecentStackFrame="static Boolean System.Threading.WaitHandle.InternalWaitOne(System.Runtime.InteropServices.SafeHandle waitableSafeHandle, System.Int64 millisecondsTimeout, System.Boolean hasThreadAffinity, System.Boolean exitContext)"

4
src/AddIns/Debugger/Debugger.Tests/Tests/DebugType_Tests.cs

@ -232,8 +232,8 @@ namespace Debugger.Tests { @@ -232,8 +232,8 @@ namespace Debugger.Tests {
process.Options.StepOverSingleLineProperties = false;
process.Options.StepOverFieldAccessProperties = true;
ObjectDump("DefinedTypes", process.Modules["DebugType_Tests.exe"].GetNamesOfDefinedTypes());
ObjectDump("DefinedTypes", process.Modules["DebugType_Tests.exe"].GetDefinedTypes());
ObjectDump("DefinedTypes", process.GetModule("DebugType_Tests.exe").GetNamesOfDefinedTypes());
ObjectDump("DefinedTypes", process.GetModule("DebugType_Tests.exe").GetDefinedTypes());
ObjectDump("Members", process.SelectedStackFrame.GetLocalVariableValue("members").Type.GetMembers(DebugType.BindingFlagsAllDeclared));
ObjectDump("Access-Members", process.SelectedStackFrame.GetLocalVariableValue("access").Type.GetMembers());

44
src/AddIns/Debugger/Debugger.Tests/Tests/Thread_Tests.cs

@ -9,6 +9,7 @@ namespace Debugger.Tests @@ -9,6 +9,7 @@ namespace Debugger.Tests
{
public static void Main()
{
System.Diagnostics.Debugger.Break();
System.Threading.Thread.CurrentThread.Priority = System.Threading.ThreadPriority.AboveNormal;
System.Diagnostics.Debugger.Break();
System.Threading.Thread.CurrentThread.Name = "ThreadName";
@ -24,21 +25,14 @@ namespace Debugger.Tests { @@ -24,21 +25,14 @@ namespace Debugger.Tests {
[NUnit.Framework.Test]
public void Thread_Tests()
{
debugger.Processes.Added += debugger_ProcessStarted;
StartTest();
debugger.Processes.Added -= debugger_ProcessStarted;
ObjectDump("Thread", process.SelectedThread);
process.Continue();
ObjectDump("Thread", process.SelectedThread);
process.Continue();
ObjectDump("Thread", process.SelectedThread);
EndTest();
}
void debugger_ProcessStarted(object sender, CollectionItemEventArgs<Process> e)
{
e.Item.Threads.Added += delegate(object sender2, CollectionItemEventArgs<Thread> f) {
ObjectDump("ThreadStartedEvent", f.Item);
};
}
}
}
#endif
@ -50,23 +44,23 @@ namespace Debugger.Tests { @@ -50,23 +44,23 @@ namespace Debugger.Tests {
name="Thread_Tests.cs">
<ProcessStarted />
<ModuleLoaded>mscorlib.dll (No symbols)</ModuleLoaded>
<ThreadStartedEvent>
<ModuleLoaded>Thread_Tests.exe (Has symbols)</ModuleLoaded>
<DebuggingPaused>Break Thread_Tests.cs:12,4-12,40</DebuggingPaused>
<Thread>
<Thread
Callstack="{System.Void System.AppDomain.SetupDomain(System.Boolean allowRedirects, System.String path, System.String configFile, System.String[] propertyNames, System.String[] propertyValues)}"
CurrentExceptionType="0"
Callstack="{static System.Void Debugger.Tests.Thread_Tests.Main()}"
IsAtSafePoint="True"
IsInValidState="True"
MostRecentStackFrame="System.Void System.AppDomain.SetupDomain(System.Boolean allowRedirects, System.String path, System.String configFile, System.String[] propertyNames, System.String[] propertyValues)"
MostRecentStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()"
Name=""
Priority="Normal"
RuntimeValue="null" />
</ThreadStartedEvent>
<ModuleLoaded>Thread_Tests.exe (Has symbols)</ModuleLoaded>
<DebuggingPaused>Break Thread_Tests.cs:13,4-13,40</DebuggingPaused>
RuntimeValue="{System.Threading.Thread}"
SelectedStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()" />
</Thread>
<DebuggingPaused>Break Thread_Tests.cs:14,4-14,40</DebuggingPaused>
<Thread>
<Thread
Callstack="{static System.Void Debugger.Tests.Thread_Tests.Main()}"
CurrentExceptionType="0"
IsAtSafePoint="True"
IsInValidState="True"
MostRecentStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()"
@ -75,11 +69,10 @@ namespace Debugger.Tests { @@ -75,11 +69,10 @@ namespace Debugger.Tests {
RuntimeValue="{System.Threading.Thread}"
SelectedStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()" />
</Thread>
<DebuggingPaused>Break Thread_Tests.cs:15,4-15,40</DebuggingPaused>
<DebuggingPaused>Break Thread_Tests.cs:16,4-16,40</DebuggingPaused>
<Thread>
<Thread
Callstack="{static System.Void Debugger.Tests.Thread_Tests.Main()}"
CurrentExceptionType="0"
IsAtSafePoint="True"
IsInValidState="True"
MostRecentStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()"
@ -88,17 +81,6 @@ namespace Debugger.Tests { @@ -88,17 +81,6 @@ namespace Debugger.Tests {
RuntimeValue="{System.Threading.Thread}"
SelectedStackFrame="static System.Void Debugger.Tests.Thread_Tests.Main()" />
</Thread>
<ThreadStartedEvent>
<Thread
Callstack="{System.Void System.Threading.ReaderWriterLock.Finalize()}"
CurrentExceptionType="0"
IsAtSafePoint="True"
IsInValidState="True"
MostRecentStackFrame="System.Void System.Threading.ReaderWriterLock.Finalize()"
Name=""
Priority="Normal"
RuntimeValue="null" />
</ThreadStartedEvent>
<ProcessExited />
</Test>
</DebuggerTests>

2
src/Main/Base/Project/Src/Services/Debugger/BreakpointBookmark.cs

@ -49,6 +49,8 @@ namespace ICSharpCode.SharpDevelop.Debugging @@ -49,6 +49,8 @@ namespace ICSharpCode.SharpDevelop.Debugging
}
}
public object InternalBreakpointObject { get; set; }
public virtual bool IsHealthy {
get {
return isHealthy;

Loading…
Cancel
Save