GSIStreamBuilder.h 4.9 KB

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