public SettingsUpdates(/*OPTIONAL*/ ExceptionBreakpointState? initialNewCategoryState, /*OPTIONAL*/ ReadOnlyDictionary<string, ExceptionBreakpointState> initialRuleChanges) { this.NewCategoryState = initialNewCategoryState; // The dictionary constructor which takes a read only dictionary is unhappy if we pass in null, so switch off which constructor we call if (initialRuleChanges != null) this.RulesToAdd = new Dictionary<string, ExceptionBreakpointState>(initialRuleChanges); else this.RulesToAdd = new Dictionary<string, ExceptionBreakpointState>(); }
public override void DecodeExceptionReceivedProperties(Results miExceptionResult, out Guid? exceptionCategory, out ExceptionBreakpointState state) { string category = miExceptionResult.FindString("exception-category"); if (category == "mda") { exceptionCategory = s_exceptionCategory_MDA; } else { Debug.Assert(category == "clr"); exceptionCategory = s_exceptionCategory_CLR; } string stage = miExceptionResult.FindString("exception-stage"); switch (stage) { case "throw": state = ExceptionBreakpointState.BreakThrown; break; case "user-unhandled": state = ExceptionBreakpointState.BreakUserHandled; break; case "unhandled": state = ExceptionBreakpointState.None; break; default: Debug.Fail("Unknown exception-stage value"); state = ExceptionBreakpointState.None; break; } }
public override async Task<IEnumerable<ulong>> SetExceptionBreakpoints(Guid exceptionCategory, /*OPTIONAL*/ IEnumerable<string> exceptionNames, ExceptionBreakpointState exceptionBreakpointState) { List<string> commandTokens = new List<string>(); commandTokens.Add("-break-exception-insert"); if (exceptionCategory == s_exceptionCategory_MDA) { commandTokens.Add("--mda"); } else if (exceptionCategory != s_exceptionCategory_CLR) { throw new ArgumentOutOfRangeException("exceptionCategory"); } if (exceptionBreakpointState.HasFlag(ExceptionBreakpointState.BreakThrown)) { if (exceptionBreakpointState.HasFlag(ExceptionBreakpointState.BreakUserHandled)) commandTokens.Add("throw+user-unhandled"); else commandTokens.Add("throw"); } else { if (exceptionBreakpointState.HasFlag(ExceptionBreakpointState.BreakUserHandled)) commandTokens.Add("user-unhandled"); else commandTokens.Add("unhandled"); } if (exceptionNames == null) commandTokens.Add("*"); else commandTokens.AddRange(exceptionNames); string command = string.Join(" ", commandTokens); Results results = await _debugger.CmdAsync(command, ResultClass.done); ResultValue bkpt; if (results.TryFind("bkpt", out bkpt)) { if (bkpt is ValueListValue) { MICore.ValueListValue list = bkpt as MICore.ValueListValue; return list.Content.Select((x) => x.FindAddr("number")); } else { return new ulong[1] { bkpt.FindAddr("number") }; } } else { return new ulong[0]; } }
/// <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 ExceptionBreakpointState state) { exceptionCategory = null; state = ExceptionBreakpointState.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, ExceptionBreakpointState 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, ExceptionBreakpointState state) { _name = name; _code = code; _description = description ?? name; _category = exceptionCategory ?? EngineConstants.EngineId; switch (state) { case ExceptionBreakpointState.None: _state = enum_EXCEPTION_STATE.EXCEPTION_STOP_SECOND_CHANCE; break; case ExceptionBreakpointState.BreakThrown: _state = enum_EXCEPTION_STATE.EXCEPTION_STOP_FIRST_CHANCE | enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_FIRST_CHANCE; break; case ExceptionBreakpointState.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; } }
/// <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, ExceptionBreakpointState 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 override void DecodeExceptionReceivedProperties(Results miExceptionResult, out Guid?exceptionCategory, out ExceptionBreakpointState state) { string category = miExceptionResult.FindString("exception-category"); if (category == "mda") { exceptionCategory = s_exceptionCategory_MDA; } else { Debug.Assert(category == "clr"); exceptionCategory = s_exceptionCategory_CLR; } string stage = miExceptionResult.FindString("exception-stage"); switch (stage) { case "throw": state = ExceptionBreakpointState.BreakThrown; break; case "user-unhandled": state = ExceptionBreakpointState.BreakUserHandled; break; case "unhandled": state = ExceptionBreakpointState.None; break; default: Debug.Fail("Unknown exception-stage value"); state = ExceptionBreakpointState.None; break; } }
// 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, ExceptionBreakpointState state = ExceptionBreakpointState.None) { AD7ExceptionEvent eventObject = new AD7ExceptionEvent(name, description, code, exceptionCategory, state); AD7Thread ad7Thread = (AD7Thread)thread.Client; Send(eventObject, AD7ExceptionEvent.IID, ad7Thread); }
public ExceptionCategorySettings(ExceptionManager parent, HostConfigurationSection categoryKey, string categoryName) { _parent = parent; this.CategoryName = categoryName; this.DefaultCategoryState = RegistryToExceptionBreakpointState(categoryKey.GetValue("*")); Dictionary<string, ExceptionBreakpointState> exceptionSettings = new Dictionary<string, ExceptionBreakpointState>(); foreach (string valueName in categoryKey.GetValueNames()) { if (string.IsNullOrEmpty(valueName) || valueName == "*" || !ExceptionManager.IsSupportedException(valueName)) continue; ExceptionBreakpointState 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, ExceptionBreakpointState>(exceptionSettings); _settingsUpdate = new SettingsUpdates(this.DefaultCategoryState, this.DefaultRules); }
private async Task UpdateCatagory(Guid categoryId, ExceptionCategorySettings categorySettings, SettingsUpdates updates) { // Update the category if (updates.NewCategoryState.HasValue && ( updates.NewCategoryState.Value != ExceptionBreakpointState.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 { ExceptionBreakpointState newCategoryState = updates.NewCategoryState.Value; categorySettings.CategoryState = newCategoryState; categorySettings.CurrentRules.Clear(); IEnumerable <ulong> breakpointIds = await _commandFactory.SetExceptionBreakpoints(categoryId, null, newCategoryState); if (newCategoryState != ExceptionBreakpointState.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 <ExceptionBreakpointState, 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 } }
public AD7ExceptionEvent(string name, string description, uint code, Guid?exceptionCategory, ExceptionBreakpointState state) { _name = name; _code = code; _description = description ?? name; _category = exceptionCategory ?? new Guid(EngineConstants.EngineId); switch (state) { case ExceptionBreakpointState.None: _state = enum_EXCEPTION_STATE.EXCEPTION_STOP_SECOND_CHANCE; break; case ExceptionBreakpointState.BreakThrown: _state = enum_EXCEPTION_STATE.EXCEPTION_STOP_FIRST_CHANCE | enum_EXCEPTION_STATE.EXCEPTION_STOP_USER_FIRST_CHANCE; break; case ExceptionBreakpointState.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; } }
// 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, ExceptionBreakpointState state = ExceptionBreakpointState.None) { AD7ExceptionEvent eventObject = new AD7ExceptionEvent(name, description, code, exceptionCategory, state); AD7Thread ad7Thread = (AD7Thread)thread.Client; Send(eventObject, AD7ExceptionEvent.IID, ad7Thread); }
public override async Task <IEnumerable <ulong> > SetExceptionBreakpoints(Guid exceptionCategory, /*OPTIONAL*/ IEnumerable <string> exceptionNames, ExceptionBreakpointState exceptionBreakpointState) { List <string> commandTokens = new List <string>(); commandTokens.Add("-break-exception-insert"); if (exceptionCategory == s_exceptionCategory_MDA) { commandTokens.Add("--mda"); } else if (exceptionCategory != s_exceptionCategory_CLR) { throw new ArgumentOutOfRangeException("exceptionCategory"); } if (exceptionBreakpointState.HasFlag(ExceptionBreakpointState.BreakThrown)) { if (exceptionBreakpointState.HasFlag(ExceptionBreakpointState.BreakUserHandled)) { commandTokens.Add("throw+user-unhandled"); } else { commandTokens.Add("throw"); } } else { if (exceptionBreakpointState.HasFlag(ExceptionBreakpointState.BreakUserHandled)) { commandTokens.Add("user-unhandled"); } else { commandTokens.Add("unhandled"); } } if (exceptionNames == null) { commandTokens.Add("*"); } else { commandTokens.AddRange(exceptionNames); } string command = string.Join(" ", commandTokens); Results results = await _debugger.CmdAsync(command, ResultClass.done); ResultValue bkpt; if (results.TryFind("bkpt", out bkpt)) { if (bkpt is ValueListValue) { MICore.ValueListValue list = bkpt as MICore.ValueListValue; return(list.Content.Select((x) => x.FindAddr("number"))); } else { return(new ulong[1] { bkpt.FindAddr("number") }); } } else { return(new ulong[0]); } }
// VS CODE TODO: RegistryKey should be replaced with some sort of generic configuration store, and it should NOT be // optional. public ExceptionCategorySettings(ExceptionManager parent, /*OPTIONAL*/ RegistryKey categoryKey) { _parent = parent; if (categoryKey != null) { this.CategoryName = categoryKey.GetSubKeyNames().Single(); this.DefaultCategoryState = RegistryToExceptionBreakpointState(categoryKey.GetValue("*")); Dictionary<string, ExceptionBreakpointState> exceptionSettings = new Dictionary<string, ExceptionBreakpointState>(); foreach (string valueName in categoryKey.GetValueNames()) { if (string.IsNullOrEmpty(valueName) || valueName == "*" || !ExceptionManager.IsSupportedException(valueName)) continue; ExceptionBreakpointState 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, ExceptionBreakpointState>(exceptionSettings); } else { this.CategoryName = string.Empty; this.DefaultCategoryState = ExceptionBreakpointState.None; this.DefaultRules = new ReadOnlyDictionary<string, ExceptionBreakpointState>(new Dictionary<string, ExceptionBreakpointState>(0)); } this._settingsUpdate = new SettingsUpdates(this.DefaultCategoryState, this.DefaultRules); }
/// <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 ExceptionBreakpointState state) { exceptionCategory = null; state = ExceptionBreakpointState.None; }
private static void SetCategory(ExceptionCategorySettings categorySettings, ExceptionBreakpointState newState) { using (var settingsUpdateHolder = categorySettings.GetSettingsUpdate()) { settingsUpdateHolder.Value.NewCategoryState = newState; settingsUpdateHolder.Value.RulesToAdd.Clear(); settingsUpdateHolder.Value.RulesToRemove.Clear(); } }