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