internal bool TryGetDocument(string fullPath, out DocumentHandle documentHandle) { var fileName = FileNameUtilities.GetFileName(fullPath); KeyValuePair <DocumentNameAndHandle, ImmutableArray <DocumentNameAndHandle> > documents; if (!_map.TryGetValue(fileName, out documents)) { documentHandle = default(DocumentHandle); return(false); } // SymReader first attempts to find the document by the full path, then by file name with extension. if (documents.Key.FileName != null) { // There is only one document with the specified file name. // SymReader returns the document regardless of whether the path matches the name. documentHandle = documents.Key.Handle; return(true); } Debug.Assert(documents.Value.Length > 1); // We have multiple candidates with the same file name. Find the one whose name matches the specified full path. // If none does return the first one. It will be the one with the smallest handle, due to the multi-map construction implementation. // First try to find candidate whose full name is exactly matching. foreach (DocumentNameAndHandle candidate in documents.Value) { if (_reader.StringComparer.Equals(_reader.GetDocument(candidate.Handle).Name, fullPath, ignoreCase: false)) { documentHandle = candidate.Handle; return(true); } } // Then try to find candidate whose full name is matching ignoring case. foreach (DocumentNameAndHandle candidate in documents.Value) { if (_reader.StringComparer.Equals(_reader.GetDocument(candidate.Handle).Name, fullPath, ignoreCase: true)) { documentHandle = candidate.Handle; return(true); } } // Then try to find candidate whose file name is matching exactly. foreach (DocumentNameAndHandle candidate in documents.Value) { if (candidate.FileName == fileName) { documentHandle = candidate.Handle; return(true); } } documentHandle = documents.Value[0].Handle; return(true); }
/// <summary> /// Returns method token and IL offset for given source line number. /// </summary> /// <param name="filePath">source file name and path</param> /// <param name="lineNumber">source line number</param> /// <param name="methodToken">method token return</param> /// <param name="ilOffset">IL offset return</param> /// <returns>true if information is available</returns> public bool ResolveSequencePoint( string filePath, int lineNumber, out int methodToken, out int ilOffset) { methodToken = 0; ilOffset = 0; try { string fileName = SymbolService.GetFileName(filePath); foreach (MethodDebugInformationHandle methodDebugInformationHandle in _reader.MethodDebugInformation) { MethodDebugInformation methodDebugInfo = _reader.GetMethodDebugInformation(methodDebugInformationHandle); SequencePointCollection sequencePoints = methodDebugInfo.GetSequencePoints(); foreach (SequencePoint point in sequencePoints) { string sourceName = _reader.GetString(_reader.GetDocument(point.Document).Name); if (point.StartLine == lineNumber && SymbolService.GetFileName(sourceName) == fileName) { methodToken = MetadataTokens.GetToken(methodDebugInformationHandle.ToDefinitionHandle()); ilOffset = point.Offset; return(true); } } } } catch (Exception ex) { Trace.TraceError($"ResolveSequencePoint: {ex.Message}"); } return(false); }
private void CollectMethods(MetadataReader reader) { foreach (var mh in reader.MethodDebugInformation) { if (mh.IsNil) { continue; } var mdbg = reader.GetMethodDebugInformation(mh); if (mdbg.Document.IsNil) { continue; } // TODO: maybe we should add more error-checking here... var doc = reader.GetDocument(mdbg.Document); var mdh = mh.ToDefinitionHandle(); var token = reader.GetToken(mdh); var language = reader.GetGuid(doc.Language); // Note that we're lying here by specifying "cpp" as the language when it is C# in reality // (this is so we get some syntax-highlighting in Sourcetrail) var languageName = language == SymLanguageType.CSharp ? "cpp" : language == SymLanguageType.Basic ? "basic" : "c"; var method = new PdbMethod(token, reader.GetString(doc.Name), languageName); foreach (var sph in mdbg.GetSequencePoints()) { if (sph.IsHidden) { continue; } method.AddSequence(sph.Offset, sph.StartLine, sph.StartColumn, sph.EndLine, sph.EndColumn); } methodsByToken[token] = method; } }
private IReadOnlyList <AssemblyDebugSourceDocument> GetSourceDocuments() { var list = new List <AssemblyDebugSourceDocument>(); foreach (var docHandle in _reader.Documents) { var document = _reader.GetDocument(docHandle); var langGuid = _reader.GetGuid(document.Language); var hashGuid = _reader.GetGuid(document.HashAlgorithm); var docName = _reader.GetString(document.Name).Replace(@"\", @"/"); // use forward slashes for the url var doc = new AssemblyDebugSourceDocument ( docName, _reader.GetBlobBytes(document.Hash), langGuid, hashGuid ); list.Add(doc); if (doc.Language == SymbolLanguage.Unknown) { DiagnosticsClient.TrackEvent("Unknown language Guid", new Dictionary <string, string> { { "LanguageGuid", langGuid.ToString() },
/// <summary> /// Unpacks all files stored in a PortablePDB meta-data. The key in the dictionary is the location of a source file /// on the build machine. The value is the content of the source file itself. /// The function will throw an exception if PortablePDB file is not found or anything else went wrong. /// </summary> /// <param name="pdbFilePath">Path to PortablePDB file to load source files from.</param> public static Dictionary <string, CompressedSourceFile> GetEmbeddedFiles(string pdbFilePath) { Dictionary <string, CompressedSourceFile> embeddedFiles = new Dictionary <string, CompressedSourceFile>(); using (FileStream stream = File.OpenRead(pdbFilePath)) using (MetadataReaderProvider metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(stream)) { MetadataReader metadataReader = metadataReaderProvider.GetMetadataReader(); CustomDebugInformationHandleCollection customDebugInformationHandles = metadataReader.CustomDebugInformation; foreach (var customDebugInformationHandle in customDebugInformationHandles) { CustomDebugInformation customDebugInformation = metadataReader.GetCustomDebugInformation(customDebugInformationHandle); if (metadataReader.GetGuid(customDebugInformation.Kind) == EmbeddedSource) { byte[] embeddedSource = metadataReader.GetBlobBytes(customDebugInformation.Value); Int32 uncompressedSourceFileSize = BitConverter.ToInt32(embeddedSource, 0); if (uncompressedSourceFileSize != 0) { Document document = metadataReader.GetDocument((DocumentHandle)customDebugInformation.Parent); string sourceFileName = System.IO.Path.GetFullPath(metadataReader.GetString(document.Name)); embeddedFiles.Add(sourceFileName, new CompressedSourceFile(embeddedSource)); } } } } return(embeddedFiles); }
public override IEnumerable <ILSequencePoint> GetSequencePointsForMethod(int methodToken) { var debugInformationHandle = ((MethodDefinitionHandle)MetadataTokens.EntityHandle(methodToken)).ToDebugInformationHandle(); var debugInformation = _reader.GetMethodDebugInformation(debugInformationHandle); var sequencePoints = debugInformation.GetSequencePoints(); DocumentHandle previousDocumentHandle = default; string previousDocumentUrl = null; foreach (var sequencePoint in sequencePoints) { if (sequencePoint.StartLine == SequencePoint.HiddenLine) { continue; } string url; if (sequencePoint.Document == previousDocumentHandle) { url = previousDocumentUrl; } else { url = _reader.GetString(_reader.GetDocument(sequencePoint.Document).Name); previousDocumentHandle = sequencePoint.Document; previousDocumentUrl = url; } yield return(new ILSequencePoint(sequencePoint.Offset, url, sequencePoint.StartLine)); } }
private void AddFunctionSourceLines(Function function, SequencePointCollection points, MetadataReader pdbReader) { var slines = new List <SourceLine>(); function.SourceLines = slines; foreach (var p in points) { try { var sname = pdbReader.GetString(pdbReader.GetDocument(p.Document).Name); var plSourceLine = new SourceLine { InternalId = SourceLine.UndefinedSourceLineId, SourceFileIntId = GetSourceFileId(sname), FunctionIntId = function.InternalId, StartLine = (ulong)p.StartLine, StartColumn = (ulong)p.StartColumn, EndLine = (ulong)p.EndLine, EndColumn = (ulong)p.EndColumn, Offset = (uint)p.Offset, Name = sname }; slines.Add(plSourceLine); } catch (Exception) { // Debug.WriteLine(ex.Message); } } }
public void LoadSourceLinks() { SourceLinks = new Dictionary <string, DocumentHandle>(); using (var fileStream = File.OpenRead(FilePath)) { try { var metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(fileStream); MetadataReader = metadataReaderProvider.GetMetadataReader(); foreach (var documentHandle in MetadataReader.Documents) { var document = MetadataReader.GetDocument(documentHandle); var fileLink = MetadataReader.GetString(document.Name); SourceLinks[fileLink] = documentHandle; } } catch (BadImageFormatException exp) { throw new NotSupportedException("The pdb format is not supported.", exp); } } }
private IEnumerable <AssemblyDebugSourceDocument> GetSourceDocuments() { foreach (var dh in _reader.Documents) { if (dh.IsNil) { continue; } var d = _reader.GetDocument(dh); if (d.Name.IsNil || d.Language.IsNil || d.HashAlgorithm.IsNil || d.Hash.IsNil) { continue; } var name = _reader.GetString(d.Name); var language = _reader.GetGuid(d.Language); var hashAlgorithm = _reader.GetGuid(d.HashAlgorithm); var hash = _reader.GetBlobBytes(d.Hash); var isEmbedded = IsEmbedded(dh); var doc = new AssemblyDebugSourceDocument ( name, hash, language, hashAlgorithm, isEmbedded ); if (doc.Language == SymbolLanguage.Unknown) { DiagnosticsClient.TrackEvent("Unknown language Guid", new Dictionary <string, string> { { "LanguageGuid", language.ToString() },
public static bool EmbeddedPortablePdbHasLocalSource(string module) { using (FileStream moduleStream = File.OpenRead(module)) using (var peReader = new PEReader(moduleStream)) { foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb) { using (MetadataReaderProvider embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(entry)) { MetadataReader metadataReader = embeddedMetadataProvider.GetMetadataReader(); foreach (DocumentHandle docHandle in metadataReader.Documents) { Document document = metadataReader.GetDocument(docHandle); string docName = metadataReader.GetString(document.Name); // We verify all docs and return false if not all are present in local // We could have false negative if doc is not a source // Btw check for all possible extension could be weak approach if (!File.Exists(docName)) { return(false); } } } } } } // If we don't have EmbeddedPortablePdb entry return true, for instance empty dll // We should call this method only on embedded pdb module return(true); }
public static void ReadPdbDocuments(string pdbPath) { // Open Portable PDB file using var fs = new FileStream(pdbPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); using MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(fs); MetadataReader reader = provider.GetMetadataReader(); // Display information about documents in each MethodDebugInformation table entry foreach (MethodDebugInformationHandle h in reader.MethodDebugInformation) { MethodDebugInformation mdi = reader.GetMethodDebugInformation(h); if (mdi.Document.IsNil) { continue; } int token = MetadataTokens.GetToken(h); Console.WriteLine($"MethodDebugInformation 0x{token.ToString("X")}"); Document doc = reader.GetDocument(mdi.Document); Console.WriteLine($"File: {ReadDocumentPath(reader, doc)}"); Guid guidLang = reader.GetGuid(doc.Language); Console.WriteLine($"Language: {guidLang}"); Guid guidHashAlg = reader.GetGuid(doc.HashAlgorithm); Console.WriteLine($"Hash algorithm: {guidHashAlg}"); Console.WriteLine(); } }
/// <summary> /// Returns method token and IL offset for given source line number. /// </summary> /// <param name="symbolReaderHandle">symbol reader handle returned by LoadSymbolsForModule</param> /// <param name="filePath">source file name and path</param> /// <param name="lineNumber">source line number</param> /// <param name="methodToken">method token return</param> /// <param name="ilOffset">IL offset return</param> /// <returns> true if information is available</returns> internal static bool ResolveSequencePoint(IntPtr symbolReaderHandle, string filePath, int lineNumber, out int methodToken, out int ilOffset) { Debug.Assert(symbolReaderHandle != IntPtr.Zero); methodToken = 0; ilOffset = 0; GCHandle gch = GCHandle.FromIntPtr(symbolReaderHandle); MetadataReader reader = ((OpenedReader)gch.Target).Reader; try { string fileName = Path.GetFileName(filePath); foreach (MethodDebugInformationHandle methodDebugInformationHandle in reader.MethodDebugInformation) { MethodDebugInformation methodDebugInfo = reader.GetMethodDebugInformation(methodDebugInformationHandle); SequencePointCollection sequencePoints = methodDebugInfo.GetSequencePoints(); foreach (SequencePoint point in sequencePoints) { string sourceName = reader.GetString(reader.GetDocument(point.Document).Name); if (point.StartLine == lineNumber && Path.GetFileName(sourceName) == fileName) { methodToken = MetadataTokens.GetToken(methodDebugInformationHandle.ToDefinitionHandle()); ilOffset = point.Offset; return(true); } } } } catch { } return(false); }
public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDocument) { firstNotFoundDocument = ""; using (var moduleStream = File.OpenRead(module)) using (var peReader = new PEReader(moduleStream)) { foreach (var entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); using FileStream pdbStream = new FileStream(codeViewData.Path, FileMode.Open); using MetadataReaderProvider metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); MetadataReader metadataReader = metadataReaderProvider.GetMetadataReader(); foreach (DocumentHandle docHandle in metadataReader.Documents) { Document document = metadataReader.GetDocument(docHandle); string docName = metadataReader.GetString(document.Name); // We verify all docs and return false if not all are present in local // We could have false negative if doc is not a source // Btw check for all possible extension could be weak approach if (!_fileSystem.Exists(docName)) { firstNotFoundDocument = docName; return(false); } } } } } return(true); }
/// <summary> /// Loads sequence points for the given information handle. /// </summary> /// <param name="readerOperationProvider">The parent reader provider.</param> /// <param name="handle">The source information handle.</param> /// <returns>The array of all sequence points.</returns> private static ImmutableArray <SequencePoint> LoadSequencePoints <TProvider>( TProvider readerOperationProvider, MethodDefinitionHandle handle) where TProvider : IMetadataReaderOperationProvider { using var operation = readerOperationProvider.BeginOperation(); MetadataReader reader = operation.Reader; var debugInformation = reader.GetMethodDebugInformation(handle); // Gather sequence points var result = ImmutableArray.CreateBuilder <SequencePoint>(); foreach (var sequencePoint in debugInformation.GetSequencePoints()) { if (sequencePoint.IsHidden || sequencePoint.Document.IsNil) { continue; } var doc = reader.GetDocument(sequencePoint.Document); result.Add(new SequencePoint( doc.Name.IsNil ? string.Empty : reader.GetString(doc.Name), sequencePoint.Offset, sequencePoint.StartColumn, sequencePoint.EndColumn, sequencePoint.StartLine, sequencePoint.EndLine)); } return(result.ToImmutable()); }
private IReadOnlyList <AssemblyDebugSourceDocument> GetSourceDocuments() { var list = new List <AssemblyDebugSourceDocument>(); foreach (var docHandle in _reader.Documents) { var document = _reader.GetDocument(docHandle); var langGuid = _reader.GetGuid(document.Language); var hashGuid = _reader.GetGuid(document.HashAlgorithm); var docName = _reader.GetString(document.Name).Replace(@"\", @"/"); // use forward slashes for the url try { var doc = new AssemblyDebugSourceDocument ( docName, _reader.GetBlobBytes(document.Hash), langGuid, hashGuid ); list.Add(doc); } catch (ArgumentOutOfRangeException ex) { DiagnosticsClient.TrackException(ex, new Dictionary <string, string> { { "LanguageGuid", langGuid.ToString() },
public void GetSourceLineInfoWithoutCasAssert(string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize, IntPtr inMemoryPdbAddress, int inMemoryPdbSize, int methodToken, int ilOffset, out string sourceFile, out int sourceLine, out int sourceColumn) { sourceFile = null; sourceLine = 0; sourceColumn = 0; try { MetadataReader reader = TryGetReader(assemblyPath, loadedPeAddress, loadedPeSize, inMemoryPdbAddress, inMemoryPdbSize); if (reader == null) { return; } Handle handle = MetadataTokens.Handle(methodToken); if (handle.Kind != HandleKind.MethodDefinition) { return; } MethodDebugInformationHandle methodDebugHandle = ((MethodDefinitionHandle)handle).ToDebugInformationHandle(); MethodDebugInformation methodInfo = reader.GetMethodDebugInformation(methodDebugHandle); if (!methodInfo.SequencePointsBlob.IsNil) { SequencePointCollection sequencePoints = methodInfo.GetSequencePoints(); SequencePoint?bestPointSoFar = null; foreach (SequencePoint point in sequencePoints) { if (point.Offset > ilOffset) { break; } if (point.StartLine != SequencePoint.HiddenLine) { bestPointSoFar = point; } } if (bestPointSoFar.HasValue) { sourceLine = bestPointSoFar.Value.StartLine; sourceColumn = bestPointSoFar.Value.StartColumn; sourceFile = reader.GetString(reader.GetDocument(bestPointSoFar.Value.Document).Name); } } } catch (BadImageFormatException) { // ignore } catch (IOException) { // ignore } }
public IEnumerable <string> GetSourceFileNames() { foreach (var documentHandle in _metadataReader.Documents) { var document = _metadataReader.GetDocument(documentHandle); yield return(_metadataReader.GetString(document.Name)); } }
public DocumentEntry(MetadataReader metadata, bool isEmbedded, DocumentHandle handle) { this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.Document) + metadata.GetTableRowSize(TableIndex.Document) * (MetadataTokens.GetRowNumber(handle) - 1); this.metadata = metadata; this.handle = handle; this.document = metadata.GetDocument(handle); }
private static bool TryMapPortablePdb(Module module, out MetadataReaderProvider metadataReaderProvider) { metadataReaderProvider = null; MetadataReader rd = null; try { metadataReaderProvider = GetMetadataReaderProvider(module); rd = metadataReaderProvider?.GetMetadataReader(); } catch (BadImageFormatException ex) when(ex.Message == "Invalid COR20 header signature.") { TraceSourceLink("no portable PDB found: " + module.FullyQualifiedName); // todo figure out a better way to detect if PDB is portable or classic // https://github.com/dotnet/corefx/blob/06b1365d9881ed26a921490d7edd2d4e4de35565/src/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.cs#L185 } if (rd == null) { metadataReaderProvider?.Dispose(); metadataReaderProvider = null; return(false); } TraceSourceLink("found portable PDB for: " + module.FullyQualifiedName); // https://github.com/dotnet/symreader-portable/blob/d27c08d6015c4716ced790e34233c0219773ab10/src/Microsoft.DiaSymReader.PortablePdb/Utilities/MetadataUtilities.cs var sourceLinkHandles = rd .GetCustomDebugInformation(EntityHandle.ModuleDefinition) .Where(r => !r.IsNil) .Select(rd.GetCustomDebugInformation) .Where(cdi => !cdi.Value.IsNil && rd.GetGuid(cdi.Kind) == SourceLinkId) .ToList(); if (sourceLinkHandles.Count == 0) { metadataReaderProvider?.Dispose(); metadataReaderProvider = null; return(false); } var sourceLinkHandle = sourceLinkHandles.First(); var sourceLink = SourceLink.Deserialize(rd.GetBlobBytes(sourceLinkHandle.Value)); var hinstance = (long)Marshal.GetHINSTANCE(module); foreach (var dh in rd.Documents) { if (dh.IsNil) { continue; } var doc = rd.GetDocument(dh); var file = rd.GetString(doc.Name); SourceMappedPaths[Tuple.Create(hinstance, file)] = sourceLink.GetUrl(file); } return(true); }
/// <summary> /// Helper method to return source line number and source file name for given IL offset and method token. /// </summary> /// <param name="symbolReaderHandle">symbol reader handle returned by LoadSymbolsForModule</param> /// <param name="methodToken">method token</param> /// <param name="ilOffset">IL offset</param> /// <param name="lineNumber">source line number return</param> /// <param name="fileName">source file name return</param> /// <returns> true if information is available</returns> private static bool GetSourceLineByILOffset(IntPtr symbolReaderHandle, int methodToken, long ilOffset, out int lineNumber, out string fileName) { Debug.Assert(symbolReaderHandle != IntPtr.Zero); lineNumber = 0; fileName = null; GCHandle gch = GCHandle.FromIntPtr(symbolReaderHandle); MetadataReader reader = ((OpenedReader)gch.Target).Reader; try { Handle handle = MetadataTokens.Handle(methodToken); if (handle.Kind != HandleKind.MethodDefinition) { return(false); } MethodDebugInformationHandle methodDebugHandle = ((MethodDefinitionHandle)handle).ToDebugInformationHandle(); if (methodDebugHandle.IsNil) { return(false); } MethodDebugInformation methodDebugInfo = reader.GetMethodDebugInformation(methodDebugHandle); SequencePointCollection sequencePoints = methodDebugInfo.GetSequencePoints(); SequencePoint nearestPoint = sequencePoints.GetEnumerator().Current; foreach (SequencePoint point in sequencePoints) { if (point.Offset < ilOffset) { nearestPoint = point; } else { if (point.Offset == ilOffset) { nearestPoint = point; } if (nearestPoint.StartLine == 0 || nearestPoint.StartLine == SequencePoint.HiddenLine) { return(false); } break; } } lineNumber = nearestPoint.StartLine; fileName = reader.GetString(reader.GetDocument(nearestPoint.Document).Name); return(true); } catch { } return(false); }
/// <summary> /// Helper method to return source line number and source file name for given IL offset and method token. /// </summary> /// <param name="openedReader">symbol reader returned by LoadSymbolsForModule</param> /// <param name="methodToken">method token</param> /// <param name="ilOffset">IL offset</param> /// <param name="lineNumber">source line number return</param> /// <param name="fileName">source file name return</param> /// <returns> true if information is available</returns> private bool GetSourceLineByILOffset( OpenedReader openedReader, int methodToken, long ilOffset, out int lineNumber, out string fileName) { lineNumber = 0; fileName = null; MetadataReader reader = openedReader.Reader; try { Handle handle = MetadataTokens.Handle(methodToken); if (handle.Kind != HandleKind.MethodDefinition) { return(false); } MethodDebugInformationHandle methodDebugHandle = ((MethodDefinitionHandle)handle).ToDebugInformationHandle(); if (methodDebugHandle.IsNil) { return(false); } MethodDebugInformation methodDebugInfo = reader.GetMethodDebugInformation(methodDebugHandle); SequencePointCollection sequencePoints = methodDebugInfo.GetSequencePoints(); SequencePoint?nearestPoint = null; foreach (SequencePoint point in sequencePoints) { if (point.Offset > ilOffset) { break; } if (point.StartLine != 0 && !point.IsHidden) { nearestPoint = point; } } if (nearestPoint.HasValue) { lineNumber = nearestPoint.Value.StartLine; fileName = reader.GetString(reader.GetDocument(nearestPoint.Value.Document).Name); return(true); } } catch (Exception ex) { Trace.TraceError($"GetSourceLineByILOffset: {ex.Message}"); } return(false); }
private string GetMethodFileName(MethodDebugInformation methodDebugDefinition) { var fileName = string.Empty; if (!methodDebugDefinition.Document.IsNil) { var document = _reader.GetDocument(methodDebugDefinition.Document); fileName = _reader.GetString(document.Name); } return(fileName); }
static ImmutableArray <string> getNonSourceFileDocumentNames(MetadataReader pdbReader, int sourceFileCount) { var count = pdbReader.Documents.Count - sourceFileCount; var builder = ArrayBuilder <string> .GetInstance(count); foreach (var documentHandle in pdbReader.Documents.Skip(sourceFileCount)) { var document = pdbReader.GetDocument(documentHandle); var name = pdbReader.GetString(document.Name); builder.Add(name); } return(builder.ToImmutableAndFree()); }
public ImmutableArray <SourceDocument> FindSourceDocuments(EntityHandle entityHandle) { var documentHandles = SymbolSourceDocumentFinder.FindDocumentHandles(entityHandle, _dllReader, _pdbReader); using var _ = ArrayBuilder <SourceDocument> .GetInstance(out var sourceDocuments); 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.ToImmutable()); }
private IReadOnlyList <AssemblyDebugSourceDocument> GetSourceDocuments() { var docs = (from docHandle in _reader.Documents let document = _reader.GetDocument(docHandle) select new AssemblyDebugSourceDocument ( _reader.GetString(document.Name).Replace(@"\", @"/"), // use forward slashes for the url _reader.GetBlobBytes(document.Hash), _reader.GetGuid(document.Language), _reader.GetGuid(document.HashAlgorithm) )).ToList(); return(docs); }
public override bool TryGetDocumentChecksum(string documentPath, out ImmutableArray <byte> checksum, out Guid algorithmId) { foreach (var documentHandle in _pdbReader.Documents) { var document = _pdbReader.GetDocument(documentHandle); if (_pdbReader.StringComparer.Equals(document.Name, documentPath)) { checksum = _pdbReader.GetBlobContent(document.Hash); algorithmId = _pdbReader.GetGuid(document.HashAlgorithm); return(true); } } checksum = default; algorithmId = default; return(false); }
/// <summary> /// Loads the requested sequence points. /// </summary> internal void LoadSequencePoints() { if (SequencePoints.Length > 0) { return; } var debugInformation = MetadataReader.GetMethodDebugInformation(DebugInformationHandle); // Gather sequence points var sequencePointsCollection = debugInformation.GetSequencePoints(); var sequencePointEnumerator = sequencePointsCollection.GetEnumerator(); int numSequencePoints; for (numSequencePoints = 0; sequencePointEnumerator.MoveNext();) { var sequencePoint = sequencePointEnumerator.Current; if (sequencePoint.IsHidden || sequencePoint.Document.IsNil) { continue; } ++numSequencePoints; } var sequencePoints = ImmutableArray.CreateBuilder <SequencePoint>(numSequencePoints); sequencePointEnumerator = sequencePointsCollection.GetEnumerator(); while (sequencePointEnumerator.MoveNext()) { var sequencePoint = sequencePointEnumerator.Current; if (sequencePoint.IsHidden || sequencePoint.Document.IsNil) { continue; } var doc = MetadataReader.GetDocument(sequencePoint.Document); sequencePoints.Add(new SequencePoint( doc.Name.IsNil ? string.Empty : MetadataReader.GetString(doc.Name), sequencePoint.Offset, sequencePoint.StartColumn, sequencePoint.EndColumn, sequencePoint.StartLine, sequencePoint.EndLine)); } SequencePoints = sequencePoints.MoveToImmutable(); }
public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDocument) { firstNotFoundDocument = ""; using (var moduleStream = _fileSystem.OpenRead(module)) using (var peReader = new PEReader(moduleStream)) { foreach (var entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); using Stream pdbStream = _fileSystem.OpenRead(_sourceRootTranslator.ResolveFilePath(codeViewData.Path)); using MetadataReaderProvider metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); MetadataReader metadataReader = null; try { metadataReader = metadataReaderProvider.GetMetadataReader(); } catch (BadImageFormatException) { _logger.LogWarning($"{nameof(BadImageFormatException)} during MetadataReaderProvider.FromPortablePdbStream in InstrumentationHelper.PortablePdbHasLocalSource, unable to check if module has got local source."); return(true); } foreach (DocumentHandle docHandle in metadataReader.Documents) { Document document = metadataReader.GetDocument(docHandle); string docName = _sourceRootTranslator.ResolveFilePath(metadataReader.GetString(document.Name)); // We verify all docs and return false if not all are present in local // We could have false negative if doc is not a source // Btw check for all possible extension could be weak approach // We exlude from the check the autogenerated source file(i.e. source generators) if (!_fileSystem.Exists(docName) && !docName.EndsWith(".g.cs")) { firstNotFoundDocument = docName; return(false); } } } } } return(true); }
/// <summary> /// Loads the requested sequence points. /// </summary> internal void LoadSequencePoints() { if (SequencePointArray != null) { return; } var debugInformation = MetadataReader.GetMethodDebugInformation(DebugInformationHandle); // Gather sequence points var sequencePointsCollection = debugInformation.GetSequencePoints(); var sequencePointEnumerator = sequencePointsCollection.GetEnumerator(); int numSequencePoints = 0; for (numSequencePoints = 0; sequencePointEnumerator.MoveNext();) { var sequencePoint = sequencePointEnumerator.Current; if (sequencePoint.IsHidden || sequencePoint.Document.IsNil) { continue; } ++numSequencePoints; } var sequencePoints = new SequencePoint[numSequencePoints]; sequencePointEnumerator = sequencePointsCollection.GetEnumerator(); for (numSequencePoints = 0; sequencePointEnumerator.MoveNext();) { var sequencePoint = sequencePointEnumerator.Current; if (sequencePoint.IsHidden || sequencePoint.Document.IsNil) { continue; } var doc = MetadataReader.GetDocument(sequencePoint.Document); sequencePoints[numSequencePoints++] = new SequencePoint( doc.Name.IsNil ? string.Empty : MetadataReader.GetString(doc.Name), sequencePoint.Offset, sequencePoint.StartColumn, sequencePoint.EndColumn, sequencePoint.StartLine, sequencePoint.EndLine); } SequencePointArray = sequencePoints; }
public bool PortablePdbHasLocalSource(string module, out string firstNotFoundDocument) { firstNotFoundDocument = ""; using (var moduleStream = _fileSystem.OpenRead(module)) using (var peReader = new PEReader(moduleStream)) { foreach (var entry in peReader.ReadDebugDirectory()) { if (entry.Type == DebugDirectoryEntryType.CodeView) { var codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry); using Stream pdbStream = _fileSystem.OpenRead(codeViewData.Path); using MetadataReaderProvider metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(pdbStream); MetadataReader metadataReader = null; try { metadataReader = metadataReaderProvider.GetMetadataReader(); } catch (BadImageFormatException) { // TODO log this to warning // In case of non portable pdb we get exception so we skip file sources check return(true); } foreach (DocumentHandle docHandle in metadataReader.Documents) { Document document = metadataReader.GetDocument(docHandle); string docName = metadataReader.GetString(document.Name); // We verify all docs and return false if not all are present in local // We could have false negative if doc is not a source // Btw check for all possible extension could be weak approach if (!_fileSystem.Exists(docName)) { firstNotFoundDocument = docName; return(false); } } } } } return(true); }