xref: /llvm-project/llvm/lib/DebugInfo/PDB/Native/DbiStream.cpp (revision 695ed56ba5d3bd3b86c6a4ed6d79b89eb8fbd2f4)
16b6b8c4fSAdrian McCarthy //===- DbiStream.cpp - PDB Dbi Stream (Stream 3) Access -------------------===//
26b6b8c4fSAdrian McCarthy //
36b6b8c4fSAdrian McCarthy //                     The LLVM Compiler Infrastructure
46b6b8c4fSAdrian McCarthy //
56b6b8c4fSAdrian McCarthy // This file is distributed under the University of Illinois Open Source
66b6b8c4fSAdrian McCarthy // License. See LICENSE.TXT for details.
76b6b8c4fSAdrian McCarthy //
86b6b8c4fSAdrian McCarthy //===----------------------------------------------------------------------===//
96b6b8c4fSAdrian McCarthy 
106b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
116b6b8c4fSAdrian McCarthy #include "llvm/ADT/StringRef.h"
12d2684b79SZachary Turner #include "llvm/DebugInfo/MSF/BinaryStreamArray.h"
13d2684b79SZachary Turner #include "llvm/DebugInfo/MSF/BinaryStreamReader.h"
146b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
156b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/ISectionContribVisitor.h"
166b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
176b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/ModInfo.h"
186b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
196b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
206b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/RawError.h"
216b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
226b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/PDBTypes.h"
236b6b8c4fSAdrian McCarthy #include "llvm/Object/COFF.h"
246b6b8c4fSAdrian McCarthy #include "llvm/Support/Error.h"
256b6b8c4fSAdrian McCarthy #include <algorithm>
266b6b8c4fSAdrian McCarthy #include <cstddef>
276b6b8c4fSAdrian McCarthy #include <cstdint>
286b6b8c4fSAdrian McCarthy 
296b6b8c4fSAdrian McCarthy using namespace llvm;
306b6b8c4fSAdrian McCarthy using namespace llvm::codeview;
316b6b8c4fSAdrian McCarthy using namespace llvm::msf;
326b6b8c4fSAdrian McCarthy using namespace llvm::pdb;
336b6b8c4fSAdrian McCarthy using namespace llvm::support;
346b6b8c4fSAdrian McCarthy 
356b6b8c4fSAdrian McCarthy template <typename ContribType>
366b6b8c4fSAdrian McCarthy static Error loadSectionContribs(FixedStreamArray<ContribType> &Output,
37120faca4SZachary Turner                                  BinaryStreamReader &Reader) {
386b6b8c4fSAdrian McCarthy   if (Reader.bytesRemaining() % sizeof(ContribType) != 0)
396b6b8c4fSAdrian McCarthy     return make_error<RawError>(
406b6b8c4fSAdrian McCarthy         raw_error_code::corrupt_file,
416b6b8c4fSAdrian McCarthy         "Invalid number of bytes of section contributions");
426b6b8c4fSAdrian McCarthy 
436b6b8c4fSAdrian McCarthy   uint32_t Count = Reader.bytesRemaining() / sizeof(ContribType);
446b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readArray(Output, Count))
456b6b8c4fSAdrian McCarthy     return EC;
466b6b8c4fSAdrian McCarthy   return Error::success();
476b6b8c4fSAdrian McCarthy }
486b6b8c4fSAdrian McCarthy 
496b6b8c4fSAdrian McCarthy DbiStream::DbiStream(PDBFile &File, std::unique_ptr<MappedBlockStream> Stream)
506b6b8c4fSAdrian McCarthy     : Pdb(File), Stream(std::move(Stream)), Header(nullptr) {}
516b6b8c4fSAdrian McCarthy 
526b6b8c4fSAdrian McCarthy DbiStream::~DbiStream() = default;
536b6b8c4fSAdrian McCarthy 
546b6b8c4fSAdrian McCarthy Error DbiStream::reload() {
55120faca4SZachary Turner   BinaryStreamReader Reader(*Stream);
566b6b8c4fSAdrian McCarthy 
576b6b8c4fSAdrian McCarthy   if (Stream->getLength() < sizeof(DbiStreamHeader))
586b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
596b6b8c4fSAdrian McCarthy                                 "DBI Stream does not contain a header.");
606b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readObject(Header))
616b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
626b6b8c4fSAdrian McCarthy                                 "DBI Stream does not contain a header.");
636b6b8c4fSAdrian McCarthy 
646b6b8c4fSAdrian McCarthy   if (Header->VersionSignature != -1)
656b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
666b6b8c4fSAdrian McCarthy                                 "Invalid DBI version signature.");
676b6b8c4fSAdrian McCarthy 
686b6b8c4fSAdrian McCarthy   // Require at least version 7, which should be present in all PDBs
696b6b8c4fSAdrian McCarthy   // produced in the last decade and allows us to avoid having to
706b6b8c4fSAdrian McCarthy   // special case all kinds of complicated arcane formats.
716b6b8c4fSAdrian McCarthy   if (Header->VersionHeader < PdbDbiV70)
726b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::feature_unsupported,
736b6b8c4fSAdrian McCarthy                                 "Unsupported DBI version.");
746b6b8c4fSAdrian McCarthy 
756b6b8c4fSAdrian McCarthy   auto IS = Pdb.getPDBInfoStream();
766b6b8c4fSAdrian McCarthy   if (!IS)
776b6b8c4fSAdrian McCarthy     return IS.takeError();
786b6b8c4fSAdrian McCarthy 
796b6b8c4fSAdrian McCarthy   if (Header->Age != IS->getAge())
806b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
816b6b8c4fSAdrian McCarthy                                 "DBI Age does not match PDB Age.");
826b6b8c4fSAdrian McCarthy 
836b6b8c4fSAdrian McCarthy   if (Stream->getLength() !=
846b6b8c4fSAdrian McCarthy       sizeof(DbiStreamHeader) + Header->ModiSubstreamSize +
856b6b8c4fSAdrian McCarthy           Header->SecContrSubstreamSize + Header->SectionMapSize +
866b6b8c4fSAdrian McCarthy           Header->FileInfoSize + Header->TypeServerSize +
876b6b8c4fSAdrian McCarthy           Header->OptionalDbgHdrSize + Header->ECSubstreamSize)
886b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
896b6b8c4fSAdrian McCarthy                                 "DBI Length does not equal sum of substreams.");
906b6b8c4fSAdrian McCarthy 
916b6b8c4fSAdrian McCarthy   // Only certain substreams are guaranteed to be aligned.  Validate
926b6b8c4fSAdrian McCarthy   // them here.
936b6b8c4fSAdrian McCarthy   if (Header->ModiSubstreamSize % sizeof(uint32_t) != 0)
946b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
956b6b8c4fSAdrian McCarthy                                 "DBI MODI substream not aligned.");
966b6b8c4fSAdrian McCarthy   if (Header->SecContrSubstreamSize % sizeof(uint32_t) != 0)
976b6b8c4fSAdrian McCarthy     return make_error<RawError>(
986b6b8c4fSAdrian McCarthy         raw_error_code::corrupt_file,
996b6b8c4fSAdrian McCarthy         "DBI section contribution substream not aligned.");
1006b6b8c4fSAdrian McCarthy   if (Header->SectionMapSize % sizeof(uint32_t) != 0)
1016b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
1026b6b8c4fSAdrian McCarthy                                 "DBI section map substream not aligned.");
1036b6b8c4fSAdrian McCarthy   if (Header->FileInfoSize % sizeof(uint32_t) != 0)
1046b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
1056b6b8c4fSAdrian McCarthy                                 "DBI file info substream not aligned.");
1066b6b8c4fSAdrian McCarthy   if (Header->TypeServerSize % sizeof(uint32_t) != 0)
1076b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
1086b6b8c4fSAdrian McCarthy                                 "DBI type server substream not aligned.");
1096b6b8c4fSAdrian McCarthy 
1106b6b8c4fSAdrian McCarthy   if (auto EC =
1116b6b8c4fSAdrian McCarthy           Reader.readStreamRef(ModInfoSubstream, Header->ModiSubstreamSize))
1126b6b8c4fSAdrian McCarthy     return EC;
1136b6b8c4fSAdrian McCarthy   if (auto EC = initializeModInfoArray())
1146b6b8c4fSAdrian McCarthy     return EC;
1156b6b8c4fSAdrian McCarthy 
1166b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readStreamRef(SecContrSubstream,
1176b6b8c4fSAdrian McCarthy                                      Header->SecContrSubstreamSize))
1186b6b8c4fSAdrian McCarthy     return EC;
1196b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readStreamRef(SecMapSubstream, Header->SectionMapSize))
1206b6b8c4fSAdrian McCarthy     return EC;
1216b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readStreamRef(FileInfoSubstream, Header->FileInfoSize))
1226b6b8c4fSAdrian McCarthy     return EC;
1236b6b8c4fSAdrian McCarthy   if (auto EC =
1246b6b8c4fSAdrian McCarthy           Reader.readStreamRef(TypeServerMapSubstream, Header->TypeServerSize))
1256b6b8c4fSAdrian McCarthy     return EC;
1266b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readStreamRef(ECSubstream, Header->ECSubstreamSize))
1276b6b8c4fSAdrian McCarthy     return EC;
1286b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readArray(
1296b6b8c4fSAdrian McCarthy           DbgStreams, Header->OptionalDbgHdrSize / sizeof(ulittle16_t)))
1306b6b8c4fSAdrian McCarthy     return EC;
1316b6b8c4fSAdrian McCarthy 
1326b6b8c4fSAdrian McCarthy   if (auto EC = initializeSectionContributionData())
1336b6b8c4fSAdrian McCarthy     return EC;
1346b6b8c4fSAdrian McCarthy   if (auto EC = initializeSectionHeadersData())
1356b6b8c4fSAdrian McCarthy     return EC;
1366b6b8c4fSAdrian McCarthy   if (auto EC = initializeSectionMapData())
1376b6b8c4fSAdrian McCarthy     return EC;
1386b6b8c4fSAdrian McCarthy   if (auto EC = initializeFileInfo())
1396b6b8c4fSAdrian McCarthy     return EC;
1406b6b8c4fSAdrian McCarthy   if (auto EC = initializeFpoRecords())
1416b6b8c4fSAdrian McCarthy     return EC;
1426b6b8c4fSAdrian McCarthy 
1436b6b8c4fSAdrian McCarthy   if (Reader.bytesRemaining() > 0)
1446b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
1456b6b8c4fSAdrian McCarthy                                 "Found unexpected bytes in DBI Stream.");
1466b6b8c4fSAdrian McCarthy 
1476b6b8c4fSAdrian McCarthy   if (ECSubstream.getLength() > 0) {
148120faca4SZachary Turner     BinaryStreamReader ECReader(ECSubstream);
1496b6b8c4fSAdrian McCarthy     if (auto EC = ECNames.load(ECReader))
1506b6b8c4fSAdrian McCarthy       return EC;
1516b6b8c4fSAdrian McCarthy   }
1526b6b8c4fSAdrian McCarthy 
1536b6b8c4fSAdrian McCarthy   return Error::success();
1546b6b8c4fSAdrian McCarthy }
1556b6b8c4fSAdrian McCarthy 
1566b6b8c4fSAdrian McCarthy PdbRaw_DbiVer DbiStream::getDbiVersion() const {
1576b6b8c4fSAdrian McCarthy   uint32_t Value = Header->VersionHeader;
1586b6b8c4fSAdrian McCarthy   return static_cast<PdbRaw_DbiVer>(Value);
1596b6b8c4fSAdrian McCarthy }
1606b6b8c4fSAdrian McCarthy 
1616b6b8c4fSAdrian McCarthy uint32_t DbiStream::getAge() const { return Header->Age; }
1626b6b8c4fSAdrian McCarthy 
1636b6b8c4fSAdrian McCarthy uint16_t DbiStream::getPublicSymbolStreamIndex() const {
1646b6b8c4fSAdrian McCarthy   return Header->PublicSymbolStreamIndex;
1656b6b8c4fSAdrian McCarthy }
1666b6b8c4fSAdrian McCarthy 
1676b6b8c4fSAdrian McCarthy uint16_t DbiStream::getGlobalSymbolStreamIndex() const {
1686b6b8c4fSAdrian McCarthy   return Header->GlobalSymbolStreamIndex;
1696b6b8c4fSAdrian McCarthy }
1706b6b8c4fSAdrian McCarthy 
1716b6b8c4fSAdrian McCarthy uint16_t DbiStream::getFlags() const { return Header->Flags; }
1726b6b8c4fSAdrian McCarthy 
1736b6b8c4fSAdrian McCarthy bool DbiStream::isIncrementallyLinked() const {
1746b6b8c4fSAdrian McCarthy   return (Header->Flags & DbiFlags::FlagIncrementalMask) != 0;
1756b6b8c4fSAdrian McCarthy }
1766b6b8c4fSAdrian McCarthy 
1776b6b8c4fSAdrian McCarthy bool DbiStream::hasCTypes() const {
1786b6b8c4fSAdrian McCarthy   return (Header->Flags & DbiFlags::FlagHasCTypesMask) != 0;
1796b6b8c4fSAdrian McCarthy }
1806b6b8c4fSAdrian McCarthy 
1816b6b8c4fSAdrian McCarthy bool DbiStream::isStripped() const {
1826b6b8c4fSAdrian McCarthy   return (Header->Flags & DbiFlags::FlagStrippedMask) != 0;
1836b6b8c4fSAdrian McCarthy }
1846b6b8c4fSAdrian McCarthy 
1856b6b8c4fSAdrian McCarthy uint16_t DbiStream::getBuildNumber() const { return Header->BuildNumber; }
1866b6b8c4fSAdrian McCarthy 
1876b6b8c4fSAdrian McCarthy uint16_t DbiStream::getBuildMajorVersion() const {
1886b6b8c4fSAdrian McCarthy   return (Header->BuildNumber & DbiBuildNo::BuildMajorMask) >>
1896b6b8c4fSAdrian McCarthy          DbiBuildNo::BuildMajorShift;
1906b6b8c4fSAdrian McCarthy }
1916b6b8c4fSAdrian McCarthy 
1926b6b8c4fSAdrian McCarthy uint16_t DbiStream::getBuildMinorVersion() const {
1936b6b8c4fSAdrian McCarthy   return (Header->BuildNumber & DbiBuildNo::BuildMinorMask) >>
1946b6b8c4fSAdrian McCarthy          DbiBuildNo::BuildMinorShift;
1956b6b8c4fSAdrian McCarthy }
1966b6b8c4fSAdrian McCarthy 
1976b6b8c4fSAdrian McCarthy uint16_t DbiStream::getPdbDllRbld() const { return Header->PdbDllRbld; }
1986b6b8c4fSAdrian McCarthy 
1996b6b8c4fSAdrian McCarthy uint32_t DbiStream::getPdbDllVersion() const { return Header->PdbDllVersion; }
2006b6b8c4fSAdrian McCarthy 
2016b6b8c4fSAdrian McCarthy uint32_t DbiStream::getSymRecordStreamIndex() const {
2026b6b8c4fSAdrian McCarthy   return Header->SymRecordStreamIndex;
2036b6b8c4fSAdrian McCarthy }
2046b6b8c4fSAdrian McCarthy 
2056b6b8c4fSAdrian McCarthy PDB_Machine DbiStream::getMachineType() const {
2066b6b8c4fSAdrian McCarthy   uint16_t Machine = Header->MachineType;
2076b6b8c4fSAdrian McCarthy   return static_cast<PDB_Machine>(Machine);
2086b6b8c4fSAdrian McCarthy }
2096b6b8c4fSAdrian McCarthy 
210120faca4SZachary Turner FixedStreamArray<object::coff_section> DbiStream::getSectionHeaders() {
2116b6b8c4fSAdrian McCarthy   return SectionHeaders;
2126b6b8c4fSAdrian McCarthy }
2136b6b8c4fSAdrian McCarthy 
214120faca4SZachary Turner FixedStreamArray<object::FpoData> DbiStream::getFpoRecords() {
2156b6b8c4fSAdrian McCarthy   return FpoRecords;
2166b6b8c4fSAdrian McCarthy }
2176b6b8c4fSAdrian McCarthy 
2186b6b8c4fSAdrian McCarthy ArrayRef<ModuleInfoEx> DbiStream::modules() const { return ModuleInfos; }
219120faca4SZachary Turner FixedStreamArray<SecMapEntry> DbiStream::getSectionMap() const {
2206b6b8c4fSAdrian McCarthy   return SectionMap;
2216b6b8c4fSAdrian McCarthy }
2226b6b8c4fSAdrian McCarthy 
2236b6b8c4fSAdrian McCarthy void DbiStream::visitSectionContributions(
2246b6b8c4fSAdrian McCarthy     ISectionContribVisitor &Visitor) const {
2256b6b8c4fSAdrian McCarthy   if (SectionContribVersion == DbiSecContribVer60) {
2266b6b8c4fSAdrian McCarthy     for (auto &SC : SectionContribs)
2276b6b8c4fSAdrian McCarthy       Visitor.visit(SC);
2286b6b8c4fSAdrian McCarthy   } else if (SectionContribVersion == DbiSecContribV2) {
2296b6b8c4fSAdrian McCarthy     for (auto &SC : SectionContribs2)
2306b6b8c4fSAdrian McCarthy       Visitor.visit(SC);
2316b6b8c4fSAdrian McCarthy   }
2326b6b8c4fSAdrian McCarthy }
2336b6b8c4fSAdrian McCarthy 
2346b6b8c4fSAdrian McCarthy Error DbiStream::initializeSectionContributionData() {
2356b6b8c4fSAdrian McCarthy   if (SecContrSubstream.getLength() == 0)
2366b6b8c4fSAdrian McCarthy     return Error::success();
2376b6b8c4fSAdrian McCarthy 
238120faca4SZachary Turner   BinaryStreamReader SCReader(SecContrSubstream);
239*695ed56bSZachary Turner   if (auto EC = SCReader.readEnum(SectionContribVersion))
2406b6b8c4fSAdrian McCarthy     return EC;
2416b6b8c4fSAdrian McCarthy 
2426b6b8c4fSAdrian McCarthy   if (SectionContribVersion == DbiSecContribVer60)
2436b6b8c4fSAdrian McCarthy     return loadSectionContribs<SectionContrib>(SectionContribs, SCReader);
2446b6b8c4fSAdrian McCarthy   if (SectionContribVersion == DbiSecContribV2)
2456b6b8c4fSAdrian McCarthy     return loadSectionContribs<SectionContrib2>(SectionContribs2, SCReader);
2466b6b8c4fSAdrian McCarthy 
2476b6b8c4fSAdrian McCarthy   return make_error<RawError>(raw_error_code::feature_unsupported,
2486b6b8c4fSAdrian McCarthy                               "Unsupported DBI Section Contribution version");
2496b6b8c4fSAdrian McCarthy }
2506b6b8c4fSAdrian McCarthy 
2516b6b8c4fSAdrian McCarthy Error DbiStream::initializeModInfoArray() {
2526b6b8c4fSAdrian McCarthy   if (ModInfoSubstream.getLength() == 0)
2536b6b8c4fSAdrian McCarthy     return Error::success();
2546b6b8c4fSAdrian McCarthy 
2556b6b8c4fSAdrian McCarthy   // Since each ModInfo in the stream is a variable length, we have to iterate
2566b6b8c4fSAdrian McCarthy   // them to know how many there actually are.
257120faca4SZachary Turner   BinaryStreamReader Reader(ModInfoSubstream);
2586b6b8c4fSAdrian McCarthy 
2596b6b8c4fSAdrian McCarthy   VarStreamArray<ModInfo> ModInfoArray;
2606b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readArray(ModInfoArray, ModInfoSubstream.getLength()))
2616b6b8c4fSAdrian McCarthy     return EC;
2626b6b8c4fSAdrian McCarthy   for (auto &Info : ModInfoArray) {
2636b6b8c4fSAdrian McCarthy     ModuleInfos.emplace_back(Info);
2646b6b8c4fSAdrian McCarthy   }
2656b6b8c4fSAdrian McCarthy 
2666b6b8c4fSAdrian McCarthy   return Error::success();
2676b6b8c4fSAdrian McCarthy }
2686b6b8c4fSAdrian McCarthy 
2696b6b8c4fSAdrian McCarthy // Initializes this->SectionHeaders.
2706b6b8c4fSAdrian McCarthy Error DbiStream::initializeSectionHeadersData() {
2716b6b8c4fSAdrian McCarthy   if (DbgStreams.size() == 0)
2726b6b8c4fSAdrian McCarthy     return Error::success();
2736b6b8c4fSAdrian McCarthy 
2746b6b8c4fSAdrian McCarthy   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::SectionHdr);
2756b6b8c4fSAdrian McCarthy   if (StreamNum >= Pdb.getNumStreams())
2766b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::no_stream);
2776b6b8c4fSAdrian McCarthy 
2786b6b8c4fSAdrian McCarthy   auto SHS = MappedBlockStream::createIndexedStream(
2796b6b8c4fSAdrian McCarthy       Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
2806b6b8c4fSAdrian McCarthy 
2816b6b8c4fSAdrian McCarthy   size_t StreamLen = SHS->getLength();
2826b6b8c4fSAdrian McCarthy   if (StreamLen % sizeof(object::coff_section))
2836b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
2846b6b8c4fSAdrian McCarthy                                 "Corrupted section header stream.");
2856b6b8c4fSAdrian McCarthy 
2866b6b8c4fSAdrian McCarthy   size_t NumSections = StreamLen / sizeof(object::coff_section);
287120faca4SZachary Turner   BinaryStreamReader Reader(*SHS);
2886b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readArray(SectionHeaders, NumSections))
2896b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
2906b6b8c4fSAdrian McCarthy                                 "Could not read a bitmap.");
2916b6b8c4fSAdrian McCarthy 
2926b6b8c4fSAdrian McCarthy   SectionHeaderStream = std::move(SHS);
2936b6b8c4fSAdrian McCarthy   return Error::success();
2946b6b8c4fSAdrian McCarthy }
2956b6b8c4fSAdrian McCarthy 
2966b6b8c4fSAdrian McCarthy // Initializes this->Fpos.
2976b6b8c4fSAdrian McCarthy Error DbiStream::initializeFpoRecords() {
2986b6b8c4fSAdrian McCarthy   if (DbgStreams.size() == 0)
2996b6b8c4fSAdrian McCarthy     return Error::success();
3006b6b8c4fSAdrian McCarthy 
3016b6b8c4fSAdrian McCarthy   uint32_t StreamNum = getDebugStreamIndex(DbgHeaderType::NewFPO);
3026b6b8c4fSAdrian McCarthy 
3036b6b8c4fSAdrian McCarthy   // This means there is no FPO data.
3046b6b8c4fSAdrian McCarthy   if (StreamNum == kInvalidStreamIndex)
3056b6b8c4fSAdrian McCarthy     return Error::success();
3066b6b8c4fSAdrian McCarthy 
3076b6b8c4fSAdrian McCarthy   if (StreamNum >= Pdb.getNumStreams())
3086b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::no_stream);
3096b6b8c4fSAdrian McCarthy 
3106b6b8c4fSAdrian McCarthy   auto FS = MappedBlockStream::createIndexedStream(
3116b6b8c4fSAdrian McCarthy       Pdb.getMsfLayout(), Pdb.getMsfBuffer(), StreamNum);
3126b6b8c4fSAdrian McCarthy 
3136b6b8c4fSAdrian McCarthy   size_t StreamLen = FS->getLength();
3146b6b8c4fSAdrian McCarthy   if (StreamLen % sizeof(object::FpoData))
3156b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
3166b6b8c4fSAdrian McCarthy                                 "Corrupted New FPO stream.");
3176b6b8c4fSAdrian McCarthy 
3186b6b8c4fSAdrian McCarthy   size_t NumRecords = StreamLen / sizeof(object::FpoData);
319120faca4SZachary Turner   BinaryStreamReader Reader(*FS);
3206b6b8c4fSAdrian McCarthy   if (auto EC = Reader.readArray(FpoRecords, NumRecords))
3216b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
3226b6b8c4fSAdrian McCarthy                                 "Corrupted New FPO stream.");
3236b6b8c4fSAdrian McCarthy   FpoStream = std::move(FS);
3246b6b8c4fSAdrian McCarthy   return Error::success();
3256b6b8c4fSAdrian McCarthy }
3266b6b8c4fSAdrian McCarthy 
3276b6b8c4fSAdrian McCarthy Error DbiStream::initializeSectionMapData() {
3286b6b8c4fSAdrian McCarthy   if (SecMapSubstream.getLength() == 0)
3296b6b8c4fSAdrian McCarthy     return Error::success();
3306b6b8c4fSAdrian McCarthy 
331120faca4SZachary Turner   BinaryStreamReader SMReader(SecMapSubstream);
3326b6b8c4fSAdrian McCarthy   const SecMapHeader *Header;
3336b6b8c4fSAdrian McCarthy   if (auto EC = SMReader.readObject(Header))
3346b6b8c4fSAdrian McCarthy     return EC;
3356b6b8c4fSAdrian McCarthy   if (auto EC = SMReader.readArray(SectionMap, Header->SecCount))
3366b6b8c4fSAdrian McCarthy     return EC;
3376b6b8c4fSAdrian McCarthy   return Error::success();
3386b6b8c4fSAdrian McCarthy }
3396b6b8c4fSAdrian McCarthy 
3406b6b8c4fSAdrian McCarthy Error DbiStream::initializeFileInfo() {
3416b6b8c4fSAdrian McCarthy   if (FileInfoSubstream.getLength() == 0)
3426b6b8c4fSAdrian McCarthy     return Error::success();
3436b6b8c4fSAdrian McCarthy 
3446b6b8c4fSAdrian McCarthy   const FileInfoSubstreamHeader *FH;
345120faca4SZachary Turner   BinaryStreamReader FISR(FileInfoSubstream);
3466b6b8c4fSAdrian McCarthy   if (auto EC = FISR.readObject(FH))
3476b6b8c4fSAdrian McCarthy     return EC;
3486b6b8c4fSAdrian McCarthy 
3496b6b8c4fSAdrian McCarthy   // The number of modules in the stream should be the same as reported by
3506b6b8c4fSAdrian McCarthy   // the FileInfoSubstreamHeader.
3516b6b8c4fSAdrian McCarthy   if (FH->NumModules != ModuleInfos.size())
3526b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::corrupt_file,
3536b6b8c4fSAdrian McCarthy                                 "FileInfo substream count doesn't match DBI.");
3546b6b8c4fSAdrian McCarthy 
3556b6b8c4fSAdrian McCarthy   FixedStreamArray<ulittle16_t> ModIndexArray;
3566b6b8c4fSAdrian McCarthy   FixedStreamArray<ulittle16_t> ModFileCountArray;
3576b6b8c4fSAdrian McCarthy 
3586b6b8c4fSAdrian McCarthy   // First is an array of `NumModules` module indices.  This is not used for the
3596b6b8c4fSAdrian McCarthy   // same reason that `NumSourceFiles` is not used.  It's an array of uint16's,
3606b6b8c4fSAdrian McCarthy   // but it's possible there are more than 64k source files, which would imply
3616b6b8c4fSAdrian McCarthy   // more than 64k modules (e.g. object files) as well.  So we ignore this
3626b6b8c4fSAdrian McCarthy   // field.
3636b6b8c4fSAdrian McCarthy   if (auto EC = FISR.readArray(ModIndexArray, ModuleInfos.size()))
3646b6b8c4fSAdrian McCarthy     return EC;
3656b6b8c4fSAdrian McCarthy   if (auto EC = FISR.readArray(ModFileCountArray, ModuleInfos.size()))
3666b6b8c4fSAdrian McCarthy     return EC;
3676b6b8c4fSAdrian McCarthy 
3686b6b8c4fSAdrian McCarthy   // Compute the real number of source files.
3696b6b8c4fSAdrian McCarthy   uint32_t NumSourceFiles = 0;
3706b6b8c4fSAdrian McCarthy   for (auto Count : ModFileCountArray)
3716b6b8c4fSAdrian McCarthy     NumSourceFiles += Count;
3726b6b8c4fSAdrian McCarthy 
3736b6b8c4fSAdrian McCarthy   // This is the array that in the reference implementation corresponds to
3746b6b8c4fSAdrian McCarthy   // `ModInfo::FileLayout::FileNameOffs`, which is commented there as being a
3756b6b8c4fSAdrian McCarthy   // pointer. Due to the mentioned problems of pointers causing difficulty
3766b6b8c4fSAdrian McCarthy   // when reading from the file on 64-bit systems, we continue to ignore that
3776b6b8c4fSAdrian McCarthy   // field in `ModInfo`, and instead build a vector of StringRefs and stores
3786b6b8c4fSAdrian McCarthy   // them in `ModuleInfoEx`.  The value written to and read from the file is
3796b6b8c4fSAdrian McCarthy   // not used anyway, it is only there as a way to store the offsets for the
3806b6b8c4fSAdrian McCarthy   // purposes of later accessing the names at runtime.
3816b6b8c4fSAdrian McCarthy   if (auto EC = FISR.readArray(FileNameOffsets, NumSourceFiles))
3826b6b8c4fSAdrian McCarthy     return EC;
3836b6b8c4fSAdrian McCarthy 
3846b6b8c4fSAdrian McCarthy   if (auto EC = FISR.readStreamRef(NamesBuffer))
3856b6b8c4fSAdrian McCarthy     return EC;
3866b6b8c4fSAdrian McCarthy 
3876b6b8c4fSAdrian McCarthy   // We go through each ModuleInfo, determine the number N of source files for
3886b6b8c4fSAdrian McCarthy   // that module, and then get the next N offsets from the Offsets array, using
3896b6b8c4fSAdrian McCarthy   // them to get the corresponding N names from the Names buffer and associating
3906b6b8c4fSAdrian McCarthy   // each one with the corresponding module.
3916b6b8c4fSAdrian McCarthy   uint32_t NextFileIndex = 0;
3926b6b8c4fSAdrian McCarthy   for (size_t I = 0; I < ModuleInfos.size(); ++I) {
3936b6b8c4fSAdrian McCarthy     uint32_t NumFiles = ModFileCountArray[I];
3946b6b8c4fSAdrian McCarthy     ModuleInfos[I].SourceFiles.resize(NumFiles);
3956b6b8c4fSAdrian McCarthy     for (size_t J = 0; J < NumFiles; ++J, ++NextFileIndex) {
3966b6b8c4fSAdrian McCarthy       auto ThisName = getFileNameForIndex(NextFileIndex);
3976b6b8c4fSAdrian McCarthy       if (!ThisName)
3986b6b8c4fSAdrian McCarthy         return ThisName.takeError();
3996b6b8c4fSAdrian McCarthy       ModuleInfos[I].SourceFiles[J] = *ThisName;
4006b6b8c4fSAdrian McCarthy     }
4016b6b8c4fSAdrian McCarthy   }
4026b6b8c4fSAdrian McCarthy 
4036b6b8c4fSAdrian McCarthy   return Error::success();
4046b6b8c4fSAdrian McCarthy }
4056b6b8c4fSAdrian McCarthy 
4066b6b8c4fSAdrian McCarthy uint32_t DbiStream::getDebugStreamIndex(DbgHeaderType Type) const {
4076b6b8c4fSAdrian McCarthy   uint16_t T = static_cast<uint16_t>(Type);
4086b6b8c4fSAdrian McCarthy   if (T >= DbgStreams.size())
4096b6b8c4fSAdrian McCarthy     return kInvalidStreamIndex;
4106b6b8c4fSAdrian McCarthy   return DbgStreams[T];
4116b6b8c4fSAdrian McCarthy }
4126b6b8c4fSAdrian McCarthy 
4136b6b8c4fSAdrian McCarthy Expected<StringRef> DbiStream::getFileNameForIndex(uint32_t Index) const {
414120faca4SZachary Turner   BinaryStreamReader Names(NamesBuffer);
4156b6b8c4fSAdrian McCarthy   if (Index >= FileNameOffsets.size())
4166b6b8c4fSAdrian McCarthy     return make_error<RawError>(raw_error_code::index_out_of_bounds);
4176b6b8c4fSAdrian McCarthy 
4186b6b8c4fSAdrian McCarthy   uint32_t FileOffset = FileNameOffsets[Index];
4196b6b8c4fSAdrian McCarthy   Names.setOffset(FileOffset);
4206b6b8c4fSAdrian McCarthy   StringRef Name;
421120faca4SZachary Turner   if (auto EC = Names.readCString(Name))
4226b6b8c4fSAdrian McCarthy     return std::move(EC);
4236b6b8c4fSAdrian McCarthy   return Name;
4246b6b8c4fSAdrian McCarthy }
425