Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
71 changes: 58 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,36 @@ 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)
{
if (_dacFilePath is null)
{
_dacFilePath = GetLibraryPath(DebugLibraryKind.Dac);
if (_dacFilePath is not null)
{
verifySignature = _settingsService.DacSignatureVerificationEnabled;
}
}
}
return _dacFilePath;
}

Expand All @@ -115,15 +145,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 +181,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 +344,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