Skip to content

Commit

Permalink
Merge pull request #1353 from microsoft/main
Browse files Browse the repository at this point in the history
Merge 'main' into 'release-cpptools'
  • Loading branch information
WardenGnaw authored Sep 9, 2022
2 parents a034bbd + 7ece35b commit 9b88953
Show file tree
Hide file tree
Showing 11 changed files with 411 additions and 46 deletions.
2 changes: 1 addition & 1 deletion eng/pipelines/tasks/MicroBuildSigningPlugin.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
steps:
- task: ms-vseng.MicroBuildTasks.30666190-6959-11e5-9f96-f56098202fef.MicroBuildSigningPlugin@3
- task: ms-vseng.MicroBuildTasks.30666190-6959-11e5-9f96-f56098202fef.MicroBuildSigningPlugin@4
displayName: 'Install Signing Plugin'
inputs:
signType: $(SignType)
Expand Down
18 changes: 18 additions & 0 deletions src/MICore/JsonLaunchOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;

namespace MICore.Json.LaunchOptions
Expand Down Expand Up @@ -113,6 +115,12 @@ public abstract partial class BaseOptions
/// </summary>
[JsonProperty("hardwareBreakpoints", DefaultValueHandling = DefaultValueHandling.Ignore)]
public HardwareBreakpointInfo HardwareBreakpointInfo { get; set; }

/// <summary>
/// Controls how breakpoints set externally (usually via raw GDB commands) are handled when hit. "throw" acts as if an exception was thrown by the application and "stop" only pauses the debug session.
/// </summary>
[JsonProperty("unknownBreakpointHandling", DefaultValueHandling = DefaultValueHandling.Ignore)]
public UnknownBreakpointHandling? UnknownBreakpointHandling { get; set; }
}

public partial class AttachOptions : BaseOptions
Expand Down Expand Up @@ -265,6 +273,16 @@ public HardwareBreakpointInfo(bool require = false, int? limit = null)
#endregion
}

[JsonConverter(typeof(StringEnumConverter))]
public enum UnknownBreakpointHandling
{
[EnumMember(Value = "throw")]
Throw,

[EnumMember(Value = "stop")]
Stop
}

public partial class LaunchOptions : BaseOptions
{
#region Public Properties for Serialization
Expand Down
15 changes: 15 additions & 0 deletions src/MICore/LaunchOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text;
using MICore.Json.LaunchOptions;

namespace MICore
{
Expand Down Expand Up @@ -1202,6 +1203,18 @@ public int HardwareBreakpointLimit
}
}

private UnknownBreakpointHandling _unknownBreakpointHandling;

public UnknownBreakpointHandling UnknownBreakpointHandling
{
get { return _unknownBreakpointHandling; }
set
{
VerifyCanModifyProperty(nameof(UnknownBreakpointHandling));
_unknownBreakpointHandling = value;
}
}

public string GetOptionsString()
{
try
Expand Down Expand Up @@ -1800,6 +1813,8 @@ protected void InitializeCommonOptions(Json.LaunchOptions.BaseOptions options)
{
throw new InvalidLaunchOptionsException(String.Format(CultureInfo.InvariantCulture, MICoreResources.Error_OptionNotSupported, nameof(options.HardwareBreakpointInfo.Require), nameof(MIMode.Lldb)));
}

this.UnknownBreakpointHandling = options.UnknownBreakpointHandling ?? UnknownBreakpointHandling.Throw;
}

