xref: /llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp (revision ed98c1b37661b0795a5e34517941485f0f0688d1)
16b6b8c4fSAdrian McCarthy //===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
26b6b8c4fSAdrian McCarthy //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66b6b8c4fSAdrian McCarthy //
76b6b8c4fSAdrian McCarthy //===----------------------------------------------------------------------===//
86b6b8c4fSAdrian McCarthy 
96b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
106b6b8c4fSAdrian McCarthy #include "llvm/ADT/StringRef.h"
116b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
126b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
136b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
146b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
156b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/RawError.h"
166b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
176b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/PDBTypes.h"
186b6b8c4fSAdrian McCarthy #include "llvm/Object/COFF.h"
19d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamArray.h"
20d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamReader.h"
216b6b8c4fSAdrian McCarthy #include "llvm/Support/Error.h"
226b6b8c4fSAdrian McCarthy #include <cstddef>
236b6b8c4fSAdrian McCarthy #include <cstdint>
246b6b8c4fSAdrian McCarthy 
256b6b8c4fSAdrian McCarthy using namespace llvm;
266b6b8c4fSAdrian McCarthy using namespace llvm::codeview;
276b6b8c4fSAdrian McCarthy using namespace llvm::msf;
286b6b8c4fSAdrian McCarthy using namespace llvm::pdb;
296b6b8c4fSAdrian McCarthy using namespace llvm::support;
306b6b8c4fSAdrian McCarthy 
316b6b8c4fSAdrian McCarthy template <typename ContribType>
loadSectionContribs(FixedStreamArray<ContribType> & Output,BinaryStreamReader & Reader)326b6b8c4fSAdrian McCarthy static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
33120faca4SZachary Turner                                  BinaryStreamReader &Reader) {
346b6b8c4fSAdrian McCarthy   if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
356b6b8c4fSAdrian McCarthy     return make_error<RawError>(
366b6b8c4fSAdrian McCarthy         raw_error_code::corrupt_file,
376b6b8c4fSAdrian McCarthy         "Invalid number of bytes of section contributions");
386b6b8c4fSAdrian McCarthy 
396b6b8c4fSAdrian McCarthy   uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
406b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readArray(Output, Count))
416b6b8c4fSAdrian McCarthy     return EC;
426b6b8c4fSAdrian McCarthy   return Error::success();
436b6b8c4fSAdrian McCarthy }
446b6b8c4fSAdrian McCarthy 
DbiStream(std::unique_ptr<BinaryStream> Stream)4515b2bdfdSZachary Turner DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)
4615b2bdfdSZachary Turner     : Stream(std::move(Stream)), Header(nullptr) {}
476b6b8c4fSAdrian McCarthy 
486b6b8c4fSAdrian McCarthy DbiStream::~DbiStream() = default;
496b6b8c4fSAdrian McCarthy 
reload(PDBFile * Pdb)5015b2bdfdSZachary Turner Error DbiStream::reload(PDBFile *Pdb) {
51120faca4SZachary Turner   BinaryStreamReader Reader(*Stream);
526b6b8c4fSAdrian McCarthy 
536b6b8c4fSAdrian McCarthy   if (Stream->getLength() < sizeof(DbiStreamHeader))
546b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
556b6b8c4fSAdrian McCarthy                                 "DBI Stream does not contain a header.");
566b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readObject(Header))
576b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
586b6b8c4fSAdrian McCarthy                                 "DBI Stream does not contain a header.");
596b6b8c4fSAdrian McCarthy 
606b6b8c4fSAdrian McCarthy   if (Header->VersionSignature != -1)
616b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
626b6b8c4fSAdrian McCarthy                                 "Invalid DBI version signature.");
636b6b8c4fSAdrian McCarthy 
646b6b8c4fSAdrian McCarthy   // Require at least version 7, which should be present in all PDBs
656b6b8c4fSAdrian McCarthy   // produced in the last decade and allows us to avoid having to
666b6b8c4fSAdrian McCarthy   // special case all kinds of complicated arcane formats.
676b6b8c4fSAdrian McCarthy   if (Header->VersionHeader < PdbDbiV70)
686b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::feature_unsupported,
696b6b8c4fSAdrian McCarthy                                 "Unsupported DBI version.");
706b6b8c4fSAdrian McCarthy 
716b6b8c4fSAdrian McCarthy   if (Stream->getLength() !=
726b6b8c4fSAdrian McCarthy       sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
736b6b8c4fSAdrian McCarthy           Header->SecContrSubstreamSize + Header->SectionMapSize +
746b6b8c4fSAdrian McCarthy           Header->FileInfoSize + Header->TypeServerSize +
756b6b8c4fSAdrian McCarthy           Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
766b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
776b6b8c4fSAdrian McCarthy                                 "DBI Length does not equal sum of substreams.");
786b6b8c4fSAdrian McCarthy 
796b6b8c4fSAdrian McCarthy   // Only certain substreams are guaranteed to be aligned.  Validate
806b6b8c4fSAdrian McCarthy   // them here.
816b6b8c4fSAdrian McCarthy   if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
826b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
836b6b8c4fSAdrian McCarthy                                 "DBI MODI substream not aligned.");
846b6b8c4fSAdrian McCarthy   if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
856b6b8c4fSAdrian McCarthy     return make_error<RawError>(
866b6b8c4fSAdrian McCarthy         raw_error_code::corrupt_file,
876b6b8c4fSAdrian McCarthy         "DBI section contribution substream not aligned.");
886b6b8c4fSAdrian McCarthy   if (Header->SectionMapSize % sizeof(uint32_t) != 0)
896b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
906b6b8c4fSAdrian McCarthy                                 "DBI section map substream not aligned.");
916b6b8c4fSAdrian McCarthy   if (Header->FileInfoSize % sizeof(uint32_t) != 0)
926b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
936b6b8c4fSAdrian McCarthy                                 "DBI file info substream not aligned.");
946b6b8c4fSAdrian McCarthy   if (Header->TypeServerSize % sizeof(uint32_t) != 0)
956b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
966b6b8c4fSAdrian McCarthy                                 "DBI type server substream not aligned.");
976b6b8c4fSAdrian McCarthy 
98dd739682SZachary Turner   if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))
996b6b8c4fSAdrian McCarthy     return EC;
1006b6b8c4fSAdrian McCarthy 
101dd739682SZachary Turner   if (auto EC = Reader.readSubstream(SecContrSubstream,
1026b6b8c4fSAdrian McCarthy                                      Header->SecContrSubstreamSize))
1036b6b8c4fSAdrian McCarthy     return EC;
104dd739682SZachary Turner   if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))
1056b6b8c4fSAdrian McCarthy     return EC;
106dd739682SZachary Turner   if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))
1076b6b8c4fSAdrian McCarthy     return EC;
1086b6b8c4fSAdrian McCarthy   if (auto EC =
109dd739682SZachary Turner           Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))
1106b6b8c4fSAdrian McCarthy     return EC;
111dd739682SZachary Turner   if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))
1126b6b8c4fSAdrian McCarthy     return EC;
1136b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readArray(
1146b6b8c4fSAdrian McCarthy           DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
1156b6b8c4fSAdrian McCarthy     return EC;
1166b6b8c4fSAdrian McCarthy 
117dd739682SZachary Turner   if (auto EC = Modules.initialize(ModiSubstream.StreamData,
118dd739682SZachary Turner                                    FileInfoSubstream.StreamData))
1191eb9a029SZachary Turner     return EC;
1201eb9a029SZachary Turner 
1216b6b8c4fSAdrian McCarthy   if (auto EC = initializeSectionContributionData())
1226b6b8c4fSAdrian McCarthy     return EC;
12315b2bdfdSZachary Turner   if (auto EC = initializeSectionHeadersData(Pdb))
1246b6b8c4fSAdrian McCarthy     return EC;
1256b6b8c4fSAdrian McCarthy   if (auto EC = initializeSectionMapData())
1266b6b8c4fSAdrian McCarthy     return EC;
127d17f6ab6SAleksandr Urakov   if (auto EC = initializeOldFpoRecords(Pdb))
128d17f6ab6SAleksandr Urakov     return EC;
129d17f6ab6SAleksandr Urakov   if (auto EC = initializeNewFpoRecords(Pdb))
1306b6b8c4fSAdrian McCarthy      return EC;
1316b6b8c4fSAdrian McCarthy 
1326b6b8c4fSAdrian McCarthy   if (Reader.bytesRemaining() > 0)
1336b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
1346b6b8c4fSAdrian McCarthy                                 "Found unexpected bytes in DBI Stream.");
1356b6b8c4fSAdrian McCarthy 
136dd739682SZachary Turner   if (!ECSubstream.empty()) {
137dd739682SZachary Turner     BinaryStreamReader ECReader(ECSubstream.StreamData);
138c504ae3cSZachary Turner     if (auto EC = ECNames.reload(ECReader))
1396b6b8c4fSAdrian McCarthy       return EC;
1406b6b8c4fSAdrian McCarthy   }
1416b6b8c4fSAdrian McCarthy 
1426b6b8c4fSAdrian McCarthy   return Error::success();
1436b6b8c4fSAdrian McCarthy }
1446b6b8c4fSAdrian McCarthy 
getDbiVersion() const1456b6b8c4fSAdrian McCarthy PdbRaw_DbiVer DbiStream::getDbiVersion() const {
1466b6b8c4fSAdrian McCarthy   uint32_t Value = Header->VersionHeader;
1476b6b8c4fSAdrian McCarthy   return static_cast<PdbRaw_DbiVer>(Value);
1486b6b8c4fSAdrian McCarthy }
1496b6b8c4fSAdrian McCarthy 
getAge() const1506b6b8c4fSAdrian McCarthy uint32_t DbiStream::getAge() const { return Header->Age; }
1516b6b8c4fSAdrian McCarthy 
getPublicSymbolStreamIndex() const1526b6b8c4fSAdrian McCarthy uint16_t DbiStream::getPublicSymbolStreamIndex() const {
1536b6b8c4fSAdrian McCarthy   return Header->PublicSymbolStreamIndex;
1546b6b8c4fSAdrian McCarthy }
1556b6b8c4fSAdrian McCarthy 
getGlobalSymbolStreamIndex() const1566b6b8c4fSAdrian McCarthy uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
1576b6b8c4fSAdrian McCarthy   return Header->GlobalSymbolStreamIndex;
1586b6b8c4fSAdrian McCarthy }
1596b6b8c4fSAdrian McCarthy 
getFlags() const1606b6b8c4fSAdrian McCarthy uint16_t DbiStream::getFlags() const { return Header->Flags; }
1616b6b8c4fSAdrian McCarthy 
isIncrementallyLinked() const1626b6b8c4fSAdrian McCarthy bool DbiStream::isIncrementallyLinked() const {
1636b6b8c4fSAdrian McCarthy   return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
1646b6b8c4fSAdrian McCarthy }
1656b6b8c4fSAdrian McCarthy 
hasCTypes() const1666b6b8c4fSAdrian McCarthy bool DbiStream::hasCTypes() const {
1676b6b8c4fSAdrian McCarthy   return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
1686b6b8c4fSAdrian McCarthy }
1696b6b8c4fSAdrian McCarthy 
isStripped() const1706b6b8c4fSAdrian McCarthy bool DbiStream::isStripped() const {
1716b6b8c4fSAdrian McCarthy   return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
1726b6b8c4fSAdrian McCarthy }
1736b6b8c4fSAdrian McCarthy 
getBuildNumber() const1746b6b8c4fSAdrian McCarthy uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
1756b6b8c4fSAdrian McCarthy 
getBuildMajorVersion() const1766b6b8c4fSAdrian McCarthy uint16_t DbiStream::getBuildMajorVersion() const {
1776b6b8c4fSAdrian McCarthy   return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
1786b6b8c4fSAdrian McCarthy          DbiBuildNo::BuildMajorShift;
1796b6b8c4fSAdrian McCarthy }
1806b6b8c4fSAdrian McCarthy 
getBuildMinorVersion() const1816b6b8c4fSAdrian McCarthy uint16_t DbiStream::getBuildMinorVersion() const {
1826b6b8c4fSAdrian McCarthy   return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
1836b6b8c4fSAdrian McCarthy          DbiBuildNo::BuildMinorShift;
1846b6b8c4fSAdrian McCarthy }
1856b6b8c4fSAdrian McCarthy 
getPdbDllRbld() const1866b6b8c4fSAdrian McCarthy uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
1876b6b8c4fSAdrian McCarthy 
getPdbDllVersion() const1886b6b8c4fSAdrian McCarthy uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
1896b6b8c4fSAdrian McCarthy 
getSymRecordStreamIndex() const1906b6b8c4fSAdrian McCarthy uint32_t DbiStream::getSymRecordStreamIndex() const {
1916b6b8c4fSAdrian McCarthy   return Header->SymRecordStreamIndex;
1926b6b8c4fSAdrian McCarthy }
1936b6b8c4fSAdrian McCarthy 
getMachineType() const1946b6b8c4fSAdrian McCarthy PDB_Machine DbiStream::getMachineType() const {
1956b6b8c4fSAdrian McCarthy   uint16_t Machine = Header->MachineType;
1966b6b8c4fSAdrian McCarthy   return static_cast<PDB_Machine>(Machine);
1976b6b8c4fSAdrian McCarthy }
1986b6b8c4fSAdrian McCarthy 
getSectionHeaders() const19994926a6dSZachary Turner FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const {
2006b6b8c4fSAdrian McCarthy   return SectionHeaders;
2016b6b8c4fSAdrian McCarthy }
2026b6b8c4fSAdrian McCarthy 
hasOldFpoRecords() const203d17f6ab6SAleksandr Urakov bool DbiStream::hasOldFpoRecords() const { return OldFpoStream != nullptr; }
204d17f6ab6SAleksandr Urakov 
getOldFpoRecords() const205d17f6ab6SAleksandr Urakov FixedStreamArray<object::FpoData> DbiStream::getOldFpoRecords() const {
206d17f6ab6SAleksandr Urakov   return OldFpoRecords;
207d17f6ab6SAleksandr Urakov }
208d17f6ab6SAleksandr Urakov 
hasNewFpoRecords() const209d17f6ab6SAleksandr Urakov bool DbiStream::hasNewFpoRecords() const { return NewFpoStream != nullptr; }
210d17f6ab6SAleksandr Urakov 
getNewFpoRecords() const211d17f6ab6SAleksandr Urakov const DebugFrameDataSubsectionRef &DbiStream::getNewFpoRecords() const {
212d17f6ab6SAleksandr Urakov   return NewFpoRecords;
2136b6b8c4fSAdrian McCarthy }
2146b6b8c4fSAdrian McCarthy 
modules() const2151eb9a029SZachary Turner const DbiModuleList &DbiStream::modules() const { return Modules; }
2161eb9a029SZachary Turner 
getSectionMap() const217120faca4SZachary Turner FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
2186b6b8c4fSAdrian McCarthy   return SectionMap;
2196b6b8c4fSAdrian McCarthy }
2206b6b8c4fSAdrian McCarthy 
visitSectionContributions(ISectionContribVisitor & Visitor) const2216b6b8c4fSAdrian McCarthy void DbiStream::visitSectionContributions(
2226b6b8c4fSAdrian McCarthy     ISectionContribVisitor &Visitor) const {
2231bfb9f47SZachary Turner   if (!SectionContribs.empty()) {
2241bfb9f47SZachary Turner     assert(SectionContribVersion == DbiSecContribVer60);
2256b6b8c4fSAdrian McCarthy     for (auto &SC : SectionContribs)
2266b6b8c4fSAdrian McCarthy       Visitor.visit(SC);
2271bfb9f47SZachary Turner   } else if (!SectionContribs2.empty()) {
2281bfb9f47SZachary Turner     assert(SectionContribVersion == DbiSecContribV2);
2296b6b8c4fSAdrian McCarthy     for (auto &SC : SectionContribs2)
2306b6b8c4fSAdrian McCarthy       Visitor.visit(SC);
2316b6b8c4fSAdrian McCarthy   }
2326b6b8c4fSAdrian McCarthy }
2336b6b8c4fSAdrian McCarthy 
getECName(uint32_t NI) const2346c4bfba8SZachary Turner Expected<StringRef> DbiStream::getECName(uint32_t NI) const {
2356c4bfba8SZachary Turner   return ECNames.getStringForID(NI);
2366c4bfba8SZachary Turner }
2376c4bfba8SZachary Turner 
initializeSectionContributionData()2386b6b8c4fSAdrian McCarthy Error DbiStream::initializeSectionContributionData() {
239dd739682SZachary Turner   if (SecContrSubstream.empty())
2406b6b8c4fSAdrian McCarthy     return Error::success();
2416b6b8c4fSAdrian McCarthy 
242dd739682SZachary Turner   BinaryStreamReader SCReader(SecContrSubstream.StreamData);
243695ed56bSZachary Turner   if (auto EC = SCReader.readEnum(SectionContribVersion))
2446b6b8c4fSAdrian McCarthy     return EC;
2456b6b8c4fSAdrian McCarthy 
2466b6b8c4fSAdrian McCarthy   if (SectionContribVersion == DbiSecContribVer60)
2476b6b8c4fSAdrian McCarthy     return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
2486b6b8c4fSAdrian McCarthy   if (SectionContribVersion == DbiSecContribV2)
2496b6b8c4fSAdrian McCarthy     return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
2506b6b8c4fSAdrian McCarthy 
2516b6b8c4fSAdrian McCarthy   return make_error<RawError>(raw_error_code::feature_unsupported,
2526b6b8c4fSAdrian McCarthy                               "Unsupported DBI Section Contribution version");
2536b6b8c4fSAdrian McCarthy }
2546b6b8c4fSAdrian McCarthy 
2556b6b8c4fSAdrian McCarthy // Initializes this->SectionHeaders.
initializeSectionHeadersData(PDBFile * Pdb)25615b2bdfdSZachary Turner Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {
257d17f6ab6SAleksandr Urakov   Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
258d17f6ab6SAleksandr Urakov       createIndexedStreamForHeaderType(Pdb, DbgHeaderType::SectionHdr);
259d17f6ab6SAleksandr Urakov   if (auto EC = ExpectedStream.takeError())
260d17f6ab6SAleksandr Urakov     return EC;
261d17f6ab6SAleksandr Urakov 
262d17f6ab6SAleksandr Urakov   auto &SHS = *ExpectedStream;
263d17f6ab6SAleksandr Urakov   if (!SHS)
26415b2bdfdSZachary Turner     return Error::success();
26515b2bdfdSZachary Turner 
2666b6b8c4fSAdrian McCarthy   size_t StreamLen = SHS->getLength();
2676b6b8c4fSAdrian McCarthy   if (StreamLen % sizeof(object::coff_section))
2686b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
2696b6b8c4fSAdrian McCarthy                                 "Corrupted section header stream.");
2706b6b8c4fSAdrian McCarthy 
2716b6b8c4fSAdrian McCarthy   size_t NumSections = StreamLen / sizeof(object::coff_section);
272120faca4SZachary Turner   BinaryStreamReader Reader(*SHS);
2736b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readArray(SectionHeaders, NumSections))
2746b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
2756b6b8c4fSAdrian McCarthy                                 "Could not read a bitmap.");
2766b6b8c4fSAdrian McCarthy 
2776b6b8c4fSAdrian McCarthy   SectionHeaderStream = std::move(SHS);
2786b6b8c4fSAdrian McCarthy   return Error::success();
2796b6b8c4fSAdrian McCarthy }
2806b6b8c4fSAdrian McCarthy 
2816b6b8c4fSAdrian McCarthy // Initializes this->Fpos.
initializeOldFpoRecords(PDBFile * Pdb)282d17f6ab6SAleksandr Urakov Error DbiStream::initializeOldFpoRecords(PDBFile *Pdb) {
283d17f6ab6SAleksandr Urakov   Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
284d17f6ab6SAleksandr Urakov       createIndexedStreamForHeaderType(Pdb, DbgHeaderType::FPO);
285d17f6ab6SAleksandr Urakov   if (auto EC = ExpectedStream.takeError())
286d17f6ab6SAleksandr Urakov     return EC;
287d17f6ab6SAleksandr Urakov 
288d17f6ab6SAleksandr Urakov   auto &FS = *ExpectedStream;
289d17f6ab6SAleksandr Urakov   if (!FS)
29015b2bdfdSZachary Turner     return Error::success();
29115b2bdfdSZachary Turner 
2926b6b8c4fSAdrian McCarthy   size_t StreamLen = FS->getLength();
2936b6b8c4fSAdrian McCarthy   if (StreamLen % sizeof(object::FpoData))
2946b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
295d17f6ab6SAleksandr Urakov                                 "Corrupted Old FPO stream.");
2966b6b8c4fSAdrian McCarthy 
2976b6b8c4fSAdrian McCarthy   size_t NumRecords = StreamLen / sizeof(object::FpoData);
298120faca4SZachary Turner   BinaryStreamReader Reader(*FS);
299d17f6ab6SAleksandr Urakov   if (auto EC = Reader.readArray(OldFpoRecords, NumRecords))
3006b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
301d17f6ab6SAleksandr Urakov                                 "Corrupted Old FPO stream.");
302d17f6ab6SAleksandr Urakov   OldFpoStream = std::move(FS);
3036b6b8c4fSAdrian McCarthy   return Error::success();
3046b6b8c4fSAdrian McCarthy }
3056b6b8c4fSAdrian McCarthy 
initializeNewFpoRecords(PDBFile * Pdb)306d17f6ab6SAleksandr Urakov Error DbiStream::initializeNewFpoRecords(PDBFile *Pdb) {
307d17f6ab6SAleksandr Urakov   Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
308d17f6ab6SAleksandr Urakov       createIndexedStreamForHeaderType(Pdb, DbgHeaderType::NewFPO);
309d17f6ab6SAleksandr Urakov   if (auto EC = ExpectedStream.takeError())
310d17f6ab6SAleksandr Urakov     return EC;
311d17f6ab6SAleksandr Urakov 
312d17f6ab6SAleksandr Urakov   auto &FS = *ExpectedStream;
313d17f6ab6SAleksandr Urakov   if (!FS)
314d17f6ab6SAleksandr Urakov     return Error::success();
315d17f6ab6SAleksandr Urakov 
316d17f6ab6SAleksandr Urakov   if (auto EC = NewFpoRecords.initialize(*FS))
317d17f6ab6SAleksandr Urakov     return EC;
318d17f6ab6SAleksandr Urakov 
319d17f6ab6SAleksandr Urakov   NewFpoStream = std::move(FS);
320d17f6ab6SAleksandr Urakov   return Error::success();
321d17f6ab6SAleksandr Urakov }
322d17f6ab6SAleksandr Urakov 
323d17f6ab6SAleksandr Urakov Expected<std::unique_ptr<msf::MappedBlockStream>>
createIndexedStreamForHeaderType(PDBFile * Pdb,DbgHeaderType Type) const324d17f6ab6SAleksandr Urakov DbiStream::createIndexedStreamForHeaderType(PDBFile *Pdb,
325d17f6ab6SAleksandr Urakov                                             DbgHeaderType Type) const {
326d17f6ab6SAleksandr Urakov   if (!Pdb)
327d17f6ab6SAleksandr Urakov     return nullptr;
328d17f6ab6SAleksandr Urakov 
329d17f6ab6SAleksandr Urakov   if (DbgStreams.empty())
330d17f6ab6SAleksandr Urakov     return nullptr;
331d17f6ab6SAleksandr Urakov 
332d17f6ab6SAleksandr Urakov   uint32_t StreamNum = getDebugStreamIndex(Type);
333d17f6ab6SAleksandr Urakov 
334*13f7ddffSNico Weber   // This means there is no such stream.
335d17f6ab6SAleksandr Urakov   if (StreamNum == kInvalidStreamIndex)
336d17f6ab6SAleksandr Urakov     return nullptr;
337d17f6ab6SAleksandr Urakov 
338*13f7ddffSNico Weber   return Pdb->safelyCreateIndexedStream(StreamNum);
339d17f6ab6SAleksandr Urakov }
340d17f6ab6SAleksandr Urakov 
getSectionContributionData() const341dd739682SZachary Turner BinarySubstreamRef DbiStream::getSectionContributionData() const {
342dd739682SZachary Turner   return SecContrSubstream;
343dd739682SZachary Turner }
344dd739682SZachary Turner 
getSecMapSubstreamData() const345dd739682SZachary Turner BinarySubstreamRef DbiStream::getSecMapSubstreamData() const {
346dd739682SZachary Turner   return SecMapSubstream;
347dd739682SZachary Turner }
348dd739682SZachary Turner 
getModiSubstreamData() const349dd739682SZachary Turner BinarySubstreamRef DbiStream::getModiSubstreamData() const {
350dd739682SZachary Turner   return ModiSubstream;
351dd739682SZachary Turner }
352dd739682SZachary Turner 
getFileInfoSubstreamData() const353dd739682SZachary Turner BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const {
354dd739682SZachary Turner   return FileInfoSubstream;
355dd739682SZachary Turner }
356dd739682SZachary Turner 
getTypeServerMapSubstreamData() const357dd739682SZachary Turner BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const {
358dd739682SZachary Turner   return TypeServerMapSubstream;
359dd739682SZachary Turner }
360dd739682SZachary Turner 
getECSubstreamData() const361dd739682SZachary Turner BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }
362dd739682SZachary Turner 
initializeSectionMapData()3636b6b8c4fSAdrian McCarthy Error DbiStream::initializeSectionMapData() {
364dd739682SZachary Turner   if (SecMapSubstream.empty())
3656b6b8c4fSAdrian McCarthy     return Error::success();
3666b6b8c4fSAdrian McCarthy 
367dd739682SZachary Turner   BinaryStreamReader SMReader(SecMapSubstream.StreamData);
3686b6b8c4fSAdrian McCarthy   const SecMapHeader *Header;
3696b6b8c4fSAdrian McCarthy   if (auto EC = SMReader.readObject(Header))
3706b6b8c4fSAdrian McCarthy     return EC;
3716b6b8c4fSAdrian McCarthy   if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
3726b6b8c4fSAdrian McCarthy     return EC;
3736b6b8c4fSAdrian McCarthy   return Error::success();
3746b6b8c4fSAdrian McCarthy }
3756b6b8c4fSAdrian McCarthy 
getDebugStreamIndex(DbgHeaderType Type) const3766b6b8c4fSAdrian McCarthy uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
3776b6b8c4fSAdrian McCarthy   uint16_t T = static_cast<uint16_t>(Type);
3786b6b8c4fSAdrian McCarthy   if (T >= DbgStreams.size())
3796b6b8c4fSAdrian McCarthy     return kInvalidStreamIndex;
3806b6b8c4fSAdrian McCarthy   return DbgStreams[T];
3816b6b8c4fSAdrian McCarthy }
382