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