LLVM: lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
29
30#include
31
32using namespace llvm;
37
38namespace llvm {
40}
41
43 : Allocator(Allocator), InjectedSourceHashTraits(Strings),
44 InjectedSourceTable(2) {}
45
47
50 if (!ExpectedMsf)
51 return ExpectedMsf.takeError();
52 Msf = std::make_unique(std::move(*ExpectedMsf));
54}
55
57
59 if (!Info)
60 Info = std::make_unique(*Msf, NamedStreams);
61 return *Info;
62}
63
65 if (!Dbi)
66 Dbi = std::make_unique(*Msf);
67 return *Dbi;
68}
69
71 if (!Tpi)
72 Tpi = std::make_unique(*Msf, StreamTPI);
73 return *Tpi;
74}
75
77 if (!Ipi)
78 Ipi = std::make_unique(*Msf, StreamIPI);
79 return *Ipi;
80}
81
85
87 if (!Gsi)
88 Gsi = std::make_unique(*Msf);
89 return *Gsi;
90}
91
94 auto ExpectedStream = Msf->addStream(Size);
95 if (ExpectedStream)
96 NamedStreams.set(Name, *ExpectedStream);
97 return ExpectedStream;
98}
99
102 if (!ExpectedIndex)
103 return ExpectedIndex.takeError();
104 assert(NamedStreamData.count(*ExpectedIndex) == 0);
105 NamedStreamData[*ExpectedIndex] = std::string(Data);
107}
108
110 std::unique_ptr Buffer) {
111
112
113
116
119
120 InjectedSourceDescriptor Desc;
121 Desc.Content = std::move(Buffer);
122 Desc.NameIndex = NI;
123 Desc.VNameIndex = VNI;
124 Desc.StreamName = "/src/files/";
125
126 Desc.StreamName += VName;
127
129}
130
131Error PDBFileBuilder::finalizeMsfLayout() {
133
134 if (Ipi && Ipi->getRecordCount() > 0) {
135
136
137
138
141 }
142
144
146 if (!SN)
148
149 if (Gsi) {
150 if (auto EC = Gsi->finalizeMsfLayout())
151 return EC;
152 if (Dbi) {
153 Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
154 Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
155 Dbi->setSymbolRecordStreamIndex(Gsi->getRecordStreamIndex());
156 }
157 }
158 if (Tpi) {
159 if (auto EC = Tpi->finalizeMsfLayout())
160 return EC;
161 }
162 if (Dbi) {
163 if (auto EC = Dbi->finalizeMsfLayout())
164 return EC;
165 }
166 SN = allocateNamedStream("/names", StringsLen);
167 if (!SN)
169
170 if (Ipi) {
171 if (auto EC = Ipi->finalizeMsfLayout())
172 return EC;
173 }
174
175
176
177 if (Info) {
178 if (auto EC = Info->finalizeMsfLayout())
179 return EC;
180 }
181
182 if (!InjectedSources.empty()) {
183 for (const auto &IS : InjectedSources) {
184 JamCRC CRC(0);
186
187 SrcHeaderBlockEntry Entry;
188 ::memset(&Entry, 0, sizeof(SrcHeaderBlockEntry));
189 Entry.Size = sizeof(SrcHeaderBlockEntry);
190 Entry.FileSize = IS.Content->getBufferSize();
191 Entry.FileNI = IS.NameIndex;
192 Entry.VFileNI = IS.VNameIndex;
194 Entry.IsVirtual = 0;
197 Entry.CRC = CRC.getCRC();
199 InjectedSourceTable.set_as(VName, std::move(Entry),
200 InjectedSourceHashTraits);
201 }
202
203 uint32_t SrcHeaderBlockSize =
204 sizeof(SrcHeaderBlockHeader) +
205 InjectedSourceTable.calculateSerializedLength();
206 SN = allocateNamedStream("/src/headerblock", SrcHeaderBlockSize);
207 if (!SN)
209 for (const auto &IS : InjectedSources) {
210 SN = allocateNamedStream(IS.StreamName, IS.Content->getBufferSize());
211 if (!SN)
213 }
214 }
215
216
217
218 if (Info) {
219 if (auto EC = Info->finalizeMsfLayout())
220 return EC;
221 }
222
224}
225
228 if (!NamedStreams.get(Name, SN))
230 return SN;
231}
232
236
239 Layout, MsfBuffer, SN, Allocator);
241
243 ::memset(&Header, 0, sizeof(Header));
245 Header.Size = Writer.bytesRemaining();
246
247 cantFail(Writer.writeObject(Header));
249
250 assert(Writer.bytesRemaining() == 0);
251}
252
255 if (InjectedSourceTable.empty())
256 return;
257
259 commitSrcHeaderBlock(MsfBuffer, Layout);
260
263
265 Layout, MsfBuffer, SN, Allocator);
267 assert(SourceWriter.bytesRemaining() == IS.Content->getBufferSize());
268 cantFail(SourceWriter.writeBytes(
270 }
271}
272
274 assert(!Filename.empty());
275 if (auto EC = finalizeMsfLayout())
276 return EC;
277
280 Msf->commit(Filename, Layout);
281 if (!ExpectedMsfBuffer)
282 return ExpectedMsfBuffer.takeError();
284
286 if (!ExpectedSN)
287 return ExpectedSN.takeError();
288
290 Layout, Buffer, *ExpectedSN, Allocator);
292 if (auto EC = Strings.commit(NSWriter))
293 return EC;
294
295 {
297 for (const auto &NSE : NamedStreamData) {
298 if (NSE.second.empty())
299 continue;
300
302 Layout, Buffer, NSE.first, Allocator);
305 return EC;
306 }
307 }
308
309 if (Info) {
310 if (auto EC = Info->commit(Layout, Buffer))
311 return EC;
312 }
313
314 if (Dbi) {
315 if (auto EC = Dbi->commit(Layout, Buffer))
316 return EC;
317 }
318
319 if (Tpi) {
320 if (auto EC = Tpi->commit(Layout, Buffer))
321 return EC;
322 }
323
324 if (Ipi) {
325 if (auto EC = Ipi->commit(Layout, Buffer))
326 return EC;
327 }
328
329 if (Gsi) {
330 if (auto EC = Gsi->commit(Layout, Buffer))
331 return EC;
332 }
333
335 assert(!InfoStreamBlocks.empty());
336 uint64_t InfoStreamFileOffset =
340
341 commitInjectedSources(Buffer, Layout);
342
343
344
345 if (Info->hashPDBContentsToGUID()) {
347
348
351
352 H->Age = 1;
353
354 memcpy(H->Guid.Guid, &Digest, 8);
355
356 memcpy(H->Guid.Guid + 8, "LLD PDB.", 8);
357
358
359 H->Signature = static_cast<uint32_t>(Digest);
360
361
362 memcpy(Guid, H->Guid.Guid, 16);
363 } else {
364 H->Age = Info->getAge();
365 H->Guid = Info->getGuid();
366 std::optional<uint32_t> Sig = Info->getSignature();
367 H->Signature = Sig ? *Sig : time(nullptr);
368 }
369
370 return Buffer.commit();
371}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the SmallString class.
static const int BlockSize
Provides write only access to a subclass of WritableBinaryStream.
LLVM_ABI Error writeBytes(ArrayRef< uint8_t > Buffer)
Write the bytes specified in Buffer to the underlying stream.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
An implementation of WritableBinaryStream backed by an llvm FileOutputBuffer.
Error commit() override
For buffered streams, commits changes to the backing store.
uint8_t * getBufferEnd() const
Returns a pointer to the end of the buffer.
uint8_t * getBufferStart() const
Returns a pointer to the start of the buffer.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
void push_back(const T &Elt)
StringRef - Represent a constant reference to a string, i.e.
The TimeTraceScope is a helper class to call the begin and end functions of the time trace profiler.
A BinaryStream which can be read from as well as written to.
static LLVM_ABI Expected< MSFBuilder > create(BumpPtrAllocator &Allocator, uint32_t BlockSize, uint32_t MinBlockCount=0, bool CanGrow=true)
Create a new MSFBuilder.
static std::unique_ptr< WritableMappedBlockStream > createIndexedStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData, uint32_t StreamIndex, BumpPtrAllocator &Allocator)
Error commit(BinaryStreamWriter &Writer) const
LLVM_ABI void set(StringRef Stream, uint32_t StreamNo)
LLVM_ABI TpiStreamBuilder & getTpiBuilder()
Definition PDBFileBuilder.cpp:70
LLVM_ABI msf::MSFBuilder & getMsfBuilder()
Definition PDBFileBuilder.cpp:56
LLVM_ABI PDBStringTableBuilder & getStringTableBuilder()
Definition PDBFileBuilder.cpp:82
LLVM_ABI Error addNamedStream(StringRef Name, StringRef Data)
Definition PDBFileBuilder.cpp:100
LLVM_ABI DbiStreamBuilder & getDbiBuilder()
Definition PDBFileBuilder.cpp:64
LLVM_ABI TpiStreamBuilder & getIpiBuilder()
Definition PDBFileBuilder.cpp:76
LLVM_ABI GSIStreamBuilder & getGsiBuilder()
Definition PDBFileBuilder.cpp:86
LLVM_ABI InfoStreamBuilder & getInfoBuilder()
Definition PDBFileBuilder.cpp:58
LLVM_ABI ~PDBFileBuilder()
LLVM_ABI Error initialize(uint32_t BlockSize)
Definition PDBFileBuilder.cpp:48
LLVM_ABI PDBFileBuilder(BumpPtrAllocator &Allocator)
Definition PDBFileBuilder.cpp:42
LLVM_ABI Error commit(StringRef Filename, codeview::GUID *Guid)
Definition PDBFileBuilder.cpp:273
LLVM_ABI void addInjectedSource(StringRef Name, std::unique_ptr< MemoryBuffer > Buffer)
Definition PDBFileBuilder.cpp:109
LLVM_ABI Expected< uint32_t > getNamedStreamIndex(StringRef Name) const
Definition PDBFileBuilder.cpp:226
LLVM_ABI uint32_t insert(StringRef S)
LLVM_ABI uint32_t calculateSerializedSize() const
LLVM_ABI StringRef getStringForId(uint32_t Id) const
uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize)
This is an optimization pass for GlobalISel generic memory operations.
ArrayRef< CharT > arrayRefFromStringRef(StringRef Input)
Construct a string ref from an array ref of unsigned chars.
LLVM_ABI uint64_t xxh3_64bits(ArrayRef< uint8_t > data)
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
BumpPtrAllocatorImpl<> BumpPtrAllocator
The standard BumpPtrAllocator which just uses the default template parameters.
This represents the 'GUID' type from windows.h.
std::vector< ArrayRef< support::ulittle32_t > > StreamMap
support::ulittle32_t BlockSize