Beispiel #1
0
        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);
        }
Beispiel #2
0
 /// <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);
 }
Beispiel #3
0
 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() },
Beispiel #5
0
        /// <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);
        }
Beispiel #6
0
        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);
                }
            }
        }
Beispiel #8
0
        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);
        }
Beispiel #11
0
        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();
            }
        }
Beispiel #12
0
        /// <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);
        }
Beispiel #13
0
        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);
        }
Beispiel #14
0
        /// <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());
        }
Beispiel #15
0
        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() },
Beispiel #16
0
        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));
     }
 }
Beispiel #18
0
 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);
 }
Beispiel #19
0
        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);
        }
Beispiel #20
0
        /// <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);
        }
Beispiel #22
0
        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);
        }
Beispiel #23
0
            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());
            }
Beispiel #24
0
        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;
        }
Beispiel #30
0
        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);
        }