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
24namespace llvm {
25class BinaryStreamWriter;
26namespace codeview {
27class DebugSubsection;
28}
29
30namespace msf {
31class MSFBuilder;
32struct MSFLayout;
33}
34namespace 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.
39struct SymbolListWrapper {
40 explicit SymbolListWrapper(ArrayRef<uint8_t> Syms)
41 : SymPtr(const_cast<uint8_t *>(Syms.data())), SymSize(Syms.size()),
42 NeedsToBeMerged(false) {}
43 explicit SymbolListWrapper(void *SymSrc, uint32_t Length)
44 : SymPtr(SymSrc), SymSize(Length), NeedsToBeMerged(true) {}
45
46 ArrayRef<uint8_t> asArray() const {
47 return ArrayRef<uint8_t>(static_cast<const uint8_t *>(SymPtr), SymSize);
48 }
49
50 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.
59struct StringTableFixup {
60 uint32_t StrTabOffset = 0;
61 uint32_t SymOffsetOfReference = 0;
62};
63
64class DbiModuleDescriptorBuilder {
65 friend class DbiStreamBuilder;
66
67public:
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
83 void setMergeSymbolsCallback(void *Ctx, MergeSymbolsCallback Callback) {
84 MergeSymsCtx = Ctx;
85 MergeSymsCallback = Callback;
86 }
87
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;
107 StringRef getModuleName() const { return ModuleName; }
108 StringRef getObjFileName() const { return ObjFileName; }
109
110 unsigned getModuleIndex() const { return Layout.Mod; }
111
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.
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
132private:
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