コード例 #1
0
        public IList <Decompiler.DebugInfo.SequencePoint> GetSequencePoints(MethodDefinitionHandle method)
        {
            var metadata       = provider.GetMetadataReader();
            var debugInfo      = metadata.GetMethodDebugInformation(method);
            var sequencePoints = new List <Decompiler.DebugInfo.SequencePoint>();

            foreach (var point in debugInfo.GetSequencePoints())
            {
                string documentFileName;

                if (!point.Document.IsNil)
                {
                    var document = metadata.GetDocument(point.Document);
                    documentFileName = metadata.GetString(document.Name);
                }
                else
                {
                    documentFileName = "";
                }

                sequencePoints.Add(new Decompiler.DebugInfo.SequencePoint()
                {
                    Offset      = point.Offset,
                    StartLine   = point.StartLine,
                    StartColumn = point.StartColumn,
                    EndLine     = point.EndLine,
                    EndColumn   = point.EndColumn,
                    DocumentUrl = documentFileName
                });
            }

            return(sequencePoints);
        }
コード例 #2
0
        /// <summary>
        /// Returns the portable PDB reader for the assembly path
        /// </summary>
        /// <param name="assemblyPath">file path of the assembly or null</param>
        /// <param name="loadedPeAddress">loaded PE image address or zero</param>
        /// <param name="loadedPeSize">loaded PE image size</param>
        /// <param name="inMemoryPdbAddress">in memory PDB address or zero</param>
        /// <param name="inMemoryPdbSize">in memory PDB size</param>
        /// <param name="reader">returns the reader</param>
        /// <returns>reader</returns>
        private MetadataReader GetReader(string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize, IntPtr inMemoryPdbAddress, int inMemoryPdbSize)
        {
            if (loadedPeAddress != IntPtr.Zero)
            {
                Tuple <MetadataReaderProvider, MetadataReader> tuple;
                if (_readerCache.TryGetValue(loadedPeAddress, out tuple))
                {
                    return(tuple.Item2);
                }
            }

            MetadataReaderProvider provider = null;
            MetadataReader         reader   = null;

            if (assemblyPath != null)
            {
                uint stamp;
                int  age;
                Guid guid;

                string pdbName = GetPdbPathFromPeStream(assemblyPath, loadedPeAddress, loadedPeSize, out age, out guid, out stamp);
                if (pdbName != null && File.Exists(pdbName))
                {
                    Stream pdbStream = File.OpenRead(pdbName);

                    provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
                    MetadataReader rdr = provider.GetMetadataReader();

                    // Validate that the PDB matches the assembly version
                    if (age == 1 && IdEquals(rdr.DebugMetadataHeader.Id, guid, stamp))
                    {
                        reader = rdr;
                    }
                    else
                    {
                        provider.Dispose();
                        provider = null;
                    }
                }
            }
            else if (inMemoryPdbAddress != IntPtr.Zero && inMemoryPdbSize > 0)
            {
                unsafe
                {
                    provider = MetadataReaderProvider.FromPortablePdbImage((byte *)inMemoryPdbAddress.ToPointer(), inMemoryPdbSize);
                    reader   = provider.GetMetadataReader();
                }
            }

            if (reader != null && loadedPeAddress != IntPtr.Zero)
            {
                _readerCache.Add(loadedPeAddress, Tuple.Create(provider, reader));
            }

            return(reader);
        }
コード例 #3
0
        private unsafe static OpenedReader TryOpenReaderForInMemoryPdb(IntPtr inMemoryPdbAddress, int inMemoryPdbSize)
        {
            Debug.Assert(inMemoryPdbAddress != IntPtr.Zero);

            // quick check to avoid throwing exceptions below in common cases:
            const uint ManagedMetadataSignature = 0x424A5342;

            if (inMemoryPdbSize < sizeof(uint) || *(uint *)inMemoryPdbAddress != ManagedMetadataSignature)
            {
                // not a Portable PDB
                return(null);
            }

            OpenedReader           result   = null;
            MetadataReaderProvider provider = null;

            try
            {
                provider = MetadataReaderProvider.FromMetadataImage((byte *)inMemoryPdbAddress, inMemoryPdbSize);
                result   = new OpenedReader(provider, provider.GetMetadataReader());
            }
            catch (BadImageFormatException)
            {
                return(null);
            }
            finally
            {
                if (result == null)
                {
                    provider?.Dispose();
                }
            }

            return(result);
        }
