From 88b0528e191227668def9265efaa71475b56bf2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Matou=C5=A1ek?= Date: Thu, 9 Aug 2018 13:41:16 -0700 Subject: [PATCH] Use Concord API to get SymReader for EnC instead of IENCSymbolReaderProvider.GetSymbolReader. (#29177) --- .../DebuggeeModuleMetadataCacheTests.cs | 27 ++-- ...deAnalysis.EditorFeatures.UnitTests.csproj | 1 + .../EditAndContinue/DebuggeeModuleInfo.cs | 38 ++++++ ...ataCache.cs => DebuggeeModuleInfoCache.cs} | 21 ++-- .../IDebuggeeModuleMetadataProvider.cs | 4 +- .../Microsoft.CodeAnalysis.Features.csproj | 1 + .../NotImplementedSymUnmanagedReader.cs | 29 ++++- .../DebuggeeModuleMetadataProvider.cs | 37 ++++-- .../VsENCRebuildableProjectImpl.cs | 115 +++--------------- 9 files changed, 141 insertions(+), 132 deletions(-) create mode 100644 src/Features/Core/Portable/EditAndContinue/DebuggeeModuleInfo.cs rename src/Features/Core/Portable/EditAndContinue/{DebuggeeModuleMetadataCache.cs => DebuggeeModuleInfoCache.cs} (77%) diff --git a/src/EditorFeatures/Test/EditAndContinue/DebuggeeModuleMetadataCacheTests.cs b/src/EditorFeatures/Test/EditAndContinue/DebuggeeModuleMetadataCacheTests.cs index 927422ebbe3..40a7376e794 100644 --- a/src/EditorFeatures/Test/EditAndContinue/DebuggeeModuleMetadataCacheTests.cs +++ b/src/EditorFeatures/Test/EditAndContinue/DebuggeeModuleMetadataCacheTests.cs @@ -2,6 +2,7 @@ using System; using Microsoft.CodeAnalysis.EditAndContinue; +using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.UnitTests.EditAndContinue @@ -11,7 +12,7 @@ public sealed class DebuggeeModuleMetadataCacheTests [Fact] public void GetOrAddNull() { - var cache = new DebuggeeModuleMetadataCache(); + var cache = new DebuggeeModuleInfoCache(); var mvid = Guid.NewGuid(); Assert.Null(cache.GetOrAdd(mvid, m => { Assert.Equal(mvid, m); return default; })); @@ -20,31 +21,33 @@ public void GetOrAddNull() [Fact] public void GetOrAdd() { - var cache = new DebuggeeModuleMetadataCache(); + var cache = new DebuggeeModuleInfoCache(); var metadata1 = ModuleMetadata.CreateFromImage((IntPtr)1, 1); + var symReader1 = NotImplementedSymUnmanagedReader.Instance; var metadata2 = ModuleMetadata.CreateFromImage((IntPtr)2, 1); + var symReader2 = NotImplementedSymUnmanagedReader.Instance; var mvid1 = Guid.NewGuid(); var mvid2 = Guid.NewGuid(); var mvid3 = Guid.NewGuid(); - Assert.Same(metadata1, cache.GetOrAdd(mvid1, _ => metadata1)); - Assert.Same(metadata2, cache.GetOrAdd(mvid2, _ => metadata2)); + Assert.Same(metadata1, cache.GetOrAdd(mvid1, _ => new DebuggeeModuleInfo(metadata1, symReader1)).Metadata); + Assert.Same(metadata2, cache.GetOrAdd(mvid2, _ => new DebuggeeModuleInfo(metadata2, symReader2)).Metadata); - Assert.Same(metadata1, cache.GetOrAdd(mvid1, _ => throw null)); - Assert.Same(metadata2, cache.GetOrAdd(mvid2, _ => throw null)); + Assert.Same(metadata1, cache.GetOrAdd(mvid1, _ => throw null).Metadata); + Assert.Same(metadata2, cache.GetOrAdd(mvid2, _ => throw null).Metadata); } [Fact] public void Remove() { - var cache = new DebuggeeModuleMetadataCache(); + var cache = new DebuggeeModuleInfoCache(); Assert.False(cache.Remove(Guid.NewGuid())); var mvid1 = Guid.NewGuid(); - cache.GetOrAdd(mvid1, _ => ModuleMetadata.CreateFromImage((IntPtr)1, 1)); + cache.GetOrAdd(mvid1, _ => new DebuggeeModuleInfo(ModuleMetadata.CreateFromImage((IntPtr)1, 1), NotImplementedSymUnmanagedReader.Instance)); Assert.True(cache.Remove(mvid1)); Assert.False(cache.Remove(mvid1)); @@ -54,20 +57,22 @@ public void Remove() [Fact] public void RemoveAdd() { - var cache = new DebuggeeModuleMetadataCache(); + var cache = new DebuggeeModuleInfoCache(); Assert.False(cache.Remove(Guid.NewGuid())); var mvid1 = Guid.NewGuid(); var metadata1 = ModuleMetadata.CreateFromImage((IntPtr)1, 1); + var symReader1 = NotImplementedSymUnmanagedReader.Instance; var metadata2 = ModuleMetadata.CreateFromImage((IntPtr)2, 1); + var symReader2 = NotImplementedSymUnmanagedReader.Instance; - Assert.Same(metadata1, cache.GetOrAdd(mvid1, _ => metadata1)); + Assert.Same(metadata1, cache.GetOrAdd(mvid1, _ => new DebuggeeModuleInfo(metadata1, symReader1)).Metadata); Assert.True(cache.Remove(mvid1)); Assert.Null(cache.GetOrAdd(mvid1, _ => default)); - Assert.Same(metadata2, cache.GetOrAdd(mvid1, _ => metadata2)); + Assert.Same(metadata2, cache.GetOrAdd(mvid1, _ => new DebuggeeModuleInfo(metadata2, symReader2)).Metadata); } } } diff --git a/src/EditorFeatures/Test/Microsoft.CodeAnalysis.EditorFeatures.UnitTests.csproj b/src/EditorFeatures/Test/Microsoft.CodeAnalysis.EditorFeatures.UnitTests.csproj index 4c99acf8823..6409e17d0d2 100644 --- a/src/EditorFeatures/Test/Microsoft.CodeAnalysis.EditorFeatures.UnitTests.csproj +++ b/src/EditorFeatures/Test/Microsoft.CodeAnalysis.EditorFeatures.UnitTests.csproj @@ -18,6 +18,7 @@ + global diff --git a/src/Features/Core/Portable/EditAndContinue/DebuggeeModuleInfo.cs b/src/Features/Core/Portable/EditAndContinue/DebuggeeModuleInfo.cs new file mode 100644 index 00000000000..ec9d02ce94f --- /dev/null +++ b/src/Features/Core/Portable/EditAndContinue/DebuggeeModuleInfo.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; +using System.Threading; +using Microsoft.DiaSymReader; + +namespace Microsoft.CodeAnalysis.EditAndContinue +{ + internal sealed class DebuggeeModuleInfo : IDisposable + { + public ModuleMetadata Metadata { get; } + + private ISymUnmanagedReader5 _symReader; + public ISymUnmanagedReader5 SymReader => _symReader; + + public DebuggeeModuleInfo(ModuleMetadata metadata, ISymUnmanagedReader5 symReader) + { + Debug.Assert(metadata != null); + Debug.Assert(symReader != null); + + Metadata = metadata; + _symReader = symReader; + } + + public void Dispose() + { + Metadata?.Dispose(); + + var symReader = Interlocked.Exchange(ref _symReader, null); + if (symReader != null && Marshal.IsComObject(symReader)) + { + Marshal.ReleaseComObject(symReader); + } + } + } +} diff --git a/src/Features/Core/Portable/EditAndContinue/DebuggeeModuleMetadataCache.cs b/src/Features/Core/Portable/EditAndContinue/DebuggeeModuleInfoCache.cs similarity index 77% rename from src/Features/Core/Portable/EditAndContinue/DebuggeeModuleMetadataCache.cs rename to src/Features/Core/Portable/EditAndContinue/DebuggeeModuleInfoCache.cs index 65086a4e3a4..71db3714e5a 100644 --- a/src/Features/Core/Portable/EditAndContinue/DebuggeeModuleMetadataCache.cs +++ b/src/Features/Core/Portable/EditAndContinue/DebuggeeModuleInfoCache.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Threading; -using Microsoft.CodeAnalysis.PooledObjects; namespace Microsoft.CodeAnalysis.EditAndContinue { @@ -12,19 +11,19 @@ namespace Microsoft.CodeAnalysis.EditAndContinue /// A cache of metadata blobs loaded into processes being debugged. /// Thread safe. /// - internal sealed class DebuggeeModuleMetadataCache + internal sealed class DebuggeeModuleInfoCache { // Maps MVIDs to metadata blobs loaded to specific processes - private Dictionary _lazyCache; + private Dictionary _lazyCache; /// /// May return null if the provider returns null. /// - public ModuleMetadata GetOrAdd(Guid mvid, Func provider) + public DebuggeeModuleInfo GetOrAdd(Guid mvid, Func provider) { if (_lazyCache == null) { - Interlocked.CompareExchange(ref _lazyCache, new Dictionary(), null); + Interlocked.CompareExchange(ref _lazyCache, new Dictionary(), null); } var cache = _lazyCache; @@ -37,22 +36,22 @@ public ModuleMetadata GetOrAdd(Guid mvid, Func provider) } } - var newMetadata = provider(mvid); - if (newMetadata == null) + var newInfo = provider(mvid); + if (newInfo == null) { - return null; + return default; } lock (cache) { if (cache.TryGetValue(mvid, out var existing)) { - newMetadata.Dispose(); + newInfo.Dispose(); return existing; } - cache.Add(mvid, newMetadata); - return newMetadata; + cache.Add(mvid, newInfo); + return newInfo; } } diff --git a/src/Features/Core/Portable/EditAndContinue/IDebuggeeModuleMetadataProvider.cs b/src/Features/Core/Portable/EditAndContinue/IDebuggeeModuleMetadataProvider.cs index 662b29f35be..978a757b66d 100644 --- a/src/Features/Core/Portable/EditAndContinue/IDebuggeeModuleMetadataProvider.cs +++ b/src/Features/Core/Portable/EditAndContinue/IDebuggeeModuleMetadataProvider.cs @@ -10,9 +10,9 @@ namespace Microsoft.CodeAnalysis.EditAndContinue internal interface IDebuggeeModuleMetadataProvider { /// - /// Finds a module of given MVID in one of the processes being debugged and returns its baseline metadata. + /// Finds a module of given MVID in one of the processes being debugged and returns its baseline metadata and symbols. /// Shall only be called while in debug mode. /// - ModuleMetadata TryGetBaselineMetadata(Guid mvid); + DebuggeeModuleInfo TryGetBaselineModuleInfo(Guid mvid); } } diff --git a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj index 49b403ac57e..8f859b69608 100644 --- a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj +++ b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj @@ -108,6 +108,7 @@ + \ No newline at end of file diff --git a/src/Test/PdbUtilities/Reader/NotImplementedSymUnmanagedReader.cs b/src/Test/PdbUtilities/Reader/NotImplementedSymUnmanagedReader.cs index 3e57064c846..bb7502d83e7 100644 --- a/src/Test/PdbUtilities/Reader/NotImplementedSymUnmanagedReader.cs +++ b/src/Test/PdbUtilities/Reader/NotImplementedSymUnmanagedReader.cs @@ -7,7 +7,7 @@ namespace Roslyn.Test.Utilities { - internal sealed class NotImplementedSymUnmanagedReader : ISymUnmanagedReader, ISymUnmanagedReader2, ISymUnmanagedReader3 + public sealed class NotImplementedSymUnmanagedReader : ISymUnmanagedReader5 { public static readonly NotImplementedSymUnmanagedReader Instance = new NotImplementedSymUnmanagedReader(); @@ -142,5 +142,32 @@ public int UpdateSymbolStore(string filename, IStream stream) { return HResult.E_NOTIMPL; } + + public int MatchesModule(Guid guid, uint stamp, int age, out bool result) + { + result = false; + return HResult.E_NOTIMPL; + } + + public unsafe int GetPortableDebugMetadata(out byte* metadata, out int size) + { + metadata = null; + size = 0; + return HResult.E_NOTIMPL; + } + + public unsafe int GetSourceServerData(out byte* data, out int size) + { + data = null; + size = 0; + return HResult.E_NOTIMPL; + } + + public unsafe int GetPortableDebugMetadataByVersion(int version, out byte* metadata, out int size) + { + metadata = null; + size = 0; + return HResult.E_NOTIMPL; + } } } diff --git a/src/VisualStudio/Core/Def/Implementation/EditAndContinue/DebuggeeModuleMetadataProvider.cs b/src/VisualStudio/Core/Def/Implementation/EditAndContinue/DebuggeeModuleMetadataProvider.cs index fae0bcbc226..296e551e274 100644 --- a/src/VisualStudio/Core/Def/Implementation/EditAndContinue/DebuggeeModuleMetadataProvider.cs +++ b/src/VisualStudio/Core/Def/Implementation/EditAndContinue/DebuggeeModuleMetadataProvider.cs @@ -2,12 +2,16 @@ using System; using System.Composition; +using System.Diagnostics; +using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Debugging; using Microsoft.CodeAnalysis.EditAndContinue; +using Microsoft.DiaSymReader; using Microsoft.VisualStudio.Debugger; using Microsoft.VisualStudio.Debugger.Clr; using Microsoft.VisualStudio.Debugger.ComponentInterfaces; +using Roslyn.Utilities; namespace Microsoft.VisualStudio.LanguageServices.EditAndContinue { @@ -50,11 +54,11 @@ DkmCustomMessage IDkmCustomMessageForwardReceiver.SendLower(DkmCustomMessage cus } } - private readonly DebuggeeModuleMetadataCache _baselineMetadata; + private readonly DebuggeeModuleInfoCache _baselineMetadata; public DebuggeeModuleMetadataProvider() { - _baselineMetadata = new DebuggeeModuleMetadataCache(); + _baselineMetadata = new DebuggeeModuleInfoCache(); } private void OnModuleInstanceUnload(Guid mvid) @@ -63,9 +67,12 @@ private void OnModuleInstanceUnload(Guid mvid) /// /// Finds a module of given MVID in one of the processes being debugged and returns its baseline metadata. /// Shall only be called while in debug mode. + /// Shall only be called on MTA thread. /// - public ModuleMetadata TryGetBaselineMetadata(Guid mvid) + public DebuggeeModuleInfo TryGetBaselineModuleInfo(Guid mvid) { + Contract.ThrowIfFalse(Thread.CurrentThread.GetApartmentState() == ApartmentState.MTA); + return _baselineMetadata.GetOrAdd(mvid, m => { using (DebuggerComponent.ManagedEditAndContinueService()) @@ -76,8 +83,7 @@ public ModuleMetadata TryGetBaselineMetadata(Guid mvid) return default; } - var metadata = GetBaselineModuleMetadata(clrModuleInstance); - if (metadata == null) + if (!TryGetBaselineModuleInfo(clrModuleInstance, out var metadata, out var symReader)) { return default; } @@ -91,13 +97,15 @@ public ModuleMetadata TryGetBaselineMetadata(Guid mvid) Parameter1: this, Parameter2: clrModuleInstance).SendLower(); - return metadata; + return new DebuggeeModuleInfo(metadata, symReader); } }); } - private static ModuleMetadata GetBaselineModuleMetadata(DkmClrModuleInstance module) + private static bool TryGetBaselineModuleInfo(DkmClrModuleInstance module, out ModuleMetadata metadata, out ISymUnmanagedReader5 symReader) { + Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.MTA); + IntPtr metadataPtr; uint metadataSize; try @@ -106,10 +114,21 @@ private static ModuleMetadata GetBaselineModuleMetadata(DkmClrModuleInstance mod } catch (Exception e) when (DkmExceptionUtilities.IsBadOrMissingMetadataException(e)) { - return null; + metadata = null; + symReader = null; + return false; + } + + symReader = module.GetSymUnmanagedReader() as ISymUnmanagedReader5; + if (symReader == null) + { + metadata = null; + symReader = null; + return false; } - return ModuleMetadata.CreateFromMetadata(metadataPtr, (int)metadataSize); + metadata = ModuleMetadata.CreateFromMetadata(metadataPtr, (int)metadataSize); + return true; } private static DkmClrModuleInstance FindClrModuleInstance(Guid mvid) diff --git a/src/VisualStudio/Core/Def/Implementation/EditAndContinue/VsENCRebuildableProjectImpl.cs b/src/VisualStudio/Core/Def/Implementation/EditAndContinue/VsENCRebuildableProjectImpl.cs index 67feb384a6e..96ffe35ab5e 100644 --- a/src/VisualStudio/Core/Def/Implementation/EditAndContinue/VsENCRebuildableProjectImpl.cs +++ b/src/VisualStudio/Core/Def/Implementation/EditAndContinue/VsENCRebuildableProjectImpl.cs @@ -89,8 +89,6 @@ internal sealed class VsENCRebuildableProjectImpl /// private Guid _mvid; - private Lazy _pdbReader; - #endregion private bool IsDebuggable => _mvid != Guid.Empty; @@ -338,8 +336,6 @@ public int StopDebuggingPE() _committedBaseline = null; _projectBeingEmitted = null; - ReleasePdbReader(Interlocked.Exchange(ref _pdbReader, null)); - // The HResult is ignored by the debugger. return VSConstants.S_OK; } @@ -349,18 +345,6 @@ public int StopDebuggingPE() } } - private static void ReleasePdbReader(Lazy pdbReader) - { - if (pdbReader?.IsValueCreated == true) - { - var symReader = pdbReader.Value; - if (Marshal.IsComObject(symReader)) - { - Marshal.ReleaseComObject(symReader); - } - } - } - private static void LogEncSession() { var sessionId = DebugLogMessage.GetNextId(); @@ -765,18 +749,7 @@ public unsafe int BuildForEnc(object pUpdatePE) // so we'll to emit an empty delta. See bug 839558. Debug.Assert(_lastEditSessionSummary == ProjectAnalysisSummary.ValidInsignificantChanges || _lastEditSessionSummary == ProjectAnalysisSummary.ValidChanges); - - var updater = (IDebugUpdateInMemoryPE3)pUpdatePE; - - // Acquire PDB reader lazily. _pdbReader is cleared when the debugging session stops. - if (_pdbReader == null) - { - var previousPdbReader = Interlocked.Exchange(ref _pdbReader, MarshalPdbReader(updater)); - - // This method should only be called on UI thread, thus the previous value should be null. - Contract.ThrowIfFalse(previousPdbReader == null); - } - + // ISymUnmanagedReader can only be accessed from an MTA thread, // so dispatch emit to one of thread pool threads, which are MTA. var emitTask = Task.Factory.SafeStartNew(EmitProjectDelta, CancellationToken.None, TaskScheduler.Default); @@ -808,6 +781,8 @@ public unsafe int BuildForEnc(object pUpdatePE) } _documentsWithEmitError = ImmutableArray.Empty; + + var updater = (IDebugUpdateInMemoryPE3)pUpdatePE; SetFileUpdates(updater, delta.LineEdits); updater.SetDeltaIL(delta.IL.Value, (uint)delta.IL.Value.Length); @@ -949,14 +924,14 @@ private Deltas EmitProjectDelta() var baseline = _committedBaseline; if (baseline == null) { - var baselineMetadata = _moduleMetadataProvider.TryGetBaselineMetadata(_mvid); - if (baselineMetadata != null) + var info = _moduleMetadataProvider.TryGetBaselineModuleInfo(_mvid); + if (info != null) { baseline = EmitBaseline.CreateInitialBaseline( - baselineMetadata, - GetBaselineEncDebugInfo, - GetBaselineLocalSignature, - HasPortableMetadata(_pdbReader.Value)); + info.Metadata, + h => GetBaselineEncDebugInfo(info.SymReader, h), + h => GetBaselineLocalSignature(info.SymReader, h), + HasPortableMetadata(info.SymReader)); } } @@ -985,11 +960,11 @@ private Deltas EmitProjectDelta() private unsafe bool HasPortableMetadata(ISymUnmanagedReader5 symReader) => symReader.GetPortableDebugMetadata(out _, out _) == 0; - private StandaloneSignatureHandle GetBaselineLocalSignature(MethodDefinitionHandle methodHandle) + private static StandaloneSignatureHandle GetBaselineLocalSignature(ISymUnmanagedReader5 symReader, MethodDefinitionHandle methodHandle) { Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.MTA); - var symMethod = (ISymUnmanagedMethod2)_pdbReader.Value.GetMethodByVersion(MetadataTokens.GetToken(methodHandle), methodVersion: 1); + var symMethod = (ISymUnmanagedMethod2)symReader.GetMethodByVersion(MetadataTokens.GetToken(methodHandle), methodVersion: 1); // Compiler generated methods (e.g. async kick-off methods) might not have debug information. return symMethod == null ? default : MetadataTokens.StandaloneSignatureHandle(symMethod.GetLocalSignatureToken()); @@ -999,40 +974,20 @@ private StandaloneSignatureHandle GetBaselineLocalSignature(MethodDefinitionHand /// Returns EnC debug information for initial version of the specified method. /// /// The debug information data is corrupt or can't be retrieved from the debugger. - private EditAndContinueMethodDebugInformation GetBaselineEncDebugInfo(MethodDefinitionHandle methodHandle) + private static EditAndContinueMethodDebugInformation GetBaselineEncDebugInfo(ISymUnmanagedReader5 symReader, MethodDefinitionHandle methodHandle) { Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.MTA); - return GetEditAndContinueMethodDebugInfo(_pdbReader.Value, methodHandle); + return GetEditAndContinueMethodDebugInfo(symReader, methodHandle); } - // Unmarshal the symbol reader (being marshalled cross thread from STA -> MTA). - private static ISymUnmanagedReader5 UnmarshalSymReader(IntPtr stream) - { - Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.MTA); - try - { - return (ISymUnmanagedReader5)NativeMethods.GetObjectAndRelease(stream); - } - catch (Exception exception) when (FatalError.ReportWithoutCrash(exception)) - { - throw new InvalidDataException(exception.Message, exception); - } - } - - private static EditAndContinueMethodDebugInformation GetEditAndContinueMethodDebugInfo(ISymUnmanagedReader3 symReader, MethodDefinitionHandle methodHandle) + private static EditAndContinueMethodDebugInformation GetEditAndContinueMethodDebugInfo(ISymUnmanagedReader5 symReader, MethodDefinitionHandle methodHandle) { return TryGetPortableEncDebugInfo(symReader, methodHandle, out var info) ? info : GetNativeEncDebugInfo(symReader, methodHandle); } - private static unsafe bool TryGetPortableEncDebugInfo(ISymUnmanagedReader symReader, MethodDefinitionHandle methodHandle, out EditAndContinueMethodDebugInformation info) + private static unsafe bool TryGetPortableEncDebugInfo(ISymUnmanagedReader5 symReader, MethodDefinitionHandle methodHandle, out EditAndContinueMethodDebugInformation info) { - if (!(symReader is ISymUnmanagedReader5 symReader5)) - { - info = default; - return false; - } - - int hr = symReader5.GetPortableDebugMetadataByVersion(version: 1, metadata: out byte* metadata, size: out int size); + int hr = symReader.GetPortableDebugMetadataByVersion(version: 1, metadata: out byte* metadata, size: out int size); Marshal.ThrowExceptionForHR(hr); if (hr != 0) @@ -1075,7 +1030,7 @@ private static bool TryGetCustomDebugInformation(System.Reflection.Metadata.Meta return foundAny; } - private static EditAndContinueMethodDebugInformation GetNativeEncDebugInfo(ISymUnmanagedReader3 symReader, MethodDefinitionHandle methodHandle) + private static EditAndContinueMethodDebugInformation GetNativeEncDebugInfo(ISymUnmanagedReader5 symReader, MethodDefinitionHandle methodHandle) { int methodToken = MetadataTokens.GetToken(methodHandle); @@ -1145,42 +1100,6 @@ public int EncApplySucceeded(int hrApplyResult) } } - private static Lazy MarshalPdbReader(IDebugUpdateInMemoryPE2 updater) - { - // ISymUnmanagedReader can only be accessed from an MTA thread, however, we need - // fetch the IUnknown instance (call IENCSymbolReaderProvider.GetSymbolReader) here - // in the STA. To further complicate things, we need to return synchronously from - // this method. Waiting for the MTA thread to complete so we can return synchronously - // blocks the STA thread, so we need to make sure the CLR doesn't try to marshal - // ISymUnmanagedReader calls made in an MTA back to the STA for execution (if this - // happens we'll be deadlocked). We'll use CoMarshalInterThreadInterfaceInStream to - // achieve this. First, we'll marshal the object in a Stream and pass a Stream pointer - // over to the MTA. In the MTA, we'll get the Stream from the pointer and unmarshal - // the object. The reader object was originally created on an MTA thread, and the - // instance we retrieved in the STA was a proxy. When we unmarshal the Stream in the - // MTA, it "unwraps" the proxy, allowing us to directly call the implementation. - // Another way to achieve this would be for the symbol reader to implement IAgileObject, - // but the symbol reader we use today does not. If that changes, we should consider - // removing this marshal/unmarshal code. - updater.GetENCDebugInfo(out IENCDebugInfo debugInfo); - - var symbolReaderProvider = (IENCSymbolReaderProvider)debugInfo; - symbolReaderProvider.GetSymbolReader(out object pdbReaderObjSta); - if (Marshal.IsComObject(pdbReaderObjSta)) - { - int hr = NativeMethods.GetStreamForObject(pdbReaderObjSta, out IntPtr stream); - Marshal.ReleaseComObject(pdbReaderObjSta); - Marshal.ThrowExceptionForHR(hr); - - return new Lazy(() => UnmarshalSymReader(stream)); - } - else - { - var managedSymReader = (ISymUnmanagedReader5)pdbReaderObjSta; - return new Lazy(() => managedSymReader); - } - } - private enum InternalErrorCode { CantApplyChangesModuleHasBeenUnloaded = 1, -- GitLab