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