コード例 #4
0
        /// <summary>
        /// Constructs new assembly debug information.
        /// </summary>
        /// <param name="assembly">The referenced assembly.</param>
        /// <param name="fileName">The associated PDB file.</param>
        internal AssemblyDebugInformation(Assembly assembly, string fileName)
        {
            Assembly = assembly;
            modules  = assembly.GetModules();

            using (var pdbFileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
            {
                metadataReaderProvider = MetadataReaderProvider.FromPortablePdbStream(
                    pdbFileStream,
                    MetadataStreamOptions.PrefetchMetadata);
                MetadataReader = metadataReaderProvider.GetMetadataReader();
            }

            var methodDebugInformationEnumerator = MetadataReader.MethodDebugInformation.GetEnumerator();

            while (methodDebugInformationEnumerator.MoveNext())
            {
                var methodDebugRef         = methodDebugInformationEnumerator.Current;
                var methodDefinitionHandle = methodDebugRef.ToDefinitionHandle();
                var metadataToken          = MetadataTokens.GetToken(methodDefinitionHandle);
                if (TryResolveMethod(metadataToken, out MethodBase method))
                {
                    debugInformation.Add(method, new MethodDebugInformation(this, method, methodDebugRef));
                }
            }
        }
コード例 #5
0
        public bool EmbeddedPortablePdbHasLocalSource(string module, out string firstNotFoundDocument)
        {
            firstNotFoundDocument = "";
            using (Stream moduleStream = _fileSystem.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();

                                var matchingResult = MatchDocumentsWithSources(metadataReader);

                                if (!matchingResult.allDocumentsMatch)
                                {
                                    firstNotFoundDocument = matchingResult.notFoundDocument;
                                    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);
        }
コード例 #6
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);
        }
コード例 #7
0
        /// <summary>
        /// Constructs new assembly debug information.
        /// </summary>
        /// <param name="assembly">The referenced assembly.</param>
        /// <param name="pdbStream">
        /// The associated PDB stream (hast to be kept open).
        /// </param>
        internal AssemblyDebugInformation(Assembly assembly, Stream pdbStream)
        {
            Assembly = assembly;
            Modules  = ImmutableArray.Create(assembly.GetModules());

            readerProvider = MetadataReaderProvider.FromPortablePdbStream(
                pdbStream,
                MetadataStreamOptions.Default);
            MetadataReader = readerProvider.GetMetadataReader();

            foreach (var methodHandle in MetadataReader.MethodDebugInformation)
            {
                var definitionHandle = methodHandle.ToDefinitionHandle();
                var metadataToken    = MetadataTokens.GetToken(definitionHandle);
                if (TryResolveMethod(metadataToken, out MethodBase method))
                {
                    debugInformation.Add(
                        method,
                        new MethodDebugInformation(
                            this,
                            method,
                            definitionHandle));
                }
            }
        }
コード例 #8
0
        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);
        }
コード例 #9
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();
            }
        }
コード例 #10
0
ファイル: PEReaderTests.cs プロジェクト: pgovind/runtime
        public unsafe void TryOpenAssociatedPortablePdb_EmbeddedUnused()
        {
            var peStream = new MemoryStream(PortablePdbs.DocumentsEmbeddedDll);

            using (var reader = new PEReader(peStream))
            {
                using (MetadataReaderProvider embeddedProvider = reader.ReadEmbeddedPortablePdbDebugDirectoryData(reader.ReadDebugDirectory()[2]))
                {
                    var embeddedReader = embeddedProvider.GetMetadataReader();
                    var embeddedBytes  = new BlobReader(embeddedReader.MetadataPointer, embeddedReader.MetadataLength).ReadBytes(embeddedReader.MetadataLength);

                    string pathQueried = null;

                    Func <string, Stream> streamProvider = p =>
                    {
                        Assert.Null(pathQueried);
                        pathQueried = p;
                        return(new MemoryStream(embeddedBytes));
                    };

                    MetadataReaderProvider pdbProvider;
                    string pdbPath;

                    Assert.True(reader.TryOpenAssociatedPortablePdb(Path.Combine("pedir", "file.exe"), streamProvider, out pdbProvider, out pdbPath));
                    Assert.Equal(Path.Combine("pedir", "Documents.Embedded.pdb"), pathQueried);

                    Assert.Equal(Path.Combine("pedir", "Documents.Embedded.pdb"), pdbPath);
                    var pdbReader = pdbProvider.GetMetadataReader();
                    Assert.Equal(13, pdbReader.Documents.Count);
                }
            }
        }
