xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1*0b57cec5SDimitry Andric //===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
10*0b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
11*0b57cec5SDimitry Andric #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
12*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
13*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
14*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
15*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawError.h"
16*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
17*0b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBTypes.h"
18*0b57cec5SDimitry Andric #include "llvm/Object/COFF.h"
19*0b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamArray.h"
20*0b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
21*0b57cec5SDimitry Andric #include "llvm/Support/Error.h"
22*0b57cec5SDimitry Andric #include <cstddef>
23*0b57cec5SDimitry Andric #include <cstdint>
24*0b57cec5SDimitry Andric 
25*0b57cec5SDimitry Andric using namespace llvm;
26*0b57cec5SDimitry Andric using namespace llvm::codeview;
27*0b57cec5SDimitry Andric using namespace llvm::msf;
28*0b57cec5SDimitry Andric using namespace llvm::pdb;
29*0b57cec5SDimitry Andric using namespace llvm::support;
30*0b57cec5SDimitry Andric 
31*0b57cec5SDimitry Andric template <typename ContribType>
loadSectionContribs(FixedStreamArray<ContribType> & Output,BinaryStreamReader & Reader)32*0b57cec5SDimitry Andric static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
33*0b57cec5SDimitry Andric                                  BinaryStreamReader &Reader) {
34*0b57cec5SDimitry Andric   if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
35*0b57cec5SDimitry Andric     return make_error<RawError>(
36*0b57cec5SDimitry Andric         raw_error_code::corrupt_file,
37*0b57cec5SDimitry Andric         "Invalid number of bytes of section contributions");
38*0b57cec5SDimitry Andric 
39*0b57cec5SDimitry Andric   uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
40*0b57cec5SDimitry Andric   if (auto EC = Reader.readArray(Output, Count))
41*0b57cec5SDimitry Andric     return EC;
42*0b57cec5SDimitry Andric   return Error::success();
43*0b57cec5SDimitry Andric }
44*0b57cec5SDimitry Andric 
DbiStream(std::unique_ptr<BinaryStream> Stream)45*0b57cec5SDimitry Andric DbiStream::DbiStream(std::unique_ptr<BinaryStream> Stream)
46*0b57cec5SDimitry Andric     : Stream(std::move(Stream)), Header(nullptr) {}
47*0b57cec5SDimitry Andric 
48*0b57cec5SDimitry Andric DbiStream::~DbiStream() = default;
49*0b57cec5SDimitry Andric 
reload(PDBFile * Pdb)50*0b57cec5SDimitry Andric Error DbiStream::reload(PDBFile *Pdb) {
51*0b57cec5SDimitry Andric   BinaryStreamReader Reader(*Stream);
52*0b57cec5SDimitry Andric 
53*0b57cec5SDimitry Andric   if (Stream->getLength() < sizeof(DbiStreamHeader))
54*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
55*0b57cec5SDimitry Andric                                 "DBI Stream does not contain a header.");
56*0b57cec5SDimitry Andric   if (auto EC = Reader.readObject(Header))
57*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
58*0b57cec5SDimitry Andric                                 "DBI Stream does not contain a header.");
59*0b57cec5SDimitry Andric 
60*0b57cec5SDimitry Andric   if (Header->VersionSignature != -1)
61*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
62*0b57cec5SDimitry Andric                                 "Invalid DBI version signature.");
63*0b57cec5SDimitry Andric 
64*0b57cec5SDimitry Andric   // Require at least version 7, which should be present in all PDBs
65*0b57cec5SDimitry Andric   // produced in the last decade and allows us to avoid having to
66*0b57cec5SDimitry Andric   // special case all kinds of complicated arcane formats.
67*0b57cec5SDimitry Andric   if (Header->VersionHeader < PdbDbiV70)
68*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::feature_unsupported,
69*0b57cec5SDimitry Andric                                 "Unsupported DBI version.");
70*0b57cec5SDimitry Andric 
71*0b57cec5SDimitry Andric   if (Stream->getLength() !=
72*0b57cec5SDimitry Andric       sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
73*0b57cec5SDimitry Andric           Header->SecContrSubstreamSize + Header->SectionMapSize +
74*0b57cec5SDimitry Andric           Header->FileInfoSize + Header->TypeServerSize +
75*0b57cec5SDimitry Andric           Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
76*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
77*0b57cec5SDimitry Andric                                 "DBI Length does not equal sum of substreams.");
78*0b57cec5SDimitry Andric 
79*0b57cec5SDimitry Andric   // Only certain substreams are guaranteed to be aligned.  Validate
80*0b57cec5SDimitry Andric   // them here.
81*0b57cec5SDimitry Andric   if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
82*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
83*0b57cec5SDimitry Andric                                 "DBI MODI substream not aligned.");
84*0b57cec5SDimitry Andric   if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
85*0b57cec5SDimitry Andric     return make_error<RawError>(
86*0b57cec5SDimitry Andric         raw_error_code::corrupt_file,
87*0b57cec5SDimitry Andric         "DBI section contribution substream not aligned.");
88*0b57cec5SDimitry Andric   if (Header->SectionMapSize % sizeof(uint32_t) != 0)
89*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
90*0b57cec5SDimitry Andric                                 "DBI section map substream not aligned.");
91*0b57cec5SDimitry Andric   if (Header->FileInfoSize % sizeof(uint32_t) != 0)
92*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
93*0b57cec5SDimitry Andric                                 "DBI file info substream not aligned.");
94*0b57cec5SDimitry Andric   if (Header->TypeServerSize % sizeof(uint32_t) != 0)
95*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
96*0b57cec5SDimitry Andric                                 "DBI type server substream not aligned.");
97*0b57cec5SDimitry Andric 
98*0b57cec5SDimitry Andric   if (auto EC = Reader.readSubstream(ModiSubstream, Header->ModiSubstreamSize))
99*0b57cec5SDimitry Andric     return EC;
100*0b57cec5SDimitry Andric 
101*0b57cec5SDimitry Andric   if (auto EC = Reader.readSubstream(SecContrSubstream,
102*0b57cec5SDimitry Andric                                      Header->SecContrSubstreamSize))
103*0b57cec5SDimitry Andric     return EC;
104*0b57cec5SDimitry Andric   if (auto EC = Reader.readSubstream(SecMapSubstream, Header->SectionMapSize))
105*0b57cec5SDimitry Andric     return EC;
106*0b57cec5SDimitry Andric   if (auto EC = Reader.readSubstream(FileInfoSubstream, Header->FileInfoSize))
107*0b57cec5SDimitry Andric     return EC;
108*0b57cec5SDimitry Andric   if (auto EC =
109*0b57cec5SDimitry Andric           Reader.readSubstream(TypeServerMapSubstream, Header->TypeServerSize))
110*0b57cec5SDimitry Andric     return EC;
111*0b57cec5SDimitry Andric   if (auto EC = Reader.readSubstream(ECSubstream, Header->ECSubstreamSize))
112*0b57cec5SDimitry Andric     return EC;
113*0b57cec5SDimitry Andric   if (auto EC = Reader.readArray(
114*0b57cec5SDimitry Andric           DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
115*0b57cec5SDimitry Andric     return EC;
116*0b57cec5SDimitry Andric 
117*0b57cec5SDimitry Andric   if (auto EC = Modules.initialize(ModiSubstream.StreamData,
118*0b57cec5SDimitry Andric                                    FileInfoSubstream.StreamData))
119*0b57cec5SDimitry Andric     return EC;
120*0b57cec5SDimitry Andric 
121*0b57cec5SDimitry Andric   if (auto EC = initializeSectionContributionData())
122*0b57cec5SDimitry Andric     return EC;
123*0b57cec5SDimitry Andric   if (auto EC = initializeSectionHeadersData(Pdb))
124*0b57cec5SDimitry Andric     return EC;
125*0b57cec5SDimitry Andric   if (auto EC = initializeSectionMapData())
126*0b57cec5SDimitry Andric     return EC;
127*0b57cec5SDimitry Andric   if (auto EC = initializeOldFpoRecords(Pdb))
128*0b57cec5SDimitry Andric     return EC;
129*0b57cec5SDimitry Andric   if (auto EC = initializeNewFpoRecords(Pdb))
130*0b57cec5SDimitry Andric      return EC;
131*0b57cec5SDimitry Andric 
132*0b57cec5SDimitry Andric   if (Reader.bytesRemaining() > 0)
133*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
134*0b57cec5SDimitry Andric                                 "Found unexpected bytes in DBI Stream.");
135*0b57cec5SDimitry Andric 
136*0b57cec5SDimitry Andric   if (!ECSubstream.empty()) {
137*0b57cec5SDimitry Andric     BinaryStreamReader ECReader(ECSubstream.StreamData);
138*0b57cec5SDimitry Andric     if (auto EC = ECNames.reload(ECReader))
139*0b57cec5SDimitry Andric       return EC;
140*0b57cec5SDimitry Andric   }
141*0b57cec5SDimitry Andric 
142*0b57cec5SDimitry Andric   return Error::success();
143*0b57cec5SDimitry Andric }
144*0b57cec5SDimitry Andric 
getDbiVersion() const145*0b57cec5SDimitry Andric PdbRaw_DbiVer DbiStream::getDbiVersion() const {
146*0b57cec5SDimitry Andric   uint32_t Value = Header->VersionHeader;
147*0b57cec5SDimitry Andric   return static_cast<PdbRaw_DbiVer>(Value);
148*0b57cec5SDimitry Andric }
149*0b57cec5SDimitry Andric 
getAge() const150*0b57cec5SDimitry Andric uint32_t DbiStream::getAge() const { return Header->Age; }
151*0b57cec5SDimitry Andric 
getPublicSymbolStreamIndex() const152*0b57cec5SDimitry Andric uint16_t DbiStream::getPublicSymbolStreamIndex() const {
153*0b57cec5SDimitry Andric   return Header->PublicSymbolStreamIndex;
154*0b57cec5SDimitry Andric }
155*0b57cec5SDimitry Andric 
getGlobalSymbolStreamIndex() const156*0b57cec5SDimitry Andric uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
157*0b57cec5SDimitry Andric   return Header->GlobalSymbolStreamIndex;
158*0b57cec5SDimitry Andric }
159*0b57cec5SDimitry Andric 
getFlags() const160*0b57cec5SDimitry Andric uint16_t DbiStream::getFlags() const { return Header->Flags; }
161*0b57cec5SDimitry Andric 
isIncrementallyLinked() const162*0b57cec5SDimitry Andric bool DbiStream::isIncrementallyLinked() const {
163*0b57cec5SDimitry Andric   return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
164*0b57cec5SDimitry Andric }
165*0b57cec5SDimitry Andric 
hasCTypes() const166*0b57cec5SDimitry Andric bool DbiStream::hasCTypes() const {
167*0b57cec5SDimitry Andric   return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
168*0b57cec5SDimitry Andric }
169*0b57cec5SDimitry Andric 
isStripped() const170*0b57cec5SDimitry Andric bool DbiStream::isStripped() const {
171*0b57cec5SDimitry Andric   return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
172*0b57cec5SDimitry Andric }
173*0b57cec5SDimitry Andric 
getBuildNumber() const174*0b57cec5SDimitry Andric uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
175*0b57cec5SDimitry Andric 
getBuildMajorVersion() const176*0b57cec5SDimitry Andric uint16_t DbiStream::getBuildMajorVersion() const {
177*0b57cec5SDimitry Andric   return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
178*0b57cec5SDimitry Andric          DbiBuildNo::BuildMajorShift;
179*0b57cec5SDimitry Andric }
180*0b57cec5SDimitry Andric 
getBuildMinorVersion() const181*0b57cec5SDimitry Andric uint16_t DbiStream::getBuildMinorVersion() const {
182*0b57cec5SDimitry Andric   return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
183*0b57cec5SDimitry Andric          DbiBuildNo::BuildMinorShift;
184*0b57cec5SDimitry Andric }
185*0b57cec5SDimitry Andric 
getPdbDllRbld() const186*0b57cec5SDimitry Andric uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
187*0b57cec5SDimitry Andric 
getPdbDllVersion() const188*0b57cec5SDimitry Andric uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
189*0b57cec5SDimitry Andric 
getSymRecordStreamIndex() const190*0b57cec5SDimitry Andric uint32_t DbiStream::getSymRecordStreamIndex() const {
191*0b57cec5SDimitry Andric   return Header->SymRecordStreamIndex;
192*0b57cec5SDimitry Andric }
193*0b57cec5SDimitry Andric 
getMachineType() const194*0b57cec5SDimitry Andric PDB_Machine DbiStream::getMachineType() const {
195*0b57cec5SDimitry Andric   uint16_t Machine = Header->MachineType;
196*0b57cec5SDimitry Andric   return static_cast<PDB_Machine>(Machine);
197*0b57cec5SDimitry Andric }
198*0b57cec5SDimitry Andric 
getSectionHeaders() const199*0b57cec5SDimitry Andric FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() const {
200*0b57cec5SDimitry Andric   return SectionHeaders;
201*0b57cec5SDimitry Andric }
202*0b57cec5SDimitry Andric 
hasOldFpoRecords() const203*0b57cec5SDimitry Andric bool DbiStream::hasOldFpoRecords() const { return OldFpoStream != nullptr; }
204*0b57cec5SDimitry Andric 
getOldFpoRecords() const205*0b57cec5SDimitry Andric FixedStreamArray<object::FpoData> DbiStream::getOldFpoRecords() const {
206*0b57cec5SDimitry Andric   return OldFpoRecords;
207*0b57cec5SDimitry Andric }
208*0b57cec5SDimitry Andric 
hasNewFpoRecords() const209*0b57cec5SDimitry Andric bool DbiStream::hasNewFpoRecords() const { return NewFpoStream != nullptr; }
210*0b57cec5SDimitry Andric 
getNewFpoRecords() const211*0b57cec5SDimitry Andric const DebugFrameDataSubsectionRef &DbiStream::getNewFpoRecords() const {
212*0b57cec5SDimitry Andric   return NewFpoRecords;
213*0b57cec5SDimitry Andric }
214*0b57cec5SDimitry Andric 
modules() const215*0b57cec5SDimitry Andric const DbiModuleList &DbiStream::modules() const { return Modules; }
216*0b57cec5SDimitry Andric 
getSectionMap() const217*0b57cec5SDimitry Andric FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
218*0b57cec5SDimitry Andric   return SectionMap;
219*0b57cec5SDimitry Andric }
220*0b57cec5SDimitry Andric 
visitSectionContributions(ISectionContribVisitor & Visitor) const221*0b57cec5SDimitry Andric void DbiStream::visitSectionContributions(
222*0b57cec5SDimitry Andric     ISectionContribVisitor &Visitor) const {
223*0b57cec5SDimitry Andric   if (!SectionContribs.empty()) {
224*0b57cec5SDimitry Andric     assert(SectionContribVersion == DbiSecContribVer60);
225*0b57cec5SDimitry Andric     for (auto &SC : SectionContribs)
226*0b57cec5SDimitry Andric       Visitor.visit(SC);
227*0b57cec5SDimitry Andric   } else if (!SectionContribs2.empty()) {
228*0b57cec5SDimitry Andric     assert(SectionContribVersion == DbiSecContribV2);
229*0b57cec5SDimitry Andric     for (auto &SC : SectionContribs2)
230*0b57cec5SDimitry Andric       Visitor.visit(SC);
231*0b57cec5SDimitry Andric   }
232*0b57cec5SDimitry Andric }
233*0b57cec5SDimitry Andric 
getECName(uint32_t NI) const234*0b57cec5SDimitry Andric Expected<StringRef> DbiStream::getECName(uint32_t NI) const {
235*0b57cec5SDimitry Andric   return ECNames.getStringForID(NI);
236*0b57cec5SDimitry Andric }
237*0b57cec5SDimitry Andric 
initializeSectionContributionData()238*0b57cec5SDimitry Andric Error DbiStream::initializeSectionContributionData() {
239*0b57cec5SDimitry Andric   if (SecContrSubstream.empty())
240*0b57cec5SDimitry Andric     return Error::success();
241*0b57cec5SDimitry Andric 
242*0b57cec5SDimitry Andric   BinaryStreamReader SCReader(SecContrSubstream.StreamData);
243*0b57cec5SDimitry Andric   if (auto EC = SCReader.readEnum(SectionContribVersion))
244*0b57cec5SDimitry Andric     return EC;
245*0b57cec5SDimitry Andric 
246*0b57cec5SDimitry Andric   if (SectionContribVersion == DbiSecContribVer60)
247*0b57cec5SDimitry Andric     return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
248*0b57cec5SDimitry Andric   if (SectionContribVersion == DbiSecContribV2)
249*0b57cec5SDimitry Andric     return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
250*0b57cec5SDimitry Andric 
251*0b57cec5SDimitry Andric   return make_error<RawError>(raw_error_code::feature_unsupported,
252*0b57cec5SDimitry Andric                               "Unsupported DBI Section Contribution version");
253*0b57cec5SDimitry Andric }
254*0b57cec5SDimitry Andric 
255*0b57cec5SDimitry Andric // Initializes this->SectionHeaders.
initializeSectionHeadersData(PDBFile * Pdb)256*0b57cec5SDimitry Andric Error DbiStream::initializeSectionHeadersData(PDBFile *Pdb) {
257*0b57cec5SDimitry Andric   Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
258*0b57cec5SDimitry Andric       createIndexedStreamForHeaderType(Pdb, DbgHeaderType::SectionHdr);
259*0b57cec5SDimitry Andric   if (auto EC = ExpectedStream.takeError())
260*0b57cec5SDimitry Andric     return EC;
261*0b57cec5SDimitry Andric 
262*0b57cec5SDimitry Andric   auto &SHS = *ExpectedStream;
263*0b57cec5SDimitry Andric   if (!SHS)
264*0b57cec5SDimitry Andric     return Error::success();
265*0b57cec5SDimitry Andric 
266*0b57cec5SDimitry Andric   size_t StreamLen = SHS->getLength();
267*0b57cec5SDimitry Andric   if (StreamLen % sizeof(object::coff_section))
268*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
269*0b57cec5SDimitry Andric                                 "Corrupted section header stream.");
270*0b57cec5SDimitry Andric 
271*0b57cec5SDimitry Andric   size_t NumSections = StreamLen / sizeof(object::coff_section);
272*0b57cec5SDimitry Andric   BinaryStreamReader Reader(*SHS);
273*0b57cec5SDimitry Andric   if (auto EC = Reader.readArray(SectionHeaders, NumSections))
274*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
275*0b57cec5SDimitry Andric                                 "Could not read a bitmap.");
276*0b57cec5SDimitry Andric 
277*0b57cec5SDimitry Andric   SectionHeaderStream = std::move(SHS);
278*0b57cec5SDimitry Andric   return Error::success();
279*0b57cec5SDimitry Andric }
280*0b57cec5SDimitry Andric 
281*0b57cec5SDimitry Andric // Initializes this->Fpos.
initializeOldFpoRecords(PDBFile * Pdb)282*0b57cec5SDimitry Andric Error DbiStream::initializeOldFpoRecords(PDBFile *Pdb) {
283*0b57cec5SDimitry Andric   Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
284*0b57cec5SDimitry Andric       createIndexedStreamForHeaderType(Pdb, DbgHeaderType::FPO);
285*0b57cec5SDimitry Andric   if (auto EC = ExpectedStream.takeError())
286*0b57cec5SDimitry Andric     return EC;
287*0b57cec5SDimitry Andric 
288*0b57cec5SDimitry Andric   auto &FS = *ExpectedStream;
289*0b57cec5SDimitry Andric   if (!FS)
290*0b57cec5SDimitry Andric     return Error::success();
291*0b57cec5SDimitry Andric 
292*0b57cec5SDimitry Andric   size_t StreamLen = FS->getLength();
293*0b57cec5SDimitry Andric   if (StreamLen % sizeof(object::FpoData))
294*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
295*0b57cec5SDimitry Andric                                 "Corrupted Old FPO stream.");
296*0b57cec5SDimitry Andric 
297*0b57cec5SDimitry Andric   size_t NumRecords = StreamLen / sizeof(object::FpoData);
298*0b57cec5SDimitry Andric   BinaryStreamReader Reader(*FS);
299*0b57cec5SDimitry Andric   if (auto EC = Reader.readArray(OldFpoRecords, NumRecords))
300*0b57cec5SDimitry Andric     return make_error<RawError>(raw_error_code::corrupt_file,
301*0b57cec5SDimitry Andric                                 "Corrupted Old FPO stream.");
302*0b57cec5SDimitry Andric   OldFpoStream = std::move(FS);
303*0b57cec5SDimitry Andric   return Error::success();
304*0b57cec5SDimitry Andric }
305*0b57cec5SDimitry Andric 
initializeNewFpoRecords(PDBFile * Pdb)306*0b57cec5SDimitry Andric Error DbiStream::initializeNewFpoRecords(PDBFile *Pdb) {
307*0b57cec5SDimitry Andric   Expected<std::unique_ptr<msf::MappedBlockStream>> ExpectedStream =
308*0b57cec5SDimitry Andric       createIndexedStreamForHeaderType(Pdb, DbgHeaderType::NewFPO);
309*0b57cec5SDimitry Andric   if (auto EC = ExpectedStream.takeError())
310*0b57cec5SDimitry Andric     return EC;
311*0b57cec5SDimitry Andric 
312*0b57cec5SDimitry Andric   auto &FS = *ExpectedStream;
313*0b57cec5SDimitry Andric   if (!FS)
314*0b57cec5SDimitry Andric     return Error::success();
315*0b57cec5SDimitry Andric 
316*0b57cec5SDimitry Andric   if (auto EC = NewFpoRecords.initialize(*FS))
317*0b57cec5SDimitry Andric     return EC;
318*0b57cec5SDimitry Andric 
319*0b57cec5SDimitry Andric   NewFpoStream = std::move(FS);
320*0b57cec5SDimitry Andric   return Error::success();
321*0b57cec5SDimitry Andric }
322*0b57cec5SDimitry Andric 
323*0b57cec5SDimitry Andric Expected<std::unique_ptr<msf::MappedBlockStream>>
createIndexedStreamForHeaderType(PDBFile * Pdb,DbgHeaderType Type) const324*0b57cec5SDimitry Andric DbiStream::createIndexedStreamForHeaderType(PDBFile *Pdb,
325*0b57cec5SDimitry Andric                                             DbgHeaderType Type) const {
326*0b57cec5SDimitry Andric   if (!Pdb)
327*0b57cec5SDimitry Andric     return nullptr;
328*0b57cec5SDimitry Andric 
329*0b57cec5SDimitry Andric   if (DbgStreams.empty())
330*0b57cec5SDimitry Andric     return nullptr;
331*0b57cec5SDimitry Andric 
332*0b57cec5SDimitry Andric   uint32_t StreamNum = getDebugStreamIndex(Type);
333*0b57cec5SDimitry Andric 
334*0b57cec5SDimitry Andric   // This means there is no such stream.
335*0b57cec5SDimitry Andric   if (StreamNum == kInvalidStreamIndex)
336*0b57cec5SDimitry Andric     return nullptr;
337*0b57cec5SDimitry Andric 
338*0b57cec5SDimitry Andric   return Pdb->safelyCreateIndexedStream(StreamNum);
339*0b57cec5SDimitry Andric }
340*0b57cec5SDimitry Andric 
getSectionContributionData() const341*0b57cec5SDimitry Andric BinarySubstreamRef DbiStream::getSectionContributionData() const {
342*0b57cec5SDimitry Andric   return SecContrSubstream;
343*0b57cec5SDimitry Andric }
344*0b57cec5SDimitry Andric 
getSecMapSubstreamData() const345*0b57cec5SDimitry Andric BinarySubstreamRef DbiStream::getSecMapSubstreamData() const {
346*0b57cec5SDimitry Andric   return SecMapSubstream;
347*0b57cec5SDimitry Andric }
348*0b57cec5SDimitry Andric 
getModiSubstreamData() const349*0b57cec5SDimitry Andric BinarySubstreamRef DbiStream::getModiSubstreamData() const {
350*0b57cec5SDimitry Andric   return ModiSubstream;
351*0b57cec5SDimitry Andric }
352*0b57cec5SDimitry Andric 
getFileInfoSubstreamData() const353*0b57cec5SDimitry Andric BinarySubstreamRef DbiStream::getFileInfoSubstreamData() const {
354*0b57cec5SDimitry Andric   return FileInfoSubstream;
355*0b57cec5SDimitry Andric }
356*0b57cec5SDimitry Andric 
getTypeServerMapSubstreamData() const357*0b57cec5SDimitry Andric BinarySubstreamRef DbiStream::getTypeServerMapSubstreamData() const {
358*0b57cec5SDimitry Andric   return TypeServerMapSubstream;
359*0b57cec5SDimitry Andric }
360*0b57cec5SDimitry Andric 
getECSubstreamData() const361*0b57cec5SDimitry Andric BinarySubstreamRef DbiStream::getECSubstreamData() const { return ECSubstream; }
362*0b57cec5SDimitry Andric 
initializeSectionMapData()363*0b57cec5SDimitry Andric Error DbiStream::initializeSectionMapData() {
364*0b57cec5SDimitry Andric   if (SecMapSubstream.empty())
365*0b57cec5SDimitry Andric     return Error::success();
366*0b57cec5SDimitry Andric 
367*0b57cec5SDimitry Andric   BinaryStreamReader SMReader(SecMapSubstream.StreamData);
368*0b57cec5SDimitry Andric   const SecMapHeader *Header;
369*0b57cec5SDimitry Andric   if (auto EC = SMReader.readObject(Header))
370*0b57cec5SDimitry Andric     return EC;
371*0b57cec5SDimitry Andric   if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
372*0b57cec5SDimitry Andric     return EC;
373*0b57cec5SDimitry Andric   return Error::success();
374*0b57cec5SDimitry Andric }
375*0b57cec5SDimitry Andric 
getDebugStreamIndex(DbgHeaderType Type) const376*0b57cec5SDimitry Andric uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
377*0b57cec5SDimitry Andric   uint16_t T = static_cast<uint16_t>(Type);
378*0b57cec5SDimitry Andric   if (T >= DbgStreams.size())
379*0b57cec5SDimitry Andric     return kInvalidStreamIndex;
380*0b57cec5SDimitry Andric   return DbgStreams[T];
381*0b57cec5SDimitry Andric }
382