Skip to content

Commit

Permalink
[#1349] Always use --simple-values in newer versions of GDB. (#1400)
Browse files Browse the repository at this point in the history
* [#1349] Always use `--simple-values` in newer versions of GDB.

In newer versions of GDB, the `--simple-values` option to the
`-stack-list-arguments`, `-stack-list-locals` and
`-stack-list-variables` commands no longer prints the value for
references to compound types. This improves the performance of these
commands when the stack has references to large data structures.

When these versions of GDB are available, take advantage by using
`--simple-values` in `DebuggedProcess.GetParameterInfoOnly` to fetch
names and types in a single `-stack-list-arguments` command. This is
faster than the old approach of using `--no-values` followed with
`-var-create` and `-var-delete` for each parameter to get the type.

The new method `MICommandFactory.SupportsSimpleValuesExcludesRefTypes`
determines if the debugger supports the improved behaviour of the
`--simple-values` option, by executing the `-list-features` command
and checking for the `"simple-values-ref-types"` feature in the
output. We cache the result on the `DebuggedProcess` object as the set
of supported features does not change during the lifetime of the debug
session.

* fixup! [#1349] Always use `--simple-values` in newer versions of GDB.
  • Loading branch information
gareth-rees authored May 30, 2023
1 parent f530168 commit 73d569d
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
18 changes: 18 additions & 0 deletions src/MICore/CommandFactories/MICommandFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,24 @@ 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 excludes the printing of references to
/// compound types when PrintValue.SimpleValues is used as an argument to
/// StackListLocals(), StackListArguments() and StackListVariables().
/// </summary>
public virtual Task<bool> SupportsSimpleValuesExcludesRefTypes()
{
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> SupportsSimpleValuesExcludesRefTypes()
{
HashSet<string> features = await GetFeatures();
return features.Contains("simple-values-ref-types");
}

public override async Task Terminate()
{
// Although the mi documentation states that the correct command to terminate is -exec-abort
Expand Down
23 changes: 21 additions & 2 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? _simpleValuesExcludesRefTypes = null;

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 @@ -1985,8 +1986,26 @@ 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);
PrintValue printValue = values ? PrintValue.SimpleValues : PrintValue.NoValues;
if (types && !values)
{
// We want types but not values. There is no PrintValue option for this, but if
// SimpleValues excludes printing values for references to compound types, then
// the fastest approach is to use SimpleValues (and ignore the values).
// Otherwise, the potential performance penalty of fetching values for
// references to compound types is too high, so use NoValues and follow up with
// -var-create to get the types.
if (!_simpleValuesExcludesRefTypes.HasValue)
{
_simpleValuesExcludesRefTypes = await this.MICommandFactory.SupportsSimpleValuesExcludesRefTypes();
}
if (_simpleValuesExcludesRefTypes.Value)
{
printValue = PrintValue.SimpleValues;
}
}

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 73d569d

Please sign in to comment.