コード例 #11
0
        partial void TryOpenEmbeddedPortablePdb(DebugDirectoryEntry embeddedPdbEntry, ref bool openedEmbeddedPdb, ref MetadataReaderProvider provider, ref Exception errorToReport)
        {
            provider = null;
            MetadataReaderProvider candidate = null;

            try
            {
                candidate = ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdbEntry);

                // throws if headers are invalid:
                candidate.GetMetadataReader();

                provider          = candidate;
                openedEmbeddedPdb = true;
                return;
            }
            catch (Exception e) when(e is BadImageFormatException || e is IOException)
            {
                errorToReport     = errorToReport ?? e;
                openedEmbeddedPdb = false;
            }
            finally
            {
                if (candidate == null)
                {
                    candidate?.Dispose();
                }
            }
        }
コード例 #12
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);
        }
コード例 #13
0
        public override IEnumerable <SymbolStoreKey> GetKeys(KeyTypeFlags flags)
        {
            if ((flags & KeyTypeFlags.IdentityKey) != 0)
            {
                SymbolStoreKey key = null;

                try
                {
                    _file.Stream.Position = 0;
                    using (MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(_file.Stream, MetadataStreamOptions.LeaveOpen))
                    {
                        MetadataReader reader = provider.GetMetadataReader();
                        var            blob   = new BlobContentId(reader.DebugMetadataHeader.Id);
                        if ((flags & KeyTypeFlags.ForceWindowsPdbs) == 0)
                        {
                            key = GetKey(_file.FileName, blob.Guid);
                        }
                        else
                        {
                            // Force the Windows PDB index
                            key = PDBFileKeyGenerator.GetKey(_file.FileName, blob.Guid, 1);
                        }
                    }
                }
                catch (BadImageFormatException ex)
                {
                    Tracer.Warning("PortablePDBFileKeyGenerator {0}", ex.Message);
                }

                if (key != null)
                {
                    yield return(key);
                }
            }
        }
コード例 #14
0
        private static OpenedReader TryOpenReaderFromEmbeddedPdb(PEReader peReader, DebugDirectoryEntry embeddedPdbEntry)
        {
            OpenedReader           result   = null;
            MetadataReaderProvider provider = null;

            try
            {
                // TODO: We might want to cache this provider globally (across stack traces),
                // since decompressing embedded PDB takes some time.
                provider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdbEntry);
                result   = new OpenedReader(provider, provider.GetMetadataReader());
            }
            catch (Exception e) when(e is BadImageFormatException || e is IOException)
            {
                return(null);
            }
            finally
            {
                if (result == null)
                {
                    provider?.Dispose();
                }
            }

            return(result);
        }
コード例 #15
0
        private static OpenedReader TryOpenReaderFromCodeView(PEReader peReader, DebugDirectoryEntry codeViewEntry, string assemblyPath)
        {
            OpenedReader           result   = null;
            MetadataReaderProvider provider = null;

            try
            {
                CodeViewDebugDirectoryData data = peReader.ReadCodeViewDebugDirectoryData(codeViewEntry);
                string pdbPath   = data.Path;
                Stream pdbStream = null;

                if (assemblyPath != null)
                {
                    try
                    {
                        pdbPath = Path.Combine(Path.GetDirectoryName(assemblyPath), GetFileName(pdbPath));
                    }
                    catch
                    {
                        // invalid characters in CodeView path
                        return(null);
                    }
                    pdbStream = TryOpenFile(pdbPath);
                }

                if (pdbStream == null)
                {
                    if (s_symbolStore == null)
                    {
                        return(null);
                    }
                    Debug.Assert(codeViewEntry.MinorVersion == ImageDebugDirectory.PortablePDBMinorVersion);
                    SymbolStoreKey key = PortablePDBFileKeyGenerator.GetKey(pdbPath, data.Guid);
                    pdbStream = GetSymbolStoreFile(key)?.Stream;
                }

                provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
                MetadataReader reader = provider.GetMetadataReader();

                // Validate that the PDB matches the assembly version
                if (data.Age == 1 && new BlobContentId(reader.DebugMetadataHeader.Id) == new BlobContentId(data.Guid, codeViewEntry.Stamp))
                {
                    result = new OpenedReader(provider, reader);
                }
            }
            catch (Exception e) when(e is BadImageFormatException || e is IOException)
            {
                return(null);
            }
            finally
            {
                if (result == null)
                {
                    provider?.Dispose();
                }
            }

            return(result);
        }
