16b6b8c4fSAdrian McCarthy //===- InfoStreamBuilder.cpp - PDB Info Stream Creation ---------*- C++ -*-===//
26b6b8c4fSAdrian McCarthy //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66b6b8c4fSAdrian McCarthy //
76b6b8c4fSAdrian McCarthy //===----------------------------------------------------------------------===//
86b6b8c4fSAdrian McCarthy 
96b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
106b6b8c4fSAdrian McCarthy 
116b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/MSF/MSFBuilder.h"
126b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
136b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/NamedStreamMap.h"
146b6b8c4fSAdrian McCarthy #include "llvm/DebugInfo/PDB/Native/RawTypes.h"
15*ed98c1b3Sserge-sans-paille #include "llvm/Support/BinaryStreamReader.h"
16d9dc2829SZachary Turner #include "llvm/Support/BinaryStreamWriter.h"
176b6b8c4fSAdrian McCarthy 
186b6b8c4fSAdrian McCarthy using namespace llvm;
196b6b8c4fSAdrian McCarthy using namespace llvm::codeview;
206b6b8c4fSAdrian McCarthy using namespace llvm::msf;
216b6b8c4fSAdrian McCarthy using namespace llvm::pdb;
226b6b8c4fSAdrian McCarthy 
InfoStreamBuilder(msf::MSFBuilder & Msf,NamedStreamMap & NamedStreams)236b6b8c4fSAdrian McCarthy InfoStreamBuilder::InfoStreamBuilder(msf::MSFBuilder &Msf,
246b6b8c4fSAdrian McCarthy                                      NamedStreamMap &NamedStreams)
25c6a75a69SZachary Turner     : Msf(Msf), Ver(PdbRaw_ImplVer::PdbImplVC70), Age(0),
26c6a75a69SZachary Turner       NamedStreams(NamedStreams) {
27c6a75a69SZachary Turner   ::memset(&Guid, 0, sizeof(Guid));
28c6a75a69SZachary Turner }
296b6b8c4fSAdrian McCarthy 
setVersion(PdbRaw_ImplVer V)306b6b8c4fSAdrian McCarthy void InfoStreamBuilder::setVersion(PdbRaw_ImplVer V) { Ver = V; }
316b6b8c4fSAdrian McCarthy 
addFeature(PdbRaw_FeatureSig Sig)32205ca68bSNico Weber void InfoStreamBuilder::addFeature(PdbRaw_FeatureSig Sig) {
33205ca68bSNico Weber   Features.push_back(Sig);
34205ca68bSNico Weber }
35205ca68bSNico Weber 
setHashPDBContentsToGUID(bool B)36205ca68bSNico Weber void InfoStreamBuilder::setHashPDBContentsToGUID(bool B) {
37205ca68bSNico Weber   HashPDBContentsToGUID = B;
38205ca68bSNico Weber }
39205ca68bSNico Weber 
setAge(uint32_t A)406b6b8c4fSAdrian McCarthy void InfoStreamBuilder::setAge(uint32_t A) { Age = A; }
416b6b8c4fSAdrian McCarthy 
setSignature(uint32_t S)42c6a75a69SZachary Turner void InfoStreamBuilder::setSignature(uint32_t S) { Signature = S; }
43c6a75a69SZachary Turner 
setGuid(GUID G)4467653ee0SReid Kleckner void InfoStreamBuilder::setGuid(GUID G) { Guid = G; }
456b6b8c4fSAdrian McCarthy 
4605d5e613SZachary Turner 
finalizeMsfLayout()476b6b8c4fSAdrian McCarthy Error InfoStreamBuilder::finalizeMsfLayout() {
48cafd4768SZachary Turner   uint32_t Length = sizeof(InfoStreamHeader) +
49cafd4768SZachary Turner                     NamedStreams.calculateSerializedLength() +
5005d5e613SZachary Turner                     (Features.size() + 1) * sizeof(uint32_t);
516b6b8c4fSAdrian McCarthy   if (auto EC = Msf.setStreamSize(StreamPDB, Length))
526b6b8c4fSAdrian McCarthy     return EC;
536b6b8c4fSAdrian McCarthy   return Error::success();
546b6b8c4fSAdrian McCarthy }
556b6b8c4fSAdrian McCarthy 
commit(const msf::MSFLayout & Layout,WritableBinaryStreamRef Buffer) const566b6b8c4fSAdrian McCarthy Error InfoStreamBuilder::commit(const msf::MSFLayout &Layout,
57120faca4SZachary Turner                                 WritableBinaryStreamRef Buffer) const {
585b74ff33SZachary Turner   auto InfoS = WritableMappedBlockStream::createIndexedStream(
595b74ff33SZachary Turner       Layout, Buffer, StreamPDB, Msf.getAllocator());
60120faca4SZachary Turner   BinaryStreamWriter Writer(*InfoS);
616b6b8c4fSAdrian McCarthy 
626b6b8c4fSAdrian McCarthy   InfoStreamHeader H;
63c6a75a69SZachary Turner   // Leave the build id fields 0 so they can be set as the last step before
64c6a75a69SZachary Turner   // committing the file to disk.
65c6a75a69SZachary Turner   ::memset(&H, 0, sizeof(H));
666b6b8c4fSAdrian McCarthy   H.Version = Ver;
676b6b8c4fSAdrian McCarthy   if (auto EC = Writer.writeObject(H))
686b6b8c4fSAdrian McCarthy     return EC;
696b6b8c4fSAdrian McCarthy 
7005d5e613SZachary Turner   if (auto EC = NamedStreams.commit(Writer))
7105d5e613SZachary Turner     return EC;
7205d5e613SZachary Turner   if (auto EC = Writer.writeInteger(0))
7305d5e613SZachary Turner     return EC;
7405d5e613SZachary Turner   for (auto E : Features) {
7505d5e613SZachary Turner     if (auto EC = Writer.writeEnum(E))
7605d5e613SZachary Turner       return EC;
7705d5e613SZachary Turner   }
78a6fb536eSZachary Turner   assert(Writer.bytesRemaining() == 0);
7905d5e613SZachary Turner   return Error::success();
806b6b8c4fSAdrian McCarthy }
81