public ExceptionCategorySettings(ExceptionManager parent, HostConfigurationSection categoryKey, string categoryName) { _parent = parent; this.CategoryName = categoryName; this.DefaultCategoryState = RegistryToExceptionBreakpointState(categoryKey.GetValue("*")); Dictionary <string, ExceptionBreakpointStates> exceptionSettings = new Dictionary <string, ExceptionBreakpointStates>(); foreach (string valueName in categoryKey.GetValueNames()) { if (string.IsNullOrEmpty(valueName) || valueName == "*" || !ExceptionManager.IsSupportedException(valueName)) { continue; } ExceptionBreakpointStates value = RegistryToExceptionBreakpointState(categoryKey.GetValue(valueName)); if (value == this.DefaultCategoryState) { Debug.Fail("Redundant exception trigger found in the registry."); continue; } exceptionSettings.Add(valueName, value); } this.DefaultRules = new ReadOnlyDictionary <string, ExceptionBreakpointStates>(exceptionSettings); _settingsUpdate = new SettingsUpdates(this.DefaultCategoryState, this.DefaultRules); }
private static void SetCategory(ExceptionCategorySettings categorySettings, ExceptionBreakpointStates newState) { using (var settingsUpdateHolder = categorySettings.GetSettingsUpdate()) { settingsUpdateHolder.Value.NewCategoryState = newState; settingsUpdateHolder.Value.RulesToAdd.Clear(); settingsUpdateHolder.Value.RulesToRemove.Clear(); } }
private static ExceptionBreakpointStates ToExceptionBreakpointState(enum_EXCEPTION_STATE ad7ExceptionState) { ExceptionBreakpointStates returnValue = ExceptionBreakpointStates.None; if ((ad7ExceptionState & (enum_EXCEPTION_STATE.EXCEPTION_STOP_FIRST_CHANCE | enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_FIRST_CHANCE)) != 0) { returnValue |= ExceptionBreakpointStates.BreakThrown; } if (ad7ExceptionState.HasFlag(enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_UNCAUGHT)) { returnValue |= ExceptionBreakpointStates.BreakUserHandled; } return(returnValue); }
/// <summary> /// Decode properties from an exception-received event. /// </summary> /// <param name="miExceptionResult">Results object for the exception-received event</param> /// <param name="exceptionCategory">AD7 Exception Category to return</param> /// <param name="state">Exception state</param> public virtual void DecodeExceptionReceivedProperties(Results miExceptionResult, out Guid?exceptionCategory, out ExceptionBreakpointStates state) { exceptionCategory = null; state = ExceptionBreakpointStates.None; }
/// <summary> /// Adds a breakpoint which will be triggered when an exception is thrown and/or goes user-unhandled /// </summary> /// <param name="exceptionCategory">AD7 category for the execption</param> /// <param name="exceptionNames">[Optional] names of the exceptions to set a breakpoint on. If null, this sets an breakpoint for all /// exceptions in the category. Note that this clear all previous exception breakpoints set in this category.</param> /// <param name="exceptionBreakpointState">Indicates when the exception breakpoint should fire</param> /// <returns>Task containing the exception breakpoint id's for the various set exceptions</returns> public virtual Task <IEnumerable <ulong> > SetExceptionBreakpoints(Guid exceptionCategory, /*OPTIONAL*/ IEnumerable <string> exceptionNames, ExceptionBreakpointStates exceptionBreakpointState) { // NOTES: // GDB /MI has no support for exceptions. Though they do have it through the non-MI through a 'catch' command. Example: // catch throw MyException // Catchpoint 3 (throw) // =breakpoint-created,bkpt={number="3",type="breakpoint",disp="keep",enabled="y",addr="0xa1b5f830",what="exception throw",catch-type="throw",thread-groups=["i1"],regexp="MyException",times="0"} // Documentation: http://www.sourceware.org/gdb/onlinedocs/gdb/Set-Catchpoints.html#Set-Catchpoints // // LLDB-MI has no support for exceptions. Though they do have it through the non-MI breakpoint command. Example: // break set -F std::range_error // And they do have it in their API: // SBTarget::BreakpointCreateForException throw new NotImplementedException(); }
public AD7ExceptionEvent(string name, string description, uint code, Guid?exceptionCategory, ExceptionBreakpointStates state) { _name = name; _code = code; _description = string.IsNullOrEmpty(description) ? name : description; _category = exceptionCategory ?? EngineConstants.EngineId; switch (state) { case ExceptionBreakpointStates.None: _state = enum_EXCEPTION_STATE.EXCEPTION_STOP_SECOND_CHANCE; break; case ExceptionBreakpointStates.BreakThrown: _state = enum_EXCEPTION_STATE.EXCEPTION_STOP_FIRST_CHANCE | enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_FIRST_CHANCE; break; case ExceptionBreakpointStates.BreakUserHandled: _state = enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_UNCAUGHT; break; default: Debug.Fail("Unexpected state value"); _state = enum_EXCEPTION_STATE.EXCEPTION_STOP_SECOND_CHANCE; break; } }
private async Task UpdateCatagory(Guid categoryId, ExceptionCategorySettings categorySettings, SettingsUpdates updates) { // Update the category if (updates.NewCategoryState.HasValue && ( updates.NewCategoryState.Value != ExceptionBreakpointStates.None || // send down a rule if the category isn't in the default state categorySettings.CurrentRules.Count != 0)) // Or if we have other rules for the category that we need to blow away { ExceptionBreakpointStates newCategoryState = updates.NewCategoryState.Value; categorySettings.CategoryState = newCategoryState; categorySettings.CurrentRules.Clear(); IEnumerable <ulong> breakpointIds = await _commandFactory.SetExceptionBreakpoints(categoryId, null, newCategoryState); if (newCategoryState != ExceptionBreakpointStates.None) { ulong breakpointId = breakpointIds.Single(); categorySettings.CurrentRules.Add("*", breakpointId); } } // Process any removes if (updates.RulesToRemove.Count > 0) { // Detach these exceptions from 'CurrentRules' List <ulong> breakpointsToRemove = new List <ulong>(); foreach (string exceptionToRemove in updates.RulesToRemove) { ulong breakpointId; if (!categorySettings.CurrentRules.TryGetValue(exceptionToRemove, out breakpointId)) { continue; } categorySettings.CurrentRules.Remove(exceptionToRemove); breakpointsToRemove.Add(breakpointId); } if (breakpointsToRemove.Count > 0) { await _commandFactory.RemoveExceptionBreakpoint(categoryId, breakpointsToRemove); } } // process any adds foreach (IGrouping <ExceptionBreakpointStates, string> grouping in updates.RulesToAdd.GroupBy((pair) => pair.Value, (pair) => pair.Key)) { IEnumerable <string> exceptionNames = grouping; if (grouping.Key == categorySettings.CategoryState) { // A request to set an exception to the same state as the category is redundant unless we have previously changed the state of that exception to something else exceptionNames = exceptionNames.Intersect(categorySettings.CurrentRules.Keys); if (!exceptionNames.Any()) { continue; // no exceptions left, so ignore this group } } IEnumerable <ulong> breakpointIds = await _commandFactory.SetExceptionBreakpoints(categoryId, exceptionNames, grouping.Key); int count = exceptionNames.Zip(breakpointIds, (exceptionName, breakpointId) => { categorySettings.CurrentRules[exceptionName] = breakpointId; return(1); }).Sum(); #if DEBUG Debug.Assert(count == exceptionNames.Count()); #endif } }
// Exception events are sent when an exception occurs in the debuggee that the debugger was not expecting. public void OnException(DebuggedThread thread, string name, string description, uint code, Guid?exceptionCategory = null, ExceptionBreakpointStates state = ExceptionBreakpointStates.None) { AD7ExceptionEvent eventObject = new AD7ExceptionEvent(name, description, code, exceptionCategory, state); AD7Thread ad7Thread = (AD7Thread)thread.Client; Send(eventObject, AD7ExceptionEvent.IID, ad7Thread); }