/// <summary>
 /// Reads <see cref="SectionContributionEntry2"/> from the stream.
 /// </summary>
 /// <param name="reader">Stream binary reader.</param>
 public static SectionContributionEntry2 Read(IBinaryReader reader)
 {
     return(new SectionContributionEntry2
     {
         Base = SectionContributionEntry.Read(reader),
         CoffSectionIndex = reader.ReadUint(),
     });
 }
Пример #2
0
 /// <summary>
 /// Reads <see cref="ModuleInfoHeader"/> from the stream.
 /// </summary>
 /// <param name="reader">Stream binary reader.</param>
 public static ModuleInfoHeader Read(IBinaryReader reader)
 {
     return(new ModuleInfoHeader
     {
         ModulePointer = reader.ReadUint(),
         SectionContribution = SectionContributionEntry.Read(reader),
         Flags = ModuleInfoFlags.Read(reader),
         ModuleStreamIndex = reader.ReadUshort(),
         SymbolDebugInfoByteSize = reader.ReadUint(),
         C11LineInfoByteSize = reader.ReadUint(),
         C13LineInfoByteSize = reader.ReadUint(),
         NumberOfFiles = reader.ReadUshort(),
         Padding = reader.ReadUshort(),
         FileNameOffsetsPointer = reader.ReadUint(),
         SourceFileNameIndex = reader.ReadUint(),
         PdbFilePathNameIndex = reader.ReadUint(),
     });
 }
