Example #1
0
        /// <summary>
        /// Read the pdb file name and assembly version information from the PE file.
        /// </summary>
        /// <param name="assemblyPath">PE file path</param>
        /// <param name="loadedPeAddress">loaded PE image address or zero</param>
        /// <param name="loadedPeSize">loaded PE image size</param>
        /// <param name="age">age</param>
        /// <param name="guid">assembly guid</param>
        /// <param name="stamp">time stamp</param>
        /// <returns>pdb name or null</returns>
        /// <remarks>
        /// loadedPeAddress and loadedPeSize will be used here when/if the PEReader
        /// support runtime loaded images instead of just file images.
        /// </remarks>
        private static unsafe string GetPdbPathFromPeStream(string assemblyPath, IntPtr loadedPeAddress, int loadedPeSize, out int age, out Guid guid, out uint stamp)
        {
            if (File.Exists(assemblyPath))
            {
                Stream peStream = File.OpenRead(assemblyPath);

                using (PEReader peReader = new PEReader(peStream))
                {
                    foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory())
                    {
                        if (entry.Type == DebugDirectoryEntryType.CodeView)
                        {
                            CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);

                            stamp = entry.Stamp;
                            age   = codeViewData.Age;
                            guid  = codeViewData.Guid;

                            string peDirectory = Path.GetDirectoryName(assemblyPath);
                            return(Path.Combine(peDirectory, Path.GetFileName(codeViewData.Path)));
                        }
                    }
                }
            }

            stamp = 0;
            age   = 0;
            guid  = new Guid();
            return(null);
        }
        private bool TryReadCodeViewData(string peFilePath, out CodeViewDebugDirectoryData codeViewData, out uint stamp)
        {
            try
            {
                var peStream = PortableShim.FileStream.CreateReadShareDelete(peFilePath);
                using (var peReader = new PEReader(peStream))
                {
                    foreach (var entry in peReader.ReadDebugDirectory())
                    {
                        if (entry.Type == DebugDirectoryEntryType.CodeView)
                        {
                            codeViewData = peReader.ReadCodeViewDebugDirectoryData(entry);
                            stamp        = entry.Stamp;
                            return(true);
                        }
                    }
                }
            }
            catch
            {
            }

            codeViewData = default(CodeViewDebugDirectoryData);
            stamp        = 0;
            return(false);
        }
Example #3
0
        private static void PrintAssemblyInfo(string dll)
        {
            var debugDirectory = PdbInfo.ReadDebugDirectoryEntries(dll);

            foreach (var debugDirectoryEntry in debugDirectory)
            {
                PrintNameValue("Debug directory entry", debugDirectoryEntry.entry.Type.ToString());
                if (debugDirectoryEntry.entry.Type == DebugDirectoryEntryType.CodeView)
                {
                    CodeViewDebugDirectoryData data = (CodeViewDebugDirectoryData)debugDirectoryEntry.data;
                    PrintNameValue("Guid", data.Guid.ToString());
                    PrintNameValue("Age", data.Age.ToString());
                    PrintNameValue("Pdb path", data.Path.ToString());
                    PrintNameValue("Stamp", debugDirectoryEntry.entry.Stamp.ToString("X8"));
                }

                Console.WriteLine();
            }

            var pdb = Path.ChangeExtension(dll, ".pdb");

            if (File.Exists(pdb))
            {
                Console.WriteLine("Found " + Path.GetFileName(pdb) + ":");
                CheckMatch(dll, pdb);
            }
        }
Example #4
0
        private bool TryReadCodeViewData(string peFilePath, out CodeViewDebugDirectoryData codeViewData, out uint stamp)
        {
            try
            {
                var peStream = PortableShim.File.OpenRead(peFilePath);
                using (var peReader = new PEReader(peStream))
                {
                    foreach (var entry in PEUtilities.ReadDebugDirectory(peReader, peStream))
                    {
                        if (entry.EntryType == DebugDirectoryEntryType.CodeView)
                        {
                            codeViewData = PEUtilities.ReadCodeViewDebugDirectoryData(peStream, entry);
                            stamp        = entry.Stamp;
                            return(true);
                        }
                    }
                }
            }
            catch
            {
            }

            codeViewData = default(CodeViewDebugDirectoryData);
            stamp        = 0;
            return(false);
        }
