Exemplo n.º 1
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);
        }
Exemplo n.º 2
0
        private static void ReadPortableDebugTableEntries(PEReader peReader, out DebugDirectoryEntry codeViewEntry, out DebugDirectoryEntry embeddedPdbEntry)
        {
            // See spec: https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/specs/PE-COFF.md

            codeViewEntry    = default(DebugDirectoryEntry);
            embeddedPdbEntry = default(DebugDirectoryEntry);

            foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory())
            {
                if (entry.Type == DebugDirectoryEntryType.CodeView)
                {
                    const ushort PortableCodeViewVersionMagic = 0x504d;
                    if (entry.MinorVersion != PortableCodeViewVersionMagic)
                    {
                        continue;
                    }

                    codeViewEntry = entry;
                }
                else if (entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb)
                {
                    embeddedPdbEntry = entry;
                }
            }
        }
Exemplo n.º 3
0
        internal EmitOutput(ImmutableArray <byte> assembly, ImmutableArray <byte> pdb)
        {
            Assembly = assembly;

            if (pdb.IsDefault)
            {
                // We didn't emit a discrete PDB file, so we'll look for an embedded PDB instead.
                using (var peReader = new PEReader(Assembly))
                {
                    DebugDirectoryEntry portablePdbEntry = peReader.ReadDebugDirectory().FirstOrDefault(e => e.Type == DebugDirectoryEntryType.EmbeddedPortablePdb);
                    if (portablePdbEntry.DataSize != 0)
                    {
                        using (var embeddedMetadataProvider = peReader.ReadEmbeddedPortablePdbDebugDirectoryData(portablePdbEntry))
                        {
                            var mdReader = embeddedMetadataProvider.GetMetadataReader();
                            pdb = readMetadata(mdReader);
                        }
                    }
                }
            }

            Pdb = pdb;

            unsafe ImmutableArray <byte> readMetadata(MetadataReader mdReader)
            {
                var length = mdReader.MetadataLength;
                var bytes  = new byte[length];

                Marshal.Copy((IntPtr)mdReader.MetadataPointer, bytes, 0, length);
                return(ImmutableArray.Create(bytes));
            }
        }
    }
Exemplo n.º 4
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);
        }
Exemplo n.º 5
0
 public DebugDirectoryEntryView(DebugDirectoryEntry entry, string data)
 {
     this.RawData          = data;
     this.Timestamp        = entry.Stamp;
     this.MajorVersion     = entry.MajorVersion;
     this.MinorVersion     = entry.MinorVersion;
     this.Type             = entry.Type.ToString();
     this.SizeOfRawData    = entry.DataSize;
     this.AddressOfRawData = entry.DataRelativeVirtualAddress;
     this.AddressOfRawData = entry.DataPointer;
 }
Exemplo n.º 6
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);
        }
Exemplo n.º 7
0
        public static DebugData Get(DebugDirectoryEntry entry)
        {
            if (entry.PointerToRawData == 0 && entry.SizeOfData == 0)
                return null;

            LocationCalculator calc = entry.Directory.DataDirectory.Directories.Image.GetCalculator();
            uint rva = entry.AddressOfRawData;
            Section section = calc.RVAToSection(rva);
            ulong image_base = entry.Directory.DataDirectory.Directories.Image.NTHeaders.OptionalHeader.ImageBase;
            Location location = new Location(entry.PointerToRawData, rva, image_base + rva, entry.SizeOfData, entry.SizeOfData, section);
            DebugData data = new DebugData(entry, location);

            return data;
        }
Exemplo n.º 8
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            if (relocsOnly)
            {
                return(new ObjectData(Array.Empty <byte>(), Array.Empty <Relocation>(), 1, new ISymbolDefinitionNode[] { this }));
            }

            ImmutableArray <DebugDirectoryEntry> entries = _module.PEReader.ReadDebugDirectory();

            Debug.Assert(entries != null && _debugEntryIndex < entries.Length);

            DebugDirectoryEntry sourceDebugEntry = entries[_debugEntryIndex];

            PEMemoryBlock block = _module.PEReader.GetSectionData(sourceDebugEntry.DataRelativeVirtualAddress);

            byte[] result = new byte[sourceDebugEntry.DataSize];
            block.GetContent(0, sourceDebugEntry.DataSize).CopyTo(result);

            return(new ObjectData(result, Array.Empty <Relocation>(), _module.Context.Target.PointerSize, new ISymbolDefinitionNode[] { this }));
        }
