From 0fb4c666804ae443b6866b5fde5f3c1159c9a417 Mon Sep 17 00:00:00 2001 From: Max Charlamb <44248479+max-charlamb@users.noreply.github.com> Date: Fri, 24 Oct 2025 10:03:25 -0400 Subject: [PATCH] support dynamic contracts --- .../ContractRegistry.cs | 4 +++- .../IContractFactory.cs | 1 + .../CachingContractRegistry.cs | 21 +++++++++++++++---- .../ContractDescriptorTarget.cs | 3 ++- .../Legacy/SOSDacImpl.cs | 2 +- 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.cs index 85f4f954404536..0516c0dac2c964 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.cs @@ -89,5 +89,7 @@ public abstract class ContractRegistry /// /// Gets an instance of the SignatureDecoder contract for the target. /// - public abstract ISignatureDecoder SignatureDecoder { get; } + // public abstract ISignatureDecoder SignatureDecoder { get; } + + public abstract TContract GetContract() where TContract : IContract; } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/IContractFactory.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/IContractFactory.cs index ca19d7ed3d05fb..2973c86784f554 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/IContractFactory.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/IContractFactory.cs @@ -8,4 +8,5 @@ namespace Microsoft.Diagnostics.DataContractReader; public interface IContractFactory where TContract : Contracts.IContract { TContract CreateContract(Target target, int version); + Type ContractType => typeof(TContract); } diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.cs index 0afe774efde541..210e12c8c356b0 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.cs @@ -20,7 +20,11 @@ internal sealed class CachingContractRegistry : ContractRegistry private readonly Target _target; private readonly TryGetContractVersionDelegate _tryGetContractVersion; - public CachingContractRegistry(Target target, TryGetContractVersionDelegate tryGetContractVersion, Action>>? configureFactories = null) + public CachingContractRegistry( + Target target, + TryGetContractVersionDelegate tryGetContractVersion, + IEnumerable>? additionalFactories = null, + Action>>? configureFactories = null) { _target = target; _tryGetContractVersion = tryGetContractVersion; @@ -45,8 +49,17 @@ public CachingContractRegistry(Target target, TryGetContractVersionDelegate tryG [typeof(ISHash)] = new SHashFactory(), [typeof(IGC)] = new GCFactory(), [typeof(INotifications)] = new NotificationsFactory(), - [typeof(ISignatureDecoder)] = new SignatureDecoderFactory(), + // [typeof(ISignatureDecoder)] = new SignatureDecoderFactory(), }; + + if (additionalFactories != null) + { + foreach (IContractFactory factory in additionalFactories) + { + _factories[factory.ContractType] = factory; + } + } + configureFactories?.Invoke(_factories); } @@ -69,9 +82,9 @@ public CachingContractRegistry(Target target, TryGetContractVersionDelegate tryG public override ISHash SHash => GetContract(); public override IGC GC => GetContract(); public override INotifications Notifications => GetContract(); - public override ISignatureDecoder SignatureDecoder => GetContract(); + // public override ISignatureDecoder SignatureDecoder => GetContract(); - private TContract GetContract() where TContract : IContract + public override TContract GetContract() { if (_contracts.TryGetValue(typeof(TContract), out IContract? contractMaybe)) return (TContract)contractMaybe; diff --git a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs index bec5c1cb7dc3f1..62255ee52a4ea5 100644 --- a/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs +++ b/src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs @@ -8,6 +8,7 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Text; +using Microsoft.Diagnostics.DataContractReader.Contracts; using Microsoft.Diagnostics.DataContractReader.Data; namespace Microsoft.Diagnostics.DataContractReader; @@ -108,7 +109,7 @@ public static ContractDescriptorTarget Create( private ContractDescriptorTarget(Descriptor[] descriptors, DataTargetDelegates dataTargetDelegates) { - Contracts = new CachingContractRegistry(this, this.TryGetContractVersion); + Contracts = new CachingContractRegistry(this, this.TryGetContractVersion, [new SignatureDecoderFactory()]); ProcessedData = new DataCache(this); _config = descriptors[0].Config; _dataTargetDelegates = dataTargetDelegates; diff --git a/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs b/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs index 9061601fd126c6..8b7ee7a40933f7 100644 --- a/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs +++ b/src/native/managed/cdac/mscordaccore_universal/Legacy/SOSDacImpl.cs @@ -765,7 +765,7 @@ int ISOSDacInterface.GetFieldDescData(ClrDataAddress fieldDesc, DacpFieldDescDat IRuntimeTypeSystem rtsContract = _target.Contracts.RuntimeTypeSystem; IEcmaMetadata ecmaMetadataContract = _target.Contracts.EcmaMetadata; - ISignatureDecoder signatureDecoder = _target.Contracts.SignatureDecoder; + ISignatureDecoder signatureDecoder = _target.Contracts.GetContract(); TargetPointer fieldDescTargetPtr = fieldDesc.ToTargetPointer(_target); CorElementType fieldDescType = rtsContract.GetFieldDescType(fieldDescTargetPtr);