Example #5
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);
        }
        public async Task <PdbFilePathResult?> GetPdbFilePathAsync(string dllPath, PEReader peReader, bool useDefaultSymbolServers, CancellationToken cancellationToken)
        {
            var  hasCodeViewEntry = false;
            uint timeStamp        = 0;
            CodeViewDebugDirectoryData codeViewEntry = default;

            using var _ = ArrayBuilder <PdbChecksum> .GetInstance(out var checksums);

            foreach (var entry in peReader.ReadDebugDirectory())
            {
                if (entry.Type == DebugDirectoryEntryType.PdbChecksum)
                {
                    var checksum = peReader.ReadPdbChecksumDebugDirectoryData(entry);
                    checksums.Add(new PdbChecksum(checksum.AlgorithmName, checksum.Checksum));
                }
                else if (entry.Type == DebugDirectoryEntryType.CodeView && entry.IsPortableCodeView)
                {
                    hasCodeViewEntry = true;
                    timeStamp        = entry.Stamp;
                    codeViewEntry    = peReader.ReadCodeViewDebugDirectoryData(entry);
                }
            }

            if (!hasCodeViewEntry)
            {
                return(null);
            }

            var pdbInfo = new SymbolLocatorPdbInfo(
                Path.GetFileName(codeViewEntry.Path),
                codeViewEntry.Guid,
                (uint)codeViewEntry.Age,
                timeStamp,
                checksums.ToImmutable(),
                dllPath,
                codeViewEntry.Path);

            var flags = useDefaultSymbolServers
                ? SymbolLocatorSearchFlags.ForceNuGetSymbolServer | SymbolLocatorSearchFlags.ForceMsftSymbolServer
                : SymbolLocatorSearchFlags.None;
            var result = await _debuggerSymbolLocatorService.LocateSymbolFileAsync(pdbInfo, flags, progress : null, cancellationToken).ConfigureAwait(false);

            if (result.Found && result.SymbolFilePath is not null)
            {
                return(new PdbFilePathResult(result.SymbolFilePath));
            }
            else if (_logger is not null)
            {
                // We log specific info from the debugger if there is a failure, but the caller will log general failure
                // information otherwise
                _logger.Log(result.Status);
                _logger.Log(result.Log);
            }

            return(null);
        }
Example #7
0
        //
        // Symbols
        //

        private PdbSymbolReader OpenAssociatedSymbolFile(string peFilePath, PEReader peReader)
        {
            string        pdbFileName  = null;
            BlobContentId pdbContentId = default;

            foreach (DebugDirectoryEntry debugEntry in peReader.ReadDebugDirectory())
            {
                if (debugEntry.Type != DebugDirectoryEntryType.CodeView)
                {
                    continue;
                }

                CodeViewDebugDirectoryData debugDirectoryData = peReader.ReadCodeViewDebugDirectoryData(debugEntry);

                string candidatePath = debugDirectoryData.Path;
                if (!Path.IsPathRooted(candidatePath) || !File.Exists(candidatePath))
                {
                    // Also check next to the PE file
                    candidatePath = Path.Combine(Path.GetDirectoryName(peFilePath), Path.GetFileName(candidatePath));
                    if (!File.Exists(candidatePath))
                    {
                        continue;
                    }
                }

                pdbFileName  = candidatePath;
                pdbContentId = new BlobContentId(debugDirectoryData.Guid, debugEntry.Stamp);
                break;
            }

            if (pdbFileName == null)
            {
                return(null);
            }

            // Try to open the symbol file as portable pdb first
            PdbSymbolReader reader = PortablePdbSymbolReader.TryOpen(pdbFileName, GetMetadataStringDecoder(), pdbContentId);

            if (reader == null)
            {
                // Fallback to the diasymreader for non-portable pdbs
                reader = UnmanagedPdbSymbolReader.TryOpenSymbolReaderForMetadataFile(peFilePath, Path.GetDirectoryName(pdbFileName));
            }

            return(reader);
        }
