1 //===- GSIStreamBuilder.h - PDB Publics/Globals Stream Creation -*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_DEBUGINFO_PDB_NATIVE_GSISTREAMBUILDER_H 10 #define LLVM_DEBUGINFO_PDB_NATIVE_GSISTREAMBUILDER_H 11 12 #include "llvm/ADT/DenseSet.h" 13 #include "llvm/DebugInfo/CodeView/CVRecord.h" 14 #include "llvm/DebugInfo/CodeView/CodeView.h" 15 #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" 16 #include "llvm/DebugInfo/PDB/Native/RawConstants.h" 17 #include "llvm/Support/BinaryStreamRef.h" 18 #include "llvm/Support/Error.h" 19 20 namespace llvm { 21 namespace codeview { 22 class ConstantSym; 23 class DataSym; 24 class ProcRefSym; 25 } // namespace codeview 26 template <typename T> struct BinaryItemTraits; 27 28 template <> struct BinaryItemTraits<codeview::CVSymbol> { 29 static size_t length(const codeview::CVSymbol &Item) { 30 return Item.RecordData.size(); 31 } 32 static ArrayRef<uint8_t> bytes(const codeview::CVSymbol &Item) { 33 return Item.RecordData; 34 } 35 }; 36 37 namespace msf { 38 class MSFBuilder; 39 struct MSFLayout; 40 } // namespace msf 41 namespace pdb { 42 struct GSIHashStreamBuilder; 43 struct BulkPublic; 44 struct SymbolDenseMapInfo; 45 46 class GSIStreamBuilder { 47 48 public: 49 explicit GSIStreamBuilder(msf::MSFBuilder &Msf); 50 ~GSIStreamBuilder(); 51 52 GSIStreamBuilder(const GSIStreamBuilder &) = delete; 53 GSIStreamBuilder &operator=(const GSIStreamBuilder &) = delete; 54 55 Error finalizeMsfLayout(); 56 57 Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer); 58 59 uint32_t getPublicsStreamIndex() const { return PublicsStreamIndex; } 60 uint32_t getGlobalsStreamIndex() const { return GlobalsStreamIndex; } 61 uint32_t getRecordStreamIndex() const { return RecordStreamIndex; } 62 63 // Add public symbols in bulk. 64 void addPublicSymbols(std::vector<BulkPublic> &&PublicsIn); 65 66 void addGlobalSymbol(const codeview::ProcRefSym &Sym); 67 void addGlobalSymbol(const codeview::DataSym &Sym); 68 void addGlobalSymbol(const codeview::ConstantSym &Sym); 69 70 // Add a pre-serialized global symbol record. The caller must ensure that the 71 // symbol data remains alive until the global stream is committed to disk. 72 void addGlobalSymbol(const codeview::CVSymbol &Sym); 73 74 private: 75 void finalizePublicBuckets(); 76 void finalizeGlobalBuckets(uint32_t RecordZeroOffset); 77 78 template <typename T> void serializeAndAddGlobal(const T &Symbol); 79 80 uint32_t calculatePublicsHashStreamSize() const; 81 uint32_t calculateGlobalsHashStreamSize() const; 82 Error commitSymbolRecordStream(WritableBinaryStreamRef Stream); 83 Error commitPublicsHashStream(WritableBinaryStreamRef Stream); 84 Error commitGlobalsHashStream(WritableBinaryStreamRef Stream); 85 86 uint32_t PublicsStreamIndex = kInvalidStreamIndex; 87 uint32_t GlobalsStreamIndex = kInvalidStreamIndex; 88 uint32_t RecordStreamIndex = kInvalidStreamIndex; 89 msf::MSFBuilder &Msf; 90 std::unique_ptr<GSIHashStreamBuilder> PSH; 91 std::unique_ptr<GSIHashStreamBuilder> GSH; 92 93 // List of all of the public records. These are stored unserialized so that we 94 // can defer copying the names until we are ready to commit the PDB. 95 std::vector<BulkPublic> Publics; 96 97 // List of all of the global records. 98 std::vector<codeview::CVSymbol> Globals; 99 100 // Hash table for deduplicating global typedef and constant records. Only used 101 // for globals. 102 llvm::DenseSet<codeview::CVSymbol, SymbolDenseMapInfo> GlobalsSeen; 103 }; 104 105 /// This struct is equivalent to codeview::PublicSym32, but it has been 106 /// optimized for size to speed up bulk serialization and sorting operations 107 /// during PDB writing. 108 struct BulkPublic { 109 BulkPublic() : Flags(0), BucketIdx(0) {} 110 111 const char *Name = nullptr; 112 uint32_t NameLen = 0; 113 114 // Offset of the symbol record in the publics stream. 115 uint32_t SymOffset = 0; 116 117 // Section offset of the symbol in the image. 118 uint32_t Offset = 0; 119 120 // Section index of the section containing the symbol. 121 uint16_t Segment = 0; 122 123 // PublicSymFlags. 124 uint16_t Flags : 4; 125 126 // GSI hash table bucket index. The maximum value is IPHR_HASH. 127 uint16_t BucketIdx : 12; 128 static_assert(IPHR_HASH <= 1 << 12, "bitfield too small"); 129 130 void setFlags(codeview::PublicSymFlags F) { 131 Flags = uint32_t(F); 132 assert(Flags == uint32_t(F) && "truncated"); 133 } 134 135 void setBucketIdx(uint16_t B) { 136 assert(B < IPHR_HASH); 137 BucketIdx = B; 138 } 139 140 StringRef getName() const { return StringRef(Name, NameLen); } 141 }; 142 143 static_assert(sizeof(BulkPublic) <= 24, "unexpected size increase"); 144 static_assert(std::is_trivially_copyable<BulkPublic>::value, 145 "should be trivial"); 146 147 } // namespace pdb 148 } // namespace llvm 149 150 #endif 151