Browse Source

Rewritten exception handling - Debugger.Exception is now just a convenience wrapper class around the run-time value.

Added "$exception" variable to the local variables pad.  
ExceptionForm generalized to DebuggerEventForm.  
Permanently removed exception history pad.

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@3099 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 18 years ago
parent
commit
5c4b0a9fd4
  1. 16
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin
  2. 13
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj
  3. 157
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/ExceptionHistoryPad.cs
  4. 4
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.Designer.cs
  5. 38
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.cs
  6. 0
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.resx
  7. 34
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs
  8. 52
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewExceptionNode.cs
  9. 46
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ExceptionNode.cs
  10. 3
      src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/StackFrameNode.cs
  11. 3
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj
  12. 82
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs
  13. 69
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/DebugeeInnerException.cs
  14. 168
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Exception.cs
  15. 8
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/ExceptionType.cs
  16. 21
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/IDebugeeException.cs
  17. 46
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/CurrentExceptionExpression.cs
  18. 2
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/ThisReferenceExpression.cs
  19. 15
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs
  20. 9
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs
  21. BIN
      src/Main/StartUp/Project/Resources/StringResources.resources

16
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin

@ -25,15 +25,6 @@ @@ -25,15 +25,6 @@
</Condition>
</Path>
<!--<Path name = "/SharpDevelop/Workbench/MainMenu/Debug">
<MenuItem id = "CatchHandledExceptionsSeparator"
type = "Separator"
insertafter = "Step out" />
<MenuItem id = "CatchHandledExceptions"
label = ""
class = "ICSharpCode.SharpDevelop.Services.DebbugerExceptionMenuBuilder"/>
</Path>-->
<Path name = "/SharpDevelop/Workbench/Pads">
<Pad id = "BreakPointsPad"
category = "Debugger"
@ -69,12 +60,5 @@ @@ -69,12 +60,5 @@
icon = "PadIcons.LocalVariables"
shortcut = "Control|Alt|V"
class = "ICSharpCode.SharpDevelop.Gui.Pads.LocalVarPad"/>
<!--<Pad id = "ExceptionHistoryPad"
category = "Debugger"
title = "${res:MainWindow.Windows.Debug.ExceptionHistory}"
icon = "PadIcons.Exceptions"
shortcut = "Control|Alt|E"
class = "ICSharpCode.SharpDevelop.Gui.Pads.ExceptionHistoryPad"/>-->
</Path>
</AddIn>

13
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj

@ -48,20 +48,19 @@ @@ -48,20 +48,19 @@
<Compile Include="Src\Expressions\SimpleParser.cs" />
<Compile Include="Src\Pads\BreakPointsPad.cs" />
<Compile Include="Src\Pads\CallStackPad.cs" />
<Compile Include="Src\Pads\ExceptionHistoryPad.cs" />
<Compile Include="Src\Pads\LoadedModulesPad.cs" />
<Compile Include="Src\Pads\LocalVarPad.cs" />
<Compile Include="Src\Pads\RunningThreadsPad.cs" />
<Compile Include="Src\Service\ExceptionForm.cs">
<Compile Include="Src\Service\DebuggerEventForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Src\Service\ExceptionForm.Designer.cs">
<DependentUpon>ExceptionForm.cs</DependentUpon>
<Compile Include="Src\Service\DebuggerEventForm.Designer.cs">
<DependentUpon>DebuggerEventForm.cs</DependentUpon>
</Compile>
<Compile Include="Src\Service\RemotingConfigurationHelpper.cs" />
<Compile Include="Src\Service\WindowsDebugger.cs" />
<EmbeddedResource Include="Src\Service\ExceptionForm.resx">
<DependentUpon>ExceptionForm.cs</DependentUpon>
<EmbeddedResource Include="Src\Service\DebuggerEventForm.resx">
<DependentUpon>DebuggerEventForm.cs</DependentUpon>
</EmbeddedResource>
<Compile Include="Src\Service\SetCurrentStatementCommand.cs" />
<Compile Include="Src\Service\DebuggerIcons.cs" />
@ -73,11 +72,9 @@ @@ -73,11 +72,9 @@
<Compile Include="Src\Pads\RunningThreadsPad.Menu.cs" />
<Compile Include="Src\TreeModel\AbstractNode.cs" />
<Compile Include="Src\TreeModel\Adapters\DynamicTreeDebuggerRow.cs" />
<Compile Include="Src\TreeModel\Adapters\TreeViewExceptionNode.cs" />
<Compile Include="Src\TreeModel\Adapters\TreeViewVarNode.cs" />
<Compile Include="Src\TreeModel\ArrayRangeNode.cs" />
<Compile Include="Src\TreeModel\ErrorNode.cs" />
<Compile Include="Src\TreeModel\ExceptionNode.cs" />
<Compile Include="Src\TreeModel\Extensions\IList.cs" />
<Compile Include="Src\TreeModel\ValueNode.cs" />
<Compile Include="Src\TreeModel\IContextMenu.cs" />