protected void InitializeCommonOptions(Xml.LaunchOptions.BaseLaunchOptions source)
Expand Down
21 changes: 14 additions & 7 deletions src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1234,13 +1234,20 @@ private async Task HandleBreakModeEvent(ResultEventArgs results, BreakRequest br
}
else
{
// This is not one of our breakpoints, so stop with a message. Possibly it
// was set by the user via "-exec break ...", so display the available
// information.
string desc = String.Format(CultureInfo.CurrentCulture,
ResourceStrings.UnknownBreakpoint,
bkptno, addr);
_callback.OnException(thread, desc, "", 0);
// This is not one of our breakpoints. Possibly it was set by the user
// via "-exec break ...", so display the available information.
switch (_launchOptions.UnknownBreakpointHandling)
{
case MICore.Json.LaunchOptions.UnknownBreakpointHandling.Throw:
string desc = String.Format(CultureInfo.CurrentCulture,
ResourceStrings.UnknownBreakpoint,
bkptno, addr);
_callback.OnException(thread, desc, "", 0);
break;
case MICore.Json.LaunchOptions.UnknownBreakpointHandling.Stop:
_callback.OnBreakpoint(thread, new ReadOnlyCollection<object>(new AD7BoundBreakpoint[] { }));
break;
}
}
}
}
Expand Down
88 changes: 78 additions & 10 deletions src/MIDebugEngine/Engine.Impl/Variables.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ internal VariableInformation(string displayName, string expr, ThreadContext ctx,
: this(ctx, engine, thread)
{
// strip off formatting string
_strippedName = StripFormatSpecifier(expr, out _format);
_strippedName = ProcessFormatSpecifiers(expr, out _format);
Name = displayName;
IsParameter = isParameter;
_parent = null;
Expand All @@ -225,7 +225,7 @@ internal VariableInformation(string expr, IVariableInformation parent, AD7Engine
: this(parent.ThreadContext, engine, parent.Client)
{
// strip off formatting string
_strippedName = StripFormatSpecifier(expr, out _format);
_strippedName = ProcessFormatSpecifiers(expr, out _format);
Name = displayName ?? expr;
_parent = parent;
VariableNodeType = NodeType.Synthetic;
Expand All @@ -236,7 +236,7 @@ internal VariableInformation(string expr, VariableInformation parent)
: this(parent._ctx, parent._engine, parent.Client)
{
// strip off formatting string
_strippedName = StripFormatSpecifier(expr, out _format);
_strippedName = ProcessFormatSpecifiers(expr, out _format);
Name = expr;
VariableNodeType = NodeType.Root;
}
Expand Down Expand Up @@ -337,9 +337,19 @@ public VariableInformation FindChildByName(string name)
private ThreadContext _ctx;
private bool _attribsFetched;
private bool _isReadonly;
/// <summary>
/// This callback is used when we need to call into the engine for additional information for
/// the format specifier.
///
/// <param name="threadId">The threadId to use when calling the engine.</param>
/// <param name="frameLevel">The frameLevel to use when calling the engine.</param>
/// <returns>The expression to send to the engine</returns>
/// </summary>
private delegate Task<string> DeferedFormatExpression(int threadId, uint frameLevel);
private DeferedFormatExpression _deferedFormatExpression;
private IVariableInformation _parent;
private string _format;
private string _strippedName; // "Name" stripped of format specifiers
private IVariableInformation _parent;
private string _fullname;

public enum NodeType
Expand All @@ -365,7 +375,7 @@ public enum NodeType

private static Regex s_isFunction = new Regex(@".+\(.*\).*");

private string StripFormatSpecifier(string exp, out string formatSpecifier)
private string ProcessFormatSpecifiers(string exp, out string formatSpecifier)
{
formatSpecifier = null; // will be used with -var-set-format

Expand Down Expand Up @@ -428,16 +438,35 @@ private string StripFormatSpecifier(string exp, out string formatSpecifier)
}

// array with static size
// TODO: could return '(T(*)[n])(exp)' but requires T
var m = Regex.Match(trimmed, @"^\[?(\d+)\]?$");
if (m.Success)
{
string count = m.Groups[1].Value; // (\d+) capture group
string expr = exp.Substring(0, lastComma);

if (_engine.DebuggedProcess.MICommandFactory.Mode == MIMode.Gdb)
return "*" + exp.Substring(0, lastComma) + "@" + trimmed; // this does not work for lldb
{
// return *<expression>@<count> which is only supported in GDB
return FormattableString.Invariant($"*{expr}@{count}");
}
else
{
_deferedFormatExpression = async (int threadId, uint frameLevel) =>
{
string derefType = await GetDereferencedTypeStringAsync(expr, threadId, frameLevel);

return exp.Substring(0, lastComma);
}
if (!string.IsNullOrEmpty(derefType))
{
// Cast 'exp' to a pointer of an array of type 'T' with size 'n' with '*(T(*)[n])(exp)'
return FormattableString.Invariant($"*({derefType}(*)[{count}])({expr})");
}

return string.Empty;
};

return expr;
}
}

// array with dynamic size
if (Regex.Match(trimmed, @"^\[([a-zA-Z_][a-zA-Z_\d]*)\]$").Success)
Expand All @@ -446,6 +475,27 @@ private string StripFormatSpecifier(string exp, out string formatSpecifier)
return exp;
}

private async Task<string> GetDereferencedTypeStringAsync(string expr, int threadId, uint frameLevel)
{
// TODO: Should we error if the current type is not a pointer type?

// Evaluates: *expr
Results results = await _engine.DebuggedProcess.MICommandFactory.VarCreate($"*({expr})", threadId, frameLevel, 0, ResultClass.None);

if (results.ResultClass == ResultClass.done)
{
string varName = results.TryFindString("name");
if (!String.IsNullOrWhiteSpace(varName))
{
// Remove the variable we created as we don't track it.
await _engine.DebuggedProcess.MICommandFactory.VarDelete(varName);
}

return results.TryFindString("type");
}
return null;
}

public void AsyncEval(IDebugEventCallback2 pExprCallback)
{
EngineCallback engineCallback;
Expand Down Expand Up @@ -547,7 +597,25 @@ internal async Task Eval(uint radix, enum_EVALFLAGS dwFlags = 0, DAPEvalFlags dw

int threadId = Client.GetDebuggedThread().Id;
uint frameLevel = _ctx.Level;
Results results = await _engine.DebuggedProcess.MICommandFactory.VarCreate(_strippedName, threadId, frameLevel, dwFlags, ResultClass.None);

string expression = _strippedName;

// If we have a deferred format expression, resolve it.
if (_deferedFormatExpression != null)
{
string deferedExpression = await _deferedFormatExpression(threadId, frameLevel);

if (!string.IsNullOrEmpty(deferedExpression))
{
expression = deferedExpression;
}
else
{
Debug.Fail(FormattableString.Invariant($"Failed to resolve deferred expression. Falling back to original: '{expression}'."));
}
}

Results results = await _engine.DebuggedProcess.MICommandFactory.VarCreate(expression, threadId, frameLevel, dwFlags, ResultClass.None);

if (results.ResultClass == ResultClass.done)
{
Expand Down
Loading

0 comments on commit 9b88953

Please sign in to comment.