1 //===- DbiModuleDescriptorBuilder.h - PDB module information ----*- 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_DBIMODULEDESCRIPTORBUILDER_H 10 #define LLVM_DEBUGINFO_PDB_NATIVE_DBIMODULEDESCRIPTORBUILDER_H 11 12 #include "llvm/ADT/ArrayRef.h" 13 #include "llvm/ADT/StringRef.h" 14 #include "llvm/DebugInfo/CodeView/CVRecord.h" 15 #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" 16 #include "llvm/DebugInfo/PDB/Native/RawTypes.h" 17 #include "llvm/Support/BinaryStreamRef.h" 18 #include "llvm/Support/Error.h" 19 #include <cstdint> 20 #include <string> 21 #include <vector> 22 23 namespace llvm { 24 class BinaryStreamWriter; 25 namespace codeview { 26 class DebugSubsection; 27 } 28 29 namespace msf { 30 class MSFBuilder; 31 struct MSFLayout; 32 } 33 namespace pdb { 34 35 // Represents merged or unmerged symbols. Merged symbols can be written to the 36 // output file as is, but unmerged symbols must be rewritten first. In either 37 // case, the size must be known up front. 38 struct SymbolListWrapper { 39 explicit SymbolListWrapper(ArrayRef<uint8_t> Syms) 40 : SymPtr(const_cast<uint8_t *>(Syms.data())), SymSize(Syms.size()), 41 NeedsToBeMerged(false) {} 42 explicit SymbolListWrapper(void *SymSrc, uint32_t Length) 43 : SymPtr(SymSrc), SymSize(Length), NeedsToBeMerged(true) {} 44 45 ArrayRef<uint8_t> asArray() const { 46 return ArrayRef<uint8_t>(static_cast<const uint8_t *>(SymPtr), SymSize); 47 } 48 49 uint32_t size() const { return SymSize; } 50 51 void *SymPtr = nullptr; 52 uint32_t SymSize = 0; 53 bool NeedsToBeMerged = false; 54 }; 55 56 /// Represents a string table reference at some offset in the module symbol 57 /// stream. 58 struct StringTableFixup { 59 uint32_t StrTabOffset = 0; 60 uint32_t SymOffsetOfReference = 0; 61 }; 62 63 class DbiModuleDescriptorBuilder { 64 friend class DbiStreamBuilder; 65 66 public: 67 DbiModuleDescriptorBuilder(StringRef ModuleName, uint32_t ModIndex, 68 msf::MSFBuilder &Msf); 69 ~DbiModuleDescriptorBuilder(); 70 71 DbiModuleDescriptorBuilder(const DbiModuleDescriptorBuilder &) = delete; 72 DbiModuleDescriptorBuilder & 73 operator=(const DbiModuleDescriptorBuilder &) = delete; 74 75 void setPdbFilePathNI(uint32_t NI); 76 void setObjFileName(StringRef Name); 77 78 // Callback to merge one source of unmerged symbols. 79 using MergeSymbolsCallback = Error (*)(void *Ctx, void *Symbols, 80 BinaryStreamWriter &Writer); 81 82 void setMergeSymbolsCallback(void *Ctx, MergeSymbolsCallback Callback) { 83 MergeSymsCtx = Ctx; 84 MergeSymsCallback = Callback; 85 } 86 87 void setStringTableFixups(std::vector<StringTableFixup> &&Fixups) { 88 StringTableFixups = std::move(Fixups); 89 } 90 91 void setFirstSectionContrib(const SectionContrib &SC); 92 void addSymbol(codeview::CVSymbol Symbol); 93 void addSymbolsInBulk(ArrayRef<uint8_t> BulkSymbols); 94 95 // Add symbols of known size which will be merged (rewritten) when committing 96 // the PDB to disk. 97 void addUnmergedSymbols(void *SymSrc, uint32_t SymLength); 98 99 void 100 addDebugSubsection(std::shared_ptr<codeview::DebugSubsection> Subsection); 101 102 void 103 addDebugSubsection(const codeview::DebugSubsectionRecord &SubsectionContents); 104 105 uint16_t getStreamIndex() const; 106 StringRef getModuleName() const { return ModuleName; } 107 StringRef getObjFileName() const { return ObjFileName; } 108 109 unsigned getModuleIndex() const { return Layout.Mod; } 110 111 ArrayRef<std::string> source_files() const { 112 return makeArrayRef(SourceFiles); 113 } 114 115 uint32_t calculateSerializedLength() const; 116 117 /// Return the offset within the module symbol stream of the next symbol 118 /// record passed to addSymbol. Add four to account for the signature. 119 uint32_t getNextSymbolOffset() const { return SymbolByteSize + 4; } 120 121 void finalize(); 122 Error finalizeMsfLayout(); 123 124 /// Commit the DBI descriptor to the DBI stream. 125 Error commit(BinaryStreamWriter &ModiWriter); 126 127 /// Commit the accumulated symbols to the module symbol stream. Safe to call 128 /// in parallel on different DbiModuleDescriptorBuilder objects. Only modifies 129 /// the pre-allocated stream in question. 130 Error commitSymbolStream(const msf::MSFLayout &MsfLayout, 131 WritableBinaryStreamRef MsfBuffer); 132 133 private: 134 uint32_t calculateC13DebugInfoSize() const; 135 136 void addSourceFile(StringRef Path); 137 msf::MSFBuilder &MSF; 138 139 uint32_t SymbolByteSize = 0; 140 uint32_t PdbFilePathNI = 0; 141 std::string ModuleName; 142 std::string ObjFileName; 143 std::vector<std::string> SourceFiles; 144 std::vector<SymbolListWrapper> Symbols; 145 146 void *MergeSymsCtx = nullptr; 147 MergeSymbolsCallback MergeSymsCallback = nullptr; 148 149 std::vector<StringTableFixup> StringTableFixups; 150 151 std::vector<codeview::DebugSubsectionRecordBuilder> C13Builders; 152 153 ModuleInfoHeader Layout; 154 }; 155 156 } // end namespace pdb 157 158 } // end namespace llvm 159 160 #endif // LLVM_DEBUGINFO_PDB_NATIVE_DBIMODULEDESCRIPTORBUILDER_H 161