Пример #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="DbiStream"/> class.
        /// </summary>
        /// <param name="stream">PDB stream that contains DBI stream.</param>
        public DbiStream(PdbStream stream)
        {
            Stream = stream;
            stream.Reader.Position = 0;
            if (Stream.Length < DbiStreamHeader.Size)
            {
                throw new Exception("DBI Stream does not contain a header.");
            }
            Header = DbiStreamHeader.Read(stream.Reader);
            if (Header.VersionSignature != -1)
            {
                throw new Exception("Invalid DBI version signature.");
            }

            // Require at least version 7, which should be present in all PDBs
            // produced in the last decade and allows us to avoid having to
            // special case all kinds of complicated arcane formats.
            if (Header.Version < DbiStreamVersion.V70)
            {
                throw new Exception("Unsupported DBI version.");
            }

            int expectedSize = DbiStreamHeader.Size + Header.ModuleInfoSubstreamSize + Header.SectionContributionSubstreamSize +
                               Header.SectionMapSize + Header.FileInfoSize + Header.TypeServerSize +
                               Header.OptionalDebugHeaderSize + Header.ECSubstreamSize;

            if (Stream.Length != expectedSize)
            {
                throw new Exception("DBI Length does not equal sum of substreams.");
            }

            // Only certain substreams are guaranteed to be aligned. Validate
            // them here.
            if (Header.ModuleInfoSubstreamSize % 4 != 0)
            {
                throw new Exception("DBI MODI substream not aligned.");
            }
            if (Header.SectionContributionSubstreamSize % 4 != 0)
            {
                throw new Exception("DBI section contribution substream not aligned.");
            }
            if (Header.SectionMapSize % 4 != 0)
            {
                throw new Exception("DBI section map substream not aligned.");
            }
            if (Header.FileInfoSize % 4 != 0)
            {
                throw new Exception("DBI file info substream not aligned.");
            }
            if (Header.TypeServerSize % 4 != 0)
            {
                throw new Exception("DBI type server substream not aligned.");
            }

            // Get substreams
            ModuleInfoSubstream          = stream.Reader.ReadSubstream(Header.ModuleInfoSubstreamSize);
            SectionContributionSubstream = stream.Reader.ReadSubstream(Header.SectionContributionSubstreamSize);
            SectionMapSubstream          = stream.Reader.ReadSubstream(Header.SectionMapSize);
            FileInfoSubstream            = stream.Reader.ReadSubstream(Header.FileInfoSize);
            TypeServerMapSubstream       = stream.Reader.ReadSubstream(Header.TypeServerSize);
            ECSubstream        = stream.Reader.ReadSubstream(Header.ECSubstreamSize);
            DebugStreamIndexes = stream.Reader.ReadUshortArray(Header.OptionalDebugHeaderSize / 2);
            if (stream.Reader.BytesRemaining > 0)
            {
                throw new Exception("Found unexpected bytes in DBI Stream.");
            }

            // Create caches for reading substreams
            modulesCache = SimpleCache.CreateStruct(() =>
            {
                ModuleInfoSubstream.Position = 0;
                FileInfoSubstream.Position   = 0;
                return(new DbiModuleList(ModuleInfoSubstream, FileInfoSubstream, this));
            });
            if (SectionContributionSubstream.Length > 0)
            {
                DbiSectionContributionVersion version = (DbiSectionContributionVersion)SectionContributionSubstream.ReadUint();

                if (version != DbiSectionContributionVersion.V60 && version != DbiSectionContributionVersion.V2)
                {
                    throw new Exception("Unsupported DBI Section Contribution version");
                }
            }
            sectionContributionsCache = SimpleCache.CreateStruct(() =>
            {
                SectionContributionEntry[] result = null;

                if (SectionContributionSubstream.Length > 0)
                {
                    SectionContributionSubstream.Position = 0;
                    DbiSectionContributionVersion version = (DbiSectionContributionVersion)SectionContributionSubstream.ReadUint();

                    if (version == DbiSectionContributionVersion.V60)
                    {
                        // Read array from the stream
                        result = new SectionContributionEntry[SectionContributionSubstream.BytesRemaining / SectionContributionEntry.Size];
                        for (int i = 0; i < result.Length; i++)
                        {
                            result[i] = SectionContributionEntry.Read(SectionContributionSubstream);
                        }
                    }
                    else
                    {
                        // Copy values from newer section contributions since it is expanded version of us.
                        SectionContributionEntry2[] result2 = SectionContributions2;

                        if (result2 != null)
                        {
                            result = new SectionContributionEntry[result2.Length];
                            for (int i = 0; i < result.Length; i++)
                            {
                                result[i] = result2[i].Base;
                            }
                        }
                    }
                }
                return(result);
            });
            sectionContributions2Cache = SimpleCache.CreateStruct(() =>
            {
                SectionContributionEntry2[] result = null;

                if (SectionContributionSubstream.Length > 0)
                {
                    SectionContributionSubstream.Position = 0;
                    DbiSectionContributionVersion version = (DbiSectionContributionVersion)SectionContributionSubstream.ReadUint();

                    if (version == DbiSectionContributionVersion.V2)
                    {
                        // Read array from the stream
                        result = new SectionContributionEntry2[SectionContributionSubstream.BytesRemaining / SectionContributionEntry2.Size];
                        for (int i = 0; i < result.Length; i++)
                        {
                            result[i] = SectionContributionEntry2.Read(SectionContributionSubstream);
                        }
                    }
                }
                return(result);
            });

            CoffSectionHeader[] ReadSectionHeadersStream(IBinaryReader sectionHeaderStream)
            {
                if (sectionHeaderStream != null)
                {
                    sectionHeaderStream.Position = 0;
                    if (sectionHeaderStream.Length % CoffSectionHeader.Size != 0)
                    {
                        throw new Exception("Corrupted section header stream.");
                    }

                    int numSections = (int)(sectionHeaderStream.Length / CoffSectionHeader.Size);
                    CoffSectionHeader[] sectionHeaders = new CoffSectionHeader[numSections];

                    for (int i = 0; i < numSections; i++)
                    {
                        sectionHeaders[i] = CoffSectionHeader.Read(sectionHeaderStream);
                    }
                    return(sectionHeaders);
                }
                return(null);
            };

            sectionHeadersCache         = SimpleCache.CreateStruct(() => ReadSectionHeadersStream(GetKnownDebugStream(KnownDebugStreamIndex.SectionHdr)?.Reader));
            originalSectionHeadersCache = SimpleCache.CreateStruct(() => ReadSectionHeadersStream(GetKnownDebugStream(KnownDebugStreamIndex.SectionHdrOrig)?.Reader));
            sectionMapCache             = SimpleCache.CreateStruct(() =>
            {
                if (SectionMapSubstream.Length > 0)
                {
                    SectionMapSubstream.Position = 0;
                    ushort secCount    = SectionMapSubstream.ReadUshort();
                    ushort secCountLog = SectionMapSubstream.ReadUshort();

                    SectionMapEntry[] sectionMap = new SectionMapEntry[secCount];
                    for (int i = 0; i < sectionMap.Length; i++)
                    {
                        sectionMap[i] = SectionMapEntry.Read(SectionMapSubstream);
                    }
                    return(sectionMap);
                }
                return(null);
            });
            fpoStreamCache  = SimpleCache.CreateStruct(() => GetKnownDebugStream(KnownDebugStreamIndex.FPO)?.Reader);
            fpoRecordsCache = SimpleCache.CreateStruct(() =>
            {
                if (FpoStream != null)
                {
                    FpoStream.Position = 0;
                    if (FpoStream.Length % FpoData.Size != 0)
                    {
                        throw new Exception("Corrupted New FPO stream.");
                    }

                    int numRecords       = (int)(FpoStream.Length / FpoData.Size);
                    FpoData[] fpoRecords = new FpoData[numRecords];

                    for (int i = 0; i < numRecords; i++)
                    {
                        fpoRecords[i] = FpoData.Read(FpoStream);
                    }
                    return(fpoRecords);
                }
                return(null);
            });
            OmapEntry[] LoadOmapStream(IBinaryReader omapReader)
            {
                if (omapReader != null)
                {
                    omapReader.Position = 0;
                    if (omapReader.Length % OmapEntry.Size != 0)
                    {
                        throw new Exception("Corrupted Omap stream.");
                    }

                    int         count   = (int)(omapReader.Length / OmapEntry.Size);
                    OmapEntry[] entries = new OmapEntry[count];

                    for (int i = 0; i < count; i++)
                    {
                        entries[i] = OmapEntry.Read(omapReader);
                    }
                    return(entries);
                }
                return(null);
            };

            omapToSourceEntriesCache   = SimpleCache.CreateStruct(() => LoadOmapStream(GetKnownDebugStream(KnownDebugStreamIndex.OmapToSrc)?.Reader));
            omapFromSourceEntriesCache = SimpleCache.CreateStruct(() => LoadOmapStream(GetKnownDebugStream(KnownDebugStreamIndex.OmapFromSrc)?.Reader));
            ecNamesCache = SimpleCache.CreateStruct(() => ECSubstream.Length > 0 ? new PdbStringTable(ECSubstream) : null);
        }