| File: PdbSourceDocument\DocumentDebugInfoReader.cs | Web Access |
| Project: src\roslyn\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Collections.Immutable; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using Microsoft.CodeAnalysis.Debugging; using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Text; using Microsoft.SourceLink.Tools; namespace Microsoft.CodeAnalysis.PdbSourceDocument; /// <summary> /// Gets information from DLL and/or PDB files needed for navigating to source documents /// </summary> internal sealed class DocumentDebugInfoReader : IDisposable { private readonly MetadataReaderProvider _pdbReaderProvider; private readonly PEReader _peReader; private readonly MetadataReader _dllReader; private readonly MetadataReader _pdbReader; public DocumentDebugInfoReader(PEReader peReader, MetadataReaderProvider pdbReaderProvider) { _peReader = peReader; _pdbReaderProvider = pdbReaderProvider; _dllReader = _peReader.GetMetadataReader(); _pdbReader = _pdbReaderProvider.GetMetadataReader(); } public ImmutableArray<SourceDocument> FindSourceDocuments(EntityHandle entityHandle) { var documentHandles = SymbolSourceDocumentFinder.FindDocumentHandles(entityHandle, _dllReader, _pdbReader); var sourceDocuments = new FixedSizeArrayBuilder<SourceDocument>(documentHandles.Count); foreach (var handle in documentHandles) { var document = _pdbReader.GetDocument(handle); var filePath = _pdbReader.GetString(document.Name); var hashAlgorithmGuid = _pdbReader.GetGuid(document.HashAlgorithm); var hashAlgorithm = SourceHashAlgorithms.GetSourceHashAlgorithm(hashAlgorithmGuid); var checksum = _pdbReader.GetBlobContent(document.Hash); var embeddedTextBytes = TryGetEmbeddedTextBytes(handle); var sourceLinkUrl = TryGetSourceLinkUrl(handle); sourceDocuments.Add(new SourceDocument(filePath, hashAlgorithm, checksum, embeddedTextBytes, sourceLinkUrl)); } return sourceDocuments.MoveToImmutable(); } private string? TryGetSourceLinkUrl(DocumentHandle handle) { var document = _pdbReader.GetDocument(handle); if (document.Name.IsNil) return null; var documentName = _pdbReader.GetString(document.Name); if (documentName is null) return null; if (!_pdbReader.TryGetCustomDebugInformation(EntityHandle.ModuleDefinition, PortableCustomDebugInfoKinds.SourceLink, out var cdi) || cdi.Value.IsNil) return null; var blobReader = _pdbReader.GetBlobReader(cdi.Value); var sourceLinkJson = blobReader.ReadUTF8(blobReader.Length); var map = SourceLinkMap.Parse(sourceLinkJson); return map.TryGetUri(documentName, out var uri) ? uri : null; } private byte[]? TryGetEmbeddedTextBytes(DocumentHandle handle) => _pdbReader.TryGetCustomDebugInformation(handle, PortableCustomDebugInfoKinds.EmbeddedSource, out var cdi) ? _pdbReader.GetBlobBytes(cdi.Value) : null; public ImmutableDictionary<string, string> GetCompilationOptions() => _pdbReader.GetCompilationOptions(); public void Dispose() { _pdbReaderProvider.Dispose(); _peReader.Dispose(); } }