コード例 #16
0
        public DocumentDebugInfoReader(PEReader peReader, MetadataReaderProvider pdbReaderProvider)
        {
            _peReader          = peReader;
            _pdbReaderProvider = pdbReaderProvider;

            _dllReader = _peReader.GetMetadataReader();
            _pdbReader = _pdbReaderProvider.GetMetadataReader();
        }
コード例 #17
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);
        }
コード例 #18
0
        public AssemblyDebugParser(MetadataReaderProvider readerProvider, PdbType pdbType)
        {
            _readerProvider = readerProvider;
            _pdbType        = pdbType;

            // Possible BadImageFormatException if a full PDB is passed
            // in. We'll let the throw bubble up to something that can handle it
            _reader = _readerProvider.GetMetadataReader();
        }
コード例 #19
0
        public PdbDebugInfoProvider(Stream symbolStream)
        {
            if (symbolStream is null)
            {
                throw new ArgumentNullException(nameof(symbolStream));
            }

            this._readerProvider = MetadataReaderProvider.FromPortablePdbStream(symbolStream);
            this._reader         = _readerProvider.GetMetadataReader();
        }
コード例 #20
0
ファイル: PEReader.cs プロジェクト: dox0/DotNet471RS3
        private bool TryOpenPortablePdbFile(string path, BlobContentId id, Func <string, Stream> pdbFileStreamProvider, out MetadataReaderProvider provider, ref Exception errorToReport)
        {
            provider = null;
            MetadataReaderProvider candidate = null;

            try
            {
                Stream pdbStream;

                try
                {
                    pdbStream = pdbFileStreamProvider(path);
                }
                catch (FileNotFoundException)
                {
                    // Not an unexpected IO exception, continue witout reporting the error.
                    pdbStream = null;
                }

                if (pdbStream == null)
                {
                    return(false);
                }

                if (!pdbStream.CanRead || !pdbStream.CanSeek)
                {
                    throw new InvalidOperationException("StreamMustSupportReadAndSeek");
                }

                candidate = MetadataReaderProvider.FromPortablePdbStream(pdbStream);

                // Validate that the PDB matches the assembly version
                if (new BlobContentId(candidate.GetMetadataReader().DebugMetadataHeader.Id) != id)
                {
                    return(false);
                }

                provider = candidate;
                return(true);
            }
            catch (Exception e) when(e is BadImageFormatException || e is IOException)
            {
                errorToReport = errorToReport ?? e;
                return(false);
            }
            finally
            {
                if (provider == null)
                {
                    candidate?.Dispose();
                }
            }
        }
コード例 #21
0
        private static OpenedReader TryOpenReaderFromCodeView(PEReader peReader, DebugDirectoryEntry codeViewEntry, string assemblyPath)
        {
            OpenedReader           result   = null;
            MetadataReaderProvider provider = null;

            try
            {
                var data = peReader.ReadCodeViewDebugDirectoryData(codeViewEntry);

                string pdbPath = data.Path;
                if (assemblyPath != null)
                {
                    try
                    {
                        pdbPath = Path.Combine(Path.GetDirectoryName(assemblyPath), Path.GetFileName(pdbPath));
                    }
                    catch
                    {
                        // invalid characters in CodeView path
                        return(null);
                    }
                }

                var pdbStream = TryOpenFile(pdbPath);
                if (pdbStream == null)
                {
                    return(null);
                }

                provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
                var reader = provider.GetMetadataReader();

                // Validate that the PDB matches the assembly version
                if (data.Age == 1 && new BlobContentId(reader.DebugMetadataHeader.Id) == new BlobContentId(data.Guid, codeViewEntry.Stamp))
                {
                    result = new OpenedReader(provider, reader);
                }
            }
            catch (Exception e) when(e is BadImageFormatException || e is IOException)
            {
                return(null);
            }
            finally
            {
                if (result == null)
                {
                    provider?.Dispose();
                }
            }

            return(result);
        }
