Index: lld/trunk/COFF/PDB.cpp =================================================================== --- lld/trunk/COFF/PDB.cpp +++ lld/trunk/COFF/PDB.cpp @@ -597,6 +597,10 @@ for (const PublicSym32 &Pub : Publics) PublicsBuilder.addPublicSymbol(Pub); } + // Add globals stream. For now we don't actually write any thing useful to + // the globals stream, but the act of "getting" it also creates it lazily so + // that we write an empty stream. + (void)Builder.getGlobalsBuilder(); } static void addLinkerModuleSymbols(StringRef Path, Index: lld/trunk/test/COFF/pdb-diff.test =================================================================== --- lld/trunk/test/COFF/pdb-diff.test +++ lld/trunk/test/COFF/pdb-diff.test @@ -25,7 +25,7 @@ CHECK-NEXT: |------------------------------+---| CHECK-NEXT: | File | | CHECK-NEXT: |------------------------------+---| -CHECK-NEXT: | Stream Count | D | +CHECK-NEXT: | Stream Count | I | CHECK-NEXT: |------------------------------+---| CHECK-NEXT: | Old MSF Directory | I | CHECK-NEXT: |------------------------------+---| @@ -57,7 +57,7 @@ CHECK-NEXT: |------------------------------+---| CHECK-NEXT: | Public Symbol Records | {{[EI]}} | CHECK-NEXT: |------------------------------+---| -CHECK-NEXT: | Global Symbol Hash | D | +CHECK-NEXT: | Global Symbol Hash | {{[EI]}} | CHECK-NEXT: |------------------------------+---| CHECK-NEXT: ------------------------------------ CHECK-NEXT: | String Table | @@ -152,7 +152,7 @@ CHECK-NEXT: |----------------------------------------+---| CHECK-NEXT: | DBG (SectionHdrOrig) | I | CHECK-NEXT: |----------------------------------------+---| -CHECK-NEXT: | Globals Stream | D | +CHECK-NEXT: | Globals Stream | {{[EI]}} | CHECK-NEXT: |----------------------------------------+---| CHECK-NEXT: | Publics Stream | {{[EI]}} | CHECK-NEXT: |----------------------------------------+---| @@ -186,7 +186,7 @@ CHECK-NEXT: |----------------------------------------+---| CHECK-NEXT: | - Source File Name Index | I | CHECK-NEXT: |----------------------------------------+---| -CHECK-NEXT: | - Symbol Byte Size | D | +CHECK-NEXT: | - Symbol Byte Size | CHECK-NEXT: |----------------------------------------+---| CHECK-NEXT: | Module "* Linker *" | CHECK-NEXT: |----------------------------------------+---| Index: llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h @@ -59,6 +59,7 @@ uint32_t calculateSerializedLength() const; + void setGlobalsStreamIndex(uint32_t Index); void setPublicsStreamIndex(uint32_t Index); void setSymbolRecordStreamIndex(uint32_t Index); @@ -105,6 +106,7 @@ uint16_t PdbDllRbld; uint16_t Flags; PDB_Machine MachineType; + uint32_t GlobalsStreamIndex = kInvalidStreamIndex; uint32_t PublicsStreamIndex = kInvalidStreamIndex; uint32_t SymRecordStreamIndex = kInvalidStreamIndex; Index: llvm/trunk/include/llvm/DebugInfo/PDB/Native/GlobalsStreamBuilder.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/Native/GlobalsStreamBuilder.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/GlobalsStreamBuilder.h @@ -0,0 +1,50 @@ +//===- GlobalsStreamBuilder.h - PDB Globals Stream Creation -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBGLOBALSTREAMBUILDER_H +#define LLVM_DEBUGINFO_PDB_RAW_PDBGLOBALSTREAMBUILDER_H + +#include "llvm/DebugInfo/PDB/Native/RawConstants.h" +#include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/Support/BinaryByteStream.h" +#include "llvm/Support/BinaryStreamRef.h" +#include "llvm/Support/BinaryStreamWriter.h" +#include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" + +namespace llvm { +namespace msf { +class MSFBuilder; +} +namespace pdb { +class GlobalsStream; + +class GlobalsStreamBuilder { +public: + explicit GlobalsStreamBuilder(msf::MSFBuilder &Msf); + ~GlobalsStreamBuilder(); + + GlobalsStreamBuilder(const GlobalsStreamBuilder &) = delete; + GlobalsStreamBuilder &operator=(const GlobalsStreamBuilder &) = delete; + + Error finalizeMsfLayout(); + uint32_t calculateSerializedLength() const; + + Error commit(BinaryStreamWriter &PublicsWriter); + + uint32_t getStreamIndex() const { return StreamIdx; } + +private: + uint32_t StreamIdx = kInvalidStreamIndex; + msf::MSFBuilder &Msf; +}; +} // namespace pdb +} // namespace llvm + +#endif Index: llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h @@ -32,6 +32,7 @@ class DbiStreamBuilder; class InfoStreamBuilder; class PublicsStreamBuilder; +class GlobalsStreamBuilder; class TpiStreamBuilder; class PDBFileBuilder { @@ -50,6 +51,7 @@ TpiStreamBuilder &getIpiBuilder(); PDBStringTableBuilder &getStringTableBuilder(); PublicsStreamBuilder &getPublicsBuilder(); + GlobalsStreamBuilder &getGlobalsBuilder(); Error commit(StringRef Filename); @@ -64,6 +66,7 @@ std::unique_ptr Msf; std::unique_ptr Info; std::unique_ptr Dbi; + std::unique_ptr Globals; std::unique_ptr Publics; std::unique_ptr Tpi; std::unique_ptr Ipi; Index: llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt +++ llvm/trunk/lib/DebugInfo/PDB/CMakeLists.txt @@ -35,6 +35,7 @@ Native/DbiStreamBuilder.cpp Native/EnumTables.cpp Native/GlobalsStream.cpp + Native/GlobalsStreamBuilder.cpp Native/Hash.cpp Native/HashTable.cpp Native/InfoStream.cpp Index: llvm/trunk/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Native/DbiStreamBuilder.cpp @@ -49,6 +49,10 @@ SectionMap = SecMap; } +void DbiStreamBuilder::setGlobalsStreamIndex(uint32_t Index) { + GlobalsStreamIndex = Index; +} + void DbiStreamBuilder::setSymbolRecordStreamIndex(uint32_t Index) { SymRecordStreamIndex = Index; } @@ -270,7 +274,7 @@ H->SymRecordStreamIndex = SymRecordStreamIndex; H->PublicSymbolStreamIndex = PublicsStreamIndex; H->MFCTypeServerIndex = kInvalidStreamIndex; - H->GlobalSymbolStreamIndex = kInvalidStreamIndex; + H->GlobalSymbolStreamIndex = GlobalsStreamIndex; Header = H; return Error::success(); Index: llvm/trunk/lib/DebugInfo/PDB/Native/GlobalsStreamBuilder.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Native/GlobalsStreamBuilder.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Native/GlobalsStreamBuilder.cpp @@ -0,0 +1,79 @@ +//===- GlobalsStreamBuilder.cpp - PDB Globals Stream Creation ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/PDB/Native/GlobalsStreamBuilder.h" + +#include "llvm/DebugInfo/MSF/MSFBuilder.h" +#include "llvm/DebugInfo/MSF/MSFCommon.h" +#include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" + +using namespace llvm; +using namespace llvm::msf; +using namespace llvm::pdb; + +GlobalsStreamBuilder::GlobalsStreamBuilder(msf::MSFBuilder &Msf) : Msf(Msf) {} + +GlobalsStreamBuilder::~GlobalsStreamBuilder() {} + +uint32_t GlobalsStreamBuilder::calculateSerializedLength() const { + uint32_t Size = 0; + // First is the header + Size += sizeof(GSIHashHeader); + + // Next is the records. For now we don't write any records, just an empty + // stream. + // FIXME: Write records and account for their size here. + Size += 0; + + // Next is a bitmap indicating which hash buckets are valid. The bitmap + // is alway present, but we only write buckets for bitmap entries which are + // non-zero, which now is noting. + size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32); + uint32_t NumBitmapEntries = BitmapSizeInBits / 8; + Size += NumBitmapEntries; + + // FIXME: Account for hash buckets. For now since we we write a zero-bitmap + // indicating that no hash buckets are valid, we also write zero byets of hash + // bucket data. + Size += 0; + return Size; +} + +Error GlobalsStreamBuilder::finalizeMsfLayout() { + Expected Idx = Msf.addStream(calculateSerializedLength()); + if (!Idx) + return Idx.takeError(); + StreamIdx = *Idx; + return Error::success(); +} + +Error GlobalsStreamBuilder::commit(BinaryStreamWriter &PublicsWriter) { + GSIHashHeader GSH; + + GSH.VerSignature = GSIHashHeader::HdrSignature; + GSH.VerHdr = GSIHashHeader::HdrVersion; + GSH.HrSize = 0; + GSH.NumBuckets = 0; + + if (auto EC = PublicsWriter.writeObject(GSH)) + return EC; + + // FIXME: Once we start writing a value other than 0 for GSH.HrSize, we need + // to write the hash records here. + size_t BitmapSizeInBits = alignTo(IPHR_HASH + 1, 32); + uint32_t NumBitmapEntries = BitmapSizeInBits / 8; + std::vector BitmapData(NumBitmapEntries); + // FIXME: Build an actual bitmap + if (auto EC = PublicsWriter.writeBytes(makeArrayRef(BitmapData))) + return EC; + + // FIXME: Write actual hash buckets. + return Error::success(); +} Index: llvm/trunk/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -15,6 +15,7 @@ #include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" +#include "llvm/DebugInfo/PDB/Native/GlobalsStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/InfoStream.h" #include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h" @@ -80,6 +81,12 @@ return *Publics; } +GlobalsStreamBuilder &PDBFileBuilder::getGlobalsBuilder() { + if (!Globals) + Globals = llvm::make_unique(*Msf); + return *Globals; +} + Error PDBFileBuilder::addNamedStream(StringRef Name, uint32_t Size) { auto ExpectedStream = Msf->addStream(Size); if (!ExpectedStream) @@ -131,6 +138,13 @@ } } + if (Globals) { + if (auto EC = Globals->finalizeMsfLayout()) + return std::move(EC); + if (Dbi) + Dbi->setGlobalsStreamIndex(Globals->getStreamIndex()); + } + return Msf->build(); } @@ -220,5 +234,13 @@ return EC; } + if (Globals) { + auto GS = WritableMappedBlockStream::createIndexedStream( + Layout, Buffer, Globals->getStreamIndex(), Allocator); + BinaryStreamWriter GSWriter(*GS); + if (auto EC = Globals->commit(GSWriter)) + return EC; + } + return Buffer.commit(); }