diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin index e95e34555f..08060e5c91 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.addin @@ -25,15 +25,6 @@ - - - - diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj index 11d2747c72..99eb227ce4 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Debugger.AddIn.csproj @@ -48,20 +48,19 @@ - - + Form - - ExceptionForm.cs + + DebuggerEventForm.cs - - ExceptionForm.cs + + DebuggerEventForm.cs @@ -73,11 +72,9 @@ - - diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/ExceptionHistoryPad.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/ExceptionHistoryPad.cs deleted file mode 100644 index 0c42834b06..0000000000 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Pads/ExceptionHistoryPad.cs +++ /dev/null @@ -1,157 +0,0 @@ -// -// -// -// $Revision$ -// -#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 exceptions = new List(); - - 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(); - } - } -} diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/ExceptionForm.Designer.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.Designer.cs similarity index 97% rename from src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/ExceptionForm.Designer.cs rename to src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.Designer.cs index 29496d7913..24bb381df5 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/ExceptionForm.Designer.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.Designer.cs @@ -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 /// @@ -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); diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/ExceptionForm.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.cs similarity index 69% rename from src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/ExceptionForm.cs rename to src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.cs index 8eac5dd42e..121314a752 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/ExceptionForm.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.cs @@ -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 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 result = Result.Terminate; Close(); } - #endregion Form Event Handlers } } diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/ExceptionForm.resx b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.resx similarity index 100% rename from src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/ExceptionForm.resx rename to src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/DebuggerEventForm.resx diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs index 10867f3fad..63c220cc62 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/Service/WindowsDebugger.cs @@ -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 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 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; } diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewExceptionNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewExceptionNode.cs deleted file mode 100644 index daf431d605..0000000000 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/Adapters/TreeViewExceptionNode.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// -// -// $Revision: 3047 $ -// - -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 -{ - /// - /// This TreeNodeAdv displays exception data. - /// - public class TreeViewExceptionNode: TreeNodeAdv - { - private static Dictionary expandedNodes = new Dictionary(); - - private TreeViewAdv localVarList; - - /// - /// The content of the exception - /// - 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); - } - - /// - /// 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. - /// - /// Contains the exception that will be stored in this particular TreeViewNode. - public static void SetContentRecursive(ExceptionNode exception) { - throw new NotImplementedException(); - } - } -} \ No newline at end of file diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ExceptionNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ExceptionNode.cs deleted file mode 100644 index 913c237e01..0000000000 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/ExceptionNode.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// -// -// $Revision: 2813 $ -// - -using System; - - -namespace Debugger.AddIn.TreeModel -{ - /// - /// Represents a row in a TreeViewAdv that contains an IDebugeeException - /// - 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; } - } - } -} diff --git a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/StackFrameNode.cs b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/StackFrameNode.cs index c656e20325..a9f1a0c780 100644 --- a/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/StackFrameNode.cs +++ b/src/AddIns/Misc/Debugger/Debugger.AddIn/Project/Src/TreeModel/StackFrameNode.cs @@ -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()); + } } } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj index bba9e553c3..0a1404deab 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Debugger.Core.csproj @@ -59,13 +59,12 @@ - - + diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs index 214d0f2624..8701068746 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Control/Thread.cs @@ -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 public partial class Thread: DebuggerObject { Process process; - + ICorDebugThread corThread; - - Exception currentException; + + Exception currentException; + DebuggeeState currentException_DebuggeeState; + ExceptionType currentExceptionType; + bool currentExceptionIsUnhandled; List steppers = new List(); @@ -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; } + } + + /// Tryies to intercept the current exception. + /// The intercepted expression stays available through the CurrentException property. + /// False, if the exception was already intercepted or + /// if it can not be intercepted. + public bool InterceptCurrentException() + { + if (!this.CorThread.Is()) 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().InterceptCurrentException(this.MostRecentStackFrame.CorILFrame.CastTo()); + } 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 } } + 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; diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/DebugeeInnerException.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/DebugeeInnerException.cs deleted file mode 100644 index bef33a7609..0000000000 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/DebugeeInnerException.cs +++ /dev/null @@ -1,69 +0,0 @@ -// -// -// -// -// $Revision: 2900 $ -// - -using System.Text; -using Debugger.Wrappers.CorDebug; - -namespace Debugger -{ - /// - /// This contains the nested InnerExceptions of a Debugger.Exception class - /// - /// - /// - public class DebugeeInnerException : IDebugeeException - { - Debugger.Value exceptionValue; - - internal DebugeeInnerException (Debugger.Value exception) - { - this.exceptionValue = exception; - } - - /// - /// The InnerException property of the exception. - /// - /// - public DebugeeInnerException InnerException { - get { - Debugger.Value exVal = this.exceptionValue.GetMemberValue("_innerException"); - return (exVal.IsNull) ? null : new DebugeeInnerException(exVal); - } - } - - /// - /// The Message property of the exception. - /// - /// - public string Message { - get { - return this.exceptionValue.GetMemberValue("_message").AsString; - } - } - - /// - /// The GetType().FullName of the 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(); - } - } -} diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Exception.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Exception.cs index c8d8678bf8..a5bd504b74 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Exception.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/Exception.cs @@ -13,159 +13,113 @@ using Debugger.Wrappers.CorDebug; namespace Debugger { - /// - /// This class contains data from an Exception throw by an application - /// being debugged. Since the System.Exception object being thrown - /// lives in the debugged application and not in debugger, this class is - /// neccessary. - /// + /// This convenience class provides access to an exception within the debugee. /// - 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; } - - /// - /// The GetType().FullName of the exception. - /// + /// The GetType().FullName of the exception. /// public string Type { get { - return this.RuntimeValue.Type.FullName; + return exception.Type.FullName; } } - - /// - /// The InnerException property of the exception. - /// - /// - public DebugeeInnerException InnerException { - get { - Debugger.Value exVal = this.RuntimeValue.GetMemberValue("_innerException"); - return (exVal.IsNull) ? null : new DebugeeInnerException(exVal); - } - } - - /// - /// The Message property of the exception. - /// + /// The Message property of the 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 { + /// The InnerException property of the 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(); } - /// - /// This is the call stack as represented by the Debugger.ThreadObject. - /// - /// - /// - 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()) 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().InterceptCurrentException(thread.MostRecentStackFrame.CorILFrame.CastTo()); - } 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; } } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/ExceptionType.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/ExceptionType.cs index 3db5329f65..390460a72f 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/ExceptionType.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/ExceptionType.cs @@ -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, } } diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/IDebugeeException.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/IDebugeeException.cs deleted file mode 100644 index 86132edd84..0000000000 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Debugger/IDebugeeException.cs +++ /dev/null @@ -1,21 +0,0 @@ -// -// -// -// -// $Revision: 3047 $ -// - -using System; - -namespace Debugger -{ - /// - /// Interface shared by Debugger.Exception and Debugger.DebugeeInnerException. - /// - public interface IDebugeeException - { - DebugeeInnerException InnerException { get; } - string Message { get; } - string Type { get; } - } -} diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/CurrentExceptionExpression.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/CurrentExceptionExpression.cs new file mode 100644 index 0000000000..fd96b30bcf --- /dev/null +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/CurrentExceptionExpression.cs @@ -0,0 +1,46 @@ +// +// +// +// +// $Revision$ +// + +using System; + +namespace Debugger.Expressions +{ + /// + /// An expression which returns the current exception on the thread + /// + 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 + } +} diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/ThisReferenceExpression.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/ThisReferenceExpression.cs index 3c5dae495b..75e39cd977 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/ThisReferenceExpression.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Expressions/Ast/ThisReferenceExpression.cs @@ -10,7 +10,7 @@ using System; namespace Debugger.Expressions { /// - /// 'this' regerence of a non-static method. + /// 'this' reference of a non-static method. /// public class ThisReferenceExpression: Expression { diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs index c9fe4c4359..e909335324 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Internal/ManagedCallback.cs @@ -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 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 // 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; diff --git a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs index d5446491bd..a82fbc4db8 100644 --- a/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs +++ b/src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Values/Value.cs @@ -115,6 +115,15 @@ namespace Debugger } } + public Value GetPermanentReference() + { + ICorDebugValue corValue; + corValue = this.RawCorValue; + corValue = DereferenceUnbox(corValue); + corValue = corValue.CastTo().CreateHandle(CorDebugHandleType.HANDLE_STRONG).CastTo(); + return new Value(process, expression, corValue); + } + internal Value(Process process, ICorDebugValue rawCorValue) :this (process, new EmptyExpression(), rawCorValue) diff --git a/src/Main/StartUp/Project/Resources/StringResources.resources b/src/Main/StartUp/Project/Resources/StringResources.resources index f4d572ae59..01b84e1ac7 100644 Binary files a/src/Main/StartUp/Project/Resources/StringResources.resources and b/src/Main/StartUp/Project/Resources/StringResources.resources differ