DbiModuleDescriptorBuilder.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. //===- DbiModuleDescriptorBuilder.cpp - PDB Mod Info 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. #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
  9. #include "llvm/ADT/ArrayRef.h"
  10. #include "llvm/BinaryFormat/COFF.h"
  11. #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
  12. #include "llvm/DebugInfo/MSF/MSFBuilder.h"
  13. #include "llvm/DebugInfo/MSF/MSFCommon.h"
  14. #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
  15. #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
  16. #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h"
  17. #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
  18. #include "llvm/DebugInfo/PDB/Native/RawError.h"
  19. #include "llvm/Support/BinaryStreamWriter.h"
  20. using namespace llvm;
  21. using namespace llvm::codeview;
  22. using namespace llvm::msf;
  23. using namespace llvm::pdb;
  24. static uint32_t calculateDiSymbolStreamSize(uint32_t SymbolByteSize,
  25. uint32_t C13Size) {
  26. uint32_t Size = sizeof(uint32_t); // Signature
  27. Size += alignTo(SymbolByteSize, 4); // Symbol Data
  28. Size += 0; // TODO: Layout.C11Bytes
  29. Size += C13Size; // C13 Debug Info Size
  30. Size += sizeof(uint32_t); // GlobalRefs substream size (always 0)
  31. Size += 0; // GlobalRefs substream bytes
  32. return Size;
  33. }
  34. DbiModuleDescriptorBuilder::DbiModuleDescriptorBuilder(StringRef ModuleName,
  35. uint32_t ModIndex,
  36. msf::MSFBuilder &Msf)
  37. : MSF(Msf), ModuleName(std::string(ModuleName)) {
  38. ::memset(&Layout, 0, sizeof(Layout));
  39. Layout.Mod = ModIndex;
  40. }
  41. DbiModuleDescriptorBuilder::~DbiModuleDescriptorBuilder() {}
  42. uint16_t DbiModuleDescriptorBuilder::getStreamIndex() const {
  43. return Layout.ModDiStream;
  44. }
  45. void DbiModuleDescriptorBuilder::setObjFileName(StringRef Name) {
  46. ObjFileName = std::string(Name);
  47. }
  48. void DbiModuleDescriptorBuilder::setPdbFilePathNI(uint32_t NI) {
  49. PdbFilePathNI = NI;
  50. }
  51. void DbiModuleDescriptorBuilder::setFirstSectionContrib(
  52. const SectionContrib &SC) {
  53. Layout.SC = SC;
  54. }
  55. void DbiModuleDescriptorBuilder::addSymbol(CVSymbol Symbol) {
  56. // Defer to the bulk API. It does the same thing.
  57. addSymbolsInBulk(Symbol.data());
  58. }
  59. void DbiModuleDescriptorBuilder::addSymbolsInBulk(
  60. ArrayRef<uint8_t> BulkSymbols) {
  61. // Do nothing for empty runs of symbols.
  62. if (BulkSymbols.empty())
  63. return;
  64. Symbols.push_back(SymbolListWrapper(BulkSymbols));
  65. // Symbols written to a PDB file are required to be 4 byte aligned. The same
  66. // is not true of object files.
  67. assert(BulkSymbols.size() % alignOf(CodeViewContainer::Pdb) == 0 &&
  68. "Invalid Symbol alignment!");
  69. SymbolByteSize += BulkSymbols.size();
  70. }
  71. void DbiModuleDescriptorBuilder::addUnmergedSymbols(void *SymSrc,
  72. uint32_t SymLength) {
  73. assert(SymLength > 0);
  74. Symbols.push_back(SymbolListWrapper(SymSrc, SymLength));
  75. // Symbols written to a PDB file are required to be 4 byte aligned. The same
  76. // is not true of object files.
  77. assert(SymLength % alignOf(CodeViewContainer::Pdb) == 0 &&
  78. "Invalid Symbol alignment!");
  79. SymbolByteSize += SymLength;
  80. }
  81. void DbiModuleDescriptorBuilder::addSourceFile(StringRef Path) {
  82. SourceFiles.push_back(std::string(Path));
  83. }
  84. uint32_t DbiModuleDescriptorBuilder::calculateC13DebugInfoSize() const {
  85. uint32_t Result = 0;
  86. for (const auto &Builder : C13Builders) {
  87. Result += Builder.calculateSerializedLength();
  88. }
  89. return Result;
  90. }
  91. uint32_t DbiModuleDescriptorBuilder::calculateSerializedLength() const {
  92. uint32_t L = sizeof(Layout);
  93. uint32_t M = ModuleName.size() + 1;
  94. uint32_t O = ObjFileName.size() + 1;
  95. return alignTo(L + M + O, sizeof(uint32_t));
  96. }
  97. void DbiModuleDescriptorBuilder::finalize() {
  98. Layout.FileNameOffs = 0; // TODO: Fix this
  99. Layout.Flags = 0; // TODO: Fix this
  100. Layout.C11Bytes = 0;
  101. Layout.C13Bytes = calculateC13DebugInfoSize();
  102. (void)Layout.Mod; // Set in constructor
  103. (void)Layout.ModDiStream; // Set in finalizeMsfLayout
  104. Layout.NumFiles = SourceFiles.size();
  105. Layout.PdbFilePathNI = PdbFilePathNI;
  106. Layout.SrcFileNameNI = 0;
  107. // This value includes both the signature field as well as the record bytes
  108. // from the symbol stream.
  109. Layout.SymBytes =
  110. Layout.ModDiStream == kInvalidStreamIndex ? 0 : getNextSymbolOffset();
  111. }
  112. Error DbiModuleDescriptorBuilder::finalizeMsfLayout() {
  113. this->Layout.ModDiStream = kInvalidStreamIndex;
  114. uint32_t C13Size = calculateC13DebugInfoSize();
  115. if (!C13Size && !SymbolByteSize)
  116. return Error::success();
  117. auto ExpectedSN =
  118. MSF.addStream(calculateDiSymbolStreamSize(SymbolByteSize, C13Size));
  119. if (!ExpectedSN)
  120. return ExpectedSN.takeError();
  121. Layout.ModDiStream = *ExpectedSN;
  122. return Error::success();
  123. }
  124. Error DbiModuleDescriptorBuilder::commit(BinaryStreamWriter &ModiWriter) {
  125. // We write the Modi record to the `ModiWriter`, but we additionally write its
  126. // symbol stream to a brand new stream.
  127. if (auto EC = ModiWriter.writeObject(Layout))
  128. return EC;
  129. if (auto EC = ModiWriter.writeCString(ModuleName))
  130. return EC;
  131. if (auto EC = ModiWriter.writeCString(ObjFileName))
  132. return EC;
  133. if (auto EC = ModiWriter.padToAlignment(sizeof(uint32_t)))
  134. return EC;
  135. return Error::success();
  136. }
  137. Error DbiModuleDescriptorBuilder::commitSymbolStream(
  138. const msf::MSFLayout &MsfLayout, WritableBinaryStreamRef MsfBuffer) {
  139. if (Layout.ModDiStream == kInvalidStreamIndex)
  140. return Error::success();
  141. auto NS = WritableMappedBlockStream::createIndexedStream(
  142. MsfLayout, MsfBuffer, Layout.ModDiStream, MSF.getAllocator());
  143. WritableBinaryStreamRef Ref(*NS);
  144. BinaryStreamWriter SymbolWriter(Ref);
  145. // Write the symbols.
  146. if (auto EC = SymbolWriter.writeInteger<uint32_t>(COFF::DEBUG_SECTION_MAGIC))
  147. return EC;
  148. for (const SymbolListWrapper &Sym : Symbols) {
  149. if (Sym.NeedsToBeMerged) {
  150. assert(MergeSymsCallback);
  151. if (auto EC = MergeSymsCallback(MergeSymsCtx, Sym.SymPtr, SymbolWriter))
  152. return EC;
  153. } else {
  154. if (auto EC = SymbolWriter.writeBytes(Sym.asArray()))
  155. return EC;
  156. }
  157. }
  158. // Apply the string table fixups.
  159. auto SavedOffset = SymbolWriter.getOffset();
  160. for (const StringTableFixup &Fixup : StringTableFixups) {
  161. SymbolWriter.setOffset(Fixup.SymOffsetOfReference);
  162. if (auto E = SymbolWriter.writeInteger<uint32_t>(Fixup.StrTabOffset))
  163. return E;
  164. }
  165. SymbolWriter.setOffset(SavedOffset);
  166. assert(SymbolWriter.getOffset() % alignOf(CodeViewContainer::Pdb) == 0 &&
  167. "Invalid debug section alignment!");
  168. // TODO: Write C11 Line data
  169. for (const auto &Builder : C13Builders) {
  170. if (auto EC = Builder.commit(SymbolWriter, CodeViewContainer::Pdb))
  171. return EC;
  172. }
  173. // TODO: Figure out what GlobalRefs substream actually is and populate it.
  174. if (auto EC = SymbolWriter.writeInteger<uint32_t>(0))
  175. return EC;
  176. if (SymbolWriter.bytesRemaining() > 0)
  177. return make_error<RawError>(raw_error_code::stream_too_long);
  178. return Error::success();
  179. }
  180. void DbiModuleDescriptorBuilder::addDebugSubsection(
  181. std::shared_ptr<DebugSubsection> Subsection) {
  182. assert(Subsection);
  183. C13Builders.push_back(DebugSubsectionRecordBuilder(std::move(Subsection)));
  184. }
  185. void DbiModuleDescriptorBuilder::addDebugSubsection(
  186. const DebugSubsectionRecord &SubsectionContents) {
  187. C13Builders.push_back(DebugSubsectionRecordBuilder(SubsectionContents));
  188. }