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