From 98881c091c81af515d925d4d899ea39e7fc89cfd Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Wed, 26 Mar 2025 16:07:57 -0700 Subject: [PATCH 1/2] Add CDAC support to SOS Add --usecdac and --forceusecdac options "runtimes" to control cdac loading. Currently --usecdac enables using the CDAC for only the CLRMA APIs. --forceusecdac forces all SOS to use the CDAC for testing. Move ISettingsService impl's to Host class. Add UseContractReader property. Add IRuntime.GetCDacFilePath() and add a "bool verifySignature" parameter to IRuntime.GetDacFilePath. Add DotNetRuntimeContractDescriptor address to !runtimes info. Clean up the formatting a little. Publish SOS.Hosting package --- eng/Versions.props | 2 +- .../Host.cs | 13 +- .../Runtime.cs | 71 +++++++-- .../RuntimeProvider.cs | 2 - .../IRuntime.cs | 8 +- .../ISettingsService.cs | 10 ++ .../Host/CommandFormatHelpers.cs | 65 ++++---- .../Host/RuntimesCommand.cs | 35 ++++- .../TestHost/TestDataWriter.cs | 2 +- .../TestHost/TestDump.cs | 9 +- src/SOS/SOS.Extensions/HostServices.cs | 44 ++++-- src/SOS/SOS.Hosting/DataTargetWrapper.cs | 37 +++++ src/SOS/SOS.Hosting/RuntimeWrapper.cs | 148 +++++++++++++----- src/SOS/SOS.Hosting/SOS.Hosting.csproj | 5 +- src/SOS/Strike/clrma/managedanalysis.cpp | 2 +- src/SOS/Strike/platform/runtimeimpl.cpp | 2 +- src/SOS/Strike/platform/runtimeimpl.h | 2 +- src/SOS/Strike/util.cpp | 2 +- src/SOS/inc/runtime.h | 18 ++- src/Tools/dotnet-dump/Analyzer.cs | 10 +- src/shared/inc/clrdata.idl | 14 ++ src/shared/pal/prebuilt/idl/clrdata_i.cpp | 11 +- src/shared/pal/prebuilt/inc/clrdata.h | 93 ++++++++++- src/tests/DbgShim.UnitTests/DbgShimTests.cs | 2 +- 24 files changed, 471 insertions(+), 136 deletions(-) diff --git a/eng/Versions.props b/eng/Versions.props index cd3ae1a1c5..1851348517 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -37,7 +37,7 @@ 8.0.0 6.0.0 - 4.0.0-beta.25167.1 + 4.0.0-beta.25201.1 17.10.0-beta1.24272.1 3.1.16 6.0.0 diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs index f8935fb0d5..d15d09b028 100644 --- a/src/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs +++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/Host.cs @@ -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; @@ -49,6 +49,7 @@ public ServiceContainer CreateServiceContainer() _serviceContainer = _serviceManager.CreateServiceContainer(ServiceScope.Global, parent: null); _serviceContainer.AddService(_serviceManager); _serviceContainer.AddService(this); + _serviceContainer.AddService(this); return _serviceContainer; } @@ -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) diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs index 26513a095c..757a5db4ba 100644 --- a/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs +++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs @@ -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; @@ -33,7 +35,8 @@ public Runtime(IServiceProvider services, int id, ClrInfo clrInfo) Target = services.GetService() ?? throw new DiagnosticsException("Dump or live session target required"); Id = id; _clrInfo = clrInfo ?? throw new ArgumentNullException(nameof(clrInfo)); - _symbolService = services.GetService(); + _settingsService = services.GetService() ?? throw new ArgumentException("ISettingsService required"); + _symbolService = services.GetService() ?? throw new ArgumentException("ISymbolService required"); RuntimeType = RuntimeType.Unknown; if (clrInfo.Flavor == ClrFlavor.Core) @@ -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; } @@ -115,7 +145,7 @@ public string GetDbiFilePath() /// private ClrRuntime CreateRuntime() { - string dacFilePath = GetDacFilePath(); + string dacFilePath = GetDacFilePath(out bool verifySignature); if (dacFilePath is not null) { Trace.TraceInformation($"Creating ClrRuntime #{Id} {dacFilePath}"); @@ -123,7 +153,7 @@ private ClrRuntime CreateRuntime() { // 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 @@ -151,15 +181,18 @@ 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; + } } } } @@ -167,16 +200,23 @@ private string GetLibraryPath(DebugLibraryKind kind) 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)) { @@ -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(); diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.cs index 44ddf04715..4639a0ebcf 100644 --- a/src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.cs +++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/RuntimeProvider.cs @@ -29,14 +29,12 @@ public RuntimeProvider(IServiceProvider services) /// Enumeration control flags public IEnumerable EnumerateRuntimes(int startingRuntimeId, RuntimeEnumerationFlags flags) { - ISettingsService settingsService = _services.GetService(); // 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()) { ForceCompleteRuntimeEnumeration = (flags & RuntimeEnumerationFlags.All) != 0, - DacSignatureVerificationEnabled = settingsService is null || settingsService.DacSignatureVerificationEnabled, FileLocator = null }); for (int i = 0; i < dataTarget.ClrVersions.Length; i++) diff --git a/src/Microsoft.Diagnostics.DebugServices/IRuntime.cs b/src/Microsoft.Diagnostics.DebugServices/IRuntime.cs index 5dd9e4ce93..6bf7f05ef6 100644 --- a/src/Microsoft.Diagnostics.DebugServices/IRuntime.cs +++ b/src/Microsoft.Diagnostics.DebugServices/IRuntime.cs @@ -62,7 +62,13 @@ public interface IRuntime /// /// Returns the DAC file path /// - string GetDacFilePath(); + /// returns if the DAC signature should be verified + string GetDacFilePath(out bool verifySignature); + + /// + /// Returns the CDac file path if enabled by global settings + /// + string GetCDacFilePath(); /// /// Returns the DBI file path diff --git a/src/Microsoft.Diagnostics.DebugServices/ISettingsService.cs b/src/Microsoft.Diagnostics.DebugServices/ISettingsService.cs index ae3ce83160..60ad98c338 100644 --- a/src/Microsoft.Diagnostics.DebugServices/ISettingsService.cs +++ b/src/Microsoft.Diagnostics.DebugServices/ISettingsService.cs @@ -15,5 +15,15 @@ public interface ISettingsService /// If true, enforces the proper DAC certificate signing when loaded /// bool DacSignatureVerificationEnabled { get; set; } + + /// + /// If true, uses the CDAC contract reader if available. + /// + bool UseContractReader { get; set; } + + /// + /// If true, always use the CDAC contract reader even when not requested + /// + bool ForceUseContractReader { get; set; } } } diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.cs b/src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.cs index 6ef5026f5c..9b490156e4 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/Host/CommandFormatHelpers.cs @@ -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"; /// /// Displays the special diagnostics info header memory block (.NET Core 8 or later on Linux/MacOS) @@ -127,28 +128,28 @@ IConsoleService Console() IExportSymbols symbols = module.Services.GetService(); 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 ? "" : " "); - 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() ?? ""}"); + Console().WriteLine($"{indent} RuntimeVersion: {info.RuntimeVersion?.ToString() ?? ""}"); } else { @@ -157,7 +158,7 @@ IConsoleService Console() } else if (error) { - Console().WriteLine($"{indent}{RuntimeInfo.RUNTIME_INFO_SYMBOL,-24}: "); + Console().WriteLine($"{indent}{RuntimeInfo.RUNTIME_INFO_SYMBOL}: "); } // Print the Windows runtime engine metrics (.NET Core and .NET Framework) @@ -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 { @@ -181,28 +182,38 @@ IConsoleService Console() } else if (error) { - Console().WriteLine($"{indent}{ClrEngineMetrics.Symbol,-24}: "); + Console().WriteLine($"{indent}{ClrEngineMetrics.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}: "); + Console().WriteLine($"{indent}{DacTableExport}: "); } // 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}: "); + Console().WriteLine($"{indent}{DebugHeaderExport}: "); + } + + // 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}: "); } } } diff --git a/src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.cs b/src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.cs index 751df3a496..95c93e8cef 100644 --- a/src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.cs +++ b/src/Microsoft.Diagnostics.ExtensionCommands/Host/RuntimesCommand.cs @@ -18,7 +18,7 @@ public class RuntimesCommand : CommandBase [ServiceImport] public IContextService ContextService { get; set; } - [ServiceImport(Optional = true)] + [ServiceImport] public ISettingsService SettingsService { get; set; } [ServiceImport] @@ -36,6 +36,12 @@ public class RuntimesCommand : CommandBase [Option(Name = "--all", Aliases = new string[] { "-a" }, Help = "Forces all runtimes to be enumerated.")] public bool All { get; set; } + [Option(Name = "--usecdac", Help = "Use the CDAC if available and requested (true/false).")] + public bool? UseContractReader { get; set; } + + [Option(Name = "--forceusecdac", Help = "Always use the CDAC (true/false).")] + public bool? ForceUseContractReader { get; set; } + [Option(Name = "--DacSignatureVerification", Aliases = new string[] { "-v" }, Help = "Enforce the proper DAC certificate signing when loaded (true/false).")] public bool? DacSignatureVerification { get; set; } @@ -46,14 +52,24 @@ public override void Invoke() throw new DiagnosticsException("Cannot specify both -netfx and -netcore options"); } + bool flush = false; + if (UseContractReader.HasValue) + { + SettingsService.UseContractReader = UseContractReader.Value; + flush = true; + } + + if (ForceUseContractReader.HasValue) + { + SettingsService.UseContractReader = ForceUseContractReader.Value; + SettingsService.ForceUseContractReader = ForceUseContractReader.Value; + flush = true; + } + if (DacSignatureVerification.HasValue) { - if (SettingsService is null) - { - throw new DiagnosticsException("Changing the DAC signature verification setting not supported"); - } SettingsService.DacSignatureVerificationEnabled = DacSignatureVerification.Value; - Target.Flush(); + flush = true; } RuntimeEnumerationFlags flags = RuntimeEnumerationFlags.Default; @@ -61,6 +77,11 @@ public override void Invoke() { // Force all runtimes to be enumerated. This requires a target flush. flags = RuntimeEnumerationFlags.All; + flush = true; + } + + if (flush) + { Target.Flush(); } @@ -107,6 +128,8 @@ public override void Invoke() } this.DisplayResources(runtime.RuntimeModule, all: false, indent: " "); this.DisplayRuntimeExports(runtime.RuntimeModule, error: true, indent: " "); + WriteLine($"Use CDAC contract reader: {SettingsService.UseContractReader}"); + WriteLine($"Force use CDAC contract reader: {SettingsService.ForceUseContractReader}"); WriteLine($"DAC signature verification check enabled: {SettingsService.DacSignatureVerificationEnabled}"); } } diff --git a/src/Microsoft.Diagnostics.TestHelpers/TestHost/TestDataWriter.cs b/src/Microsoft.Diagnostics.TestHelpers/TestHost/TestDataWriter.cs index 700b028659..7612d3d07c 100644 --- a/src/Microsoft.Diagnostics.TestHelpers/TestHost/TestDataWriter.cs +++ b/src/Microsoft.Diagnostics.TestHelpers/TestHost/TestDataWriter.cs @@ -84,7 +84,7 @@ public void Build(IServiceProvider services) { XElement runtimeElement = new("Runtime"); runtimesElement.Add(runtimeElement); - AddMembers(runtimeElement, typeof(IRuntime), runtime, nameof(IRuntime.GetDacFilePath), nameof(IRuntime.GetDbiFilePath)); + AddMembers(runtimeElement, typeof(IRuntime), runtime, nameof(IRuntime.GetDacFilePath), nameof(IRuntime.GetCDacFilePath), nameof(IRuntime.GetDbiFilePath)); XElement runtimeModuleElement = new("RuntimeModule"); runtimeElement.Add(runtimeModuleElement); diff --git a/src/Microsoft.Diagnostics.TestHelpers/TestHost/TestDump.cs b/src/Microsoft.Diagnostics.TestHelpers/TestHost/TestDump.cs index 271ca304d9..96a136d98c 100644 --- a/src/Microsoft.Diagnostics.TestHelpers/TestHost/TestDump.cs +++ b/src/Microsoft.Diagnostics.TestHelpers/TestHost/TestDump.cs @@ -8,7 +8,7 @@ namespace Microsoft.Diagnostics.TestHelpers { - public class TestDump : TestHost, ISettingsService + public class TestDump : TestHost { private readonly Host _host; private readonly ContextService _contextService; @@ -26,7 +26,6 @@ public TestDump(TestConfiguration config) _contextService = new(_host); serviceContainer.AddService(_contextService); - serviceContainer.AddService(this); _commandService = new(); serviceContainer.AddService(_commandService); @@ -53,11 +52,5 @@ protected override ITarget GetTarget() _symbolService.AddDirectoryPath(Path.GetDirectoryName(DumpFile)); return _dumpTargetFactory.OpenDump(DumpFile); } - - #region ISettingsService - - public bool DacSignatureVerificationEnabled { get; set; } - - #endregion } } diff --git a/src/SOS/SOS.Extensions/HostServices.cs b/src/SOS/SOS.Extensions/HostServices.cs index e8155b7be6..114d4d2b96 100644 --- a/src/SOS/SOS.Extensions/HostServices.cs +++ b/src/SOS/SOS.Extensions/HostServices.cs @@ -22,7 +22,7 @@ namespace SOS.Extensions /// /// The extension services Wrapper the native hosts are given /// - public sealed unsafe class HostServices : COMCallableIUnknown, SOSLibrary.ISOSModule, ISettingsService + public sealed unsafe class HostServices : COMCallableIUnknown, SOSLibrary.ISOSModule { private static readonly Guid IID_IHostServices = new("27B2CB8D-BDEE-4CBD-B6EF-75880D76D46F"); @@ -130,7 +130,7 @@ private HostServices(string extensionPath, IntPtr extensionsLibrary) SOSPath = Path.GetDirectoryName(extensionPath); SOSHandle = extensionsLibrary; - _host = new Host(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? HostType.DbgEng : HostType.Lldb); + _host = new HostForHostServices(this); _commandService = new CommandService(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ">!sos" : null); _host.ServiceManager.NotifyExtensionLoad.Register(_commandService.AddCommands); @@ -228,7 +228,6 @@ private int RegisterDebuggerServices( // Add all the global services to the global service container serviceContainer.AddService(this); - serviceContainer.AddService(this); serviceContainer.AddService(DebuggerServices); serviceContainer.AddService(_commandService); serviceContainer.AddService(_symbolService); @@ -414,23 +413,38 @@ private void Uninitialize( #endregion - #region ISettingsService + #region HostForHostServices - public bool DacSignatureVerificationEnabled + internal sealed class HostForHostServices : Host { - get + private readonly HostServices _hostServices; + + public HostForHostServices(HostServices hostServices) + : base(RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? HostType.DbgEng : HostType.Lldb) { - HResult hr = DebuggerServices.GetDacSignatureVerificationSettings(out bool value); - if (hr.IsOK) - { - return value; - } - // Return true (verify DAC signature) if any errors. Secure by default. - return true; + _hostServices = hostServices; } - set + + public override bool DacSignatureVerificationEnabled { - throw new NotSupportedException("Changing the DacSignatureVerificationEnabled setting is not supported."); + get + { + if (_hostServices.DebuggerServices is null) + { + throw new InvalidOperationException("DacSignatureVerificationEnabled called too soon in initialization"); + } + HResult hr = _hostServices.DebuggerServices.GetDacSignatureVerificationSettings(out bool value); + if (hr.IsOK) + { + return value; + } + // Return true (verify DAC signature) if any errors. Secure by default. + return true; + } + set + { + throw new NotSupportedException("Changing the DacSignatureVerificationEnabled setting is not supported."); + } } } diff --git a/src/SOS/SOS.Hosting/DataTargetWrapper.cs b/src/SOS/SOS.Hosting/DataTargetWrapper.cs index 3feade5d10..0a01ceea22 100644 --- a/src/SOS/SOS.Hosting/DataTargetWrapper.cs +++ b/src/SOS/SOS.Hosting/DataTargetWrapper.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Runtime.InteropServices; using Microsoft.Diagnostics.DebugServices; +using Microsoft.Diagnostics.Runtime; using Microsoft.Diagnostics.Runtime.Utilities; using SOS.Hosting.DbgEng.Interop; @@ -17,6 +18,7 @@ internal sealed unsafe class DataTargetWrapper : COMCallableIUnknown private static readonly Guid IID_ICLRDataTarget4 = new("E799DC06-E099-4713-BDD9-906D3CC02CF2"); private static readonly Guid IID_ICLRMetadataLocator = new("aa8fa804-bc05-4642-b2c5-c353ed22fc63"); private static readonly Guid IID_ICLRRuntimeLocator = new("b760bf44-9377-4597-8be7-58083bdc5146"); + private static readonly Guid IID_ICLRContractLocator = new("17d5b8c6-34a9-407f-af4f-a930201d4e02"); // For ClrMD's magic hand shake private const ulong MagicCallbackConstant = 0x43; @@ -67,6 +69,10 @@ public DataTargetWrapper(IServiceProvider services, IRuntime runtime) builder.AddMethod(new GetRuntimeBaseDelegate(GetRuntimeBase)); builder.Complete(); + builder = AddInterface(IID_ICLRContractLocator, false); + builder.AddMethod(new GetContractDescriptorDelegate(GetContractDescriptor)); + builder.Complete(); + AddRef(); } @@ -350,6 +356,28 @@ private int GetRuntimeBase( #endregion + #region ICLRContractLocator + + private int GetContractDescriptor( + IntPtr self, + out ulong address) + { + address = 0; + ClrInfo clrInfo = _runtime.Services.GetService(); + if (clrInfo is null) + { + return HResult.E_FAIL; + } + address = clrInfo.ContractDescriptorAddress; + if (address == 0) + { + return HResult.E_FAIL; + } + return HResult.S_OK; + } + + #endregion + #region ICLRDataTarget delegates [UnmanagedFunctionPointer(CallingConvention.Winapi)] @@ -485,5 +513,14 @@ private delegate int GetRuntimeBaseDelegate( [Out] out ulong address); #endregion + + #region ICLRContractLocator delegate + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + private delegate int GetContractDescriptorDelegate( + [In] IntPtr self, + [Out] out ulong address); + + #endregion } } diff --git a/src/SOS/SOS.Hosting/RuntimeWrapper.cs b/src/SOS/SOS.Hosting/RuntimeWrapper.cs index a2c64cfd8a..98d223def6 100644 --- a/src/SOS/SOS.Hosting/RuntimeWrapper.cs +++ b/src/SOS/SOS.Hosting/RuntimeWrapper.cs @@ -9,6 +9,7 @@ using Microsoft.Diagnostics.DebugServices; using Microsoft.Diagnostics.Runtime; using Microsoft.Diagnostics.Runtime.Utilities; +using Microsoft.FileFormats.ELF; using SOS.Hosting.DbgEng.Interop; namespace SOS.Hosting @@ -28,6 +29,22 @@ private enum RuntimeConfiguration Unknown = 4 } + /// + /// Flags to GetClrDataProcess when creating the DAC instance + /// + private enum ClrDataProcessFlags + { + /// + /// No flags + /// + None, + + /// + /// Use the cdac if available and enabled by global setting + /// + UseCDac + } + public static Guid IID_IXCLRDataProcess = new("5c552ab6-fc09-4cb3-8e36-22fa03c798b7"); public static Guid IID_ICorDebugProcess = new("3d6f5f64-7538-11d3-8d5b-00104b35e7ef"); private static readonly Guid IID_IRuntime = new("A5F152B9-BA78-4512-9228-5091A4CB7E35"); @@ -84,8 +101,10 @@ private delegate IntPtr LoadLibraryWDelegate( private readonly IServiceProvider _services; private readonly IRuntime _runtime; private IntPtr _clrDataProcess = IntPtr.Zero; + private IntPtr _cdacDataProcess = IntPtr.Zero; private IntPtr _corDebugProcess = IntPtr.Zero; private IntPtr _dacHandle = IntPtr.Zero; + private IntPtr _cdacHandle = IntPtr.Zero; private IntPtr _dbiHandle = IntPtr.Zero; public IntPtr IRuntime { get; } @@ -132,11 +151,21 @@ protected override void Destroy() ComWrapper.ReleaseWithCheck(_clrDataProcess); _clrDataProcess = IntPtr.Zero; } + if (_cdacDataProcess != IntPtr.Zero) + { + ComWrapper.ReleaseWithCheck(_cdacDataProcess); + _cdacDataProcess = IntPtr.Zero; + } if (_dacHandle != IntPtr.Zero) { DataTarget.PlatformFunctions.FreeLibrary(_dacHandle); _dacHandle = IntPtr.Zero; } + if (_cdacHandle != IntPtr.Zero) + { + DataTarget.PlatformFunctions.FreeLibrary(_cdacHandle); + _cdacHandle = IntPtr.Zero; + } if (_dbiHandle != IntPtr.Zero) { DataTarget.PlatformFunctions.FreeLibrary(_dbiHandle); @@ -200,24 +229,45 @@ private string GetRuntimeDirectory( private int GetClrDataProcess( IntPtr self, + ClrDataProcessFlags flags, IntPtr* ppClrDataProcess) { if (ppClrDataProcess == null) { return HResult.E_INVALIDARG; } - if (_clrDataProcess == IntPtr.Zero) + *ppClrDataProcess = IntPtr.Zero; + if ((flags & ClrDataProcessFlags.UseCDac) != 0) { - try + if (_cdacDataProcess == IntPtr.Zero) { - _clrDataProcess = CreateClrDataProcess(); + try + { + _cdacDataProcess = CreateClrDataProcess(GetCDacHandle()); + } + catch (Exception ex) + { + Trace.TraceError(ex.ToString()); + } } - catch (Exception ex) + *ppClrDataProcess = _cdacDataProcess; + } + // Fallback to regular DAC instance if CDac isn't enabled or there where errors creating the instance + if (*ppClrDataProcess == IntPtr.Zero) + { + if (_clrDataProcess == IntPtr.Zero) { - Trace.TraceError(ex.ToString()); + try + { + _clrDataProcess = CreateClrDataProcess(GetDacHandle()); + } + catch (Exception ex) + { + Trace.TraceError(ex.ToString()); + } } + *ppClrDataProcess = _clrDataProcess; } - *ppClrDataProcess = _clrDataProcess; if (*ppClrDataProcess == IntPtr.Zero) { return HResult.E_NOINTERFACE; @@ -301,9 +351,8 @@ private int GetEEVersion( #endregion - private IntPtr CreateClrDataProcess() + private IntPtr CreateClrDataProcess(IntPtr dacHandle) { - IntPtr dacHandle = GetDacHandle(); if (dacHandle == IntPtr.Zero) { return IntPtr.Zero; @@ -334,7 +383,7 @@ private IntPtr CreateClrDataProcess() private IntPtr CreateCorDebugProcess() { string dbiFilePath = _runtime.GetDbiFilePath(); - string dacFilePath = _runtime.GetDacFilePath(); + string dacFilePath = _runtime.GetDacFilePath(out bool verifySignature); if (dbiFilePath == null || dacFilePath == null) { Trace.TraceError($"Could not find matching DBI {dbiFilePath ?? ""} or DAC {dacFilePath ?? ""} for this runtime: {_runtime.RuntimeModule.FileName}"); @@ -465,49 +514,65 @@ private IntPtr GetDacHandle() { if (_dacHandle == IntPtr.Zero) { - string dacFilePath = _runtime.GetDacFilePath(); - if (dacFilePath == null) - { - Trace.TraceError($"Could not find matching DAC {dacFilePath ?? ""} for this runtime: {_runtime.RuntimeModule.FileName}"); - return IntPtr.Zero; - } - ISettingsService settingsService = _services.GetService(); - IDisposable fileLock = null; - try + _dacHandle = GetDacHandle(useCDac: false); + } + return _dacHandle; + } + + private IntPtr GetCDacHandle() + { + if (_cdacHandle == IntPtr.Zero) + { + _cdacHandle = GetDacHandle(useCDac: true); + } + return _cdacHandle; + } + + private IntPtr GetDacHandle(bool useCDac) + { + bool verifySignature = false; + string dacFilePath = useCDac ? _runtime.GetCDacFilePath() : _runtime.GetDacFilePath(out verifySignature); + if (dacFilePath == null) + { + Trace.TraceError($"Could not find matching DAC {dacFilePath ?? ""} {useCDac} for this runtime: {_runtime.RuntimeModule.FileName}"); + return IntPtr.Zero; + } + IntPtr dacHandle = IntPtr.Zero; + IDisposable fileLock = null; + try + { + if (verifySignature) { - if (settingsService is null || settingsService.DacSignatureVerificationEnabled) - { - Trace.TraceInformation($"Verifying DAC signing and cert {dacFilePath}"); + Trace.TraceInformation($"Verifying DAC signing and cert {dacFilePath} {useCDac}"); - // Check if the DAC cert is valid before loading - if (!AuthenticodeUtil.VerifyDacDll(dacFilePath, out fileLock)) - { - return IntPtr.Zero; - } - } - try + // Check if the DAC cert is valid before loading + if (!AuthenticodeUtil.VerifyDacDll(dacFilePath, out fileLock)) { - _dacHandle = DataTarget.PlatformFunctions.LoadLibrary(dacFilePath); - } - catch (Exception ex) when (ex is DllNotFoundException or BadImageFormatException) - { - Trace.TraceError($"LoadLibrary({dacFilePath}) FAILED {ex}"); return IntPtr.Zero; } } - finally + try { - // Keep DAC file locked until it loaded - fileLock?.Dispose(); + dacHandle = DataTarget.PlatformFunctions.LoadLibrary(dacFilePath); } - Debug.Assert(_dacHandle != IntPtr.Zero); - if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + catch (Exception ex) when (ex is DllNotFoundException or BadImageFormatException) { - DllMainDelegate dllmain = SOSHost.GetDelegateFunction(_dacHandle, "DllMain"); - dllmain?.Invoke(_dacHandle, 1, IntPtr.Zero); + Trace.TraceError($"LoadLibrary({dacFilePath}) {useCDac} FAILED {ex}"); + return IntPtr.Zero; } } - return _dacHandle; + finally + { + // Keep DAC file locked until it loaded + fileLock?.Dispose(); + } + Debug.Assert(dacHandle != IntPtr.Zero); + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + DllMainDelegate dllmain = SOSHost.GetDelegateFunction(dacHandle, "DllMain"); + dllmain?.Invoke(dacHandle, 1, IntPtr.Zero); + } + return dacHandle; } #region IRuntime delegates @@ -537,6 +602,7 @@ private delegate string GetRuntimeDirectoryDelegate( [UnmanagedFunctionPointer(CallingConvention.Winapi)] private delegate int GetClrDataProcessDelegate( [In] IntPtr self, + [In] ClrDataProcessFlags flags, [Out] IntPtr* ppClrDataProcess); [UnmanagedFunctionPointer(CallingConvention.Winapi)] diff --git a/src/SOS/SOS.Hosting/SOS.Hosting.csproj b/src/SOS/SOS.Hosting/SOS.Hosting.csproj index 645c0ec264..bb438ecf78 100644 --- a/src/SOS/SOS.Hosting/SOS.Hosting.csproj +++ b/src/SOS/SOS.Hosting/SOS.Hosting.csproj @@ -3,7 +3,10 @@ netstandard2.0 SOS.Hosting $(NoWarn);1591;1701;IDE0060 - SOS Hosting support + true + Diagnostic SOS hosting support + $(Description) + SOS true true false diff --git a/src/SOS/Strike/clrma/managedanalysis.cpp b/src/SOS/Strike/clrma/managedanalysis.cpp index 0483ff9269..24250b4de6 100644 --- a/src/SOS/Strike/clrma/managedanalysis.cpp +++ b/src/SOS/Strike/clrma/managedanalysis.cpp @@ -260,7 +260,7 @@ ClrmaManagedAnalysis::AssociateClient( TraceError("AssociateClient GetRuntime FAILED %08x\n", hr); return hr; } - if (FAILED(hr = runtime->GetClrDataProcess(&m_clrData))) + if (FAILED(hr = runtime->GetClrDataProcess(IRuntime::ClrDataProcessFlags::UseCDac, &m_clrData))) { m_clrData = GetClrDataFromDbgEng(); if (m_clrData == nullptr) diff --git a/src/SOS/Strike/platform/runtimeimpl.cpp b/src/SOS/Strike/platform/runtimeimpl.cpp index 546c28ddad..3f356315a9 100644 --- a/src/SOS/Strike/platform/runtimeimpl.cpp +++ b/src/SOS/Strike/platform/runtimeimpl.cpp @@ -421,7 +421,7 @@ LPCSTR Runtime::GetRuntimeDirectory() /**********************************************************************\ * Creates an instance of the DAC clr data process \**********************************************************************/ -HRESULT Runtime::GetClrDataProcess(IXCLRDataProcess** ppClrDataProcess) +HRESULT Runtime::GetClrDataProcess(ClrDataProcessFlags flags, IXCLRDataProcess** ppClrDataProcess) { if (m_clrDataProcess == nullptr) { diff --git a/src/SOS/Strike/platform/runtimeimpl.h b/src/SOS/Strike/platform/runtimeimpl.h index 27b3069407..6d8994eaeb 100644 --- a/src/SOS/Strike/platform/runtimeimpl.h +++ b/src/SOS/Strike/platform/runtimeimpl.h @@ -180,7 +180,7 @@ class Runtime : public IRuntime LPCSTR STDMETHODCALLTYPE GetRuntimeDirectory(); - HRESULT STDMETHODCALLTYPE GetClrDataProcess(IXCLRDataProcess** ppClrDataProcess); + HRESULT STDMETHODCALLTYPE GetClrDataProcess(ClrDataProcessFlags flags, IXCLRDataProcess** ppClrDataProcess); HRESULT STDMETHODCALLTYPE GetCorDebugInterface(ICorDebugProcess** ppCorDebugProcess); diff --git a/src/SOS/Strike/util.cpp b/src/SOS/Strike/util.cpp index 689b480db1..1ffdcce6f4 100644 --- a/src/SOS/Strike/util.cpp +++ b/src/SOS/Strike/util.cpp @@ -4088,7 +4088,7 @@ class SOSDacInterface15Simulator : public ISOSDacInterface15 HRESULT LoadClrDebugDll(void) { _ASSERTE(g_pRuntime != nullptr); - HRESULT hr = g_pRuntime->GetClrDataProcess(&g_clrData); + HRESULT hr = g_pRuntime->GetClrDataProcess(IRuntime::ClrDataProcessFlags::None, &g_clrData); if (FAILED(hr)) { g_clrData = GetClrDataFromDbgEng(); diff --git a/src/SOS/inc/runtime.h b/src/SOS/inc/runtime.h index 25aebaa92c..b6c7b0ce7f 100644 --- a/src/SOS/inc/runtime.h +++ b/src/SOS/inc/runtime.h @@ -38,6 +38,22 @@ IRuntime : public IUnknown #endif }; + /// + /// Flags to GetClrDataProcess when creating the DAC instance + /// + enum ClrDataProcessFlags + { + /// + /// No flags + /// + None, + + /// + /// Use the CDac if available and enabled by global setting + /// + UseCDac + }; + /// /// Returns the runtime configuration /// @@ -66,7 +82,7 @@ IRuntime : public IUnknown /// /// Returns the DAC data process instance /// - virtual HRESULT STDMETHODCALLTYPE GetClrDataProcess(IXCLRDataProcess** ppClrDataProcess) = 0; + virtual HRESULT STDMETHODCALLTYPE GetClrDataProcess(ClrDataProcessFlags flags, IXCLRDataProcess** ppClrDataProcess) = 0; /// /// Initializes and returns the DBI debugging interface instance diff --git a/src/Tools/dotnet-dump/Analyzer.cs b/src/Tools/dotnet-dump/Analyzer.cs index 7723964f08..c503256428 100644 --- a/src/Tools/dotnet-dump/Analyzer.cs +++ b/src/Tools/dotnet-dump/Analyzer.cs @@ -17,7 +17,7 @@ namespace Microsoft.Diagnostics.Tools.Dump { - public class Analyzer : Host, ISettingsService + public class Analyzer : Host { private readonly ConsoleService _consoleService; private readonly FileLoggingConsoleService _fileLoggingConsoleService; @@ -27,6 +27,7 @@ public Analyzer() : base(HostType.DotnetDump) { DiagnosticLoggingService.Initialize(); + DacSignatureVerificationEnabled = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? true : false; _consoleService = new ConsoleService(); _fileLoggingConsoleService = new FileLoggingConsoleService(_consoleService); @@ -85,7 +86,6 @@ or NotSupportedException serviceContainer.AddService(DiagnosticLoggingService.Instance); serviceContainer.AddService(_commandService); serviceContainer.AddService(_commandService); - serviceContainer.AddService(this); DumpTargetFactory dumpTargetFactory = new(this); serviceContainer.AddService(dumpTargetFactory); @@ -175,11 +175,5 @@ or NotSupportedException } return Task.FromResult(0); } - - #region ISettingsService - - public bool DacSignatureVerificationEnabled { get; set; } = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? true : false; - - #endregion } } diff --git a/src/shared/inc/clrdata.idl b/src/shared/inc/clrdata.idl index 81b0e0bc7f..cfc57ba212 100644 --- a/src/shared/inc/clrdata.idl +++ b/src/shared/inc/clrdata.idl @@ -211,6 +211,20 @@ interface ICLRRuntimeLocator : IUnknown HRESULT GetRuntimeBase([out] CLRDATA_ADDRESS* baseAddress); }; +[ + object, + local, + uuid(17d5b8c6-34a9-407f-af4f-a930201d4e02), + pointer_default(unique) +] +interface ICLRContractLocator : IUnknown +{ + /* + Returns the address of the runtime's contract descriptor. + */ + HRESULT GetContractDescriptor([out] CLRDATA_ADDRESS* contractAddress); +} + /* * Interface used by the data access services layer to locate metadata * of assemblies in a target. diff --git a/src/shared/pal/prebuilt/idl/clrdata_i.cpp b/src/shared/pal/prebuilt/idl/clrdata_i.cpp index 26d36c133b..a638dd3f75 100644 --- a/src/shared/pal/prebuilt/idl/clrdata_i.cpp +++ b/src/shared/pal/prebuilt/idl/clrdata_i.cpp @@ -8,10 +8,10 @@ /* File created by MIDL compiler version 8.01.0626 */ /* Compiler settings for clrdata.idl: - Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0626 + Oicf, W1, Zp8, env=Win64 (32b run), target_arch=AMD64 8.01.0626 protocol : dce , ms_ext, c_ext, robust - error checks: allocation ref bounds_check enum stub_data - VC __declspec() decoration level: + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: __declspec(uuid()), __declspec(selectany), __declspec(novtable) DECLSPEC_UUID(), MIDL_INTERFACE() */ @@ -22,7 +22,7 @@ #ifdef __cplusplus extern "C"{ -#endif +#endif #include @@ -78,6 +78,9 @@ MIDL_DEFINE_GUID(IID, IID_ICLRDataTarget3,0xa5664f95,0x0af4,0x4a1b,0x96,0x0e,0x2 MIDL_DEFINE_GUID(IID, IID_ICLRRuntimeLocator,0xb760bf44,0x9377,0x4597,0x8b,0xe7,0x58,0x08,0x3b,0xdc,0x51,0x46); +MIDL_DEFINE_GUID(IID, IID_ICLRContractLocator,0x17d5b8c6,0x34a9,0x407f,0xaf,0x4f,0xa9,0x30,0x20,0x1d,0x4e,0x02); + + MIDL_DEFINE_GUID(IID, IID_ICLRMetadataLocator,0xaa8fa804,0xbc05,0x4642,0xb2,0xc5,0xc3,0x53,0xed,0x22,0xfc,0x63); diff --git a/src/shared/pal/prebuilt/inc/clrdata.h b/src/shared/pal/prebuilt/inc/clrdata.h index 802c34a87b..e8e3cfbb6b 100644 --- a/src/shared/pal/prebuilt/inc/clrdata.h +++ b/src/shared/pal/prebuilt/inc/clrdata.h @@ -77,7 +77,14 @@ typedef interface ICLRDataTarget3 ICLRDataTarget3; #define __ICLRRuntimeLocator_FWD_DEFINED__ typedef interface ICLRRuntimeLocator ICLRRuntimeLocator; -#endif /* __ICLRRuntimeLocator_FWD_DEFINED__ */ + +#endif /* __ICLRContractLocator_FWD_DEFINED__ */ + +#ifndef __ICLRContractLocator_FWD_DEFINED__ +#define __ICLRContractLocator_FWD_DEFINED__ +typedef interface ICLRContractLocator ICLRContractLocator; + +#endif /* __ICLRContractLocator_FWD_DEFINED__ */ #ifndef __ICLRMetadataLocator_FWD_DEFINED__ @@ -919,6 +926,90 @@ EXTERN_C const IID IID_ICLRRuntimeLocator; +#endif /* __ICLRRuntimeLocator_INTERFACE_DEFINED__ */ + + +#ifndef __ICLRContractLocator_INTERFACE_DEFINED__ +#define __ICLRContractLocator_INTERFACE_DEFINED__ + +/* interface ICLRContractLocator */ +/* [unique][uuid][local][object] */ + + +EXTERN_C const IID IID_ICLRContractLocator; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("17d5b8c6-34a9-407f-af4f-a930201d4e02") + ICLRContractLocator : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE GetContractDescriptor( + /* [out] */ CLRDATA_ADDRESS *contractAddress) = 0; + + }; + + +#else /* C style interface */ + + typedef struct ICLRContractLocatorVtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + ICLRContractLocator * This, + /* [in] */ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + ICLRContractLocator * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + ICLRContractLocator * This); + + DECLSPEC_XFGVIRT(ICLRContractLocator, GetContractDescriptor) + HRESULT ( STDMETHODCALLTYPE *GetContractDescriptor )( + ICLRContractLocator * This, + /* [out] */ CLRDATA_ADDRESS *contractAddress); + + END_INTERFACE + } ICLRRuntimeLocatorVtbl; + + interface ICLRContractLocator + { + CONST_VTBL struct ICLRRuntimeLocatorVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define ICLRContractLocator_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define ICLRContractLocator_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define ICLRContractLocator_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define ICLRContractLocator_GetContractDescriptor(This,contractAddress) \ + ( (This)->lpVtbl -> GetContractDescriptor(This,contractAddress) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + #endif /* __ICLRRuntimeLocator_INTERFACE_DEFINED__ */ diff --git a/src/tests/DbgShim.UnitTests/DbgShimTests.cs b/src/tests/DbgShim.UnitTests/DbgShimTests.cs index 907fb57d66..118cf2527c 100644 --- a/src/tests/DbgShim.UnitTests/DbgShimTests.cs +++ b/src/tests/DbgShim.UnitTests/DbgShimTests.cs @@ -261,7 +261,7 @@ await RemoteInvoke(config, nameof(OpenVirtualProcess), static (string configXml) IRuntime runtime = runtimeService.EnumerateRuntimes().Single(); CorDebugDataTargetWrapper dataTarget = new(target.Services, runtime); - LibraryProviderWrapper libraryProvider = new(target.OperatingSystem, runtime.RuntimeModule.BuildId, runtime.GetDbiFilePath(), runtime.GetDacFilePath()); + LibraryProviderWrapper libraryProvider = new(target.OperatingSystem, runtime.RuntimeModule.BuildId, runtime.GetDbiFilePath(), runtime.GetDacFilePath(out bool verifySignature)); ClrDebuggingVersion maxDebuggerSupportedVersion = new() { StructVersion = 0, From da68614d2710544b95e49b8d3c5b1e4d4eaff678 Mon Sep 17 00:00:00 2001 From: Mike McLaughlin Date: Mon, 7 Apr 2025 13:07:35 -0700 Subject: [PATCH 2/2] Code review feedback --- .../Runtime.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs b/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs index 757a5db4ba..7e02dcaf0f 100644 --- a/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs +++ b/src/Microsoft.Diagnostics.DebugServices.Implementation/Runtime.cs @@ -120,13 +120,10 @@ public string GetDacFilePath(out bool verifySignature) } if (_dacFilePath is null) { - if (_dacFilePath is null) + _dacFilePath = GetLibraryPath(DebugLibraryKind.Dac); + if (_dacFilePath is not null) { - _dacFilePath = GetLibraryPath(DebugLibraryKind.Dac); - if (_dacFilePath is not null) - { - verifySignature = _settingsService.DacSignatureVerificationEnabled; - } + verifySignature = _settingsService.DacSignatureVerificationEnabled; } } return _dacFilePath;