10b57cec5SDimitry Andric //===- PDBFileBuilder.cpp - PDB File Creation -------------------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h" 1006c3fb27SDimitry Andric #include "llvm/ADT/SmallString.h" 1106c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 1281ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeView.h" 1381ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/GUID.h" 140b57cec5SDimitry Andric #include "llvm/DebugInfo/MSF/MSFBuilder.h" 1581ad6265SDimitry Andric #include "llvm/DebugInfo/MSF/MSFCommon.h" 1681ad6265SDimitry Andric #include "llvm/DebugInfo/MSF/MappedBlockStream.h" 170b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" 180b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" 190b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" 200b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" 2181ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawConstants.h" 220b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawError.h" 2381ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawTypes.h" 240b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h" 250b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h" 268bcb0991SDimitry Andric #include "llvm/Support/CRC.h" 270b57cec5SDimitry Andric #include "llvm/Support/Path.h" 28*5f757f3fSDimitry Andric #include "llvm/Support/TimeProfiler.h" 290b57cec5SDimitry Andric #include "llvm/Support/xxhash.h" 300b57cec5SDimitry Andric 3181ad6265SDimitry Andric #include <ctime> 3281ad6265SDimitry Andric 330b57cec5SDimitry Andric using namespace llvm; 340b57cec5SDimitry Andric using namespace llvm::codeview; 350b57cec5SDimitry Andric using namespace llvm::msf; 360b57cec5SDimitry Andric using namespace llvm::pdb; 370b57cec5SDimitry Andric using namespace llvm::support; 380b57cec5SDimitry Andric 3981ad6265SDimitry Andric namespace llvm { 4081ad6265SDimitry Andric class WritableBinaryStream; 4181ad6265SDimitry Andric } 4281ad6265SDimitry Andric 430b57cec5SDimitry Andric PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator) 440b57cec5SDimitry Andric : Allocator(Allocator), InjectedSourceHashTraits(Strings), 450b57cec5SDimitry Andric InjectedSourceTable(2) {} 460b57cec5SDimitry Andric 4781ad6265SDimitry Andric PDBFileBuilder::~PDBFileBuilder() = default; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric Error PDBFileBuilder::initialize(uint32_t BlockSize) { 500b57cec5SDimitry Andric auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize); 510b57cec5SDimitry Andric if (!ExpectedMsf) 520b57cec5SDimitry Andric return ExpectedMsf.takeError(); 538bcb0991SDimitry Andric Msf = std::make_unique<MSFBuilder>(std::move(*ExpectedMsf)); 540b57cec5SDimitry Andric return Error::success(); 550b57cec5SDimitry Andric } 560b57cec5SDimitry Andric 570b57cec5SDimitry Andric MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; } 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() { 600b57cec5SDimitry Andric if (!Info) 618bcb0991SDimitry Andric Info = std::make_unique<InfoStreamBuilder>(*Msf, NamedStreams); 620b57cec5SDimitry Andric return *Info; 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() { 660b57cec5SDimitry Andric if (!Dbi) 678bcb0991SDimitry Andric Dbi = std::make_unique<DbiStreamBuilder>(*Msf); 680b57cec5SDimitry Andric return *Dbi; 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() { 720b57cec5SDimitry Andric if (!Tpi) 738bcb0991SDimitry Andric Tpi = std::make_unique<TpiStreamBuilder>(*Msf, StreamTPI); 740b57cec5SDimitry Andric return *Tpi; 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() { 780b57cec5SDimitry Andric if (!Ipi) 798bcb0991SDimitry Andric Ipi = std::make_unique<TpiStreamBuilder>(*Msf, StreamIPI); 800b57cec5SDimitry Andric return *Ipi; 810b57cec5SDimitry Andric } 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() { 840b57cec5SDimitry Andric return Strings; 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() { 880b57cec5SDimitry Andric if (!Gsi) 898bcb0991SDimitry Andric Gsi = std::make_unique<GSIStreamBuilder>(*Msf); 900b57cec5SDimitry Andric return *Gsi; 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric Expected<uint32_t> PDBFileBuilder::allocateNamedStream(StringRef Name, 940b57cec5SDimitry Andric uint32_t Size) { 950b57cec5SDimitry Andric auto ExpectedStream = Msf->addStream(Size); 960b57cec5SDimitry Andric if (ExpectedStream) 970b57cec5SDimitry Andric NamedStreams.set(Name, *ExpectedStream); 980b57cec5SDimitry Andric return ExpectedStream; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric Error PDBFileBuilder::addNamedStream(StringRef Name, StringRef Data) { 1020b57cec5SDimitry Andric Expected<uint32_t> ExpectedIndex = allocateNamedStream(Name, Data.size()); 1030b57cec5SDimitry Andric if (!ExpectedIndex) 1040b57cec5SDimitry Andric return ExpectedIndex.takeError(); 1050b57cec5SDimitry Andric assert(NamedStreamData.count(*ExpectedIndex) == 0); 1065ffd83dbSDimitry Andric NamedStreamData[*ExpectedIndex] = std::string(Data); 1070b57cec5SDimitry Andric return Error::success(); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric void PDBFileBuilder::addInjectedSource(StringRef Name, 1110b57cec5SDimitry Andric std::unique_ptr<MemoryBuffer> Buffer) { 1120b57cec5SDimitry Andric // Stream names must be exact matches, since they get looked up in a hash 1130b57cec5SDimitry Andric // table and the hash value is dependent on the exact contents of the string. 1140b57cec5SDimitry Andric // link.exe lowercases a path and converts / to \, so we must do the same. 1150b57cec5SDimitry Andric SmallString<64> VName; 116349cc55cSDimitry Andric sys::path::native(Name.lower(), VName, sys::path::Style::windows_backslash); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric uint32_t NI = getStringTableBuilder().insert(Name); 1190b57cec5SDimitry Andric uint32_t VNI = getStringTableBuilder().insert(VName); 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric InjectedSourceDescriptor Desc; 1220b57cec5SDimitry Andric Desc.Content = std::move(Buffer); 1230b57cec5SDimitry Andric Desc.NameIndex = NI; 1240b57cec5SDimitry Andric Desc.VNameIndex = VNI; 1250b57cec5SDimitry Andric Desc.StreamName = "/src/files/"; 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric Desc.StreamName += VName; 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric InjectedSources.push_back(std::move(Desc)); 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric Error PDBFileBuilder::finalizeMsfLayout() { 133*5f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("MSF layout"); 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric if (Ipi && Ipi->getRecordCount() > 0) { 1360b57cec5SDimitry Andric // In theory newer PDBs always have an ID stream, but by saying that we're 1370b57cec5SDimitry Andric // only going to *really* have an ID stream if there is at least one ID 1380b57cec5SDimitry Andric // record, we leave open the opportunity to test older PDBs such as those 1390b57cec5SDimitry Andric // that don't have an ID stream. 1400b57cec5SDimitry Andric auto &Info = getInfoBuilder(); 1410b57cec5SDimitry Andric Info.addFeature(PdbRaw_FeatureSig::VC140); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric uint32_t StringsLen = Strings.calculateSerializedSize(); 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric Expected<uint32_t> SN = allocateNamedStream("/LinkInfo", 0); 1470b57cec5SDimitry Andric if (!SN) 1480b57cec5SDimitry Andric return SN.takeError(); 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric if (Gsi) { 1510b57cec5SDimitry Andric if (auto EC = Gsi->finalizeMsfLayout()) 1520b57cec5SDimitry Andric return EC; 1530b57cec5SDimitry Andric if (Dbi) { 1540b57cec5SDimitry Andric Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex()); 1550b57cec5SDimitry Andric Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex()); 1565ffd83dbSDimitry Andric Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIndex()); 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric if (Tpi) { 1600b57cec5SDimitry Andric if (auto EC = Tpi->finalizeMsfLayout()) 1610b57cec5SDimitry Andric return EC; 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric if (Dbi) { 1640b57cec5SDimitry Andric if (auto EC = Dbi->finalizeMsfLayout()) 1650b57cec5SDimitry Andric return EC; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric SN = allocateNamedStream("/names", StringsLen); 1680b57cec5SDimitry Andric if (!SN) 1690b57cec5SDimitry Andric return SN.takeError(); 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric if (Ipi) { 1720b57cec5SDimitry Andric if (auto EC = Ipi->finalizeMsfLayout()) 1730b57cec5SDimitry Andric return EC; 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric 1760b57cec5SDimitry Andric // Do this last, since it relies on the named stream map being complete, and 1770b57cec5SDimitry Andric // that can be updated by previous steps in the finalization. 1780b57cec5SDimitry Andric if (Info) { 1790b57cec5SDimitry Andric if (auto EC = Info->finalizeMsfLayout()) 1800b57cec5SDimitry Andric return EC; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric if (!InjectedSources.empty()) { 1840b57cec5SDimitry Andric for (const auto &IS : InjectedSources) { 1850b57cec5SDimitry Andric JamCRC CRC(0); 1868bcb0991SDimitry Andric CRC.update(arrayRefFromStringRef(IS.Content->getBuffer())); 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric SrcHeaderBlockEntry Entry; 1890b57cec5SDimitry Andric ::memset(&Entry, 0, sizeof(SrcHeaderBlockEntry)); 1900b57cec5SDimitry Andric Entry.Size = sizeof(SrcHeaderBlockEntry); 1910b57cec5SDimitry Andric Entry.FileSize = IS.Content->getBufferSize(); 1920b57cec5SDimitry Andric Entry.FileNI = IS.NameIndex; 1930b57cec5SDimitry Andric Entry.VFileNI = IS.VNameIndex; 1940b57cec5SDimitry Andric Entry.ObjNI = 1; 1950b57cec5SDimitry Andric Entry.IsVirtual = 0; 1960b57cec5SDimitry Andric Entry.Version = 1970b57cec5SDimitry Andric static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne); 1980b57cec5SDimitry Andric Entry.CRC = CRC.getCRC(); 1990b57cec5SDimitry Andric StringRef VName = getStringTableBuilder().getStringForId(IS.VNameIndex); 2000b57cec5SDimitry Andric InjectedSourceTable.set_as(VName, std::move(Entry), 2010b57cec5SDimitry Andric InjectedSourceHashTraits); 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric uint32_t SrcHeaderBlockSize = 2050b57cec5SDimitry Andric sizeof(SrcHeaderBlockHeader) + 2060b57cec5SDimitry Andric InjectedSourceTable.calculateSerializedLength(); 2070b57cec5SDimitry Andric SN = allocateNamedStream("/src/headerblock", SrcHeaderBlockSize); 2080b57cec5SDimitry Andric if (!SN) 2090b57cec5SDimitry Andric return SN.takeError(); 2100b57cec5SDimitry Andric for (const auto &IS : InjectedSources) { 2110b57cec5SDimitry Andric SN = allocateNamedStream(IS.StreamName, IS.Content->getBufferSize()); 2120b57cec5SDimitry Andric if (!SN) 2130b57cec5SDimitry Andric return SN.takeError(); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric // Do this last, since it relies on the named stream map being complete, and 2180b57cec5SDimitry Andric // that can be updated by previous steps in the finalization. 2190b57cec5SDimitry Andric if (Info) { 2200b57cec5SDimitry Andric if (auto EC = Info->finalizeMsfLayout()) 2210b57cec5SDimitry Andric return EC; 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric return Error::success(); 2250b57cec5SDimitry Andric } 2260b57cec5SDimitry Andric 2270b57cec5SDimitry Andric Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const { 2280b57cec5SDimitry Andric uint32_t SN = 0; 2290b57cec5SDimitry Andric if (!NamedStreams.get(Name, SN)) 2300b57cec5SDimitry Andric return llvm::make_error<pdb::RawError>(raw_error_code::no_stream); 2310b57cec5SDimitry Andric return SN; 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric 2340b57cec5SDimitry Andric void PDBFileBuilder::commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer, 2350b57cec5SDimitry Andric const msf::MSFLayout &Layout) { 2360b57cec5SDimitry Andric assert(!InjectedSourceTable.empty()); 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric uint32_t SN = cantFail(getNamedStreamIndex("/src/headerblock")); 2390b57cec5SDimitry Andric auto Stream = WritableMappedBlockStream::createIndexedStream( 2400b57cec5SDimitry Andric Layout, MsfBuffer, SN, Allocator); 2410b57cec5SDimitry Andric BinaryStreamWriter Writer(*Stream); 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric SrcHeaderBlockHeader Header; 2440b57cec5SDimitry Andric ::memset(&Header, 0, sizeof(Header)); 2450b57cec5SDimitry Andric Header.Version = static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne); 2460b57cec5SDimitry Andric Header.Size = Writer.bytesRemaining(); 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric cantFail(Writer.writeObject(Header)); 2490b57cec5SDimitry Andric cantFail(InjectedSourceTable.commit(Writer)); 2500b57cec5SDimitry Andric 2510b57cec5SDimitry Andric assert(Writer.bytesRemaining() == 0); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric void PDBFileBuilder::commitInjectedSources(WritableBinaryStream &MsfBuffer, 2550b57cec5SDimitry Andric const msf::MSFLayout &Layout) { 2560b57cec5SDimitry Andric if (InjectedSourceTable.empty()) 2570b57cec5SDimitry Andric return; 2580b57cec5SDimitry Andric 259*5f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Commit injected sources"); 2600b57cec5SDimitry Andric commitSrcHeaderBlock(MsfBuffer, Layout); 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric for (const auto &IS : InjectedSources) { 2630b57cec5SDimitry Andric uint32_t SN = cantFail(getNamedStreamIndex(IS.StreamName)); 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric auto SourceStream = WritableMappedBlockStream::createIndexedStream( 2660b57cec5SDimitry Andric Layout, MsfBuffer, SN, Allocator); 2670b57cec5SDimitry Andric BinaryStreamWriter SourceWriter(*SourceStream); 2680b57cec5SDimitry Andric assert(SourceWriter.bytesRemaining() == IS.Content->getBufferSize()); 2690b57cec5SDimitry Andric cantFail(SourceWriter.writeBytes( 2700b57cec5SDimitry Andric arrayRefFromStringRef(IS.Content->getBuffer()))); 2710b57cec5SDimitry Andric } 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric Error PDBFileBuilder::commit(StringRef Filename, codeview::GUID *Guid) { 2750b57cec5SDimitry Andric assert(!Filename.empty()); 2760b57cec5SDimitry Andric if (auto EC = finalizeMsfLayout()) 2770b57cec5SDimitry Andric return EC; 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric MSFLayout Layout; 2800b57cec5SDimitry Andric Expected<FileBufferByteStream> ExpectedMsfBuffer = 2810b57cec5SDimitry Andric Msf->commit(Filename, Layout); 2820b57cec5SDimitry Andric if (!ExpectedMsfBuffer) 2830b57cec5SDimitry Andric return ExpectedMsfBuffer.takeError(); 2840b57cec5SDimitry Andric FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer); 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric auto ExpectedSN = getNamedStreamIndex("/names"); 2870b57cec5SDimitry Andric if (!ExpectedSN) 2880b57cec5SDimitry Andric return ExpectedSN.takeError(); 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric auto NS = WritableMappedBlockStream::createIndexedStream( 2910b57cec5SDimitry Andric Layout, Buffer, *ExpectedSN, Allocator); 2920b57cec5SDimitry Andric BinaryStreamWriter NSWriter(*NS); 2930b57cec5SDimitry Andric if (auto EC = Strings.commit(NSWriter)) 2940b57cec5SDimitry Andric return EC; 2950b57cec5SDimitry Andric 296*5f757f3fSDimitry Andric { 297*5f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Named stream data"); 2980b57cec5SDimitry Andric for (const auto &NSE : NamedStreamData) { 2990b57cec5SDimitry Andric if (NSE.second.empty()) 3000b57cec5SDimitry Andric continue; 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric auto NS = WritableMappedBlockStream::createIndexedStream( 3030b57cec5SDimitry Andric Layout, Buffer, NSE.first, Allocator); 3040b57cec5SDimitry Andric BinaryStreamWriter NSW(*NS); 3050b57cec5SDimitry Andric if (auto EC = NSW.writeBytes(arrayRefFromStringRef(NSE.second))) 3060b57cec5SDimitry Andric return EC; 3070b57cec5SDimitry Andric } 308*5f757f3fSDimitry Andric } 3090b57cec5SDimitry Andric 3100b57cec5SDimitry Andric if (Info) { 3110b57cec5SDimitry Andric if (auto EC = Info->commit(Layout, Buffer)) 3120b57cec5SDimitry Andric return EC; 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric 3150b57cec5SDimitry Andric if (Dbi) { 3160b57cec5SDimitry Andric if (auto EC = Dbi->commit(Layout, Buffer)) 3170b57cec5SDimitry Andric return EC; 3180b57cec5SDimitry Andric } 3190b57cec5SDimitry Andric 3200b57cec5SDimitry Andric if (Tpi) { 3210b57cec5SDimitry Andric if (auto EC = Tpi->commit(Layout, Buffer)) 3220b57cec5SDimitry Andric return EC; 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric if (Ipi) { 3260b57cec5SDimitry Andric if (auto EC = Ipi->commit(Layout, Buffer)) 3270b57cec5SDimitry Andric return EC; 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric if (Gsi) { 3310b57cec5SDimitry Andric if (auto EC = Gsi->commit(Layout, Buffer)) 3320b57cec5SDimitry Andric return EC; 3330b57cec5SDimitry Andric } 3340b57cec5SDimitry Andric 3350b57cec5SDimitry Andric auto InfoStreamBlocks = Layout.StreamMap[StreamPDB]; 3360b57cec5SDimitry Andric assert(!InfoStreamBlocks.empty()); 3370b57cec5SDimitry Andric uint64_t InfoStreamFileOffset = 3380b57cec5SDimitry Andric blockToOffset(InfoStreamBlocks.front(), Layout.SB->BlockSize); 3390b57cec5SDimitry Andric InfoStreamHeader *H = reinterpret_cast<InfoStreamHeader *>( 3400b57cec5SDimitry Andric Buffer.getBufferStart() + InfoStreamFileOffset); 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric commitInjectedSources(Buffer, Layout); 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric // Set the build id at the very end, after every other byte of the PDB 3450b57cec5SDimitry Andric // has been written. 3460b57cec5SDimitry Andric if (Info->hashPDBContentsToGUID()) { 347*5f757f3fSDimitry Andric llvm::TimeTraceScope timeScope("Compute build ID"); 348*5f757f3fSDimitry Andric 3490b57cec5SDimitry Andric // Compute a hash of all sections of the output file. 3500b57cec5SDimitry Andric uint64_t Digest = 35106c3fb27SDimitry Andric xxh3_64bits({Buffer.getBufferStart(), Buffer.getBufferEnd()}); 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric H->Age = 1; 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric memcpy(H->Guid.Guid, &Digest, 8); 3560b57cec5SDimitry Andric // xxhash only gives us 8 bytes, so put some fixed data in the other half. 3570b57cec5SDimitry Andric memcpy(H->Guid.Guid + 8, "LLD PDB.", 8); 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric // Put the hash in the Signature field too. 3600b57cec5SDimitry Andric H->Signature = static_cast<uint32_t>(Digest); 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric // Return GUID to caller. 3630b57cec5SDimitry Andric memcpy(Guid, H->Guid.Guid, 16); 3640b57cec5SDimitry Andric } else { 3650b57cec5SDimitry Andric H->Age = Info->getAge(); 3660b57cec5SDimitry Andric H->Guid = Info->getGuid(); 367bdd1243dSDimitry Andric std::optional<uint32_t> Sig = Info->getSignature(); 36881ad6265SDimitry Andric H->Signature = Sig ? *Sig : time(nullptr); 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric return Buffer.commit(); 3720b57cec5SDimitry Andric } 373