コード例 #22
0
        /// <summary>
        /// Returns the portable PDB reader for the portable PDB stream
        /// </summary>
        /// <param name="pdbStream">portable PDB memory or file stream</param>
        /// <returns>symbol file or null</returns>
        /// <remarks>
        /// Assumes that the PDB loaded into memory can be unloaded or moved around.
        /// </remarks>
        public ISymbolFile OpenSymbolFile(Stream pdbStream)
        {
            if (pdbStream != null)
            {
                throw new ArgumentNullException(nameof(pdbStream));
            }
            if (!pdbStream.CanSeek)
            {
                throw new ArgumentException(nameof(pdbStream));
            }

            byte[] buffer = new byte[sizeof(uint)];
            pdbStream.Position = 0;
            if (pdbStream.Read(buffer, 0, sizeof(uint)) != sizeof(uint))
            {
                return(null);
            }
            uint signature = BitConverter.ToUInt32(buffer, 0);

            // quick check to avoid throwing exceptions below in common cases:
            const uint ManagedMetadataSignature = 0x424A5342;

            if (signature != ManagedMetadataSignature)
            {
                // not a Portable PDB
                return(null);
            }

            SymbolFile             result   = null;
            MetadataReaderProvider provider = null;

            try
            {
                pdbStream.Position = 0;
                provider           = MetadataReaderProvider.FromPortablePdbStream(pdbStream);
                result             = new SymbolFile(provider, provider.GetMetadataReader());
            }
            catch (Exception e) when(e is BadImageFormatException || e is IOException)
            {
                return(null);
            }
            finally
            {
                if (result == null)
                {
                    provider?.Dispose();
                }
            }

            return(result);
        }
コード例 #23
0
        public AssemblyDebugParser(MetadataReaderProvider readerProvider, PdbType pdbType)
        {
            _readerProvider = readerProvider;
            _pdbType        = pdbType;

            try
            {
                _reader = _readerProvider.GetMetadataReader();
            }
            catch (BadImageFormatException) // A Full PDB
            {
                _pdbType = PdbType.Full;
            }
        }
コード例 #24
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbFile"/> class.
        /// </summary>
        /// <param name="file">File loaded into memory for faster parsing.</param>
        public unsafe EmbeddedPdbFile(MemoryLoadedFile file)
        {
            PEReader peReader         = new PEReader(file.BasePointer, (int)file.Length);
            var      debugEntries     = peReader.ReadDebugDirectory();
            var      embeddedPdbEntry = debugEntries.FirstOrDefault(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb);

            if (embeddedPdbEntry.DataSize == 0)
            {
                throw new Exception("PDB wasn't embedded");
            }
            embeddedPdbReaderProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdbEntry);
            PdbFile   = new PdbFile(embeddedPdbReaderProvider.GetMetadataReader());
            this.file = file;
        }
コード例 #25
0
        //<SnippetReadSourceLineData>
        public static void ReadSourceLineData(string pdbPath, int methodToken)
        {
            // Determine method row number
            EntityHandle ehMethod = MetadataTokens.EntityHandle(methodToken);

            if (ehMethod.Kind != HandleKind.MethodDefinition)
            {
                Console.WriteLine($"Invalid token kind: {ehMethod.Kind}");
                return;
            }

            int rowNumber = MetadataTokens.GetRowNumber(ehMethod);

            // MethodDebugInformation table is indexed by same row numbers as MethodDefinition table
            MethodDebugInformationHandle hDebug = MetadataTokens.MethodDebugInformationHandle(rowNumber);

            // 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();

            if (rowNumber > reader.MethodDebugInformation.Count)
            {
                Console.WriteLine("Error: Method row number is out of range");
                return;
            }

            // Print source line information as console table
            MethodDebugInformation di = reader.GetMethodDebugInformation(hDebug);

            Console.WriteLine("IL offset | Start line | Start col. | End line | End col. |");

            foreach (SequencePoint sp in di.GetSequencePoints())
            {
                if (sp.IsHidden)
                {
                    Console.WriteLine($"{sp.Offset.ToString().PadLeft(9)} | (hidden sequence point)");
                }
                else
                {
                    Console.WriteLine("{0} |{1} |{2} |{3} |{4} |",
                                      sp.Offset.ToString().PadLeft(9),
                                      sp.StartLine.ToString().PadLeft(11),
                                      sp.StartColumn.ToString().PadLeft(11),
                                      sp.EndLine.ToString().PadLeft(9),
                                      sp.EndColumn.ToString().PadLeft(9));
                }
            }
        }
