17a7e6055SDimitry Andric //===- PDBFileBuilder.cpp - PDB File Creation -------------------*- C++ -*-===//
27a7e6055SDimitry Andric //
37a7e6055SDimitry Andric //                     The LLVM Compiler Infrastructure
47a7e6055SDimitry Andric //
57a7e6055SDimitry Andric // This file is distributed under the University of Illinois Open Source
67a7e6055SDimitry Andric // License. See LICENSE.TXT for details.
77a7e6055SDimitry Andric //
87a7e6055SDimitry Andric //===----------------------------------------------------------------------===//
97a7e6055SDimitry Andric 
107a7e6055SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
117a7e6055SDimitry Andric 
127a7e6055SDimitry Andric #include "llvm/ADT/BitVector.h"
137a7e6055SDimitry Andric 
147a7e6055SDimitry Andric #include "llvm/DebugInfo/MSF/MSFBuilder.h"
157a7e6055SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
167a7e6055SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
172cab237bSDimitry Andric #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
187a7e6055SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStream.h"
197a7e6055SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
20f37b6182SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
217a7e6055SDimitry Andric #include "llvm/DebugInfo/PDB/Native/RawError.h"
227a7e6055SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
237a7e6055SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
247a7e6055SDimitry Andric #include "llvm/Support/BinaryStream.h"
257a7e6055SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h"
264ba319b5SDimitry Andric #include "llvm/Support/JamCRC.h"
274ba319b5SDimitry Andric #include "llvm/Support/Path.h"
28*b5893f02SDimitry Andric #include "llvm/Support/xxhash.h"
297a7e6055SDimitry Andric 
307a7e6055SDimitry Andric using namespace llvm;
317a7e6055SDimitry Andric using namespace llvm::codeview;
327a7e6055SDimitry Andric using namespace llvm::msf;
337a7e6055SDimitry Andric using namespace llvm::pdb;
347a7e6055SDimitry Andric using namespace llvm::support;
357a7e6055SDimitry Andric 
PDBFileBuilder(BumpPtrAllocator & Allocator)367a7e6055SDimitry Andric PDBFileBuilder::PDBFileBuilder(BumpPtrAllocator &Allocator)
374ba319b5SDimitry Andric     : Allocator(Allocator), InjectedSourceHashTraits(Strings),
384ba319b5SDimitry Andric       InjectedSourceTable(2, InjectedSourceHashTraits) {}
397a7e6055SDimitry Andric 
~PDBFileBuilder()40c4394386SDimitry Andric PDBFileBuilder::~PDBFileBuilder() {}
41c4394386SDimitry Andric 
initialize(uint32_t BlockSize)427a7e6055SDimitry Andric Error PDBFileBuilder::initialize(uint32_t BlockSize) {
437a7e6055SDimitry Andric   auto ExpectedMsf = MSFBuilder::create(Allocator, BlockSize);
447a7e6055SDimitry Andric   if (!ExpectedMsf)
457a7e6055SDimitry Andric     return ExpectedMsf.takeError();
467a7e6055SDimitry Andric   Msf = llvm::make_unique<MSFBuilder>(std::move(*ExpectedMsf));
477a7e6055SDimitry Andric   return Error::success();
487a7e6055SDimitry Andric }
497a7e6055SDimitry Andric 
getMsfBuilder()507a7e6055SDimitry Andric MSFBuilder &PDBFileBuilder::getMsfBuilder() { return *Msf; }
517a7e6055SDimitry Andric 
getInfoBuilder()527a7e6055SDimitry Andric InfoStreamBuilder &PDBFileBuilder::getInfoBuilder() {
537a7e6055SDimitry Andric   if (!Info)
547a7e6055SDimitry Andric     Info = llvm::make_unique<InfoStreamBuilder>(*Msf, NamedStreams);
557a7e6055SDimitry Andric   return *Info;
567a7e6055SDimitry Andric }
577a7e6055SDimitry Andric 
getDbiBuilder()587a7e6055SDimitry Andric DbiStreamBuilder &PDBFileBuilder::getDbiBuilder() {
597a7e6055SDimitry Andric   if (!Dbi)
607a7e6055SDimitry Andric     Dbi = llvm::make_unique<DbiStreamBuilder>(*Msf);
617a7e6055SDimitry Andric   return *Dbi;
627a7e6055SDimitry Andric }
637a7e6055SDimitry Andric 
getTpiBuilder()647a7e6055SDimitry Andric TpiStreamBuilder &PDBFileBuilder::getTpiBuilder() {
657a7e6055SDimitry Andric   if (!Tpi)
667a7e6055SDimitry Andric     Tpi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamTPI);
677a7e6055SDimitry Andric   return *Tpi;
687a7e6055SDimitry Andric }
697a7e6055SDimitry Andric 
getIpiBuilder()707a7e6055SDimitry Andric TpiStreamBuilder &PDBFileBuilder::getIpiBuilder() {
717a7e6055SDimitry Andric   if (!Ipi)
727a7e6055SDimitry Andric     Ipi = llvm::make_unique<TpiStreamBuilder>(*Msf, StreamIPI);
737a7e6055SDimitry Andric   return *Ipi;
747a7e6055SDimitry Andric }
757a7e6055SDimitry Andric 
getStringTableBuilder()76f37b6182SDimitry Andric PDBStringTableBuilder &PDBFileBuilder::getStringTableBuilder() {
77f37b6182SDimitry Andric   return Strings;
78f37b6182SDimitry Andric }
797a7e6055SDimitry Andric 
getGsiBuilder()802cab237bSDimitry Andric GSIStreamBuilder &PDBFileBuilder::getGsiBuilder() {
812cab237bSDimitry Andric   if (!Gsi)
822cab237bSDimitry Andric     Gsi = llvm::make_unique<GSIStreamBuilder>(*Msf);
832cab237bSDimitry Andric   return *Gsi;
84c4394386SDimitry Andric }
85c4394386SDimitry Andric 
allocateNamedStream(StringRef Name,uint32_t Size)864ba319b5SDimitry Andric Expected<uint32_t> PDBFileBuilder::allocateNamedStream(StringRef Name,
874ba319b5SDimitry Andric                                                        uint32_t Size) {
887a7e6055SDimitry Andric   auto ExpectedStream = Msf->addStream(Size);
894ba319b5SDimitry Andric   if (ExpectedStream)
907a7e6055SDimitry Andric     NamedStreams.set(Name, *ExpectedStream);
914ba319b5SDimitry Andric   return ExpectedStream;
924ba319b5SDimitry Andric }
934ba319b5SDimitry Andric 
addNamedStream(StringRef Name,StringRef Data)944ba319b5SDimitry Andric Error PDBFileBuilder::addNamedStream(StringRef Name, StringRef Data) {
954ba319b5SDimitry Andric   Expected<uint32_t> ExpectedIndex = allocateNamedStream(Name, Data.size());
964ba319b5SDimitry Andric   if (!ExpectedIndex)
974ba319b5SDimitry Andric     return ExpectedIndex.takeError();
984ba319b5SDimitry Andric   assert(NamedStreamData.count(*ExpectedIndex) == 0);
994ba319b5SDimitry Andric   NamedStreamData[*ExpectedIndex] = Data;
1007a7e6055SDimitry Andric   return Error::success();
1017a7e6055SDimitry Andric }
1027a7e6055SDimitry Andric 
addInjectedSource(StringRef Name,std::unique_ptr<MemoryBuffer> Buffer)1034ba319b5SDimitry Andric void PDBFileBuilder::addInjectedSource(StringRef Name,
1044ba319b5SDimitry Andric                                        std::unique_ptr<MemoryBuffer> Buffer) {
1054ba319b5SDimitry Andric   // Stream names must be exact matches, since they get looked up in a hash
1064ba319b5SDimitry Andric   // table and the hash value is dependent on the exact contents of the string.
1074ba319b5SDimitry Andric   // link.exe lowercases a path and converts / to \, so we must do the same.
1084ba319b5SDimitry Andric   SmallString<64> VName;
1094ba319b5SDimitry Andric   sys::path::native(Name.lower(), VName);
1104ba319b5SDimitry Andric 
1114ba319b5SDimitry Andric   uint32_t NI = getStringTableBuilder().insert(Name);
1124ba319b5SDimitry Andric   uint32_t VNI = getStringTableBuilder().insert(VName);
1134ba319b5SDimitry Andric 
1144ba319b5SDimitry Andric   InjectedSourceDescriptor Desc;
1154ba319b5SDimitry Andric   Desc.Content = std::move(Buffer);
1164ba319b5SDimitry Andric   Desc.NameIndex = NI;
1174ba319b5SDimitry Andric   Desc.VNameIndex = VNI;
1184ba319b5SDimitry Andric   Desc.StreamName = "/src/files/";
1194ba319b5SDimitry Andric 
1204ba319b5SDimitry Andric   Desc.StreamName += VName;
1214ba319b5SDimitry Andric 
1224ba319b5SDimitry Andric   InjectedSources.push_back(std::move(Desc));
1234ba319b5SDimitry Andric }
1244ba319b5SDimitry Andric 
finalizeMsfLayout()1254ba319b5SDimitry Andric Error PDBFileBuilder::finalizeMsfLayout() {
12624d58133SDimitry Andric 
12724d58133SDimitry Andric   if (Ipi && Ipi->getRecordCount() > 0) {
12824d58133SDimitry Andric     // In theory newer PDBs always have an ID stream, but by saying that we're
12924d58133SDimitry Andric     // only going to *really* have an ID stream if there is at least one ID
13024d58133SDimitry Andric     // record, we leave open the opportunity to test older PDBs such as those
13124d58133SDimitry Andric     // that don't have an ID stream.
13224d58133SDimitry Andric     auto &Info = getInfoBuilder();
13324d58133SDimitry Andric     Info.addFeature(PdbRaw_FeatureSig::VC140);
13424d58133SDimitry Andric   }
13524d58133SDimitry Andric 
136f37b6182SDimitry Andric   uint32_t StringsLen = Strings.calculateSerializedSize();
1377a7e6055SDimitry Andric 
1384ba319b5SDimitry Andric   Expected<uint32_t> SN = allocateNamedStream("/LinkInfo", 0);
1394ba319b5SDimitry Andric   if (!SN)
1404ba319b5SDimitry Andric     return SN.takeError();
1417a7e6055SDimitry Andric 
1422cab237bSDimitry Andric   if (Gsi) {
1432cab237bSDimitry Andric     if (auto EC = Gsi->finalizeMsfLayout())
1444ba319b5SDimitry Andric       return EC;
145c4394386SDimitry Andric     if (Dbi) {
1462cab237bSDimitry Andric       Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
1472cab237bSDimitry Andric       Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
1482cab237bSDimitry Andric       Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIdx());
149c4394386SDimitry Andric     }
150c4394386SDimitry Andric   }
1514ba319b5SDimitry Andric   if (Tpi) {
1524ba319b5SDimitry Andric     if (auto EC = Tpi->finalizeMsfLayout())
1534ba319b5SDimitry Andric       return EC;
1544ba319b5SDimitry Andric   }
1554ba319b5SDimitry Andric   if (Dbi) {
1564ba319b5SDimitry Andric     if (auto EC = Dbi->finalizeMsfLayout())
1574ba319b5SDimitry Andric       return EC;
1584ba319b5SDimitry Andric   }
1594ba319b5SDimitry Andric   SN = allocateNamedStream("/names", StringsLen);
1604ba319b5SDimitry Andric   if (!SN)
1614ba319b5SDimitry Andric     return SN.takeError();
1627a7e6055SDimitry Andric 
1634ba319b5SDimitry Andric   if (Ipi) {
1644ba319b5SDimitry Andric     if (auto EC = Ipi->finalizeMsfLayout())
1654ba319b5SDimitry Andric       return EC;
1664ba319b5SDimitry Andric   }
1674ba319b5SDimitry Andric 
1684ba319b5SDimitry Andric   // Do this last, since it relies on the named stream map being complete, and
1694ba319b5SDimitry Andric   // that can be updated by previous steps in the finalization.
1704ba319b5SDimitry Andric   if (Info) {
1714ba319b5SDimitry Andric     if (auto EC = Info->finalizeMsfLayout())
1724ba319b5SDimitry Andric       return EC;
1734ba319b5SDimitry Andric   }
1744ba319b5SDimitry Andric 
1754ba319b5SDimitry Andric   if (!InjectedSources.empty()) {
1764ba319b5SDimitry Andric     for (const auto &IS : InjectedSources) {
1774ba319b5SDimitry Andric       JamCRC CRC(0);
1784ba319b5SDimitry Andric       CRC.update(makeArrayRef(IS.Content->getBufferStart(),
1794ba319b5SDimitry Andric                               IS.Content->getBufferSize()));
1804ba319b5SDimitry Andric 
1814ba319b5SDimitry Andric       SrcHeaderBlockEntry Entry;
1824ba319b5SDimitry Andric       ::memset(&Entry, 0, sizeof(SrcHeaderBlockEntry));
1834ba319b5SDimitry Andric       Entry.Size = sizeof(SrcHeaderBlockEntry);
1844ba319b5SDimitry Andric       Entry.FileSize = IS.Content->getBufferSize();
1854ba319b5SDimitry Andric       Entry.FileNI = IS.NameIndex;
1864ba319b5SDimitry Andric       Entry.VFileNI = IS.VNameIndex;
1874ba319b5SDimitry Andric       Entry.ObjNI = 1;
1884ba319b5SDimitry Andric       Entry.IsVirtual = 0;
1894ba319b5SDimitry Andric       Entry.Version =
1904ba319b5SDimitry Andric           static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
1914ba319b5SDimitry Andric       Entry.CRC = CRC.getCRC();
1924ba319b5SDimitry Andric       StringRef VName = getStringTableBuilder().getStringForId(IS.VNameIndex);
1934ba319b5SDimitry Andric       InjectedSourceTable.set_as(VName, std::move(Entry));
1944ba319b5SDimitry Andric     }
1954ba319b5SDimitry Andric 
1964ba319b5SDimitry Andric     uint32_t SrcHeaderBlockSize =
1974ba319b5SDimitry Andric         sizeof(SrcHeaderBlockHeader) +
1984ba319b5SDimitry Andric         InjectedSourceTable.calculateSerializedLength();
1994ba319b5SDimitry Andric     SN = allocateNamedStream("/src/headerblock", SrcHeaderBlockSize);
2004ba319b5SDimitry Andric     if (!SN)
2014ba319b5SDimitry Andric       return SN.takeError();
2024ba319b5SDimitry Andric     for (const auto &IS : InjectedSources) {
2034ba319b5SDimitry Andric       SN = allocateNamedStream(IS.StreamName, IS.Content->getBufferSize());
2044ba319b5SDimitry Andric       if (!SN)
2054ba319b5SDimitry Andric         return SN.takeError();
2064ba319b5SDimitry Andric     }
2074ba319b5SDimitry Andric   }
2084ba319b5SDimitry Andric 
2094ba319b5SDimitry Andric   // Do this last, since it relies on the named stream map being complete, and
2104ba319b5SDimitry Andric   // that can be updated by previous steps in the finalization.
2114ba319b5SDimitry Andric   if (Info) {
2124ba319b5SDimitry Andric     if (auto EC = Info->finalizeMsfLayout())
2134ba319b5SDimitry Andric       return EC;
2144ba319b5SDimitry Andric   }
2154ba319b5SDimitry Andric 
2164ba319b5SDimitry Andric   return Error::success();
2177a7e6055SDimitry Andric }
2187a7e6055SDimitry Andric 
getNamedStreamIndex(StringRef Name) const219f37b6182SDimitry Andric Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
220f37b6182SDimitry Andric   uint32_t SN = 0;
221f37b6182SDimitry Andric   if (!NamedStreams.get(Name, SN))
222f37b6182SDimitry Andric     return llvm::make_error<pdb::RawError>(raw_error_code::no_stream);
223f37b6182SDimitry Andric   return SN;
224f37b6182SDimitry Andric }
225f37b6182SDimitry Andric 
commitSrcHeaderBlock(WritableBinaryStream & MsfBuffer,const msf::MSFLayout & Layout)2264ba319b5SDimitry Andric void PDBFileBuilder::commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer,
2274ba319b5SDimitry Andric                                           const msf::MSFLayout &Layout) {
2284ba319b5SDimitry Andric   assert(!InjectedSourceTable.empty());
2292cab237bSDimitry Andric 
2304ba319b5SDimitry Andric   uint32_t SN = cantFail(getNamedStreamIndex("/src/headerblock"));
2314ba319b5SDimitry Andric   auto Stream = WritableMappedBlockStream::createIndexedStream(
2324ba319b5SDimitry Andric       Layout, MsfBuffer, SN, Allocator);
2334ba319b5SDimitry Andric   BinaryStreamWriter Writer(*Stream);
2342cab237bSDimitry Andric 
2354ba319b5SDimitry Andric   SrcHeaderBlockHeader Header;
2364ba319b5SDimitry Andric   ::memset(&Header, 0, sizeof(Header));
2374ba319b5SDimitry Andric   Header.Version = static_cast<uint32_t>(PdbRaw_SrcHeaderBlockVer::SrcVerOne);
2384ba319b5SDimitry Andric   Header.Size = Writer.bytesRemaining();
2394ba319b5SDimitry Andric 
2404ba319b5SDimitry Andric   cantFail(Writer.writeObject(Header));
2414ba319b5SDimitry Andric   cantFail(InjectedSourceTable.commit(Writer));
2424ba319b5SDimitry Andric 
2434ba319b5SDimitry Andric   assert(Writer.bytesRemaining() == 0);
2442cab237bSDimitry Andric }
2454ba319b5SDimitry Andric 
commitInjectedSources(WritableBinaryStream & MsfBuffer,const msf::MSFLayout & Layout)2464ba319b5SDimitry Andric void PDBFileBuilder::commitInjectedSources(WritableBinaryStream &MsfBuffer,
2474ba319b5SDimitry Andric                                            const msf::MSFLayout &Layout) {
2484ba319b5SDimitry Andric   if (InjectedSourceTable.empty())
2494ba319b5SDimitry Andric     return;
2504ba319b5SDimitry Andric 
2514ba319b5SDimitry Andric   commitSrcHeaderBlock(MsfBuffer, Layout);
2524ba319b5SDimitry Andric 
2534ba319b5SDimitry Andric   for (const auto &IS : InjectedSources) {
2544ba319b5SDimitry Andric     uint32_t SN = cantFail(getNamedStreamIndex(IS.StreamName));
2554ba319b5SDimitry Andric 
2564ba319b5SDimitry Andric     auto SourceStream = WritableMappedBlockStream::createIndexedStream(
2574ba319b5SDimitry Andric         Layout, MsfBuffer, SN, Allocator);
2584ba319b5SDimitry Andric     BinaryStreamWriter SourceWriter(*SourceStream);
2594ba319b5SDimitry Andric     assert(SourceWriter.bytesRemaining() == IS.Content->getBufferSize());
2604ba319b5SDimitry Andric     cantFail(SourceWriter.writeBytes(
2614ba319b5SDimitry Andric         arrayRefFromStringRef(IS.Content->getBuffer())));
2622cab237bSDimitry Andric   }
2632cab237bSDimitry Andric }
2642cab237bSDimitry Andric 
commit(StringRef Filename,codeview::GUID * Guid)265*b5893f02SDimitry Andric Error PDBFileBuilder::commit(StringRef Filename, codeview::GUID *Guid) {
266d8866befSDimitry Andric   assert(!Filename.empty());
2674ba319b5SDimitry Andric   if (auto EC = finalizeMsfLayout())
2687a7e6055SDimitry Andric     return EC;
2692cab237bSDimitry Andric 
2704ba319b5SDimitry Andric   MSFLayout Layout;
271*b5893f02SDimitry Andric   Expected<FileBufferByteStream> ExpectedMsfBuffer =
272*b5893f02SDimitry Andric       Msf->commit(Filename, Layout);
2734ba319b5SDimitry Andric   if (!ExpectedMsfBuffer)
2744ba319b5SDimitry Andric     return ExpectedMsfBuffer.takeError();
2754ba319b5SDimitry Andric   FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer);
2767a7e6055SDimitry Andric 
277f37b6182SDimitry Andric   auto ExpectedSN = getNamedStreamIndex("/names");
278f37b6182SDimitry Andric   if (!ExpectedSN)
279f37b6182SDimitry Andric     return ExpectedSN.takeError();
2807a7e6055SDimitry Andric 
2816d97bb29SDimitry Andric   auto NS = WritableMappedBlockStream::createIndexedStream(
2826d97bb29SDimitry Andric       Layout, Buffer, *ExpectedSN, Allocator);
2837a7e6055SDimitry Andric   BinaryStreamWriter NSWriter(*NS);
2847a7e6055SDimitry Andric   if (auto EC = Strings.commit(NSWriter))
2857a7e6055SDimitry Andric     return EC;
2867a7e6055SDimitry Andric 
2874ba319b5SDimitry Andric   for (const auto &NSE : NamedStreamData) {
2884ba319b5SDimitry Andric     if (NSE.second.empty())
2894ba319b5SDimitry Andric       continue;
2904ba319b5SDimitry Andric 
2914ba319b5SDimitry Andric     auto NS = WritableMappedBlockStream::createIndexedStream(
2924ba319b5SDimitry Andric         Layout, Buffer, NSE.first, Allocator);
2934ba319b5SDimitry Andric     BinaryStreamWriter NSW(*NS);
2944ba319b5SDimitry Andric     if (auto EC = NSW.writeBytes(arrayRefFromStringRef(NSE.second)))
2954ba319b5SDimitry Andric       return EC;
2964ba319b5SDimitry Andric   }
2974ba319b5SDimitry Andric 
2987a7e6055SDimitry Andric   if (Info) {
2997a7e6055SDimitry Andric     if (auto EC = Info->commit(Layout, Buffer))
3007a7e6055SDimitry Andric       return EC;
3017a7e6055SDimitry Andric   }
3027a7e6055SDimitry Andric 
3037a7e6055SDimitry Andric   if (Dbi) {
3047a7e6055SDimitry Andric     if (auto EC = Dbi->commit(Layout, Buffer))
3057a7e6055SDimitry Andric       return EC;
3067a7e6055SDimitry Andric   }
3077a7e6055SDimitry Andric 
3087a7e6055SDimitry Andric   if (Tpi) {
3097a7e6055SDimitry Andric     if (auto EC = Tpi->commit(Layout, Buffer))
3107a7e6055SDimitry Andric       return EC;
3117a7e6055SDimitry Andric   }
3127a7e6055SDimitry Andric 
3137a7e6055SDimitry Andric   if (Ipi) {
3147a7e6055SDimitry Andric     if (auto EC = Ipi->commit(Layout, Buffer))
3157a7e6055SDimitry Andric       return EC;
3167a7e6055SDimitry Andric   }
3177a7e6055SDimitry Andric 
3182cab237bSDimitry Andric   if (Gsi) {
3192cab237bSDimitry Andric     if (auto EC = Gsi->commit(Layout, Buffer))
320c4394386SDimitry Andric       return EC;
321c4394386SDimitry Andric   }
322c4394386SDimitry Andric 
3234ba319b5SDimitry Andric   auto InfoStreamBlocks = Layout.StreamMap[StreamPDB];
3244ba319b5SDimitry Andric   assert(!InfoStreamBlocks.empty());
3254ba319b5SDimitry Andric   uint64_t InfoStreamFileOffset =
3264ba319b5SDimitry Andric       blockToOffset(InfoStreamBlocks.front(), Layout.SB->BlockSize);
3274ba319b5SDimitry Andric   InfoStreamHeader *H = reinterpret_cast<InfoStreamHeader *>(
3284ba319b5SDimitry Andric       Buffer.getBufferStart() + InfoStreamFileOffset);
3294ba319b5SDimitry Andric 
3304ba319b5SDimitry Andric   commitInjectedSources(Buffer, Layout);
3314ba319b5SDimitry Andric 
3324ba319b5SDimitry Andric   // Set the build id at the very end, after every other byte of the PDB
3334ba319b5SDimitry Andric   // has been written.
334*b5893f02SDimitry Andric   if (Info->hashPDBContentsToGUID()) {
335*b5893f02SDimitry Andric     // Compute a hash of all sections of the output file.
336*b5893f02SDimitry Andric     uint64_t Digest =
337*b5893f02SDimitry Andric         xxHash64({Buffer.getBufferStart(), Buffer.getBufferEnd()});
338*b5893f02SDimitry Andric 
339*b5893f02SDimitry Andric     H->Age = 1;
340*b5893f02SDimitry Andric 
341*b5893f02SDimitry Andric     memcpy(H->Guid.Guid, &Digest, 8);
342*b5893f02SDimitry Andric     // xxhash only gives us 8 bytes, so put some fixed data in the other half.
343*b5893f02SDimitry Andric     memcpy(H->Guid.Guid + 8, "LLD PDB.", 8);
344*b5893f02SDimitry Andric 
345*b5893f02SDimitry Andric     // Put the hash in the Signature field too.
346*b5893f02SDimitry Andric     H->Signature = static_cast<uint32_t>(Digest);
347*b5893f02SDimitry Andric 
348*b5893f02SDimitry Andric     // Return GUID to caller.
349*b5893f02SDimitry Andric     memcpy(Guid, H->Guid.Guid, 16);
350*b5893f02SDimitry Andric   } else {
3514ba319b5SDimitry Andric     H->Age = Info->getAge();
3524ba319b5SDimitry Andric     H->Guid = Info->getGuid();
3534ba319b5SDimitry Andric     Optional<uint32_t> Sig = Info->getSignature();
3544ba319b5SDimitry Andric     H->Signature = Sig.hasValue() ? *Sig : time(nullptr);
355*b5893f02SDimitry Andric   }
3564ba319b5SDimitry Andric 
3577a7e6055SDimitry Andric   return Buffer.commit();
3587a7e6055SDimitry Andric }
359