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 { SymbolListWrapperSymbolListWrapper39 explicit SymbolListWrapper(ArrayRef<uint8_t> Syms) 40 : SymPtr(const_cast<uint8_t *>(Syms.data())), SymSize(Syms.size()), 41 NeedsToBeMerged(false) {} SymbolListWrapperSymbolListWrapper42 explicit SymbolListWrapper(void *SymSrc, uint32_t Length) 43 : SymPtr(SymSrc), SymSize(Length), NeedsToBeMerged(true) {} 44 asArraySymbolListWrapper45 ArrayRef<uint8_t> asArray() const { 46 return ArrayRef<uint8_t>(static_cast<const uint8_t *>(SymPtr), SymSize); 47 } 48 sizeSymbolListWrapper49 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 setMergeSymbolsCallback(void * Ctx,MergeSymbolsCallback Callback)82 void setMergeSymbolsCallback(void *Ctx, MergeSymbolsCallback Callback) { 83 MergeSymsCtx = Ctx; 84 MergeSymsCallback = Callback; 85 } 86 setStringTableFixups(std::vector<StringTableFixup> && Fixups)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; getModuleName()106 StringRef getModuleName() const { return ModuleName; } getObjFileName()107 StringRef getObjFileName() const { return ObjFileName; } 108 getModuleIndex()109 unsigned getModuleIndex() const { return Layout.Mod; } 110 source_files()111 ArrayRef<std::string> source_files() const { return SourceFiles; } 112 113 uint32_t calculateSerializedLength() const; 114 115 /// Return the offset within the module symbol stream of the next symbol 116 /// record passed to addSymbol. Add four to account for the signature. getNextSymbolOffset()117 uint32_t getNextSymbolOffset() const { return SymbolByteSize + 4; } 118 119 void finalize(); 120 Error finalizeMsfLayout(); 121 122 /// Commit the DBI descriptor to the DBI stream. 123 Error commit(BinaryStreamWriter &ModiWriter); 124 125 /// Commit the accumulated symbols to the module symbol stream. Safe to call 126 /// in parallel on different DbiModuleDescriptorBuilder objects. Only modifies 127 /// the pre-allocated stream in question. 128 Error commitSymbolStream(const msf::MSFLayout &MsfLayout, 129 WritableBinaryStreamRef MsfBuffer); 130 131 private: 132 uint32_t calculateC13DebugInfoSize() const; 133 134 void addSourceFile(StringRef Path); 135 msf::MSFBuilder &MSF; 136 137 uint32_t SymbolByteSize = 0; 138 uint32_t PdbFilePathNI = 0; 139 std::string ModuleName; 140 std::string ObjFileName; 141 std::vector<std::string> SourceFiles; 142 std::vector<SymbolListWrapper> Symbols; 143 144 void *MergeSymsCtx = nullptr; 145 MergeSymbolsCallback MergeSymsCallback = nullptr; 146 147 std::vector<StringTableFixup> StringTableFixups; 148 149 std::vector<codeview::DebugSubsectionRecordBuilder> C13Builders; 150 151 ModuleInfoHeader Layout; 152 }; 153 154 } // end namespace pdb 155 156 } // end namespace llvm 157 158 #endif // LLVM_DEBUGINFO_PDB_NATIVE_DBIMODULEDESCRIPTORBUILDER_H 159