Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
<SystemCollectionsImmutableVersion>8.0.0</SystemCollectionsImmutableVersion>
<!-- Other libs -->
<MicrosoftBclAsyncInterfacesVersion>6.0.0</MicrosoftBclAsyncInterfacesVersion>
<MicrosoftDiagnosticsRuntimeVersion>4.0.0-beta.25167.1</MicrosoftDiagnosticsRuntimeVersion>
<MicrosoftDiagnosticsRuntimeVersion>4.0.0-beta.25201.1</MicrosoftDiagnosticsRuntimeVersion>
<MicrosoftDiaSymReaderNativeVersion>17.10.0-beta1.24272.1</MicrosoftDiaSymReaderNativeVersion>
<MicrosoftDiagnosticsTracingTraceEventVersion>3.1.16</MicrosoftDiagnosticsTracingTraceEventVersion>
<MicrosoftExtensionsLoggingVersion>6.0.0</MicrosoftExtensionsLoggingVersion>
Expand Down
13 changes: 12 additions & 1 deletion src/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

namespace Microsoft.Diagnostics.DebugServices.Implementation
{
public class Host : IHost
public class Host : IHost, ISettingsService
{
private readonly ServiceManager _serviceManager;
private ServiceContainer _serviceContainer;
Expand Down Expand Up @@ -49,6 +49,7 @@ public ServiceContainer CreateServiceContainer()
_serviceContainer = _serviceManager.CreateServiceContainer(ServiceScope.Global, parent: null);
_serviceContainer.AddService<IServiceManager>(_serviceManager);
_serviceContainer.AddService<IHost>(this);
_serviceContainer.AddService<ISettingsService>(this);

return _serviceContainer;
}
Expand Down Expand Up @@ -103,6 +104,16 @@ public string GetTempDirectory()

#endregion

#region ISettingsService

public virtual bool DacSignatureVerificationEnabled { get; set; }

public bool UseContractReader { get; set; }

public bool ForceUseContractReader { get; set; }

#endregion

private void CleanupTempDirectory()
{
if (_tempDirectory != null)
Expand Down
68 changes: 55 additions & 13 deletions src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ namespace Microsoft.Diagnostics.DebugServices.Implementation
public class Runtime : IRuntime, IDisposable
{
private readonly ClrInfo _clrInfo;
private readonly ISettingsService _settingsService;
private readonly ISymbolService _symbolService;
private Version _runtimeVersion;
private ClrRuntime _clrRuntime;
private string _dacFilePath;
private string _cdacFilePath;
private string _dbiFilePath;

protected readonly ServiceContainer _serviceContainer;
Expand All @@ -33,7 +35,8 @@ public Runtime(IServiceProvider services, int id, ClrInfo clrInfo)
Target = services.GetService<ITarget>() ?? throw new DiagnosticsException("Dump or live session target required");
Id = id;
_clrInfo = clrInfo ?? throw new ArgumentNullException(nameof(clrInfo));
_symbolService = services.GetService<ISymbolService>();
_settingsService = services.GetService<ISettingsService>() ?? throw new ArgumentException("ISettingsService required");
_symbolService = services.GetService<ISymbolService>() ?? throw new ArgumentException("ISymbolService required");

RuntimeType = RuntimeType.Unknown;
if (clrInfo.Flavor == ClrFlavor.Core)
Expand Down Expand Up @@ -96,9 +99,33 @@ public Version RuntimeVersion
}
}

public string GetDacFilePath()
public string GetCDacFilePath()
{
_dacFilePath ??= GetLibraryPath(DebugLibraryKind.Dac);
if (_cdacFilePath is null)
{
if (_settingsService.UseContractReader || _settingsService.ForceUseContractReader)
{
_cdacFilePath = GetLibraryPath(DebugLibraryKind.CDac);
}
}
return _cdacFilePath;
}

public string GetDacFilePath(out bool verifySignature)
{
verifySignature = false;
if (_settingsService.ForceUseContractReader)
{
return GetCDacFilePath();
}
if (_dacFilePath is null)
{
_dacFilePath = GetLibraryPath(DebugLibraryKind.Dac);
if (_dacFilePath is not null)
{
verifySignature = _settingsService.DacSignatureVerificationEnabled;
}
}
return _dacFilePath;
}

Expand All @@ -115,15 +142,15 @@ public string GetDbiFilePath()
/// </summary>
private ClrRuntime CreateRuntime()
{
string dacFilePath = GetDacFilePath();
string dacFilePath = GetDacFilePath(out bool verifySignature);
if (dacFilePath is not null)
{
Trace.TraceInformation($"Creating ClrRuntime #{Id} {dacFilePath}");
try
{
// Ignore the DAC version mismatch that can happen because the clrmd ELF dump reader
// returns 0.0.0.0 for the runtime module that the DAC is matched against.
return _clrRuntime = _clrInfo.CreateRuntime(dacFilePath, ignoreMismatch: true);
return _clrRuntime = _clrInfo.CreateRuntime(dacFilePath, ignoreMismatch: true, verifySignature);
}
catch (Exception ex) when
(ex is DllNotFoundException or
Expand Down Expand Up @@ -151,32 +178,42 @@ private string GetLibraryPath(DebugLibraryKind kind)
{
if (libraryInfo.Kind == kind && RuntimeInformation.IsOSPlatform(libraryInfo.Platform) && libraryInfo.TargetArchitecture == currentArch)
{
libraryPath = GetLocalPath(libraryInfo.FileName);
libraryPath = GetLocalPath(libraryInfo);
if (libraryPath is not null)
{
break;
}
libraryPath = DownloadFile(libraryInfo);
if (libraryPath is not null)
if (libraryInfo.ArchivedUnder != SymbolProperties.None)
{
break;
libraryPath = DownloadFile(libraryInfo);
if (libraryPath is not null)
{
break;
}
}
}
}

return libraryPath;
}

private string GetLocalPath(string fileName)
private string GetLocalPath(DebugLibraryInfo libraryInfo)
{
string localFilePath;
if (!string.IsNullOrEmpty(RuntimeModuleDirectory))
if (libraryInfo.Kind == DebugLibraryKind.CDac)
{
localFilePath = Path.Combine(RuntimeModuleDirectory, Path.GetFileName(fileName));
localFilePath = libraryInfo.FileName;
}
else
{
localFilePath = Path.Combine(Path.GetDirectoryName(RuntimeModule.FileName), Path.GetFileName(fileName));
if (!string.IsNullOrEmpty(RuntimeModuleDirectory))
{
localFilePath = Path.Combine(RuntimeModuleDirectory, Path.GetFileName(libraryInfo.FileName));
}
else
{
localFilePath = Path.Combine(Path.GetDirectoryName(RuntimeModule.FileName), Path.GetFileName(libraryInfo.FileName));
}
}
if (!File.Exists(localFilePath))
{
Expand Down Expand Up @@ -304,6 +341,11 @@ public override string ToString()
sb.AppendLine();
sb.Append($" DAC: {_dacFilePath}");
}
if (_cdacFilePath is not null)
{
sb.AppendLine();
sb.Append($" CDAC: {_cdacFilePath}");
}
if (_dbiFilePath is not null)
{
sb.AppendLine();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,12 @@ public RuntimeProvider(IServiceProvider services)
/// <param name="flags">Enumeration control flags</param>
public IEnumerable<IRuntime> EnumerateRuntimes(int startingRuntimeId, RuntimeEnumerationFlags flags)
{
ISettingsService settingsService = _services.GetService<ISettingsService>();
// The ClrInfo and DataTarget instances are disposed when Runtime instance is disposed. Runtime instances are
// not flushed when the Target/RuntimeService is flushed; they are all disposed and the list cleared. They are
// all re-created the next time the IRuntime or ClrRuntime instance is queried.
DataTarget dataTarget = new(new CustomDataTarget(_services.GetService<IDataReader>())
{
ForceCompleteRuntimeEnumeration = (flags & RuntimeEnumerationFlags.All) != 0,
DacSignatureVerificationEnabled = settingsService is null || settingsService.DacSignatureVerificationEnabled,
FileLocator = null
});
for (int i = 0; i < dataTarget.ClrVersions.Length; i++)
Expand Down
8 changes: 7 additions & 1 deletion src/Microsoft.Diagnostics.DebugServices/IRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,13 @@ public interface IRuntime
/// <summary>
/// Returns the DAC file path
/// </summary>
string GetDacFilePath();
/// <param name="verifySignature">returns if the DAC signature should be verified</param>
string GetDacFilePath(out bool verifySignature);

/// <summary>
/// Returns the CDac file path if enabled by global settings
/// </summary>
string GetCDacFilePath();

/// <summary>
/// Returns the DBI file path
Expand Down
10 changes: 10 additions & 0 deletions src/Microsoft.Diagnostics.DebugServices/ISettingsService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,15 @@ public interface ISettingsService
/// If true, enforces the proper DAC certificate signing when loaded
/// </summary>
bool DacSignatureVerificationEnabled { get; set; }

/// <summary>
/// If true, uses the CDAC contract reader if available.
/// </summary>
bool UseContractReader { get; set; }

/// <summary>
/// If true, always use the CDAC contract reader even when not requested
/// </summary>
bool ForceUseContractReader { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ namespace Microsoft.Diagnostics.ExtensionCommands
{
public static class CommandFormatHelpers
{
public const string DacTableSymbol = "g_dacTable";
public const string DebugHeaderSymbol = "DotNetRuntimeDebugHeader";
public const string DacTableExport = "g_dacTable";
public const string DebugHeaderExport = "DotNetRuntimeDebugHeader";
public const string ContractDescriptorExport = "DotNetRuntimeContractDescriptor";

/// <summary>
/// Displays the special diagnostics info header memory block (.NET Core 8 or later on Linux/MacOS)
Expand Down Expand Up @@ -127,28 +128,28 @@ IConsoleService Console()
IExportSymbols symbols = module.Services.GetService<IExportSymbols>();
if (symbols != null && symbols.TryGetSymbolAddress(RuntimeInfo.RUNTIME_INFO_SYMBOL, out ulong infoAddress))
{
Console().Write($"{indent}{RuntimeInfo.RUNTIME_INFO_SYMBOL,-24}: {infoAddress:X16}");
Console().Write($"{indent}{RuntimeInfo.RUNTIME_INFO_SYMBOL}: {infoAddress:X16}");
if (RuntimeInfo.TryRead(command.Services, infoAddress, out RuntimeInfo info))
{
Console().WriteLine(info.IsValid ? "" : " <INVALID>");
Console().WriteLine($"{indent} Signature: {info.Signature}");
Console().WriteLine($"{indent} Version: {info.Version}");
Console().WriteLine($"{indent} RuntimeModuleIndex: {info.RawRuntimeModuleIndex.ToHex()}");
Console().WriteLine($"{indent} DacModuleIndex: {info.RawDacModuleIndex.ToHex()}");
Console().WriteLine($"{indent} DbiModuleIndex: {info.RawDbiModuleIndex.ToHex()}");
Console().WriteLine($"{indent} Signature: {info.Signature}");
Console().WriteLine($"{indent} Version: {info.Version}");
Console().WriteLine($"{indent} RuntimeModuleIndex: {info.RawRuntimeModuleIndex.ToHex()}");
Console().WriteLine($"{indent} DacModuleIndex: {info.RawDacModuleIndex.ToHex()}");
Console().WriteLine($"{indent} DbiModuleIndex: {info.RawDbiModuleIndex.ToHex()}");
if (module.IsPEImage)
{
Console().WriteLine($"{indent} RuntimePEIndex: {info.RuntimePEIIndex.timeStamp:X8}/{info.RuntimePEIIndex.fileSize:X}");
Console().WriteLine($"{indent} DacPEIndex: {info.DacPEIndex.timeStamp:X8}/{info.DacPEIndex.fileSize:X}");
Console().WriteLine($"{indent} DbiPEIndex: {info.DbiPEIndex.timeStamp:X8}/{info.DbiPEIndex.fileSize:X}");
Console().WriteLine($"{indent} RuntimePEIndex: {info.RuntimePEIIndex.timeStamp:X8}/{info.RuntimePEIIndex.fileSize:X}");
Console().WriteLine($"{indent} DacPEIndex: {info.DacPEIndex.timeStamp:X8}/{info.DacPEIndex.fileSize:X}");
Console().WriteLine($"{indent} DbiPEIndex: {info.DbiPEIndex.timeStamp:X8}/{info.DbiPEIndex.fileSize:X}");
}
else
{
Console().WriteLine($"{indent} RuntimeBuildId: {info.RuntimeBuildId.ToHex()}");
Console().WriteLine($"{indent} DacBuildId: {info.DacBuildId.ToHex()}");
Console().WriteLine($"{indent} DbiBuildId: {info.DbiBuildId.ToHex()}");
Console().WriteLine($"{indent} RuntimeBuildId: {info.RuntimeBuildId.ToHex()}");
Console().WriteLine($"{indent} DacBuildId: {info.DacBuildId.ToHex()}");
Console().WriteLine($"{indent} DbiBuildId: {info.DbiBuildId.ToHex()}");
}
Console().WriteLine($"{indent} RuntimeVersion: {info.RuntimeVersion?.ToString() ?? "<none>"}");
Console().WriteLine($"{indent} RuntimeVersion: {info.RuntimeVersion?.ToString() ?? "<none>"}");
}
else
{
Expand All @@ -157,7 +158,7 @@ IConsoleService Console()
}
else if (error)
{
Console().WriteLine($"{indent}{RuntimeInfo.RUNTIME_INFO_SYMBOL,-24}: <NO SYMBOL>");
Console().WriteLine($"{indent}{RuntimeInfo.RUNTIME_INFO_SYMBOL}: <NO SYMBOL>");
}

// Print the Windows runtime engine metrics (.NET Core and .NET Framework)
Expand All @@ -166,13 +167,13 @@ IConsoleService Console()
{
if (symbols != null && symbols.TryGetSymbolAddress(ClrEngineMetrics.Symbol, out ulong metricsAddress))
{
Console().Write($"{indent}{ClrEngineMetrics.Symbol,-24}: ({metricsAddress:X16})");
Console().Write($"{indent}{ClrEngineMetrics.Symbol}: {metricsAddress:X16}");
if (ClrEngineMetrics.TryRead(command.Services, metricsAddress, out ClrEngineMetrics metrics))
{
Console().WriteLine();
Console().WriteLine($"{indent} Size: {metrics.Size} (0x{metrics.Size:X2})");
Console().WriteLine($"{indent} DbiVersion: {metrics.DbiVersion}");
Console().WriteLine($"{indent} ContinueStartupEvent: {((ulong)metrics.ContinueStartupEvent):X16}");
Console().WriteLine($"{indent} Size: {metrics.Size} (0x{metrics.Size:X2})");
Console().WriteLine($"{indent} DbiVersion: {metrics.DbiVersion}");
Console().WriteLine($"{indent} ContinueStartupEvent: {((ulong)metrics.ContinueStartupEvent):X16}");
}
else
{
Expand All @@ -181,28 +182,38 @@ IConsoleService Console()
}
else if (error)
{
Console().WriteLine($"{indent}{ClrEngineMetrics.Symbol,-24}: <NO SYMBOL>");
Console().WriteLine($"{indent}{ClrEngineMetrics.Symbol}: <NO SYMBOL>");
}
}

// Print the DAC table address (g_dacTable)
if (symbols != null && symbols.TryGetSymbolAddress(DacTableSymbol, out ulong dacTableAddress))
if (symbols != null && symbols.TryGetSymbolAddress(DacTableExport, out ulong dacTableAddress))
{
Console().WriteLine($"{indent}{DacTableSymbol,-24}: {dacTableAddress:X16}");
Console().WriteLine($"{indent}{DacTableExport}: {dacTableAddress:X16}");
}
else if (error)
{
Console().WriteLine($"{indent}{DacTableSymbol,-24}: <NO SYMBOL>");
Console().WriteLine($"{indent}{DacTableExport}: <NO SYMBOL>");
}

// Print the Native AOT contract data address (DotNetRuntimeDebugHeader)
if (symbols != null && symbols.TryGetSymbolAddress(DebugHeaderSymbol, out ulong debugHeaderAddress))
if (symbols != null && symbols.TryGetSymbolAddress(DebugHeaderExport, out ulong debugHeaderAddress))
{
Console().WriteLine($"{indent}{DebugHeaderSymbol,-24}: {debugHeaderAddress:X16}");
Console().WriteLine($"{indent}{DebugHeaderExport}: {debugHeaderAddress:X16}");
}
else if (error)
{
Console().WriteLine($"{indent}{DebugHeaderSymbol,-24}: <NO SYMBOL>");
Console().WriteLine($"{indent}{DebugHeaderExport}: <NO SYMBOL>");
}

// Print the CDAC contract data address (DotNetRuntimeContractDescriptor)
if (symbols != null && symbols.TryGetSymbolAddress(ContractDescriptorExport, out ulong contractDescriptorAddress))
{
Console().WriteLine($"{indent}{ContractDescriptorExport}: {contractDescriptorAddress:X16}");
}
else if (error)
{
Console().WriteLine($"{indent}{ContractDescriptorExport}: <NO SYMBOL>");
}
}
}
Expand Down
Loading