GSIStreamBuilder.h 4.9 KB

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