xref: /openbsd-src/gnu/llvm/llvm/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- DbiStreamBuilder.cpp - PDB Dbi Stream Creation -----------*- C++ -*-===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
1009467b48Spatrick 
1109467b48Spatrick #include "llvm/ADT/ArrayRef.h"
1209467b48Spatrick #include "llvm/BinaryFormat/COFF.h"
1309467b48Spatrick #include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
1409467b48Spatrick #include "llvm/DebugInfo/MSF/MSFBuilder.h"
1509467b48Spatrick #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
1609467b48Spatrick #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
1709467b48Spatrick #include "llvm/DebugInfo/PDB/Native/RawError.h"
1809467b48Spatrick #include "llvm/Object/COFF.h"
1909467b48Spatrick #include "llvm/Support/BinaryStreamWriter.h"
2073471bf0Spatrick #include "llvm/Support/Parallel.h"
2109467b48Spatrick 
2209467b48Spatrick using namespace llvm;
2309467b48Spatrick using namespace llvm::codeview;
2409467b48Spatrick using namespace llvm::msf;
2509467b48Spatrick using namespace llvm::pdb;
2609467b48Spatrick 
DbiStreamBuilder(msf::MSFBuilder & Msf)2709467b48Spatrick DbiStreamBuilder::DbiStreamBuilder(msf::MSFBuilder &Msf)
2809467b48Spatrick     : Msf(Msf), Allocator(Msf.getAllocator()), Age(1), BuildNumber(0),
2909467b48Spatrick       PdbDllVersion(0), PdbDllRbld(0), Flags(0), MachineType(PDB_Machine::x86),
3009467b48Spatrick       Header(nullptr) {}
3109467b48Spatrick 
32*d415bd75Srobert DbiStreamBuilder::~DbiStreamBuilder() = default;
3309467b48Spatrick 
setVersionHeader(PdbRaw_DbiVer V)3409467b48Spatrick void DbiStreamBuilder::setVersionHeader(PdbRaw_DbiVer V) { VerHeader = V; }
3509467b48Spatrick 
setAge(uint32_t A)3609467b48Spatrick void DbiStreamBuilder::setAge(uint32_t A) { Age = A; }
3709467b48Spatrick 
setBuildNumber(uint16_t B)3809467b48Spatrick void DbiStreamBuilder::setBuildNumber(uint16_t B) { BuildNumber = B; }
3909467b48Spatrick 
setBuildNumber(uint8_t Major,uint8_t Minor)4009467b48Spatrick void DbiStreamBuilder::setBuildNumber(uint8_t Major, uint8_t Minor) {
4109467b48Spatrick   BuildNumber = (uint16_t(Major) << DbiBuildNo::BuildMajorShift) &
4209467b48Spatrick                 DbiBuildNo::BuildMajorMask;
4309467b48Spatrick   BuildNumber |= (uint16_t(Minor) << DbiBuildNo::BuildMinorShift) &
4409467b48Spatrick                  DbiBuildNo::BuildMinorMask;
4509467b48Spatrick   BuildNumber |= DbiBuildNo::NewVersionFormatMask;
4609467b48Spatrick }
4709467b48Spatrick 
setPdbDllVersion(uint16_t V)4809467b48Spatrick void DbiStreamBuilder::setPdbDllVersion(uint16_t V) { PdbDllVersion = V; }
4909467b48Spatrick 
setPdbDllRbld(uint16_t R)5009467b48Spatrick void DbiStreamBuilder::setPdbDllRbld(uint16_t R) { PdbDllRbld = R; }
5109467b48Spatrick 
setFlags(uint16_t F)5209467b48Spatrick void DbiStreamBuilder::setFlags(uint16_t F) { Flags = F; }
5309467b48Spatrick 
setMachineType(PDB_Machine M)5409467b48Spatrick void DbiStreamBuilder::setMachineType(PDB_Machine M) { MachineType = M; }
5509467b48Spatrick 
setMachineType(COFF::MachineTypes M)5609467b48Spatrick void DbiStreamBuilder::setMachineType(COFF::MachineTypes M) {
5709467b48Spatrick   // These enums are mirrors of each other, so we can just cast the value.
5809467b48Spatrick   MachineType = static_cast<pdb::PDB_Machine>(static_cast<unsigned>(M));
5909467b48Spatrick }
6009467b48Spatrick 
setGlobalsStreamIndex(uint32_t Index)6109467b48Spatrick void DbiStreamBuilder::setGlobalsStreamIndex(uint32_t Index) {
6209467b48Spatrick   GlobalsStreamIndex = Index;
6309467b48Spatrick }
6409467b48Spatrick 
setSymbolRecordStreamIndex(uint32_t Index)6509467b48Spatrick void DbiStreamBuilder::setSymbolRecordStreamIndex(uint32_t Index) {
6609467b48Spatrick   SymRecordStreamIndex = Index;
6709467b48Spatrick }
6809467b48Spatrick 
setPublicsStreamIndex(uint32_t Index)6909467b48Spatrick void DbiStreamBuilder::setPublicsStreamIndex(uint32_t Index) {
7009467b48Spatrick   PublicsStreamIndex = Index;
7109467b48Spatrick }
7209467b48Spatrick 
addNewFpoData(const codeview::FrameData & FD)7309467b48Spatrick void DbiStreamBuilder::addNewFpoData(const codeview::FrameData &FD) {
74*d415bd75Srobert   if (!NewFpoData)
7509467b48Spatrick     NewFpoData.emplace(false);
7609467b48Spatrick 
7709467b48Spatrick   NewFpoData->addFrameData(FD);
7809467b48Spatrick }
7909467b48Spatrick 
addOldFpoData(const object::FpoData & FD)8009467b48Spatrick void DbiStreamBuilder::addOldFpoData(const object::FpoData &FD) {
8109467b48Spatrick   OldFpoData.push_back(FD);
8209467b48Spatrick }
8309467b48Spatrick 
addDbgStream(pdb::DbgHeaderType Type,ArrayRef<uint8_t> Data)8409467b48Spatrick Error DbiStreamBuilder::addDbgStream(pdb::DbgHeaderType Type,
8509467b48Spatrick                                      ArrayRef<uint8_t> Data) {
8609467b48Spatrick   assert(Type != DbgHeaderType::NewFPO &&
8709467b48Spatrick          "NewFPO data should be written via addFrameData()!");
8809467b48Spatrick 
89*d415bd75Srobert   DbgStreams[(int)Type] = DebugStream{};
9009467b48Spatrick   DbgStreams[(int)Type]->Size = Data.size();
9109467b48Spatrick   DbgStreams[(int)Type]->WriteFn = [Data](BinaryStreamWriter &Writer) {
9209467b48Spatrick     return Writer.writeArray(Data);
9309467b48Spatrick   };
9409467b48Spatrick   return Error::success();
9509467b48Spatrick }
9609467b48Spatrick 
addECName(StringRef Name)9709467b48Spatrick uint32_t DbiStreamBuilder::addECName(StringRef Name) {
9809467b48Spatrick   return ECNamesBuilder.insert(Name);
9909467b48Spatrick }
10009467b48Spatrick 
calculateSerializedLength() const10109467b48Spatrick uint32_t DbiStreamBuilder::calculateSerializedLength() const {
10209467b48Spatrick   // For now we only support serializing the header.
10309467b48Spatrick   return sizeof(DbiStreamHeader) + calculateFileInfoSubstreamSize() +
10409467b48Spatrick          calculateModiSubstreamSize() + calculateSectionContribsStreamSize() +
10509467b48Spatrick          calculateSectionMapStreamSize() + calculateDbgStreamsSize() +
10609467b48Spatrick          ECNamesBuilder.calculateSerializedSize();
10709467b48Spatrick }
10809467b48Spatrick 
10909467b48Spatrick Expected<DbiModuleDescriptorBuilder &>
addModuleInfo(StringRef ModuleName)11009467b48Spatrick DbiStreamBuilder::addModuleInfo(StringRef ModuleName) {
11109467b48Spatrick   uint32_t Index = ModiList.size();
11209467b48Spatrick   ModiList.push_back(
11309467b48Spatrick       std::make_unique<DbiModuleDescriptorBuilder>(ModuleName, Index, Msf));
11409467b48Spatrick   return *ModiList.back();
11509467b48Spatrick }
11609467b48Spatrick 
addModuleSourceFile(DbiModuleDescriptorBuilder & Module,StringRef File)11709467b48Spatrick Error DbiStreamBuilder::addModuleSourceFile(DbiModuleDescriptorBuilder &Module,
11809467b48Spatrick                                             StringRef File) {
11909467b48Spatrick   uint32_t Index = SourceFileNames.size();
12009467b48Spatrick   SourceFileNames.insert(std::make_pair(File, Index));
12109467b48Spatrick   Module.addSourceFile(File);
12209467b48Spatrick   return Error::success();
12309467b48Spatrick }
12409467b48Spatrick 
getSourceFileNameIndex(StringRef File)12509467b48Spatrick Expected<uint32_t> DbiStreamBuilder::getSourceFileNameIndex(StringRef File) {
12609467b48Spatrick   auto NameIter = SourceFileNames.find(File);
12709467b48Spatrick   if (NameIter == SourceFileNames.end())
12809467b48Spatrick     return make_error<RawError>(raw_error_code::no_entry,
12909467b48Spatrick                                 "The specified source file was not found");
13009467b48Spatrick   return NameIter->getValue();
13109467b48Spatrick }
13209467b48Spatrick 
calculateModiSubstreamSize() const13309467b48Spatrick uint32_t DbiStreamBuilder::calculateModiSubstreamSize() const {
13409467b48Spatrick   uint32_t Size = 0;
13509467b48Spatrick   for (const auto &M : ModiList)
13609467b48Spatrick     Size += M->calculateSerializedLength();
13709467b48Spatrick   return Size;
13809467b48Spatrick }
13909467b48Spatrick 
calculateSectionContribsStreamSize() const14009467b48Spatrick uint32_t DbiStreamBuilder::calculateSectionContribsStreamSize() const {
14109467b48Spatrick   if (SectionContribs.empty())
14209467b48Spatrick     return 0;
14309467b48Spatrick   return sizeof(enum PdbRaw_DbiSecContribVer) +
14409467b48Spatrick          sizeof(SectionContribs[0]) * SectionContribs.size();
14509467b48Spatrick }
14609467b48Spatrick 
calculateSectionMapStreamSize() const14709467b48Spatrick uint32_t DbiStreamBuilder::calculateSectionMapStreamSize() const {
14809467b48Spatrick   if (SectionMap.empty())
14909467b48Spatrick     return 0;
15009467b48Spatrick   return sizeof(SecMapHeader) + sizeof(SecMapEntry) * SectionMap.size();
15109467b48Spatrick }
15209467b48Spatrick 
calculateNamesOffset() const15309467b48Spatrick uint32_t DbiStreamBuilder::calculateNamesOffset() const {
15409467b48Spatrick   uint32_t Offset = 0;
15509467b48Spatrick   Offset += sizeof(ulittle16_t);                         // NumModules
15609467b48Spatrick   Offset += sizeof(ulittle16_t);                         // NumSourceFiles
15709467b48Spatrick   Offset += ModiList.size() * sizeof(ulittle16_t);       // ModIndices
15809467b48Spatrick   Offset += ModiList.size() * sizeof(ulittle16_t);       // ModFileCounts
15909467b48Spatrick   uint32_t NumFileInfos = 0;
16009467b48Spatrick   for (const auto &M : ModiList)
16109467b48Spatrick     NumFileInfos += M->source_files().size();
16209467b48Spatrick   Offset += NumFileInfos * sizeof(ulittle32_t); // FileNameOffsets
16309467b48Spatrick   return Offset;
16409467b48Spatrick }
16509467b48Spatrick 
calculateFileInfoSubstreamSize() const16609467b48Spatrick uint32_t DbiStreamBuilder::calculateFileInfoSubstreamSize() const {
16709467b48Spatrick   uint32_t Size = calculateNamesOffset();
16809467b48Spatrick   Size += calculateNamesBufferSize();
16909467b48Spatrick   return alignTo(Size, sizeof(uint32_t));
17009467b48Spatrick }
17109467b48Spatrick 
calculateNamesBufferSize() const17209467b48Spatrick uint32_t DbiStreamBuilder::calculateNamesBufferSize() const {
17309467b48Spatrick   uint32_t Size = 0;
17409467b48Spatrick   for (const auto &F : SourceFileNames) {
17509467b48Spatrick     Size += F.getKeyLength() + 1; // Names[I];
17609467b48Spatrick   }
17709467b48Spatrick   return Size;
17809467b48Spatrick }
17909467b48Spatrick 
calculateDbgStreamsSize() const18009467b48Spatrick uint32_t DbiStreamBuilder::calculateDbgStreamsSize() const {
18109467b48Spatrick   return DbgStreams.size() * sizeof(uint16_t);
18209467b48Spatrick }
18309467b48Spatrick 
generateFileInfoSubstream()18409467b48Spatrick Error DbiStreamBuilder::generateFileInfoSubstream() {
18509467b48Spatrick   uint32_t Size = calculateFileInfoSubstreamSize();
18609467b48Spatrick   auto Data = Allocator.Allocate<uint8_t>(Size);
18709467b48Spatrick   uint32_t NamesOffset = calculateNamesOffset();
18809467b48Spatrick 
18909467b48Spatrick   FileInfoBuffer = MutableBinaryByteStream(MutableArrayRef<uint8_t>(Data, Size),
19009467b48Spatrick                                            llvm::support::little);
19109467b48Spatrick 
19209467b48Spatrick   WritableBinaryStreamRef MetadataBuffer =
19309467b48Spatrick       WritableBinaryStreamRef(FileInfoBuffer).keep_front(NamesOffset);
19409467b48Spatrick   BinaryStreamWriter MetadataWriter(MetadataBuffer);
19509467b48Spatrick 
19609467b48Spatrick   uint16_t ModiCount = std::min<uint32_t>(UINT16_MAX, ModiList.size());
19709467b48Spatrick   uint16_t FileCount = std::min<uint32_t>(UINT16_MAX, SourceFileNames.size());
19809467b48Spatrick   if (auto EC = MetadataWriter.writeInteger(ModiCount)) // NumModules
19909467b48Spatrick     return EC;
20009467b48Spatrick   if (auto EC = MetadataWriter.writeInteger(FileCount)) // NumSourceFiles
20109467b48Spatrick     return EC;
20209467b48Spatrick   for (uint16_t I = 0; I < ModiCount; ++I) {
20309467b48Spatrick     if (auto EC = MetadataWriter.writeInteger(I)) // Mod Indices
20409467b48Spatrick       return EC;
20509467b48Spatrick   }
20609467b48Spatrick   for (const auto &MI : ModiList) {
20709467b48Spatrick     FileCount = static_cast<uint16_t>(MI->source_files().size());
20809467b48Spatrick     if (auto EC = MetadataWriter.writeInteger(FileCount)) // Mod File Counts
20909467b48Spatrick       return EC;
21009467b48Spatrick   }
21109467b48Spatrick 
21209467b48Spatrick   // Before writing the FileNameOffsets array, write the NamesBuffer array.
21309467b48Spatrick   // A side effect of this is that this will actually compute the various
21409467b48Spatrick   // file name offsets, so we can then go back and write the FileNameOffsets
21509467b48Spatrick   // array to the other substream.
21609467b48Spatrick   NamesBuffer = WritableBinaryStreamRef(FileInfoBuffer).drop_front(NamesOffset);
21709467b48Spatrick   BinaryStreamWriter NameBufferWriter(NamesBuffer);
21809467b48Spatrick   for (auto &Name : SourceFileNames) {
21909467b48Spatrick     Name.second = NameBufferWriter.getOffset();
22009467b48Spatrick     if (auto EC = NameBufferWriter.writeCString(Name.getKey()))
22109467b48Spatrick       return EC;
22209467b48Spatrick   }
22309467b48Spatrick 
22409467b48Spatrick   for (const auto &MI : ModiList) {
22509467b48Spatrick     for (StringRef Name : MI->source_files()) {
22609467b48Spatrick       auto Result = SourceFileNames.find(Name);
22709467b48Spatrick       if (Result == SourceFileNames.end())
22809467b48Spatrick         return make_error<RawError>(raw_error_code::no_entry,
22909467b48Spatrick                                     "The source file was not found.");
23009467b48Spatrick       if (auto EC = MetadataWriter.writeInteger(Result->second))
23109467b48Spatrick         return EC;
23209467b48Spatrick     }
23309467b48Spatrick   }
23409467b48Spatrick 
23509467b48Spatrick   if (auto EC = NameBufferWriter.padToAlignment(sizeof(uint32_t)))
23609467b48Spatrick     return EC;
23709467b48Spatrick 
23809467b48Spatrick   if (NameBufferWriter.bytesRemaining() > 0)
23909467b48Spatrick     return make_error<RawError>(raw_error_code::invalid_format,
24009467b48Spatrick                                 "The names buffer contained unexpected data.");
24109467b48Spatrick 
24209467b48Spatrick   if (MetadataWriter.bytesRemaining() > sizeof(uint32_t))
24309467b48Spatrick     return make_error<RawError>(
24409467b48Spatrick         raw_error_code::invalid_format,
24509467b48Spatrick         "The metadata buffer contained unexpected data.");
24609467b48Spatrick 
24709467b48Spatrick   return Error::success();
24809467b48Spatrick }
24909467b48Spatrick 
finalize()25009467b48Spatrick Error DbiStreamBuilder::finalize() {
25109467b48Spatrick   if (Header)
25209467b48Spatrick     return Error::success();
25309467b48Spatrick 
25409467b48Spatrick   for (auto &MI : ModiList)
25509467b48Spatrick     MI->finalize();
25609467b48Spatrick 
25709467b48Spatrick   if (auto EC = generateFileInfoSubstream())
25809467b48Spatrick     return EC;
25909467b48Spatrick 
26009467b48Spatrick   DbiStreamHeader *H = Allocator.Allocate<DbiStreamHeader>();
26109467b48Spatrick   ::memset(H, 0, sizeof(DbiStreamHeader));
26209467b48Spatrick   H->VersionHeader = *VerHeader;
26309467b48Spatrick   H->VersionSignature = -1;
26409467b48Spatrick   H->Age = Age;
26509467b48Spatrick   H->BuildNumber = BuildNumber;
26609467b48Spatrick   H->Flags = Flags;
26709467b48Spatrick   H->PdbDllRbld = PdbDllRbld;
26809467b48Spatrick   H->PdbDllVersion = PdbDllVersion;
26909467b48Spatrick   H->MachineType = static_cast<uint16_t>(MachineType);
27009467b48Spatrick 
27109467b48Spatrick   H->ECSubstreamSize = ECNamesBuilder.calculateSerializedSize();
27209467b48Spatrick   H->FileInfoSize = FileInfoBuffer.getLength();
27309467b48Spatrick   H->ModiSubstreamSize = calculateModiSubstreamSize();
27409467b48Spatrick   H->OptionalDbgHdrSize = DbgStreams.size() * sizeof(uint16_t);
27509467b48Spatrick   H->SecContrSubstreamSize = calculateSectionContribsStreamSize();
27609467b48Spatrick   H->SectionMapSize = calculateSectionMapStreamSize();
27709467b48Spatrick   H->TypeServerSize = 0;
27809467b48Spatrick   H->SymRecordStreamIndex = SymRecordStreamIndex;
27909467b48Spatrick   H->PublicSymbolStreamIndex = PublicsStreamIndex;
28009467b48Spatrick   H->MFCTypeServerIndex = 0; // Not sure what this is, but link.exe writes 0.
28109467b48Spatrick   H->GlobalSymbolStreamIndex = GlobalsStreamIndex;
28209467b48Spatrick 
28309467b48Spatrick   Header = H;
28409467b48Spatrick   return Error::success();
28509467b48Spatrick }
28609467b48Spatrick 
finalizeMsfLayout()28709467b48Spatrick Error DbiStreamBuilder::finalizeMsfLayout() {
288*d415bd75Srobert   if (NewFpoData) {
289*d415bd75Srobert     DbgStreams[(int)DbgHeaderType::NewFPO] = DebugStream{};
29009467b48Spatrick     DbgStreams[(int)DbgHeaderType::NewFPO]->Size =
29109467b48Spatrick         NewFpoData->calculateSerializedSize();
29209467b48Spatrick     DbgStreams[(int)DbgHeaderType::NewFPO]->WriteFn =
29309467b48Spatrick         [this](BinaryStreamWriter &Writer) {
29409467b48Spatrick           return NewFpoData->commit(Writer);
29509467b48Spatrick         };
29609467b48Spatrick   }
29709467b48Spatrick 
29809467b48Spatrick   if (!OldFpoData.empty()) {
299*d415bd75Srobert     DbgStreams[(int)DbgHeaderType::FPO] = DebugStream{};
30009467b48Spatrick     DbgStreams[(int)DbgHeaderType::FPO]->Size =
30109467b48Spatrick         sizeof(object::FpoData) * OldFpoData.size();
30209467b48Spatrick     DbgStreams[(int)DbgHeaderType::FPO]->WriteFn =
30309467b48Spatrick         [this](BinaryStreamWriter &Writer) {
304*d415bd75Srobert           return Writer.writeArray(ArrayRef(OldFpoData));
30509467b48Spatrick         };
30609467b48Spatrick   }
30709467b48Spatrick 
30809467b48Spatrick   for (auto &S : DbgStreams) {
309*d415bd75Srobert     if (!S)
31009467b48Spatrick       continue;
31109467b48Spatrick     auto ExpectedIndex = Msf.addStream(S->Size);
31209467b48Spatrick     if (!ExpectedIndex)
31309467b48Spatrick       return ExpectedIndex.takeError();
31409467b48Spatrick     S->StreamNumber = *ExpectedIndex;
31509467b48Spatrick   }
31609467b48Spatrick 
31709467b48Spatrick   for (auto &MI : ModiList) {
31809467b48Spatrick     if (auto EC = MI->finalizeMsfLayout())
31909467b48Spatrick       return EC;
32009467b48Spatrick   }
32109467b48Spatrick 
32209467b48Spatrick   uint32_t Length = calculateSerializedLength();
32309467b48Spatrick   if (auto EC = Msf.setStreamSize(StreamDBI, Length))
32409467b48Spatrick     return EC;
32509467b48Spatrick   return Error::success();
32609467b48Spatrick }
32709467b48Spatrick 
toSecMapFlags(uint32_t Flags)32809467b48Spatrick static uint16_t toSecMapFlags(uint32_t Flags) {
32909467b48Spatrick   uint16_t Ret = 0;
33009467b48Spatrick   if (Flags & COFF::IMAGE_SCN_MEM_READ)
33109467b48Spatrick     Ret |= static_cast<uint16_t>(OMFSegDescFlags::Read);
33209467b48Spatrick   if (Flags & COFF::IMAGE_SCN_MEM_WRITE)
33309467b48Spatrick     Ret |= static_cast<uint16_t>(OMFSegDescFlags::Write);
33409467b48Spatrick   if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
33509467b48Spatrick     Ret |= static_cast<uint16_t>(OMFSegDescFlags::Execute);
33609467b48Spatrick   if (!(Flags & COFF::IMAGE_SCN_MEM_16BIT))
33709467b48Spatrick     Ret |= static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit);
33809467b48Spatrick 
33909467b48Spatrick   // This seems always 1.
34009467b48Spatrick   Ret |= static_cast<uint16_t>(OMFSegDescFlags::IsSelector);
34109467b48Spatrick 
34209467b48Spatrick   return Ret;
34309467b48Spatrick }
34409467b48Spatrick 
345097a140dSpatrick // Populate the Section Map from COFF section headers.
34609467b48Spatrick //
34709467b48Spatrick // A Section Map seem to be a copy of a COFF section list in other format.
34809467b48Spatrick // I don't know why a PDB file contains both a COFF section header and
34909467b48Spatrick // a Section Map, but it seems it must be present in a PDB.
createSectionMap(ArrayRef<llvm::object::coff_section> SecHdrs)350097a140dSpatrick void DbiStreamBuilder::createSectionMap(
35109467b48Spatrick     ArrayRef<llvm::object::coff_section> SecHdrs) {
35209467b48Spatrick   int Idx = 0;
35309467b48Spatrick 
35409467b48Spatrick   auto Add = [&]() -> SecMapEntry & {
355097a140dSpatrick     SectionMap.emplace_back();
356097a140dSpatrick     auto &Entry = SectionMap.back();
35709467b48Spatrick     memset(&Entry, 0, sizeof(Entry));
35809467b48Spatrick 
35909467b48Spatrick     Entry.Frame = Idx + 1;
36009467b48Spatrick 
36109467b48Spatrick     // We don't know the meaning of these fields yet.
36209467b48Spatrick     Entry.SecName = UINT16_MAX;
36309467b48Spatrick     Entry.ClassName = UINT16_MAX;
36409467b48Spatrick 
36509467b48Spatrick     return Entry;
36609467b48Spatrick   };
36709467b48Spatrick 
36809467b48Spatrick   for (auto &Hdr : SecHdrs) {
36909467b48Spatrick     auto &Entry = Add();
37009467b48Spatrick     Entry.Flags = toSecMapFlags(Hdr.Characteristics);
37109467b48Spatrick     Entry.SecByteLength = Hdr.VirtualSize;
37209467b48Spatrick     ++Idx;
37309467b48Spatrick   }
37409467b48Spatrick 
37509467b48Spatrick   // The last entry is for absolute symbols.
37609467b48Spatrick   auto &Entry = Add();
37709467b48Spatrick   Entry.Flags = static_cast<uint16_t>(OMFSegDescFlags::AddressIs32Bit) |
37809467b48Spatrick                 static_cast<uint16_t>(OMFSegDescFlags::IsAbsoluteAddress);
37909467b48Spatrick   Entry.SecByteLength = UINT32_MAX;
38009467b48Spatrick }
38109467b48Spatrick 
commit(const msf::MSFLayout & Layout,WritableBinaryStreamRef MsfBuffer)38209467b48Spatrick Error DbiStreamBuilder::commit(const msf::MSFLayout &Layout,
38309467b48Spatrick                                WritableBinaryStreamRef MsfBuffer) {
38409467b48Spatrick   if (auto EC = finalize())
38509467b48Spatrick     return EC;
38609467b48Spatrick 
38709467b48Spatrick   auto DbiS = WritableMappedBlockStream::createIndexedStream(
38809467b48Spatrick       Layout, MsfBuffer, StreamDBI, Allocator);
38909467b48Spatrick 
39009467b48Spatrick   BinaryStreamWriter Writer(*DbiS);
39109467b48Spatrick   if (auto EC = Writer.writeObject(*Header))
39209467b48Spatrick     return EC;
39309467b48Spatrick 
39409467b48Spatrick   for (auto &M : ModiList) {
39573471bf0Spatrick     if (auto EC = M->commit(Writer))
39609467b48Spatrick       return EC;
39709467b48Spatrick   }
39809467b48Spatrick 
39973471bf0Spatrick   // Commit symbol streams. This is a lot of data, so do it in parallel.
40073471bf0Spatrick   if (auto EC = parallelForEachError(
40173471bf0Spatrick           ModiList, [&](std::unique_ptr<DbiModuleDescriptorBuilder> &M) {
40273471bf0Spatrick             return M->commitSymbolStream(Layout, MsfBuffer);
40373471bf0Spatrick           }))
40473471bf0Spatrick     return EC;
40573471bf0Spatrick 
40609467b48Spatrick   if (!SectionContribs.empty()) {
40709467b48Spatrick     if (auto EC = Writer.writeEnum(DbiSecContribVer60))
40809467b48Spatrick       return EC;
409*d415bd75Srobert     if (auto EC = Writer.writeArray(ArrayRef(SectionContribs)))
41009467b48Spatrick       return EC;
41109467b48Spatrick   }
41209467b48Spatrick 
41309467b48Spatrick   if (!SectionMap.empty()) {
41409467b48Spatrick     ulittle16_t Size = static_cast<ulittle16_t>(SectionMap.size());
41509467b48Spatrick     SecMapHeader SMHeader = {Size, Size};
41609467b48Spatrick     if (auto EC = Writer.writeObject(SMHeader))
41709467b48Spatrick       return EC;
418*d415bd75Srobert     if (auto EC = Writer.writeArray(ArrayRef(SectionMap)))
41909467b48Spatrick       return EC;
42009467b48Spatrick   }
42109467b48Spatrick 
42209467b48Spatrick   if (auto EC = Writer.writeStreamRef(FileInfoBuffer))
42309467b48Spatrick     return EC;
42409467b48Spatrick 
42509467b48Spatrick   if (auto EC = ECNamesBuilder.commit(Writer))
42609467b48Spatrick     return EC;
42709467b48Spatrick 
42809467b48Spatrick   for (auto &Stream : DbgStreams) {
42909467b48Spatrick     uint16_t StreamNumber = kInvalidStreamIndex;
430*d415bd75Srobert     if (Stream)
43109467b48Spatrick       StreamNumber = Stream->StreamNumber;
43209467b48Spatrick     if (auto EC = Writer.writeInteger(StreamNumber))
43309467b48Spatrick       return EC;
43409467b48Spatrick   }
43509467b48Spatrick 
43609467b48Spatrick   for (auto &Stream : DbgStreams) {
437*d415bd75Srobert     if (!Stream)
43809467b48Spatrick       continue;
43909467b48Spatrick     assert(Stream->StreamNumber != kInvalidStreamIndex);
44009467b48Spatrick 
44109467b48Spatrick     auto WritableStream = WritableMappedBlockStream::createIndexedStream(
44209467b48Spatrick         Layout, MsfBuffer, Stream->StreamNumber, Allocator);
44309467b48Spatrick     BinaryStreamWriter DbgStreamWriter(*WritableStream);
44409467b48Spatrick 
44509467b48Spatrick     if (auto EC = Stream->WriteFn(DbgStreamWriter))
44609467b48Spatrick       return EC;
44709467b48Spatrick   }
44809467b48Spatrick 
44909467b48Spatrick   if (Writer.bytesRemaining() > 0)
45009467b48Spatrick     return make_error<RawError>(raw_error_code::invalid_format,
45109467b48Spatrick                                 "Unexpected bytes found in DBI Stream");
45209467b48Spatrick   return Error::success();
45309467b48Spatrick }
454