Skip to content

Commit

Permalink
[microsoft#1349] Use --scalar-values option if available.
Browse files Browse the repository at this point in the history
Newer versions of GDB support the `--scalar-values` option (with value
3) to the `-stack-list-arguments`, `-stack-list-locals` and
`-stack-list-variables` commands. This option fetches names, types,
and values for scalar types, or names and types only for non-scalar
types.

Use this in `DebuggedProcess.GetParameterInfoOnly()` if it is
available, as this gets all the required information without the
potential performance penalty of the `--simple-values` option which
potentially fetches large values for references to arrays, structures,
and unions.

New method `MICommandFactory.SupportsScalarValues()` determines if
`--scalar-values` is supported, using the `-list-features` command and
checking for the presence of the `"scalar-values"` feature. We cache
the result on the `DebuggedProcess` object, as the set of supported
features does not change during the lifetime of the debug session.
  • Loading branch information
gareth-rees committed Nov 11, 2022
1 parent d31b712 commit 64cbda8
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 3 deletions.
18 changes: 18 additions & 0 deletions src/MICore/CommandFactories/MICommandFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public enum PrintValue
NoValues = 0,
AllValues = 1,
SimpleValues = 2,
ScalarValues = 3, // Only available if SupportsScalarValues()
}

[Flags]
Expand Down Expand Up @@ -697,6 +698,23 @@ public virtual bool SupportsBreakpointChecksums()
{
return false;
}

/// <summary>
/// Get the set of features supported by the underlying debugger.
/// </summary>
public virtual Task<HashSet<string>> GetFeatures()
{
return Task.FromResult(new HashSet<string>());
}

/// <summary>
/// True if the underlying debugger supports PrintValue.ScalarValues as an argument to
/// StackListLocals(), StackListArguments() and StackListVariables().
/// </summary>
public virtual Task<bool> SupportsScalarValues()
{
return Task.FromResult(false);
}
#endregion
}
}
12 changes: 12 additions & 0 deletions src/MICore/CommandFactories/gdb.cs
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,18 @@ public override async Task EnableTargetAsyncOption()
}
}

public override async Task<HashSet<string>> GetFeatures()
{
Results results = await _debugger.CmdAsync("-list-features", ResultClass.done);
return new HashSet<string>(results.Find<ValueListValue>("features").AsStrings);
}

public override async Task<bool> SupportsScalarValues()
{
HashSet<string> features = await GetFeatures();
return features.Contains("scalar-values");
}

public override async Task Terminate()
{
// Although the mi documentation states that the correct command to terminate is -exec-abort
Expand Down
16 changes: 13 additions & 3 deletions src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ internal class DebuggedProcess : MICore.Debugger
private IProcessSequence _childProcessHandler;
private bool _deleteEntryPointBreakpoint;
private string _entryPointBreakpoint = string.Empty;
private bool _supportsScalarValues = false; // Debugger supports PrintValue.ScalarValues?

public DebuggedProcess(bool bLaunched, LaunchOptions launchOptions, ISampleEngineCallback callback, WorkerThread worker, BreakpointManager bpman, AD7Engine engine, HostConfigurationStore configStore, HostWaitLoop waitLoop = null) : base(launchOptions, engine.Logger)
{
Expand Down Expand Up @@ -550,6 +551,8 @@ public async Task Initialize(HostWaitLoop waitLoop, CancellationToken token)

try
{
_supportsScalarValues = await this.MICommandFactory.SupportsScalarValues();

await this.MICommandFactory.EnableTargetAsyncOption();

await this.CheckCygwin(_launchOptions as LocalLaunchOptions);
Expand Down Expand Up @@ -1967,7 +1970,8 @@ public async Task<List<SimpleVariableInformation>> GetParameterInfoOnly(AD7Threa
{
List<SimpleVariableInformation> parameters = new List<SimpleVariableInformation>();

ValueListValue localAndParameters = await MICommandFactory.StackListVariables(PrintValue.SimpleValues, thread.Id, ctx.Level);
PrintValue printValue = _supportsScalarValues ? PrintValue.ScalarValues: PrintValue.SimpleValues;
ValueListValue localAndParameters = await MICommandFactory.StackListVariables(printValue, thread.Id, ctx.Level);

foreach (var results in localAndParameters.Content.Where(r => r.TryFindString("arg") == "1"))
{
Expand All @@ -1981,8 +1985,14 @@ public async Task<List<SimpleVariableInformation>> GetParameterInfoOnly(AD7Threa
//NOTE: eval is not called
public async Task<List<ArgumentList>> GetParameterInfoOnly(AD7Thread thread, bool values, bool types, uint low, uint high)
{
// If values are requested, request simple values, otherwise we'll use -var-create to get the type of argument it is.
var frames = await MICommandFactory.StackListArguments(values ? PrintValue.SimpleValues : PrintValue.NoValues, thread.Id, low, high);
// If ScalarValues is supported, use it (even if values are not requested) as it gets
// types too, without the potential performance penalty of getting non-scalar values.
// Otherwise, If values are requested, use SimpleValues, otherwise the potential
// performance penalty is too high, so use NoValues and follow up with -var-create to
// get the types.
PrintValue printValue = _supportsScalarValues ? PrintValue.ScalarValues
: (values ? PrintValue.SimpleValues : PrintValue.NoValues);
var frames = await MICommandFactory.StackListArguments(printValue, thread.Id, low, high);
List<ArgumentList> parameters = new List<ArgumentList>();

foreach (var f in frames)
Expand Down

0 comments on commit 64cbda8

Please sign in to comment.