/// <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(), }); }
/// <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(), }); }
/// <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)); }); 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); }); sectionHeaderStreamCache = SimpleCache.CreateStruct(() => { uint streamNumber = DebugStreamIndexes[(int)KnownDebugStreamIndex.SectionHdr]; if (streamNumber != InvalidStreamIndex) { if (streamNumber >= Stream.File.Streams.Count) { throw new Exception("No section header stream in PDB"); } return(Stream.File.Streams[(int)streamNumber].Reader); } return(null); }); sectionHeadersCache = SimpleCache.CreateStruct(() => { 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); }); 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(() => { if (DebugStreamIndexes.Length > 0) { uint streamNumber = DebugStreamIndexes[(int)KnownDebugStreamIndex.FPO]; if (streamNumber != InvalidStreamIndex) { if (streamNumber >= Stream.File.Streams.Count) { throw new Exception("No FPO stream in PDB"); } return(Stream.File.Streams[(int)streamNumber].Reader); } } return(null); }); 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); }); ecNamesCache = SimpleCache.CreateStruct(() => ECSubstream.Length > 0 ? new PdbStringTable(ECSubstream) : null); }