157
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/ExceptionHistoryPad.cs

@ -1,157 +0,0 @@ @@ -1,157 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
#region License
//
// Copyright (c) 2007, ic#code
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of the ic#code nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#endregion
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using Debugger;
using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Gui.Pads
{
public class ExceptionHistoryPad : DebuggerPad
{
ListView exceptionHistoryList;
Debugger.Process debuggedProcess;
List<Debugger.Exception> exceptions = new List<Debugger.Exception>();
ColumnHeader time = new ColumnHeader();
ColumnHeader exception = new ColumnHeader();
ColumnHeader location = new ColumnHeader();
public override Control Control {
get {
return exceptionHistoryList;
}
}
protected override void InitializeComponents()
{
exceptionHistoryList = new ListView();
exceptionHistoryList.FullRowSelect = true;
exceptionHistoryList.AutoArrange = true;
exceptionHistoryList.Alignment = ListViewAlignment.Left;
exceptionHistoryList.View = View.Details;
exceptionHistoryList.Dock = DockStyle.Fill;
exceptionHistoryList.GridLines = false;
exceptionHistoryList.Activation = ItemActivation.OneClick;
exceptionHistoryList.Columns.AddRange(new ColumnHeader[] {time, exception, location} );
exceptionHistoryList.ItemActivate += new EventHandler(ExceptionHistoryListItemActivate);
exception.Width = 300;
location.Width = 400;
time.Width = 80;
RedrawContent();
}
public override void RedrawContent()
{
time.Text = ResourceService.GetString("MainWindow.Windows.Debug.ExceptionHistory.Time");
exception.Text = ResourceService.GetString("MainWindow.Windows.Debug.ExceptionHistory.Exception");
location.Text = ResourceService.GetString("AddIns.HtmlHelp2.Location");
}
protected override void SelectProcess(Debugger.Process process)
{
if (debuggedProcess != null) {
debuggedProcess.ExceptionThrown -= debuggedProcess_ExceptionThrown;
}
debuggedProcess = process;
if (debuggedProcess != null) {
debuggedProcess.ExceptionThrown += debuggedProcess_ExceptionThrown;
}
exceptions.Clear();
RefreshPad();
}
void debuggedProcess_ExceptionThrown(object sender, ExceptionEventArgs e)
{
exceptions.Add(e.Exception);
RefreshPad();
}
void ExceptionHistoryListItemActivate(object sender, EventArgs e)
{
SourcecodeSegment nextStatement = ((Debugger.Exception)(exceptionHistoryList.SelectedItems[0].Tag)).Location;
if (nextStatement == null) {
return;
}
FileService.OpenFile(nextStatement.SourceFullFilename);
IViewContent content = FileService.GetOpenFile(nextStatement.SourceFullFilename);
if (content is IPositionable) {
((IPositionable)content).JumpTo((int)nextStatement.StartLine - 1, (int)nextStatement.StartColumn - 1);
}
}
public override void RefreshPad()
{
exceptionHistoryList.BeginUpdate();
exceptionHistoryList.Items.Clear();
foreach(Debugger.Exception exception in exceptions) {
string location;
if (exception.Location != null) {
location = exception.Location.SourceFilename + ":" + exception.Location.StartLine;
} else {
location = ResourceService.GetString("Global.NA");
}
location += " (type=" + exception.ExceptionType.ToString() + ")";
ListViewItem item = new ListViewItem(new string[] {"" , exception.Type + " - " + exception.Message, location});
item.Tag = exception;
item.ForeColor = Color.Black;
if (exception.ExceptionType == ExceptionType.DEBUG_EXCEPTION_UNHANDLED) {
item.ForeColor = Color.Red;
}
if (exception.ExceptionType == ExceptionType.DEBUG_EXCEPTION_FIRST_CHANCE ||
exception.ExceptionType == ExceptionType.DEBUG_EXCEPTION_USER_FIRST_CHANCE) {
item.ForeColor = Color.Blue;
}
exceptionHistoryList.Items.Add(item);
}
exceptionHistoryList.EndUpdate();
}
}
}

