Home | History | Annotate | Line # | Download | only in Native
      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/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 
     24 namespace llvm {
     25 
     26 template <> 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 
     35 namespace msf {
     36 class MSFBuilder;
     37 struct MSFLayout;
     38 } // namespace msf
     39 namespace pdb {
     40 struct GSIHashStreamBuilder;
     41 struct BulkPublic;
     42 struct SymbolDenseMapInfo;
     43 
     44 class GSIStreamBuilder {
     45 
     46 public:
     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 
     72 private:
     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.
    106 struct 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 
    141 static_assert(sizeof(BulkPublic) <= 24, "unexpected size increase");
    142 static_assert(std::is_trivially_copyable<BulkPublic>::value,
    143               "should be trivial");
    144 
    145 } // namespace pdb
    146 } // namespace llvm
    147 
    148 #endif
    149