コード例 #26
0
        private void ValidateEmbeddedPortablePdb(PEReader reader)
        {
            var entries = reader.ReadDebugDirectory();

            Assert.Equal(DebugDirectoryEntryType.CodeView, entries[0].Type);
            Assert.Equal(DebugDirectoryEntryType.Reproducible, entries[1].Type);
            Assert.Equal(DebugDirectoryEntryType.EmbeddedPortablePdb, entries[2].Type);

            using (MetadataReaderProvider provider = reader.ReadEmbeddedPortablePdbDebugDirectoryData(entries[2]))
            {
                var pdbReader = provider.GetMetadataReader();
                var document  = pdbReader.GetDocument(pdbReader.Documents.First());
                Assert.Equal(@"C:\Documents.cs", pdbReader.GetString(document.Name));
            }
        }
コード例 #27
0
        public static PdbSymbolReader TryOpenEmbedded(PEReader peReader, MetadataStringDecoder stringDecoder)
        {
            foreach (DebugDirectoryEntry debugEntry in peReader.ReadDebugDirectory())
            {
                if (debugEntry.Type != DebugDirectoryEntryType.EmbeddedPortablePdb)
                {
                    continue;
                }

                MetadataReaderProvider embeddedReaderProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(debugEntry);
                MetadataReader         reader = embeddedReaderProvider.GetMetadataReader(MetadataReaderOptions.Default, stringDecoder);
                return(new PortablePdbSymbolReader(reader, mappedViewAccessor: null));
            }

            return(null);
        }
コード例 #28
0
 public override bool IsValid()
 {
     try
     {
         _file.Stream.Position = 0;
         using (MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(_file.Stream, MetadataStreamOptions.LeaveOpen))
         {
             MetadataReader reader = provider.GetMetadataReader();
             return(true);
         }
     }
     catch (BadImageFormatException)
     {
     }
     return(false);
 }
コード例 #29
0
 internal MetadataReader?GetMetadataReader()
 {
     try
     {
         hasError = false;
         return(provider.GetMetadataReader());
     }
     catch (BadImageFormatException)
     {
         hasError = true;
         return(null);
     }
     catch (IOException)
     {
         hasError = true;
         return(null);
     }
 }
コード例 #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(_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);
        }
コード例 #31
0
        private unsafe void TestGetMetadataReader(MetadataReaderProvider provider)
        {
            var decoder = new TestMetadataStringDecoder(Encoding.UTF8, (a, b) => "str");

            var reader1 = provider.GetMetadataReader(MetadataReaderOptions.None, decoder);
            Assert.Equal("str", reader1.MetadataVersion);
            Assert.Same(reader1.Utf8Decoder, decoder);
            Assert.Equal(reader1.Options, MetadataReaderOptions.None);

            var reader2 = provider.GetMetadataReader(MetadataReaderOptions.None, decoder);
            Assert.Same(reader1, reader2);

            var reader3 = provider.GetMetadataReader(MetadataReaderOptions.None);
            Assert.NotSame(reader2, reader3);
            Assert.Equal("v9.9.9.9", reader3.MetadataVersion);
            Assert.Same(reader3.Utf8Decoder, MetadataStringDecoder.DefaultUTF8);
            Assert.Equal(reader3.Options, MetadataReaderOptions.None);

            var reader4 = provider.GetMetadataReader(MetadataReaderOptions.None);
            Assert.Same(reader3, reader4);

            var reader5 = provider.GetMetadataReader(MetadataReaderOptions.ApplyWindowsRuntimeProjections);
            Assert.NotSame(reader4, reader5);
            Assert.Equal("v9.9.9.9", reader5.MetadataVersion);
            Assert.Same(reader5.Utf8Decoder, MetadataStringDecoder.DefaultUTF8);
            Assert.Equal(reader5.Options, MetadataReaderOptions.ApplyWindowsRuntimeProjections);

            provider.Dispose();
            Assert.Throws<ObjectDisposedException>(() => provider.GetMetadataReader(MetadataReaderOptions.ApplyWindowsRuntimeProjections));
            Assert.Throws<ObjectDisposedException>(() => provider.GetMetadataReader());
        }