Exemplo n.º 9
0
        private void ReadPortableDebugTableEntries(PEReader peReader, out DebugDirectoryEntry codeViewEntry, out DebugDirectoryEntry embeddedPdbEntry)
        {
            // See spec: https://github.com/dotnet/runtime/blob/main/docs/design/specs/PE-COFF.md

            codeViewEntry    = default;
            embeddedPdbEntry = default;

            foreach (DebugDirectoryEntry entry in peReader.ReadDebugDirectory())
            {
                if (entry.Type == DebugDirectoryEntryType.CodeView)
                {
                    if (entry.MinorVersion != ImageDebugDirectory.PortablePDBMinorVersion)
                    {
                        continue;
                    }
                    codeViewEntry = entry;
                }
                else if (entry.Type == DebugDirectoryEntryType.EmbeddedPortablePdb)
                {
                    embeddedPdbEntry = entry;
                }
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Reads the data pointed to by the specified Debug Directory entry and interprets them as PDB Checksum entry.
        /// </summary>
        /// <exception cref="ArgumentException"><paramref name="entry"/> is not a PDB Checksum entry.</exception>
        /// <exception cref="BadImageFormatException">Bad format of the data.</exception>
        /// <exception cref="IOException">IO error while reading from the underlying stream.</exception>
        /// <exception cref="InvalidOperationException">PE image not available.</exception>
        internal static PdbChecksumDebugDirectoryData ReadPdbChecksumDebugDirectoryData(this PEReader peReader, DebugDirectoryEntry entry)
        {
            if (entry.Type != PdbChecksumEntryType)
            {
                throw new ArgumentException("Unexpected debug directory entry type", nameof(entry));
            }

            var peImage = peReader.GetEntireImage();

            int dataOffset = peReader.IsLoadedImage ? entry.DataRelativeVirtualAddress : entry.DataPointer;
            var reader     = peImage.GetReader(dataOffset, entry.DataSize);

            int nameLength = reader.IndexOf(0);

            if (nameLength <= 0)
            {
                throw new BadImageFormatException("Invalid PDB Checksum data format");
            }

            string algorithmName = reader.ReadUTF8(nameLength);

            // NUL
            reader.Offset += 1;

            var checksum = reader.ReadBytes(reader.RemainingBytes).ToImmutableArray();

            if (checksum.Length == 0)
            {
                throw new BadImageFormatException("Invalid PDB Checksum data format");
            }

            return(new PdbChecksumDebugDirectoryData(algorithmName, checksum));
        }
Exemplo n.º 11
0
 public DebugDirectoryEntryTreeNode(PEFile module, DebugDirectoryEntry entry)
 {
     this.module = module;
     this.reader = module.Reader;
     this.entry  = entry;
 }
Exemplo n.º 12
0
 internal DebugData(DebugDirectoryEntry directorEntry, Location dataLocation)
 {
     entry = directorEntry;
     location = dataLocation;
 }
Exemplo n.º 13
0
        private string ShowDebugDirectory_Type(DebugDirectoryEntry directoryEntry)
        {
            DebugDirectoryEntryType type = directoryEntry.GetEntryType();
            EnumAnnotations<DebugDirectoryEntryType> annotations = new EnumAnnotations<DebugDirectoryEntryType>();
            EnumAnnotation<DebugDirectoryEntryType> annotation = annotations.FirstOrDefault(a => a.Value == type);

            if (annotation == null)
                return null;

            long value = Convert.ToInt64(annotation.Value);
            string result = String.Format("{0}  {1}", Utils.IntToHex(value, 8), annotation.HeaderName);

            return result;
        }
Exemplo n.º 14
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), GetFileName(pdbPath));
                    }
                    catch
                    {
                        // invalid characters in CodeView path
                        return(null);
                    }
                }

                var pdbStream = TryOpenFile(pdbPath);
                if (pdbStream == null)
                {
                    // workaround, since NI file could be generated in `.native_image` subdirectory
                    // NOTE this is temporary solution until we add option for specifying pdb path
                    try
                    {
                        int tmpLastIndex = assemblyPath.LastIndexOf(".native_image");
                        if (tmpLastIndex == -1)
                        {
                            return(null);
                        }
                        string tmpPath = assemblyPath.Substring(0, tmpLastIndex);
                        pdbPath = Path.Combine(Path.GetDirectoryName(tmpPath), GetFileName(pdbPath));
                    }
                    catch
                    {
                        // invalid characters in CodeView path
                        return(null);
                    }

                    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);
        }