Error PDBStringTableBuilder::writeHashTable(BinaryStreamWriter &Writer) const { // Write a hash table. uint32_t BucketCount = computeBucketCount(Strings.size()); if (auto EC = Writer.writeInteger(BucketCount)) return EC; std::vector<ulittle32_t> Buckets(BucketCount); for (auto &Pair : Strings) { StringRef S = Pair.getKey(); uint32_t Offset = Pair.getValue(); uint32_t Hash = hashStringV1(S); for (uint32_t I = 0; I != BucketCount; ++I) { uint32_t Slot = (Hash + I) % BucketCount; if (Buckets[Slot] != 0) continue; Buckets[Slot] = Offset; break; } } if (auto EC = Writer.writeArray(ArrayRef<ulittle32_t>(Buckets))) return EC; assert(Writer.bytesRemaining() == 0); return Error::success(); }
Error llvm::pdb::writeSparseBitVector(BinaryStreamWriter &Writer, SparseBitVector<> &Vec) { constexpr int BitsPerWord = 8 * sizeof(uint32_t); int ReqBits = Vec.find_last() + 1; uint32_t ReqWords = alignTo(ReqBits, BitsPerWord) / BitsPerWord; if (auto EC = Writer.writeInteger(ReqWords)) return joinErrors( std::move(EC), make_error<RawError>(raw_error_code::corrupt_file, "Could not write linear map number of words")); uint32_t Idx = 0; for (uint32_t I = 0; I != ReqWords; ++I) { uint32_t Word = 0; for (uint32_t WordIdx = 0; WordIdx < 32; ++WordIdx, ++Idx) { if (Vec.test(Idx)) Word |= (1 << WordIdx); } if (auto EC = Writer.writeInteger(Word)) return joinErrors(std::move(EC), make_error<RawError>( raw_error_code::corrupt_file, "Could not write linear map word")); } return Error::success(); }
Error DebugCrossModuleExportsSubsection::commit( BinaryStreamWriter &Writer) const { for (const auto &M : Mappings) { if (auto EC = Writer.writeInteger(M.first)) return EC; if (auto EC = Writer.writeInteger(M.second)) return EC; } return Error::success(); }
Error PDBStringTableBuilder::writeHeader(BinaryStreamWriter &Writer) const { // Write a header PDBStringTableHeader H; H.Signature = PDBStringTableSignature; H.HashVersion = 1; H.ByteSize = Strings.calculateSerializedSize(); if (auto EC = Writer.writeObject(H)) return EC; assert(Writer.bytesRemaining() == 0); return Error::success(); }
static void addPadding(BinaryStreamWriter &Writer) { uint32_t Align = Writer.getOffset() % 4; if (Align == 0) return; int PaddingBytes = 4 - Align; while (PaddingBytes > 0) { uint8_t Pad = static_cast<uint8_t>(LF_PAD0 + PaddingBytes); cantFail(Writer.writeInteger(Pad)); --PaddingBytes; } }
static Error writeRecords(BinaryStreamWriter &Writer, ArrayRef<CVSymbol> Records) { BinaryItemStream<CVSymbol> ItemStream(support::endianness::little); ItemStream.setItems(Records); BinaryStreamRef RecordsRef(ItemStream); return Writer.writeStreamRef(RecordsRef); }
Error PDBStringTableBuilder::writeStrings(BinaryStreamWriter &Writer) const { if (auto EC = Strings.commit(Writer)) return EC; assert(Writer.bytesRemaining() == 0); return Error::success(); }
Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter, const msf::MSFLayout &MsfLayout, WritableBinaryStreamRef MsfBuffer) { // We write the Modi record to the `ModiWriter`, but we additionally write its // symbol stream to a brand new stream. if (auto EC = ModiWriter.writeObject(Layout)) return EC; if (auto EC = ModiWriter.writeCString(ModuleName)) return EC; if (auto EC = ModiWriter.writeCString(ObjFileName)) return EC; if (auto EC = ModiWriter.padToAlignment(sizeof(uint32_t))) return EC; if (Layout.ModDiStream != kInvalidStreamIndex) { auto NS = WritableMappedBlockStream::createIndexedStream( MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator()); WritableBinaryStreamRef Ref(*NS); BinaryStreamWriter SymbolWriter(Ref); // Write the symbols. if (auto EC = SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC)) return EC; BinaryItemStream<CVSymbol> Records(llvm::support::endianness::little); Records.setItems(Symbols); BinaryStreamRef RecordsRef(Records); if (auto EC = SymbolWriter.writeStreamRef(RecordsRef)) return EC; if (auto EC = SymbolWriter.padToAlignment(4)) return EC; // TODO: Write C11 Line data assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 && "Invalid debug section alignment!"); for (const auto &Builder : C13Builders) { assert(Builder && "Empty C13 Fragment Builder!"); if (auto EC = Builder->commit(SymbolWriter)) return EC; } // TODO: Figure out what GlobalRefs substream actually is and populate it. if (auto EC = SymbolWriter.writeInteger<uint32_t>(0)) return EC; if (SymbolWriter.bytesRemaining() > 0) return make_error<RawError>(raw_error_code::stream_too_long); } return Error::success(); }
Error GSIHashStreamBuilder::commit(BinaryStreamWriter &Writer) { GSIHashHeader Header; Header.VerSignature = GSIHashHeader::HdrSignature; Header.VerHdr = GSIHashHeader::HdrVersion; Header.HrSize = HashRecords.size() * sizeof(PSHashRecord); Header.NumBuckets = HashBitmap.size() * 4 + HashBuckets.size() * 4; if (auto EC = Writer.writeObject(Header)) return EC; if (auto EC = Writer.writeArray(makeArrayRef(HashRecords))) return EC; if (auto EC = Writer.writeArray(makeArrayRef(HashBitmap))) return EC; if (auto EC = Writer.writeArray(makeArrayRef(HashBuckets))) return EC; return Error::success(); }
Error NamedStreamMap::commit(BinaryStreamWriter &Writer) const { assert(FinalizedInfo.hasValue()); // The first field is the number of bytes of string data. if (auto EC = Writer.writeInteger(FinalizedInfo->StringDataBytes)) return EC; for (const auto &Name : OrderedStreamNames) { auto Item = Mapping.find(Name); if (Item == Mapping.end()) continue; if (auto EC = Writer.writeCString(Item->getKey())) return EC; } // And finally the Offset Index map. if (auto EC = FinalizedHashTable.commit(Writer)) return EC; return Error::success(); }
Error PDBStringTableBuilder::commit(BinaryStreamWriter &Writer) const { BinaryStreamWriter SectionWriter; std::tie(SectionWriter, Writer) = Writer.split(sizeof(PDBStringTableHeader)); if (auto EC = writeHeader(SectionWriter)) return EC; std::tie(SectionWriter, Writer) = Writer.split(Strings.calculateSerializedSize()); if (auto EC = writeStrings(SectionWriter)) return EC; std::tie(SectionWriter, Writer) = Writer.split(calculateHashTableSize()); if (auto EC = writeHashTable(SectionWriter)) return EC; std::tie(SectionWriter, Writer) = Writer.split(sizeof(uint32_t)); if (auto EC = writeEpilogue(SectionWriter)) return EC; return Error::success(); }
Error DebugSymbolRVASubsection::commit(BinaryStreamWriter &Writer) const { return Writer.writeArray(makeArrayRef(RVAs)); }
Error PDBStringTableBuilder::writeEpilogue(BinaryStreamWriter &Writer) const { if (auto EC = Writer.writeInteger<uint32_t>(Strings.size())) return EC; assert(Writer.bytesRemaining() == 0); return Error::success(); }