Example #8
0
        public unsafe AssemblyInfo(MonoProxy monoProxy, SessionId sessionId, string url, byte[] assembly, byte[] pdb, CancellationToken token)
        {
            debugId             = -1;
            this.id             = Interlocked.Increment(ref next_id);
            using var asmStream = new MemoryStream(assembly);
            peReader            = new PEReader(asmStream);
            var entries = peReader.ReadDebugDirectory();

            if (entries.Length > 0)
            {
                var codeView = entries[0];
                CodeViewDebugDirectoryData codeViewData = peReader.ReadCodeViewDebugDirectoryData(codeView);
                PdbAge  = codeViewData.Age;
                PdbGuid = codeViewData.Guid;
                PdbName = codeViewData.Path;
                PdbInformationAvailable = true;
            }
            asmMetadataReader = PEReaderExtensions.GetMetadataReader(peReader);
            var asmDef = asmMetadataReader.GetAssemblyDefinition();

            Name = asmDef.GetAssemblyName().Name + ".dll";
            if (pdb != null)
            {
                var pdbStream = new MemoryStream(pdb);
                try
                {
                    // MetadataReaderProvider.FromPortablePdbStream takes ownership of the stream
                    pdbMetadataReader = MetadataReaderProvider.FromPortablePdbStream(pdbStream).GetMetadataReader();
                }
                catch (BadImageFormatException)
                {
                    monoProxy.SendLog(sessionId, $"Warning: Unable to read debug information of: {Name} (use DebugType=Portable/Embedded)", token);
                }
            }
            else
            {
                var embeddedPdbEntry = entries.FirstOrDefault(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb);
                if (embeddedPdbEntry.DataSize != 0)
                {
                    pdbMetadataReader = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(embeddedPdbEntry).GetMetadataReader();
                }
            }
            Populate();
        }
Example #9
0
        /// <summary>
        /// Returns metadata readers for assembly PE file and portable PDB.
        /// </summary>
        /// <param name="assemblyFileName">file name of the assembly</param>
        /// <param name="peReader">PE metadata reader return</param>
        /// <param name="pdbReader">PDB metadata reader return</param>
        /// <returns>true if debugging information is available</returns>
        private static bool GetReaders(string assemblyFileName, out MetadataReader peReader, out MetadataReader pdbReader)
        {
            peReader  = null;
            pdbReader = null;

            if (!File.Exists(assemblyFileName))
            {
                return(false);
            }
            Stream   peStream = File.OpenRead(assemblyFileName);
            PEReader reader   = new PEReader(peStream);
            string   pdbPath  = null;

            foreach (DebugDirectoryEntry entry in reader.ReadDebugDirectory())
            {
                if (entry.Type == DebugDirectoryEntryType.CodeView)
                {
                    CodeViewDebugDirectoryData codeViewData = reader.ReadCodeViewDebugDirectoryData(entry);
                    pdbPath = codeViewData.Path;
                    break;
                }
            }
            if (pdbPath == null)
            {
                return(false);
            }
            if (!File.Exists(pdbPath))
            {
                pdbPath = Path.GetFileName(pdbPath);
                if (!File.Exists(pdbPath))
                {
                    return(false);
                }
            }

            peReader = reader.GetMetadataReader();
            Stream pdbStream = File.OpenRead(pdbPath);
            MetadataReaderProvider provider = MetadataReaderProvider.FromPortablePdbStream(pdbStream);

            pdbReader = provider.GetMetadataReader();

            return(true);
        }
Example #10
0
        internal PeParser(byte[] dllBytes)
        {
            using (var peReader = new PEReader(new MemoryStream(dllBytes)))
            {
                DebugData = peReader.ReadCodeViewDebugDirectoryData(peReader.ReadDebugDirectory()[0]);

                PeHeaders = peReader.PEHeaders;
            }

            var peBufferHandle = GCHandle.Alloc(dllBytes, GCHandleType.Pinned);

            _peBuffer = peBufferHandle.AddrOfPinnedObject();

            BaseRelocations = GetBaseRelocations();

            ExportedFunctions = GetExportedFunctions();

            ImportedFunctions = GetImportedFunctions();

            TlsCallbacks = GetTlsCallbacks();

            peBufferHandle.Free();
        }
Example #11
0
 public PdbChecksumDebugDirectoryDataEntry(CodeViewDebugDirectoryData entry)
 {
     this.entry = entry;
 }
Example #12
0
 public CodeViewTreeNode(CodeViewDebugDirectoryData entry)
 {
     this.entry = entry;
 }