llvm.org GIT mirror llvm / 6a89efb
Move some code from PDBFileBuilder to MSFBuilder. The code to emit the pieces of the MSF file were actually in PDBFileBuilder. Move this to MSFBuilder so that we can theoretically emit an MSF without having a PDB file. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@335789 91177308-0d34-0410-b5e6-96231b3b80d8 Zachary Turner 1 year, 3 months ago
6 changed file(s) with 120 addition(s) and 85 deletion(s). Raw diff Collapse all Expand all
1919 #include
2020
2121 namespace llvm {
22 class FileBufferByteStream;
23 class WritableBinaryStream;
2224 namespace msf {
2325
2426 class MSFBuilder {
108110
109111 /// Finalize the layout and build the headers and structures that describe the
110112 /// MSF layout and can be written directly to the MSF file.
111 Expected build();
113 Expected generateLayout();
114
115 /// Write the MSF layout to the underlying file.
116 Expected commit(StringRef Path, MSFLayout &Layout);
112117
113118 BumpPtrAllocator &getAllocator() { return Allocator; }
114119
7575 std::unique_ptr Content;
7676 };
7777
78 Expected finalizeMsfLayout();
78 Error finalizeMsfLayout();
7979 Expected allocateNamedStream(StringRef Name, uint32_t Size);
8080
8181 void commitFpm(WritableBinaryStream &MsfBuffer, const msf::MSFLayout &Layout);
221221 return Error::success();
222222 }
223223
224 /// Returns a pointer to the start of the buffer.
225 uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
226
227 /// Returns a pointer to the end of the buffer.
228 uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
229
224230 private:
225231 std::unique_ptr FileBuffer;
226232 };
252258
253259 Error commit() override { return Impl.commit(); }
254260
261 /// Returns a pointer to the start of the buffer.
262 uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
263
264 /// Returns a pointer to the end of the buffer.
265 uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
266
255267 private:
256268 StreamImpl Impl;
257269 };
66 //
77 //===----------------------------------------------------------------------===//
88
9 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
910 #include "llvm/ADT/ArrayRef.h"
10 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
1111 #include "llvm/DebugInfo/MSF/MSFError.h"
12 #include "llvm/DebugInfo/MSF/MappedBlockStream.h"
13 #include "llvm/Support/BinaryByteStream.h"
14 #include "llvm/Support/BinaryStreamWriter.h"
1215 #include "llvm/Support/Endian.h"
1316 #include "llvm/Support/Error.h"
17 #include "llvm/Support/FileOutputBuffer.h"
1418 #include
1519 #include
1620 #include
243247 return Size;
244248 }
245249
246 Expected MSFBuilder::build() {
250 Expected MSFBuilder::generateLayout() {
247251 SuperBlock *SB = Allocator.Allocate();
248252 MSFLayout L;
249253 L.SB = SB;
305309
306310 return L;
307311 }
312
313 static void commitFpm(WritableBinaryStream &MsfBuffer, const MSFLayout &Layout,
314 BumpPtrAllocator &Allocator) {
315 auto FpmStream =
316 WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator);
317
318 // We only need to create the alt fpm stream so that it gets initialized.
319 WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator,
320 true);
321
322 uint32_t BI = 0;
323 BinaryStreamWriter FpmWriter(*FpmStream);
324 while (BI < Layout.SB->NumBlocks) {
325 uint8_t ThisByte = 0;
326 for (uint32_t I = 0; I < 8; ++I) {
327 bool IsFree =
328 (BI < Layout.SB->NumBlocks) ? Layout.FreePageMap.test(BI) : true;
329 uint8_t Mask = uint8_t(IsFree) << I;
330 ThisByte |= Mask;
331 ++BI;
332 }
333 cantFail(FpmWriter.writeObject(ThisByte));
334 }
335 assert(FpmWriter.bytesRemaining() == 0);
336 }
337
338 Expected MSFBuilder::commit(StringRef Path,
339 MSFLayout &Layout) {
340 Expected L = generateLayout();
341 if (!L)
342 return L.takeError();
343
344 Layout = std::move(*L);
345
346 uint64_t FileSize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
347 auto OutFileOrError = FileOutputBuffer::create(Path, FileSize);
348 if (auto EC = OutFileOrError.takeError())
349 return std::move(EC);
350
351 FileBufferByteStream Buffer(std::move(*OutFileOrError),
352 llvm::support::little);
353 BinaryStreamWriter Writer(Buffer);
354
355 if (auto EC = Writer.writeObject(*Layout.SB))
356 return std::move(EC);
357
358 commitFpm(Buffer, Layout, Allocator);
359
360 uint32_t BlockMapOffset =
361 msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
362 Writer.setOffset(BlockMapOffset);
363 if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
364 return std::move(EC);
365
366 auto DirStream = WritableMappedBlockStream::createDirectoryStream(
367 Layout, Buffer, Allocator);
368 BinaryStreamWriter DW(*DirStream);
369 if (auto EC = DW.writeInteger(Layout.StreamSizes.size()))
370 return std::move(EC);
371
372 if (auto EC = DW.writeArray(Layout.StreamSizes))
373 return std::move(EC);
374
375 for (const auto &Blocks : Layout.StreamMap) {
376 if (auto EC = DW.writeArray(Blocks))
377 return std::move(EC);
378 }
379
380 return std::move(Buffer);
381 }
121121 InjectedSources.push_back(std::move(Desc));
122122 }
123123
124 Expected PDBFileBuilder::finalizeMsfLayout() {
124 Error PDBFileBuilder::finalizeMsfLayout() {
125125
126126 if (Ipi && Ipi->getRecordCount() > 0) {
127127 // In theory newer PDBs always have an ID stream, but by saying that we're
140140
141141 if (Gsi) {
142142 if (auto EC = Gsi->finalizeMsfLayout())
143 return std::move(EC);
143 return EC;
144144 if (Dbi) {
145145 Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
146146 Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
149149 }
150150 if (Tpi) {
151151 if (auto EC = Tpi->finalizeMsfLayout())
152 return std::move(EC);
152 return EC;
153153 }
154154 if (Dbi) {
155155 if (auto EC = Dbi->finalizeMsfLayout())
156 return std::move(EC);
156 return EC;
157157 }
158158 SN = allocateNamedStream("/names", StringsLen);
159159 if (!SN)
161161
162162 if (Ipi) {
163163 if (auto EC = Ipi->finalizeMsfLayout())
164 return std::move(EC);
164 return EC;
165165 }
166166
167167 // Do this last, since it relies on the named stream map being complete, and
168168 // that can be updated by previous steps in the finalization.
169169 if (Info) {
170170 if (auto EC = Info->finalizeMsfLayout())
171 return std::move(EC);
171 return EC;
172172 }
173173
174174 if (!InjectedSources.empty()) {
209209 // that can be updated by previous steps in the finalization.
210210 if (Info) {
211211 if (auto EC = Info->finalizeMsfLayout())
212 return std::move(EC);
213 }
214
215 return Msf->build();
212 return EC;
213 }
214
215 return Error::success();
216216 }
217217
218218 Expected PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
220220 if (!NamedStreams.get(Name, SN))
221221 return llvm::make_error(raw_error_code::no_stream);
222222 return SN;
223 }
224
225 void PDBFileBuilder::commitFpm(WritableBinaryStream &MsfBuffer,
226 const MSFLayout &Layout) {
227 auto FpmStream =
228 WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator);
229
230 // We only need to create the alt fpm stream so that it gets initialized.
231 WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator,
232 true);
233
234 uint32_t BI = 0;
235 BinaryStreamWriter FpmWriter(*FpmStream);
236 while (BI < Layout.SB->NumBlocks) {
237 uint8_t ThisByte = 0;
238 for (uint32_t I = 0; I < 8; ++I) {
239 bool IsFree =
240 (BI < Layout.SB->NumBlocks) ? Layout.FreePageMap.test(BI) : true;
241 uint8_t Mask = uint8_t(IsFree) << I;
242 ThisByte |= Mask;
243 ++BI;
244 }
245 cantFail(FpmWriter.writeObject(ThisByte));
246 }
247 assert(FpmWriter.bytesRemaining() == 0);
248223 }
249224
250225 void PDBFileBuilder::commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer,
288263
289264 Error PDBFileBuilder::commit(StringRef Filename) {
290265 assert(!Filename.empty());
291 auto ExpectedLayout = finalizeMsfLayout();
292 if (!ExpectedLayout)
293 return ExpectedLayout.takeError();
294 auto &Layout = *ExpectedLayout;
295
296 uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
297 auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
298 if (auto E = OutFileOrError.takeError())
299 return E;
300 FileOutputBuffer *FOB = OutFileOrError->get();
301
302 FileBufferByteStream Buffer(std::move(*OutFileOrError),
303 llvm::support::little);
304 BinaryStreamWriter Writer(Buffer);
305
306 if (auto EC = Writer.writeObject(*Layout.SB))
266 if (auto EC = finalizeMsfLayout())
307267 return EC;
308268
309 commitFpm(Buffer, Layout);
310
311 uint32_t BlockMapOffset =
312 msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
313 Writer.setOffset(BlockMapOffset);
314 if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
315 return EC;
316
317 auto DirStream = WritableMappedBlockStream::createDirectoryStream(
318 Layout, Buffer, Allocator);
319 BinaryStreamWriter DW(*DirStream);
320 if (auto EC = DW.writeInteger(Layout.StreamSizes.size()))
321 return EC;
322
323 if (auto EC = DW.writeArray(Layout.StreamSizes))
324 return EC;
325
326 for (const auto &Blocks : Layout.StreamMap) {
327 if (auto EC = DW.writeArray(Blocks))
328 return EC;
329 }
269 MSFLayout Layout;
270 auto ExpectedMsfBuffer = Msf->commit(Filename, Layout);
271 if (!ExpectedMsfBuffer)
272 return ExpectedMsfBuffer.takeError();
273 FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer);
330274
331275 auto ExpectedSN = getNamedStreamIndex("/names");
332276 if (!ExpectedSN)
379323 uint64_t InfoStreamFileOffset =
380324 blockToOffset(InfoStreamBlocks.front(), Layout.SB->BlockSize);
381325 InfoStreamHeader *H = reinterpret_cast(
382 FOB->getBufferStart() + InfoStreamFileOffset);
326 Buffer.getBufferStart() + InfoStreamFileOffset);
383327
384328 commitInjectedSources(Buffer, Layout);
385329
111111 EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
112112 auto &Msf = *ExpectedMsf;
113113
114 auto ExpectedL1 = Msf.build();
114 auto ExpectedL1 = Msf.generateLayout();
115115 EXPECT_THAT_EXPECTED(ExpectedL1, Succeeded());
116116 MSFLayout &L1 = *ExpectedL1;
117117
128128 auto Blocks = Msf2.getStreamBlocks(0);
129129 EXPECT_EQ(1U, Blocks.size());
130130
131 auto ExpectedL2 = Msf2.build();
131 auto ExpectedL2 = Msf2.generateLayout();
132132 EXPECT_THAT_EXPECTED(ExpectedL2, Succeeded());
133133 MSFLayout &L2 = *ExpectedL2;
134134 auto NewDirBlocks = L2.DirectoryBlocks;
148148 EXPECT_THAT_EXPECTED(Msf.addStream(4096 * 4096 / sizeof(uint32_t)),
149149 Succeeded());
150150
151 auto ExpectedL1 = Msf.build();
151 auto ExpectedL1 = Msf.generateLayout();
152152 EXPECT_THAT_EXPECTED(ExpectedL1, Succeeded());
153153 MSFLayout &L1 = *ExpectedL1;
154154 auto DirBlocks = L1.DirectoryBlocks;
288288 }
289289 ++ExpectedNumBlocks; // The directory itself should use 1 block
290290
291 auto ExpectedLayout = Msf.build();
291 auto ExpectedLayout = Msf.generateLayout();
292292 EXPECT_THAT_EXPECTED(ExpectedLayout, Succeeded());
293293 MSFLayout &L = *ExpectedLayout;
294294 EXPECT_EQ(4096U, L.SB->BlockSize);
315315 EXPECT_THAT_ERROR(Msf.setDirectoryBlocksHint({B + 1}), Succeeded());
316316 EXPECT_THAT_EXPECTED(Msf.addStream(2048, {B + 2}), Succeeded());
317317
318 auto ExpectedLayout = Msf.build();
318 auto ExpectedLayout = Msf.generateLayout();
319319 EXPECT_THAT_EXPECTED(ExpectedLayout, Succeeded());
320320 MSFLayout &L = *ExpectedLayout;
321321 EXPECT_EQ(msf::getMinimumBlockCount() + 2, L.SB->NumBlocks);
337337 uint32_t Size = 4096 * 4096 / 4;
338338 EXPECT_THAT_EXPECTED(Msf.addStream(Size), Succeeded());
339339
340 auto ExpectedLayout = Msf.build();
340 auto ExpectedLayout = Msf.generateLayout();
341341 EXPECT_THAT_EXPECTED(ExpectedLayout, Succeeded());
342342 MSFLayout &L = *ExpectedLayout;
343343 EXPECT_EQ(2U, L.DirectoryBlocks.size());
355355
356356 ASSERT_THAT_EXPECTED(Msf.addStream(2048), Succeeded());
357357
358 auto ExpectedLayout = Msf.build();
358 auto ExpectedLayout = Msf.generateLayout();
359359 ASSERT_THAT_EXPECTED(ExpectedLayout, Succeeded());
360360 MSFLayout &L = *ExpectedLayout;
361361 EXPECT_EQ(1U, L.DirectoryBlocks.size());
375375 Expected SN = Msf.addStream(StreamSize);
376376 ASSERT_THAT_EXPECTED(SN, Succeeded());
377377
378 auto ExpectedLayout = Msf.build();
378 auto ExpectedLayout = Msf.generateLayout();
379379 ASSERT_THAT_EXPECTED(ExpectedLayout, Succeeded());
380380 MSFLayout &L = *ExpectedLayout;
381381 auto BlocksRef = L.StreamMap[*SN];