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