4
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/ExceptionForm.Designer.cs → src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.Designer.cs generated

@ -43,7 +43,7 @@ using System.Windows.Forms; @@ -43,7 +43,7 @@ using System.Windows.Forms;
namespace ICSharpCode.SharpDevelop.Services
{
partial class ExceptionForm : System.Windows.Forms.Form
partial class DebuggerEventForm : System.Windows.Forms.Form
{
#region Windows Forms Designer generated code
/// <summary>
@ -128,7 +128,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -128,7 +128,7 @@ namespace ICSharpCode.SharpDevelop.Services
this.MinimizeBox = false;
this.Name = "ExceptionForm";
this.ShowInTaskbar = false;
this.Text = "${res:MainWindow.Windows.Debug.ExceptionForm.Title}";
this.Text = "";
this.TopMost = true;
((System.ComponentModel.ISupportInitialize)(this.pictureBox)).EndInit();
this.ResumeLayout(false);

38
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/ExceptionForm.cs → src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.cs

@ -47,13 +47,13 @@ using ICSharpCode.Core; @@ -47,13 +47,13 @@ using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Services
{
internal sealed partial class ExceptionForm
internal sealed partial class DebuggerEventForm
{
public enum Result {Break, Continue, Terminate};
private Result result = Result.Break; // Default
private ExceptionForm()
private DebuggerEventForm()
{
InitializeComponent();
this.Text = StringParser.Parse(this.Text);
@ -62,39 +62,18 @@ namespace ICSharpCode.SharpDevelop.Services @@ -62,39 +62,18 @@ namespace ICSharpCode.SharpDevelop.Services
buttonTerminate.Text = StringParser.Parse(buttonTerminate.Text);
}
public static Result Show(Debugger.Exception exception)
public static Result Show(string title, string message, System.Drawing.Bitmap icon, bool canContinue)
{
IDebugeeException ex = exception;
StringBuilder msg = new StringBuilder();
msg.AppendFormat(ResourceService.GetString("MainWindow.Windows.Debug.ExceptionForm.Message"), ex.Type);
msg.AppendLine();
msg.AppendLine("Message:");
msg.Append("\t");
msg.AppendLine(ex.Message);
msg.AppendLine();
while(ex.InnerException != null) {
ex = ex.InnerException;
msg.AppendLine("Inner Exception:");
msg.AppendFormat("Type: [{0}]", ex.Type);
msg.AppendLine();
msg.AppendLine("Message:");
msg.Append("\t");
if (ex.Message != "null") { msg.AppendLine(ex.Message); }
msg.AppendLine();
}
msg.AppendLine("StackTrace:");
msg.AppendLine(exception.Callstack.Replace("\n","\r\n"));
using (ExceptionForm form = new ExceptionForm()) {
form.textBox.Text = msg.ToString();
form.pictureBox.Image = ResourceService.GetBitmap((exception.ExceptionType != ExceptionType.DEBUG_EXCEPTION_UNHANDLED)?"Icons.32x32.Warning":"Icons.32x32.Error");
form.buttonContinue.Enabled = exception.ExceptionType != ExceptionType.DEBUG_EXCEPTION_UNHANDLED;
using (DebuggerEventForm form = new DebuggerEventForm()) {
form.Text = title;
form.textBox.Text = message;
form.pictureBox.Image = icon;
form.buttonContinue.Enabled = canContinue;
form.ShowDialog(ICSharpCode.SharpDevelop.Gui.WorkbenchSingleton.MainForm);
return form.result;
}
}
#region Form Event Handlers
private void buttonBreak_Click(object sender, System.EventArgs e)
{
result = Result.Break;
@ -112,6 +91,5 @@ namespace ICSharpCode.SharpDevelop.Services @@ -112,6 +91,5 @@ namespace ICSharpCode.SharpDevelop.Services
result = Result.Terminate;
Close();
}
#endregion Form Event Handlers
}
}

0
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/ExceptionForm.resx → src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.resx

34
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs

@ -39,7 +39,9 @@ @@ -39,7 +39,9 @@
using System;
using System.Diagnostics;
using System.Text;
using System.Windows.Forms;
using Bitmap = System.Drawing.Bitmap;
using Debugger;
using Debugger.Expressions;
@ -476,7 +478,7 @@ namespace ICSharpCode.SharpDevelop.Services @@ -476,7 +478,7 @@ namespace ICSharpCode.SharpDevelop.Services
void debuggedProcess_ExceptionThrown(object sender, ExceptionEventArgs e)
{
if (!e.Exception.IsUnhandled) {
if (!e.IsUnhandled) {
// Ignore the exception
e.Process.AsyncContinue();
return;
@ -484,23 +486,35 @@ namespace ICSharpCode.SharpDevelop.Services @@ -484,23 +486,35 @@ namespace ICSharpCode.SharpDevelop.Services
JumpToCurrentLine();
ExceptionForm.Result result = ExceptionForm.Show(e.Exception);
StringBuilder msg = new StringBuilder();
// Need to intercept now so that we can evaluate properties
if (e.Process.SelectedThread.InterceptCurrentException()) {
msg.Append(e.Exception.ToString(StringParser.Parse("${res:MainWindow.Windows.Debug.ExceptionForm.LineFormat.EndOfInnerException}")));
} else {
// For example, happens on stack overflow
msg.Append(e.Exception.ToString());
msg.AppendLine(StringParser.Parse("(${res:MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptException})"));
msg.AppendLine(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 = msg.ToString();
Bitmap icon = ResourceService.GetBitmap(e.IsUnhandled ? "Icons.32x32.Error" : "Icons.32x32.Warning");
bool canContinue = !e.IsUnhandled;
DebuggerEventForm.Result result = DebuggerEventForm.Show(title, message, icon, canContinue);
// If the process was killed while the exception form was shown
if (e.Process.HasExpired) return;
switch (result) {
case ExceptionForm.Result.Break:
// Need to intercept now so that we can evaluate properties in local variables pad
if (!e.Process.SelectedThread.CurrentException.Intercept()) {
// For example, happens on stack overflow
MessageService.ShowMessage("${res:MainWindow.Windows.Debug.ExceptionForm.Error.CannotInterceptException}", "${res:MainWindow.Windows.Debug.ExceptionForm.Title}");
}
case DebuggerEventForm.Result.Break:
break;
case ExceptionForm.Result.Continue:
case DebuggerEventForm.Result.Continue:
e.Process.AsyncContinue();
break;
case ExceptionForm.Result.Terminate:
case DebuggerEventForm.Result.Terminate:
e.Process.Terminate();
break;
}

52
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewExceptionNode.cs

@ -1,52 +0,0 @@ @@ -1,52 +0,0 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 3047 $</version>
// </file>
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.Windows.Forms;
using Aga.Controls.Tree;
using Debugger.Util;
using ICSharpCode.Core;
using ICSharpCode.SharpDevelop.Gui.Pads;
namespace Debugger.AddIn.TreeModel
{
/// <summary>
/// This TreeNodeAdv displays exception data.
/// </summary>
public class TreeViewExceptionNode: TreeNodeAdv
{
private static Dictionary<string, bool> expandedNodes = new Dictionary<string, bool>();
private TreeViewAdv localVarList;
/// <summary>
/// The content of the exception
/// </summary>
private AbstractNode content;
// TODO: I don't know if I need localVarList
private TreeViewExceptionNode(TreeViewAdv localVarList, ExceptionNode exception): base(localVarList, new object()) {
this.localVarList = localVarList;
SetContentRecursive(exception);
}
/// <summary>
/// A simple form of SetContentRecursive that changes the current ChildViewNode to
/// display the exception parameter passed to it. If the node had any children and is expanded,
/// it will recureively set those as well.
/// </summary>
/// <param name="exception">Contains the exception that will be stored in this particular TreeViewNode.</param>
public static void SetContentRecursive(ExceptionNode exception) {
throw new NotImplementedException();
}
}
}

46
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ExceptionNode.cs

@ -1,46 +0,0 @@ @@ -1,46 +0,0 @@
// <file>
// <copyright license="BSD-new" see="prj:///COPYING"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 2813 $</version>
// </file>
using System;
namespace Debugger.AddIn.TreeModel
{
/// <summary>
/// Represents a row in a TreeViewAdv that contains an IDebugeeException
/// </summary>
public class ExceptionNode : AbstractNode
{
private IDebugeeException exception;
private ExceptionNode innerException = null;
public static ExceptionNode Create(Debugger.Exception exception) {
try {
return new ExceptionNode(exception);
} catch (GetValueException e) {
// TODO: Fix this
throw;
//return new ErrorNode(expression, e);
}
}
private ExceptionNode(IDebugeeException exception){
this.exception = exception;
this.Image = DebuggerIcons.ImageList.Images[0]; // Class
this.Name = "Unhandled Exception";
this.Type = exception.Type;
this.Text = exception.Message;
if (exception.InnerException != null) {
innerException = new ExceptionNode(exception.InnerException);
}
}
ExceptionNode InnerException {
get { return innerException; }
}
}
}

3
src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/StackFrameNode.cs

@ -34,6 +34,9 @@ namespace Debugger.AddIn.TreeModel @@ -34,6 +34,9 @@ namespace Debugger.AddIn.TreeModel
foreach(Expression expr in Expression.MethodVariables(stackFrame.MethodInfo)) {
yield return ValueNode.Create(expr);
}
if (stackFrame.Thread.CurrentException != null) {
yield return ValueNode.Create(new CurrentExceptionExpression());
}
}
}
}

3
src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj

@ -59,13 +59,12 @@ @@ -59,13 +59,12 @@
<Compile Include="Src\Debugger\DebuggerObject.cs" />
<Compile Include="Src\Debugger\Exception.cs" />
<Compile Include="Src\Debugger\ExceptionType.cs" />
<Compile Include="Src\Debugger\IDebugeeException.cs" />
<Compile Include="Src\Debugger\IExpirable.cs" />
<Compile Include="Src\Debugger\DebugeeInnerException.cs" />
<Compile Include="Src\Debugger\PausedReason.cs" />
<Compile Include="Src\Debugger\PauseSession.cs" />
<Compile Include="Src\Debugger\SourcecodeSegment.cs" />
<Compile Include="Src\Expressions\Ast\ArrayIndexerExpression.cs" />
<Compile Include="Src\Expressions\Ast\CurrentExceptionExpression.cs" />
<Compile Include="Src\Expressions\Ast\EmptyExpression.cs" />
<Compile Include="Src\Expressions\Ast\LocalVariableIdentifierExpression.cs" />
<Compile Include="Src\Expressions\Ast\MemberReferenceExpression.cs" />

82
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Debugger.Wrappers.CorDebug;
@ -17,10 +18,13 @@ namespace Debugger @@ -17,10 +18,13 @@ namespace Debugger
public partial class Thread: DebuggerObject
{
Process process;
ICorDebugThread corThread;
Exception currentException;
Exception currentException;
DebuggeeState currentException_DebuggeeState;
ExceptionType currentExceptionType;
bool currentExceptionIsUnhandled;
List<Stepper> steppers = new List<Stepper>();
@ -171,10 +175,58 @@ namespace Debugger @@ -171,10 +175,58 @@ namespace Debugger
}
public Exception CurrentException {
get { return currentException; }
get {
if (currentException_DebuggeeState == this.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
/// if it can not be intercepted. </returns>
public bool InterceptCurrentException()
{
if (!this.CorThread.Is<ICorDebugThread2>()) return false; // Is the debuggee .NET 2.0?
if (this.CorThread.CurrentException == null) return false; // Is there any exception
if (this.MostRecentStackFrame == null) return false; // Is frame available? It is not at StackOverflow
try {
// Interception will expire the CorValue so keep permanent reference
currentException.MakeValuePermanent();
this.CorThread.CastTo<ICorDebugThread2>().InterceptCurrentException(this.MostRecentStackFrame.CorILFrame.CastTo<ICorDebugFrame>());
} catch (COMException e) {
// 0x80131C02: Cannot intercept this exception
if ((uint)e.ErrorCode == 0x80131C02) {
return false;
}
throw;
}
Process.AsyncContinue_KeepDebuggeeState();
Process.WaitForPause();
return true;
}
internal Stepper GetStepper(ICorDebugStepper corStepper)
{
foreach(Stepper stepper in steppers) {
@ -248,6 +300,28 @@ namespace Debugger @@ -248,6 +300,28 @@ namespace Debugger
}
}
public string GetStackTrace()
{
return GetStackTrace("at {0} in {1}:line {2}", "at {0} in {1}");
}
public string GetStackTrace(string formatSymbols, string formatNoSymbols)
{
StringBuilder stackTrace = new StringBuilder();
foreach(StackFrame stackFrame in this.GetCallstack(100)) {
SourcecodeSegment loc = stackFrame.NextStatement;
if (loc != null) {
stackTrace.Append(" ");
stackTrace.AppendFormat(formatSymbols, stackFrame.MethodInfo.FullName, loc.SourceFullFilename, loc.StartLine);
stackTrace.AppendLine();
} else {
stackTrace.AppendFormat(formatNoSymbols, stackFrame.MethodInfo.FullName);
stackTrace.AppendLine();
}
}
return stackTrace.ToString();
}
public StackFrame SelectedStackFrame {
get {
if (selectedStackFrame != null && selectedStackFrame.HasExpired) return null;

69
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/DebugeeInnerException.cs

@ -1,69 +0,0 @@ @@ -1,69 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="Justin Dearing" email="zippy1981@gmail.com"/>
// <version>$Revision: 2900 $</version>
// </file>
using System.Text;
using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// This contains the nested InnerExceptions of a <c>Debugger.Exception</c> class
/// </summary>
/// <see cref="Debugger.Exception" />
/// <seealso cref="System.Exception" />
public class DebugeeInnerException : IDebugeeException
{
Debugger.Value exceptionValue;
internal DebugeeInnerException (Debugger.Value exception)
{
this.exceptionValue = exception;
}
/// <summary>
/// The <c>InnerException</c> property of the exception.
/// </summary>
/// <seealso cref="System.Exception" />
public DebugeeInnerException InnerException {
get {
Debugger.Value exVal = this.exceptionValue.GetMemberValue("_innerException");
return (exVal.IsNull) ? null : new DebugeeInnerException(exVal);
}
}
/// <summary>
/// The <c>Message</c> property of the exception.
/// </summary>
/// <seealso cref="System.Exception" />
public string Message {
get {
return this.exceptionValue.GetMemberValue("_message").AsString;
}
}
/// <summary>
/// The <c>GetType().FullName</c> of the exception.
/// </summary>
/// <seealso cref="System.Exception" />
public string Type {
get {
return this.exceptionValue.Type.FullName;
}
}
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.AppendFormat("Type: {0}", this.Type);
sb.AppendLine();
sb.AppendLine("Message:");
sb.Append(this.Message);
return sb.ToString();
}
}
}

168
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Exception.cs

@ -13,159 +13,113 @@ using Debugger.Wrappers.CorDebug; @@ -13,159 +13,113 @@ using Debugger.Wrappers.CorDebug;
namespace Debugger
{
/// <summary>
/// This class contains data from an Exception throw by an application
/// being debugged. Since the <c>System.Exception</c> object being thrown
/// lives in the debugged application and not in debugger, this class is
/// neccessary.
/// </summary>
/// <summary> This convenience class provides access to an exception within the debugee. </summary>
/// <seealso cref="System.Exception" />
public class Exception: DebuggerObject, IDebugeeException
public class Exception: DebuggerObject
{
Thread thread;
ExceptionType exceptionType;
Value exception;
[Debugger.Tests.Ignore]
public Process Process {
get {
return thread.Process;
}
public Value Value {
get { return exception; }
}
ICorDebugValue CorValue {
get {
return thread.CorThread.CurrentException;
}
}
internal Exception(Thread thread, ExceptionType exceptionType)
public Exception(Value exception)
{
this.thread = thread;
this.exceptionType = exceptionType;
}
public Value RuntimeValue {
get {
return new Value(Process, CorValue);
}
this.exception = exception;
}
/// <summary>
/// The <c>GetType().FullName</c> of the exception.
/// </summary>
/// <summary> The <c>GetType().FullName</c> of the exception. </summary>
/// <seealso cref="System.Exception" />
public string Type {
get {
return this.RuntimeValue.Type.FullName;
return exception.Type.FullName;
}
}
/// <summary>
/// The <c>InnerException</c> property of the exception.
/// </summary>
/// <seealso cref="System.Exception" />
public DebugeeInnerException InnerException {
get {
Debugger.Value exVal = this.RuntimeValue.GetMemberValue("_innerException");
return (exVal.IsNull) ? null : new DebugeeInnerException(exVal);
}
}
/// <summary>
/// The <c>Message</c> property of the exception.
/// </summary>
/// <summary> The <c>Message</c> property of the exception. </summary>
/// <seealso cref="System.Exception" />
public string Message {
get {
return this.RuntimeValue.GetMemberValue("_message").AsString;
Value message = exception.GetMemberValue("_message");
return message.IsNull ? string.Empty : message.AsString;
}
}
public ExceptionType ExceptionType {
public string StackTrace {
get {
return exceptionType;
try {
Value stackTrace = exception.GetMemberValue("StackTrace");
return stackTrace.IsNull ? string.Empty : stackTrace.AsString;
} catch (GetValueException) {
// Evaluation is not possible after a stackoverflow exception
return string.Empty;
}
}
}
public bool IsUnhandled {
/// <summary> The <c>InnerException</c> property of the exception. </summary>
/// <seealso cref="System.Exception" />
public Exception InnerException {
get {
return ExceptionType == ExceptionType.DEBUG_EXCEPTION_UNHANDLED;
Value innerException = exception.GetMemberValue("_innerException");
return innerException.IsNull ? null : new Exception(innerException);
}
}
public SourcecodeSegment Location {
get {
if (thread.MostRecentStackFrameWithLoadedSymbols != null) {
return thread.MostRecentStackFrameWithLoadedSymbols.NextStatement;
} else {
return null;
}
}
public void MakeValuePermanent()
{
exception = exception.GetPermanentReference();
}
/// <summary>
/// This is the call stack as represented by the <c>Debugger.ThreadObject</c>.
/// </summary>
/// <seealso cref="System.Execption.StackTrace" />
/// <see cref="Debugger.Exception.StackTrace" />
public string Callstack {
get {
StringBuilder callstack = new StringBuilder();
foreach(StackFrame stackFrame in thread.GetCallstack(100)) {
callstack.Append(stackFrame.MethodInfo.Name);
callstack.Append("()");
SourcecodeSegment loc = stackFrame.NextStatement;
if (loc != null) {
callstack.Append(" - ");
callstack.Append(loc.SourceFullFilename);
callstack.Append(":");
callstack.Append(loc.StartLine);
callstack.Append(",");
callstack.Append(loc.StartColumn);
}
callstack.Append("\n");
}
return callstack.ToString();
}
public override string ToString()
{
return ToString("--- End of inner exception stack trace ---");
}
public bool Intercept()
public string ToString(string endOfInnerExceptionFormat)
{
if (!thread.CorThread.Is<ICorDebugThread2>()) return false; // Is the debuggee .NET 2.0?
if (thread.MostRecentStackFrame == null) return false; // Is frame available? It is not at StackOverflow
try {
thread.CorThread.CastTo<ICorDebugThread2>().InterceptCurrentException(thread.MostRecentStackFrame.CorILFrame.CastTo<ICorDebugFrame>());
} catch (COMException e) {
// 0x80131C02: Cannot intercept this exception
if ((uint)e.ErrorCode == 0x80131C02) {
return false;
}
throw;
StringBuilder sb = new StringBuilder();
sb.Append(this.Type);
if (!string.IsNullOrEmpty(this.Message)) {
sb.Append(": ");
sb.Append(this.Message);
}
thread.CurrentException = null;
Process.AsyncContinue_KeepDebuggeeState();
Process.WaitForPause();
return true;
if (this.InnerException != null) {
sb.Append(" ---> ");
sb.Append(this.InnerException.ToString(endOfInnerExceptionFormat));
sb.AppendLine();
sb.Append(" ");
sb.Append(endOfInnerExceptionFormat);
}
sb.AppendLine();
sb.Append(this.StackTrace);
return sb.ToString();
}
}
public class ExceptionEventArgs: ProcessEventArgs
{
Exception exception;
ExceptionType exceptionType;
bool isUnhandled;
public Exception Exception {
get {
return exception;
}
get { return exception; }
}
public ExceptionEventArgs(Process process, Exception exception):base(process)
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;
}
}
}

8
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/ExceptionType.cs

@ -11,9 +11,9 @@ namespace Debugger @@ -11,9 +11,9 @@ namespace Debugger
{
public enum ExceptionType
{
DEBUG_EXCEPTION_FIRST_CHANCE = 1,
DEBUG_EXCEPTION_UNHANDLED = 4,
DEBUG_EXCEPTION_USER_FIRST_CHANCE = 2,
DEBUG_EXCEPTION_CATCH_HANDLER_FOUND = 3,
FirstChance = 1,
UserFirstChance = 2,
CatchHandlerFound = 3,
Unhandled = 4,
}
}

21
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/IDebugeeException.cs

@ -1,21 +0,0 @@ @@ -1,21 +0,0 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision: 3047 $</version>
// </file>
using System;
namespace Debugger
{
/// <summary>
/// Interface shared by Debugger.Exception and Debugger.DebugeeInnerException.
/// </summary>
public interface IDebugeeException
{
DebugeeInnerException InnerException { get; }
string Message { get; }
string Type { get; }
}
}

46
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/CurrentExceptionExpression.cs

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
// <file>
// <copyright see="prj:///doc/copyright.txt"/>
// <license see="prj:///doc/license.txt"/>
// <owner name="David Srbecký" email="dsrbecky@gmail.com"/>
// <version>$Revision$</version>
// </file>
using System;
namespace Debugger.Expressions
{
/// <summary>
/// An expression which returns the current exception on the thread
/// </summary>
public class CurrentExceptionExpression: Expression
{
public override string Code {
get {
return "$exception";
}
}
protected override Value EvaluateInternal(StackFrame context)
{
if (context.Thread.CurrentException != null) {
return context.Thread.CurrentException.Value;
} else {
throw new GetValueException("No current exception");
}
}
#region GetHashCode and Equals
public override int GetHashCode()
{
return typeof(CurrentExceptionExpression).GetHashCode();
}
public override bool Equals(object obj)
{
return obj is CurrentExceptionExpression;
}
#endregion
}
}

2
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/ThisReferenceExpression.cs

@ -10,7 +10,7 @@ using System; @@ -10,7 +10,7 @@ using System;
namespace Debugger.Expressions
{
/// <summary>
/// 'this' regerence of a non-static method.
/// 'this' reference of a non-static method.
/// </summary>
public class ThisReferenceExpression: Expression
{

15
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs

@ -119,7 +119,12 @@ namespace Debugger @@ -119,7 +119,12 @@ namespace Debugger
void RaiseEvents()
{
if (process.PauseSession.PausedReason == PausedReason.Exception) {
ExceptionEventArgs args = new ExceptionEventArgs(process, process.SelectedThread.CurrentException);
// Needs to be done after the debugge state is created
process.SelectedThread.CurrentException_DebuggeeState = process.DebuggeeState;
}
if (process.PauseSession.PausedReason == PausedReason.Exception) {
ExceptionEventArgs args = new ExceptionEventArgs(process, process.SelectedThread.CurrentException, process.SelectedThread.CurrentExceptionType, process.SelectedThread.CurrentExceptionIsUnhandled);
process.OnExceptionThrown(args);
// The event could have resumed or killed the process
}
@ -209,7 +214,7 @@ namespace Debugger @@ -209,7 +214,7 @@ namespace Debugger
if (process.DebuggeeVersion.StartsWith("v1.")) {
// Forward the call to Exception2, which handles EnterCallback and ExitCallback
ExceptionType exceptionType = (unhandled != 0)?ExceptionType.DEBUG_EXCEPTION_UNHANDLED:ExceptionType.DEBUG_EXCEPTION_FIRST_CHANCE;
ExceptionType exceptionType = (unhandled != 0) ? ExceptionType.Unhandled : ExceptionType.FirstChance;
Exception2(pAppDomain, pThread, null, 0, (CorDebugExceptionCallbackType)exceptionType, 0);
} else {
// This callback should be ignored in v2 applications
@ -462,9 +467,11 @@ namespace Debugger @@ -462,9 +467,11 @@ namespace Debugger
// Watch out for the zeros and null!
// Exception -> Exception2(pAppDomain, pThread, null, 0, exceptionType, 0);
process.SelectedThread.CurrentException = new Exception(process.SelectedThread, (ExceptionType)exceptionType);
process.SelectedThread.CurrentException = new Exception(new Value(process, new Expressions.CurrentExceptionExpression(), process.SelectedThread.CorThread.CurrentException));
process.SelectedThread.CurrentExceptionType = (ExceptionType)exceptionType;
process.SelectedThread.CurrentExceptionIsUnhandled = (ExceptionType)exceptionType == ExceptionType.Unhandled;
if (process.SelectedThread.CurrentException.IsUnhandled ||
if (process.SelectedThread.CurrentExceptionIsUnhandled ||
process.PauseOnHandledException)
{
pauseOnNextExit = true;

9
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs

@ -115,6 +115,15 @@ namespace Debugger @@ -115,6 +115,15 @@ namespace Debugger
}
}
public Value GetPermanentReference()
{
ICorDebugValue corValue;
corValue = this.RawCorValue;
corValue = DereferenceUnbox(corValue);
corValue = corValue.CastTo<ICorDebugHeapValue2>().CreateHandle(CorDebugHandleType.HANDLE_STRONG).CastTo<ICorDebugValue>();
return new Value(process, expression, corValue);
}
internal Value(Process process,
ICorDebugValue rawCorValue)
:this (process, new EmptyExpression(), rawCorValue)

BIN
src/Main/StartUp/Project/Resources/StringResources.resources

Binary file not shown.
Loading…
Cancel
Save