private ChecksumAlgorithmType ChecksumAlgorithmForFullPdb() { string fileName = Path.GetFileName(this.FileName); string extension = Path.GetExtension(fileName); string pdbPath = this.FileName.Replace(fileName, fileName.Replace(extension, ".pdb")); if (!File.Exists(pdbPath)) { return(ChecksumAlgorithmType.Unknown); } using var pdbStream = new FileStream(pdbPath, FileMode.Open, FileAccess.Read); var metadataProvider = new SymMetadataProvider(this.metadataReader); object importer = SymUnmanagedReaderFactory.CreateSymReaderMetadataImport(metadataProvider); ISymUnmanagedReader3 reader = SymUnmanagedReaderFactory.CreateReaderWithMetadataImport <ISymUnmanagedReader3>(pdbStream, importer, SymUnmanagedReaderCreationOptions.UseComRegistry); try { Guid algorithm = Guid.Empty; foreach (ISymUnmanagedDocument document in reader.GetDocuments()) { document.GetChecksumAlgorithmId(ref algorithm); return(algorithm == sha256guid ? ChecksumAlgorithmType.Sha256 : ChecksumAlgorithmType.Sha1); } } finally { _ = ((ISymUnmanagedDispose)reader).Destroy(); } return(ChecksumAlgorithmType.Unknown); }
private static void ReadCSharpNativeCustomDebugInfo( ISymUnmanagedReader3 reader, int methodToken, int methodVersion, IEnumerable <ISymUnmanagedScope> scopes, out ImmutableArray <HoistedLocalScopeRecord> hoistedLocalScopeRecords, out ImmutableDictionary <int, ImmutableArray <bool> > dynamicLocalMap, out ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMap) { hoistedLocalScopeRecords = ImmutableArray <HoistedLocalScopeRecord> .Empty; dynamicLocalMap = ImmutableDictionary <int, ImmutableArray <bool> > .Empty; dynamicLocalConstantMap = ImmutableDictionary <string, ImmutableArray <bool> > .Empty; byte[] customDebugInfoBytes = reader.GetCustomDebugInfoBytes(methodToken, methodVersion); if (customDebugInfoBytes == null) { return; } var customDebugInfoRecord = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfoBytes, CustomDebugInfoKind.StateMachineHoistedLocalScopes); if (!customDebugInfoRecord.IsDefault) { hoistedLocalScopeRecords = CustomDebugInfoReader.DecodeStateMachineHoistedLocalScopesRecord(customDebugInfoRecord) .SelectAsArray(s => new HoistedLocalScopeRecord(s.StartOffset, s.EndOffset - s.StartOffset + 1)); } CustomDebugInfoReader.GetCSharpDynamicLocalInfo( customDebugInfoBytes, methodToken, methodVersion, scopes, out dynamicLocalMap, out dynamicLocalConstantMap); }
public static byte[] GetCustomDebugInfoBytes( ISymUnmanagedReader3 reader, MethodDefinitionHandle handle, int methodVersion ) { return(reader.GetCustomDebugInfo(MetadataTokens.GetToken(handle), methodVersion)); }
public static void Initialize(this ISymUnmanagedReader3 reader, Stream stream, object metadataImporter, string fileName = null, string searchPath = null) { if (reader == null) { throw new ArgumentNullException(nameof(reader)); } ThrowExceptionForHR(reader.Initialize(metadataImporter, fileName, searchPath, SymUnmanagedStreamFactory.CreateStream(stream))); }
public static EditAndContinueMethodDebugInformation GetEncMethodDebugInfo(this ISymUnmanagedReader3 symReader, MethodDefinitionHandle handle) { var cdi = CustomDebugInfoUtilities.GetCustomDebugInfoBytes(symReader, handle, methodVersion: 1); if (cdi == null) { return(EditAndContinueMethodDebugInformation.Create(default(ImmutableArray <byte>), default(ImmutableArray <byte>))); } return(GetEncMethodDebugInfo(cdi)); }
/// <summary> /// Get the blob of binary custom debug info for a given method. /// </summary> private static byte[] GetCustomDebugInfoBytes(ISymUnmanagedReader3 reader, int methodToken, int methodVersion) { try { return(reader.GetCustomDebugInfo(methodToken, methodVersion)); } catch (ArgumentOutOfRangeException) { // Sometimes the debugger returns the HRESULT for ArgumentOutOfRangeException, rather than E_FAIL, // for methods without custom debug info (https://github.com/dotnet/roslyn/issues/4138). return(null); } }
public static unsafe EditAndContinueMethodDebugInformation GetEncMethodDebugInfo( this ISymUnmanagedReader3 symReader, MethodDefinitionHandle handle ) { const int S_OK = 0; if (symReader is ISymUnmanagedReader4 symReader4) { int hr = symReader4.GetPortableDebugMetadata(out byte *metadata, out int size); Marshal.ThrowExceptionForHR(hr); if (hr == S_OK) { var pdbReader = new MetadataReader(metadata, size); ImmutableArray <byte> GetCdiBytes(Guid kind) => TryGetCustomDebugInformation(pdbReader, handle, kind, out var info) ? pdbReader.GetBlobContent(info.Value) : default(ImmutableArray <byte>); return(EditAndContinueMethodDebugInformation.Create( compressedSlotMap: GetCdiBytes( PortableCustomDebugInfoKinds.EncLocalSlotMap ), compressedLambdaMap: GetCdiBytes( PortableCustomDebugInfoKinds.EncLambdaAndClosureMap ) )); } } var cdi = CustomDebugInfoUtilities.GetCustomDebugInfoBytes( symReader, handle, methodVersion: 1 ); if (cdi == null) { return(EditAndContinueMethodDebugInformation.Create( default(ImmutableArray <byte>), default(ImmutableArray <byte>) )); } return(GetEncMethodDebugInfo(cdi)); }
private static void ReadCSharpNativeImportsInfo( ISymUnmanagedReader3 reader, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, int methodToken, int methodVersion, out ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups, out ImmutableArray <ExternAliasRecord> externAliasRecords) { ImmutableArray <string> externAliasStrings; var importStringGroups = CustomDebugInfoReader.GetCSharpGroupedImportStrings( methodToken, KeyValuePair.Create(reader, methodVersion), getMethodCustomDebugInfo: (token, arg) => GetCustomDebugInfoBytes(arg.Key, token, arg.Value), getMethodImportStrings: (token, arg) => GetImportStrings(arg.Key, token, arg.Value), externAliasStrings: out externAliasStrings); Debug.Assert(importStringGroups.IsDefault == externAliasStrings.IsDefault); ArrayBuilder <ImmutableArray <ImportRecord> > importRecordGroupBuilder = null; ArrayBuilder <ExternAliasRecord> externAliasRecordBuilder = null; if (!importStringGroups.IsDefault) { importRecordGroupBuilder = ArrayBuilder <ImmutableArray <ImportRecord> > .GetInstance(importStringGroups.Length); foreach (var importStringGroup in importStringGroups) { var groupBuilder = ArrayBuilder <ImportRecord> .GetInstance(importStringGroup.Length); foreach (var importString in importStringGroup) { ImportRecord record; if (TryCreateImportRecordFromCSharpImportString(symbolProvider, importString, out record)) { groupBuilder.Add(record); } else { Debug.WriteLine($"Failed to parse import string {importString}"); } } importRecordGroupBuilder.Add(groupBuilder.ToImmutableAndFree()); } if (!externAliasStrings.IsDefault) { externAliasRecordBuilder = ArrayBuilder <ExternAliasRecord> .GetInstance(externAliasStrings.Length); foreach (string externAliasString in externAliasStrings) { string alias; string externAlias; string target; ImportTargetKind kind; if (!CustomDebugInfoReader.TryParseCSharpImportString(externAliasString, out alias, out externAlias, out target, out kind)) { Debug.WriteLine($"Unable to parse extern alias '{externAliasString}'"); continue; } Debug.Assert(kind == ImportTargetKind.Assembly, "Programmer error: How did a non-assembly get in the extern alias list?"); Debug.Assert(alias != null); // Name of the extern alias. Debug.Assert(externAlias == null); // Not used. Debug.Assert(target != null); // Name of the target assembly. AssemblyIdentity targetIdentity; if (!AssemblyIdentity.TryParseDisplayName(target, out targetIdentity)) { Debug.WriteLine($"Unable to parse target of extern alias '{externAliasString}'"); continue; } externAliasRecordBuilder.Add(new ExternAliasRecord(alias, targetIdentity)); } } } importRecordGroups = importRecordGroupBuilder?.ToImmutableAndFree() ?? ImmutableArray <ImmutableArray <ImportRecord> > .Empty; externAliasRecords = externAliasRecordBuilder?.ToImmutableAndFree() ?? ImmutableArray <ExternAliasRecord> .Empty; }
private static ImmutableArray <string> GetImportStrings(int token, Dictionary <int, ImmutableArray <string> > cache, ISymUnmanagedReader3 reader) { ImmutableArray <string> result; if (!cache.TryGetValue(token, out result)) { result = SymReaderHelpers.GetImportStrings(reader, token, methodVersion: 1); cache.Add(token, result); } return(result); }
public static byte[] GetCustomDebugInfoBytes(ISymUnmanagedReader3 reader, MethodDefinitionHandle handle, int methodVersion) { return reader.GetCustomDebugInfoBytes(MetadataTokens.GetToken(handle), methodVersion); }
public FullPdbReader(Stream pdbStream) { pdbStream.Position = 0; _symReader = CreateNativeSymReader(pdbStream); }
public FullPdbReader(Stream pdbStream) { pdbStream.Position = 0; _symReader = CreateNativeSymReader(pdbStream); }
/// <summary> /// Returns EnC debug information for initial version of the specified method. /// </summary> /// <exception cref="InvalidDataException">The debug information data is corrupt or can't be retrieved from the debugger.</exception> private EditAndContinueMethodDebugInformation GetBaselineEncDebugInfo(MethodDefinitionHandle methodHandle) { Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.MTA); if (_pdbReader == null) { // Unmarshal the symbol reader (being marshalled cross thread from STA -> MTA). Debug.Assert(_pdbReaderObjAsStream != IntPtr.Zero); object pdbReaderObjMta; var exception = Marshal.GetExceptionForHR(NativeMethods.GetObjectForStream(_pdbReaderObjAsStream, out pdbReaderObjMta)); if (exception != null) { // likely a bug in the compiler/debugger FatalError.ReportWithoutCrash(exception); throw new InvalidDataException(exception.Message, exception); } _pdbReaderObjAsStream = IntPtr.Zero; _pdbReader = (ISymUnmanagedReader3)pdbReaderObjMta; } int methodToken = MetadataTokens.GetToken(methodHandle); byte[] debugInfo; try { debugInfo = _pdbReader.GetCustomDebugInfoBytes(methodToken, methodVersion: 1); } catch (Exception e) when (FatalError.ReportWithoutCrash(e)) // likely a bug in the compiler/debugger { throw new InvalidDataException(e.Message, e); } try { ImmutableArray<byte> localSlots, lambdaMap; if (debugInfo != null) { localSlots = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(debugInfo, CustomDebugInfoKind.EditAndContinueLocalSlotMap); lambdaMap = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(debugInfo, CustomDebugInfoKind.EditAndContinueLambdaMap); } else { localSlots = lambdaMap = default(ImmutableArray<byte>); } return EditAndContinueMethodDebugInformation.Create(localSlots, lambdaMap); } catch (InvalidOperationException e) when (FatalError.ReportWithoutCrash(e)) // likely a bug in the compiler/debugger { // TODO: CustomDebugInfoReader should throw InvalidDataException throw new InvalidDataException(e.Message, e); } }
public unsafe static MethodDebugInfo <TTypeSymbol, TLocalSymbol> ReadMethodDebugInfo( ISymUnmanagedReader3 symReader, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProviderOpt, // TODO: only null in DTEE case where we looking for default namesapace int methodToken, int methodVersion, int ilOffset, bool isVisualBasicMethod) { // no symbols if (symReader == null) { return(None); } var symReader4 = symReader as ISymUnmanagedReader4; if (symReader4 != null) // TODO: VB Portable PDBs { byte *metadata; int size; // TODO: version int hr = symReader4.GetPortableDebugMetadata(out metadata, out size); SymUnmanagedReaderExtensions.ThrowExceptionForHR(hr); if (metadata != null) { var mdReader = new MetadataReader(metadata, size); try { return(ReadFromPortable(mdReader, methodToken, ilOffset, symbolProviderOpt, isVisualBasicMethod)); } catch (BadImageFormatException) { // bad CDI, ignore return(None); } } } var allScopes = ArrayBuilder <ISymUnmanagedScope> .GetInstance(); var containingScopes = ArrayBuilder <ISymUnmanagedScope> .GetInstance(); try { ImmutableArray <HoistedLocalScopeRecord> hoistedLocalScopeRecords; ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups; ImmutableArray <ExternAliasRecord> externAliasRecords; ImmutableDictionary <int, ImmutableArray <bool> > dynamicLocalMap; ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMap; string defaultNamespaceName; var symMethod = symReader.GetMethodByVersion(methodToken, methodVersion); if (symMethod != null) { symMethod.GetAllScopes(allScopes, containingScopes, ilOffset, isScopeEndInclusive: isVisualBasicMethod); } if (isVisualBasicMethod) { ReadVisualBasicImportsDebugInfo( symReader, methodToken, methodVersion, out importRecordGroups, out defaultNamespaceName); hoistedLocalScopeRecords = ImmutableArray <HoistedLocalScopeRecord> .Empty; externAliasRecords = ImmutableArray <ExternAliasRecord> .Empty; dynamicLocalMap = null; dynamicLocalConstantMap = null; } else { Debug.Assert(symbolProviderOpt != null); ReadCSharpNativeImportsInfo( symReader, symbolProviderOpt, methodToken, methodVersion, out importRecordGroups, out externAliasRecords); ReadCSharpNativeCustomDebugInfo( symReader, methodToken, methodVersion, allScopes, out hoistedLocalScopeRecords, out dynamicLocalMap, out dynamicLocalConstantMap); defaultNamespaceName = ""; } var constantsBuilder = ArrayBuilder <TLocalSymbol> .GetInstance(); if (symbolProviderOpt != null) // TODO { GetConstants(constantsBuilder, symbolProviderOpt, containingScopes, dynamicLocalConstantMap); } var reuseSpan = GetReuseSpan(allScopes, ilOffset, isVisualBasicMethod); return(new MethodDebugInfo <TTypeSymbol, TLocalSymbol>( hoistedLocalScopeRecords, importRecordGroups, externAliasRecords, dynamicLocalMap, defaultNamespaceName, containingScopes.GetLocalNames(), constantsBuilder.ToImmutableAndFree(), reuseSpan)); } catch (InvalidOperationException) { // bad CDI, ignore return(None); } finally { allScopes.Free(); containingScopes.Free(); } }
/// <summary> /// Get the import strings for a given method, following forward pointers as necessary. /// </summary> /// <returns> /// For each namespace enclosing the method, a list of import strings, innermost to outermost. /// There should always be at least one entry, for the global namespace. /// </returns> public static ImmutableArray <ImmutableArray <string> > GetCSharpGroupedImportStrings(this ISymUnmanagedReader3 reader, int methodToken, int methodVersion, out ImmutableArray <string> externAliasStrings) { externAliasStrings = default(ImmutableArray <string>); ImmutableArray <short> groupSizes = default(ImmutableArray <short>); bool seenForward = false; RETRY: byte[] bytes = reader.GetCustomDebugInfoBytes(methodToken, methodVersion); if (bytes == null) { return(default(ImmutableArray <ImmutableArray <string> >)); } foreach (var record in GetCustomDebugInfoRecords(bytes)) { switch (record.Kind) { case CustomDebugInfoKind.UsingInfo: if (!groupSizes.IsDefault) { throw new InvalidOperationException(string.Format("Expected at most one Using record for method {0}", FormatMethodToken(methodToken))); } groupSizes = DecodeUsingRecord(record.Data); break; case CustomDebugInfoKind.ForwardInfo: if (!externAliasStrings.IsDefault) { throw new InvalidOperationException(string.Format("Did not expect both Forward and ForwardToModule records for method {0}", FormatMethodToken(methodToken))); } methodToken = DecodeForwardRecord(record.Data); // Follow at most one forward link (as in FUNCBRECEE::ensureNamespaces). // NOTE: Dev11 may produce chains of forward links (e.g. for System.Collections.Immutable). if (!seenForward) { seenForward = true; goto RETRY; } break; case CustomDebugInfoKind.ForwardToModuleInfo: if (!externAliasStrings.IsDefault) { throw new InvalidOperationException(string.Format("Expected at most one ForwardToModule record for method {0}", FormatMethodToken(methodToken))); } int moduleInfoMethodToken = DecodeForwardToModuleRecord(record.Data); ImmutableArray <string> allModuleInfoImportStrings = reader.GetMethodByVersion(moduleInfoMethodToken, methodVersion).GetImportStrings(); ArrayBuilder <string> externAliasBuilder = ArrayBuilder <string> .GetInstance(); foreach (string importString in allModuleInfoImportStrings) { if (IsCSharpExternAliasInfo(importString)) { externAliasBuilder.Add(importString); } } externAliasStrings = externAliasBuilder.ToImmutableAndFree(); break; } } if (groupSizes.IsDefault) { // This can happen in malformed PDBs (e.g. chains of forwards). return(default(ImmutableArray <ImmutableArray <string> >)); } var method = reader.GetMethodByVersion(methodToken, methodVersion); if (method == null) { return(default(ImmutableArray <ImmutableArray <string> >)); } ImmutableArray <string> importStrings = method.GetImportStrings(); int numImportStrings = importStrings.Length; ArrayBuilder <ImmutableArray <string> > resultBuilder = ArrayBuilder <ImmutableArray <string> > .GetInstance(groupSizes.Length); ArrayBuilder <string> groupBuilder = ArrayBuilder <string> .GetInstance(); int pos = 0; foreach (short groupSize in groupSizes) { for (int i = 0; i < groupSize; i++, pos++) { if (pos >= numImportStrings) { throw new InvalidOperationException(string.Format("Group size indicates more imports than there are import strings (method {0}).", FormatMethodToken(methodToken))); } string importString = importStrings[pos]; if (IsCSharpExternAliasInfo(importString)) { throw new InvalidOperationException(string.Format("Encountered extern alias info before all import strings were consumed (method {0}).", FormatMethodToken(methodToken))); } groupBuilder.Add(importString); } resultBuilder.Add(groupBuilder.ToImmutable()); groupBuilder.Clear(); } if (externAliasStrings.IsDefault) { Debug.Assert(groupBuilder.Count == 0); // Extern alias detail strings (prefix "Z") are not included in the group counts. for (; pos < numImportStrings; pos++) { string importString = importStrings[pos]; if (!IsCSharpExternAliasInfo(importString)) { throw new InvalidOperationException(string.Format("Expected only extern alias info strings after consuming the indicated number of imports (method {0}).", FormatMethodToken(methodToken))); } groupBuilder.Add(importString); } externAliasStrings = groupBuilder.ToImmutableAndFree(); } else { groupBuilder.Free(); if (pos < numImportStrings) { throw new InvalidOperationException(string.Format("Group size indicates fewer imports than there are import strings (method {0}).", FormatMethodToken(methodToken))); } } return(resultBuilder.ToImmutableAndFree()); }
public unsafe static MethodDebugInfo <TTypeSymbol, TLocalSymbol> ReadMethodDebugInfo( ISymUnmanagedReader3 symReader, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProviderOpt, // TODO: only null in DTEE case where we looking for default namesapace int methodToken, int methodVersion, int ilOffset, bool isVisualBasicMethod) { // no symbols if (symReader == null) { return(None); } if (symReader is ISymUnmanagedReader5 symReader5) { int hr = symReader5.GetPortableDebugMetadataByVersion(methodVersion, out byte *metadata, out int size); ThrowExceptionForHR(hr); if (hr == S_OK) { var mdReader = new MetadataReader(metadata, size); try { return(ReadFromPortable(mdReader, methodToken, ilOffset, symbolProviderOpt, isVisualBasicMethod)); } catch (BadImageFormatException) { // bad CDI, ignore return(None); } } } var allScopes = ArrayBuilder <ISymUnmanagedScope> .GetInstance(); var containingScopes = ArrayBuilder <ISymUnmanagedScope> .GetInstance(); try { var symMethod = symReader.GetMethodByVersion(methodToken, methodVersion); if (symMethod != null) { symMethod.GetAllScopes(allScopes, containingScopes, ilOffset, isScopeEndInclusive: isVisualBasicMethod); } ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups; ImmutableArray <ExternAliasRecord> externAliasRecords; string defaultNamespaceName; if (isVisualBasicMethod) { ReadVisualBasicImportsDebugInfo( symReader, methodToken, methodVersion, out importRecordGroups, out defaultNamespaceName); externAliasRecords = ImmutableArray <ExternAliasRecord> .Empty; } else { Debug.Assert(symbolProviderOpt != null); ReadCSharpNativeImportsInfo( symReader, symbolProviderOpt, methodToken, methodVersion, out importRecordGroups, out externAliasRecords); defaultNamespaceName = ""; } // VB should read hoisted scope information from local variables: var hoistedLocalScopeRecords = isVisualBasicMethod ? default(ImmutableArray <HoistedLocalScopeRecord>) : ImmutableArray <HoistedLocalScopeRecord> .Empty; ImmutableDictionary <int, ImmutableArray <bool> > dynamicLocalMap = null; ImmutableDictionary <string, ImmutableArray <bool> > dynamicLocalConstantMap = null; ImmutableDictionary <int, ImmutableArray <string> > tupleLocalMap = null; ImmutableDictionary <LocalNameAndScope, ImmutableArray <string> > tupleLocalConstantMap = null; byte[] customDebugInfo = GetCustomDebugInfoBytes(symReader, methodToken, methodVersion); if (customDebugInfo != null) { if (!isVisualBasicMethod) { var customDebugInfoRecord = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(customDebugInfo, CustomDebugInfoKind.StateMachineHoistedLocalScopes); if (!customDebugInfoRecord.IsDefault) { hoistedLocalScopeRecords = CustomDebugInfoReader.DecodeStateMachineHoistedLocalScopesRecord(customDebugInfoRecord) .SelectAsArray(s => new HoistedLocalScopeRecord(s.StartOffset, s.Length)); } GetCSharpDynamicLocalInfo( customDebugInfo, allScopes, out dynamicLocalMap, out dynamicLocalConstantMap); } GetTupleElementNamesLocalInfo( customDebugInfo, out tupleLocalMap, out tupleLocalConstantMap); } var constantsBuilder = ArrayBuilder <TLocalSymbol> .GetInstance(); if (symbolProviderOpt != null) // TODO { GetConstants(constantsBuilder, symbolProviderOpt, containingScopes, dynamicLocalConstantMap, tupleLocalConstantMap); } var reuseSpan = GetReuseSpan(allScopes, ilOffset, isVisualBasicMethod); return(new MethodDebugInfo <TTypeSymbol, TLocalSymbol>( hoistedLocalScopeRecords, importRecordGroups, externAliasRecords, dynamicLocalMap, tupleLocalMap, defaultNamespaceName, containingScopes.GetLocalNames(), constantsBuilder.ToImmutableAndFree(), reuseSpan)); } catch (InvalidOperationException) { // bad CDI, ignore return(None); } finally { allScopes.Free(); containingScopes.Free(); } }
public int StopDebuggingPE() { try { log.Write("Exit Debug Mode: project '{0}'", _vsProject.DisplayName); Debug.Assert(s_breakStateEnteredProjects.Count == 0); // Clear the solution stored while projects were entering break mode. // It should be cleared as soon as all tracked projects enter the break mode // but if the entering break mode fails for some projects we should avoid leaking the solution. Debug.Assert(s_breakStateEntrySolution == null); s_breakStateEntrySolution = null; // EnC service is global (per solution), but the debugger calls this for each project. // Avoid ending the debug session if it has already been ended. if (_encService.DebuggingSession != null) { _encService.OnBeforeDebuggingStateChanged(DebuggingState.Run, DebuggingState.Design); _encService.EndDebuggingSession(); LogEncSession(); s_encDebuggingSessionInfo = null; s_readOnlyDocumentTracker.Dispose(); s_readOnlyDocumentTracker = null; } if (_metadata != null) { _metadata.Dispose(); _metadata = null; s_debugStateProjectCount--; } else { // an error might have been reported: var errorId = new EncErrorId(_encService.DebuggingSession, EditAndContinueDiagnosticUpdateSource.DebuggerErrorId); _diagnosticProvider.ClearDiagnostics(errorId, _vsProject.Workspace.CurrentSolution, _vsProject.Id, documentIdOpt: null); } _activeMethods = null; _exceptionRegions = null; _committedBaseline = null; _activeStatementIds = null; _projectBeingEmitted = null; Debug.Assert((_pdbReaderObjAsStream == IntPtr.Zero) || (_pdbReader == null)); if (_pdbReader != null) { Marshal.ReleaseComObject(_pdbReader); _pdbReader = null; } // The HResult is ignored by the debugger. return VSConstants.S_OK; } catch (Exception e) when (FatalError.ReportWithoutCrash(e)) { return VSConstants.E_FAIL; } }
private EditAndContinueMethodDebugInformation GetBaselineEncDebugInfo(MethodDefinitionHandle methodHandle) { Debug.Assert(Thread.CurrentThread.GetApartmentState() == ApartmentState.MTA); if (_pdbReader == null) { // Unmarshal the symbol reader (being marshalled cross thread from STA -> MTA). Debug.Assert(_pdbReaderObjAsStream != IntPtr.Zero); object pdbReaderObjMta; int hr = NativeMethods.GetObjectForStream(_pdbReaderObjAsStream, out pdbReaderObjMta); _pdbReaderObjAsStream = IntPtr.Zero; if (hr != VSConstants.S_OK) { log.Write("Error unmarshaling object from stream."); return default(EditAndContinueMethodDebugInformation); } _pdbReader = (ISymUnmanagedReader3)pdbReaderObjMta; } int methodToken = MetadataTokens.GetToken(methodHandle); byte[] debugInfo = _pdbReader.GetCustomDebugInfoBytes(methodToken, methodVersion: 1); if (debugInfo != null) { try { var localSlots = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(debugInfo, CustomDebugInfoKind.EditAndContinueLocalSlotMap); var lambdaMap = CustomDebugInfoReader.TryGetCustomDebugInfoRecord(debugInfo, CustomDebugInfoKind.EditAndContinueLambdaMap); return EditAndContinueMethodDebugInformation.Create(localSlots, lambdaMap); } catch (Exception e) when (e is InvalidOperationException || e is InvalidDataException) { log.Write($"Error reading CDI of method 0x{methodToken:X8}: {e.Message}"); } } return default(EditAndContinueMethodDebugInformation); }