Move some code from PDBFileBuilder to MSFBuilder.
authorZachary Turner <zturner@google.com>
Wed, 27 Jun 2018 21:18:15 +0000 (21:18 +0000)
committerZachary Turner <zturner@google.com>
Wed, 27 Jun 2018 21:18:15 +0000 (21:18 +0000)
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.

llvm-svn: 335789

llvm/include/llvm/DebugInfo/MSF/MSFBuilder.h
llvm/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
llvm/include/llvm/Support/BinaryByteStream.h
llvm/lib/DebugInfo/MSF/MSFBuilder.cpp
llvm/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp
llvm/unittests/DebugInfo/MSF/MSFBuilderTest.cpp

index c06a0b4..3de98c4 100644 (file)
@@ -20,6 +20,8 @@
 #include <vector>
 
 namespace llvm {
+class FileBufferByteStream;
+class WritableBinaryStream;
 namespace msf {
 
 class MSFBuilder {
@@ -109,7 +111,10 @@ public:
 
   /// Finalize the layout and build the headers and structures that describe the
   /// MSF layout and can be written directly to the MSF file.
-  Expected<MSFLayout> build();
+  Expected<MSFLayout> generateLayout();
+
+  /// Write the MSF layout to the underlying file.
+  Expected<FileBufferByteStream> commit(StringRef Path, MSFLayout &Layout);
 
   BumpPtrAllocator &getAllocator() { return Allocator; }
 
index 58dda71..7f9c4cf 100644 (file)
@@ -76,7 +76,7 @@ private:
     std::unique_ptr<MemoryBuffer> Content;
   };
 
-  Expected<msf::MSFLayout> finalizeMsfLayout();
+  Error finalizeMsfLayout();
   Expected<uint32_t> allocateNamedStream(StringRef Name, uint32_t Size);
 
   void commitFpm(WritableBinaryStream &MsfBuffer, const msf::MSFLayout &Layout);
index f39ac4e..9808d3b 100644 (file)
@@ -222,6 +222,12 @@ private:
       return Error::success();
     }
 
+    /// Returns a pointer to the start of the buffer.
+    uint8_t *getBufferStart() const { return FileBuffer->getBufferStart(); }
+
+    /// Returns a pointer to the end of the buffer.
+    uint8_t *getBufferEnd() const { return FileBuffer->getBufferEnd(); }
+
   private:
     std::unique_ptr<FileOutputBuffer> FileBuffer;
   };
@@ -253,6 +259,12 @@ public:
 
   Error commit() override { return Impl.commit(); }
 
+  /// Returns a pointer to the start of the buffer.
+  uint8_t *getBufferStart() const { return Impl.getBufferStart(); }
+
+  /// Returns a pointer to the end of the buffer.
+  uint8_t *getBufferEnd() const { return Impl.getBufferEnd(); }
+
 private:
   StreamImpl Impl;
 };
index 919f870..7160991 100644 (file)
@@ -7,11 +7,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ADT/ArrayRef.h"
 #include "llvm/DebugInfo/MSF/MSFBuilder.h"
+#include "llvm/ADT/ArrayRef.h"
 #include "llvm/DebugInfo/MSF/MSFError.h"
+#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryStreamWriter.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/FileOutputBuffer.h"
 #include <algorithm>
 #include <cassert>
 #include <cstdint>
@@ -244,7 +248,7 @@ uint32_t MSFBuilder::computeDirectoryByteSize() const {
   return Size;
 }
 
-Expected<MSFLayout> MSFBuilder::build() {
+Expected<MSFLayout> MSFBuilder::generateLayout() {
   SuperBlock *SB = Allocator.Allocate<SuperBlock>();
   MSFLayout L;
   L.SB = SB;
@@ -306,3 +310,73 @@ Expected<MSFLayout> MSFBuilder::build() {
 
   return L;
 }
+
+static void commitFpm(WritableBinaryStream &MsfBuffer, const MSFLayout &Layout,
+                      BumpPtrAllocator &Allocator) {
+  auto FpmStream =
+      WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator);
+
+  // We only need to create the alt fpm stream so that it gets initialized.
+  WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator,
+                                             true);
+
+  uint32_t BI = 0;
+  BinaryStreamWriter FpmWriter(*FpmStream);
+  while (BI < Layout.SB->NumBlocks) {
+    uint8_t ThisByte = 0;
+    for (uint32_t I = 0; I < 8; ++I) {
+      bool IsFree =
+          (BI < Layout.SB->NumBlocks) ? Layout.FreePageMap.test(BI) : true;
+      uint8_t Mask = uint8_t(IsFree) << I;
+      ThisByte |= Mask;
+      ++BI;
+    }
+    cantFail(FpmWriter.writeObject(ThisByte));
+  }
+  assert(FpmWriter.bytesRemaining() == 0);
+}
+
+Expected<FileBufferByteStream> MSFBuilder::commit(StringRef Path,
+                                                  MSFLayout &Layout) {
+  Expected<MSFLayout> L = generateLayout();
+  if (!L)
+    return L.takeError();
+
+  Layout = std::move(*L);
+
+  uint64_t FileSize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
+  auto OutFileOrError = FileOutputBuffer::create(Path, FileSize);
+  if (auto EC = OutFileOrError.takeError())
+    return std::move(EC);
+
+  FileBufferByteStream Buffer(std::move(*OutFileOrError),
+                              llvm::support::little);
+  BinaryStreamWriter Writer(Buffer);
+
+  if (auto EC = Writer.writeObject(*Layout.SB))
+    return std::move(EC);
+
+  commitFpm(Buffer, Layout, Allocator);
+
+  uint32_t BlockMapOffset =
+      msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
+  Writer.setOffset(BlockMapOffset);
+  if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
+    return std::move(EC);
+
+  auto DirStream = WritableMappedBlockStream::createDirectoryStream(
+      Layout, Buffer, Allocator);
+  BinaryStreamWriter DW(*DirStream);
+  if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size()))
+    return std::move(EC);
+
+  if (auto EC = DW.writeArray(Layout.StreamSizes))
+    return std::move(EC);
+
+  for (const auto &Blocks : Layout.StreamMap) {
+    if (auto EC = DW.writeArray(Blocks))
+      return std::move(EC);
+  }
+
+  return std::move(Buffer);
+}
index 7704858..e164e7c 100644 (file)
@@ -122,7 +122,7 @@ void PDBFileBuilder::addInjectedSource(StringRef Name,
   InjectedSources.push_back(std::move(Desc));
 }
 
-Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
+Error PDBFileBuilder::finalizeMsfLayout() {
 
   if (Ipi && Ipi->getRecordCount() > 0) {
     // In theory newer PDBs always have an ID stream, but by saying that we're
@@ -141,7 +141,7 @@ Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
 
   if (Gsi) {
     if (auto EC = Gsi->finalizeMsfLayout())
-      return std::move(EC);
+      return EC;
     if (Dbi) {
       Dbi->setPublicsStreamIndex(Gsi->getPublicsStreamIndex());
       Dbi->setGlobalsStreamIndex(Gsi->getGlobalsStreamIndex());
@@ -150,11 +150,11 @@ Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
   }
   if (Tpi) {
     if (auto EC = Tpi->finalizeMsfLayout())
-      return std::move(EC);
+      return EC;
   }
   if (Dbi) {
     if (auto EC = Dbi->finalizeMsfLayout())
-      return std::move(EC);
+      return EC;
   }
   SN = allocateNamedStream("/names", StringsLen);
   if (!SN)
@@ -162,14 +162,14 @@ Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
 
   if (Ipi) {
     if (auto EC = Ipi->finalizeMsfLayout())
-      return std::move(EC);
+      return EC;
   }
 
   // Do this last, since it relies on the named stream map being complete, and
   // that can be updated by previous steps in the finalization.
   if (Info) {
     if (auto EC = Info->finalizeMsfLayout())
-      return std::move(EC);
+      return EC;
   }
 
   if (!InjectedSources.empty()) {
@@ -210,10 +210,10 @@ Expected<msf::MSFLayout> PDBFileBuilder::finalizeMsfLayout() {
   // that can be updated by previous steps in the finalization.
   if (Info) {
     if (auto EC = Info->finalizeMsfLayout())
-      return std::move(EC);
+      return EC;
   }
 
-  return Msf->build();
+  return Error::success();
 }
 
 Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
@@ -223,31 +223,6 @@ Expected<uint32_t> PDBFileBuilder::getNamedStreamIndex(StringRef Name) const {
   return SN;
 }
 
-void PDBFileBuilder::commitFpm(WritableBinaryStream &MsfBuffer,
-                               const MSFLayout &Layout) {
-  auto FpmStream =
-      WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator);
-
-  // We only need to create the alt fpm stream so that it gets initialized.
-  WritableMappedBlockStream::createFpmStream(Layout, MsfBuffer, Allocator,
-                                             true);
-
-  uint32_t BI = 0;
-  BinaryStreamWriter FpmWriter(*FpmStream);
-  while (BI < Layout.SB->NumBlocks) {
-    uint8_t ThisByte = 0;
-    for (uint32_t I = 0; I < 8; ++I) {
-      bool IsFree =
-          (BI < Layout.SB->NumBlocks) ? Layout.FreePageMap.test(BI) : true;
-      uint8_t Mask = uint8_t(IsFree) << I;
-      ThisByte |= Mask;
-      ++BI;
-    }
-    cantFail(FpmWriter.writeObject(ThisByte));
-  }
-  assert(FpmWriter.bytesRemaining() == 0);
-}
-
 void PDBFileBuilder::commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer,
                                           const msf::MSFLayout &Layout) {
   assert(!InjectedSourceTable.empty());
@@ -289,45 +264,14 @@ void PDBFileBuilder::commitInjectedSources(WritableBinaryStream &MsfBuffer,
 
 Error PDBFileBuilder::commit(StringRef Filename) {
   assert(!Filename.empty());
-  auto ExpectedLayout = finalizeMsfLayout();
-  if (!ExpectedLayout)
-    return ExpectedLayout.takeError();
-  auto &Layout = *ExpectedLayout;
-
-  uint64_t Filesize = Layout.SB->BlockSize * Layout.SB->NumBlocks;
-  auto OutFileOrError = FileOutputBuffer::create(Filename, Filesize);
-  if (auto E = OutFileOrError.takeError())
-    return E;
-  FileOutputBuffer *FOB = OutFileOrError->get();
-
-  FileBufferByteStream Buffer(std::move(*OutFileOrError),
-                              llvm::support::little);
-  BinaryStreamWriter Writer(Buffer);
-
-  if (auto EC = Writer.writeObject(*Layout.SB))
-    return EC;
-
-  commitFpm(Buffer, Layout);
-
-  uint32_t BlockMapOffset =
-      msf::blockToOffset(Layout.SB->BlockMapAddr, Layout.SB->BlockSize);
-  Writer.setOffset(BlockMapOffset);
-  if (auto EC = Writer.writeArray(Layout.DirectoryBlocks))
-    return EC;
-
-  auto DirStream = WritableMappedBlockStream::createDirectoryStream(
-      Layout, Buffer, Allocator);
-  BinaryStreamWriter DW(*DirStream);
-  if (auto EC = DW.writeInteger<uint32_t>(Layout.StreamSizes.size()))
-    return EC;
-
-  if (auto EC = DW.writeArray(Layout.StreamSizes))
+  if (auto EC = finalizeMsfLayout())
     return EC;
 
-  for (const auto &Blocks : Layout.StreamMap) {
-    if (auto EC = DW.writeArray(Blocks))
-      return EC;
-  }
+  MSFLayout Layout;
+  auto ExpectedMsfBuffer = Msf->commit(Filename, Layout);
+  if (!ExpectedMsfBuffer)
+    return ExpectedMsfBuffer.takeError();
+  FileBufferByteStream Buffer = std::move(*ExpectedMsfBuffer);
 
   auto ExpectedSN = getNamedStreamIndex("/names");
   if (!ExpectedSN)
@@ -380,7 +324,7 @@ Error PDBFileBuilder::commit(StringRef Filename) {
   uint64_t InfoStreamFileOffset =
       blockToOffset(InfoStreamBlocks.front(), Layout.SB->BlockSize);
   InfoStreamHeader *H = reinterpret_cast<InfoStreamHeader *>(
-      FOB->getBufferStart() + InfoStreamFileOffset);
+      Buffer.getBufferStart() + InfoStreamFileOffset);
 
   commitInjectedSources(Buffer, Layout);
 
index 2e31779..1624795 100644 (file)
@@ -112,7 +112,7 @@ TEST_F(MSFBuilderTest, TestAddStreamNoDirectoryBlockIncrease) {
   EXPECT_THAT_EXPECTED(ExpectedMsf, Succeeded());
   auto &Msf = *ExpectedMsf;
 
-  auto ExpectedL1 = Msf.build();
+  auto ExpectedL1 = Msf.generateLayout();
   EXPECT_THAT_EXPECTED(ExpectedL1, Succeeded());
   MSFLayout &L1 = *ExpectedL1;
 
@@ -129,7 +129,7 @@ TEST_F(MSFBuilderTest, TestAddStreamNoDirectoryBlockIncrease) {
   auto Blocks = Msf2.getStreamBlocks(0);
   EXPECT_EQ(1U, Blocks.size());
 
-  auto ExpectedL2 = Msf2.build();
+  auto ExpectedL2 = Msf2.generateLayout();
   EXPECT_THAT_EXPECTED(ExpectedL2, Succeeded());
   MSFLayout &L2 = *ExpectedL2;
   auto NewDirBlocks = L2.DirectoryBlocks;
@@ -149,7 +149,7 @@ TEST_F(MSFBuilderTest, TestAddStreamWithDirectoryBlockIncrease) {
   EXPECT_THAT_EXPECTED(Msf.addStream(4096 * 4096 / sizeof(uint32_t)),
                        Succeeded());
 
-  auto ExpectedL1 = Msf.build();
+  auto ExpectedL1 = Msf.generateLayout();
   EXPECT_THAT_EXPECTED(ExpectedL1, Succeeded());
   MSFLayout &L1 = *ExpectedL1;
   auto DirBlocks = L1.DirectoryBlocks;
@@ -289,7 +289,7 @@ TEST_F(MSFBuilderTest, BuildMsfLayout) {
   }
   ++ExpectedNumBlocks; // The directory itself should use 1 block
 
-  auto ExpectedLayout = Msf.build();
+  auto ExpectedLayout = Msf.generateLayout();
   EXPECT_THAT_EXPECTED(ExpectedLayout, Succeeded());
   MSFLayout &L = *ExpectedLayout;
   EXPECT_EQ(4096U, L.SB->BlockSize);
@@ -316,7 +316,7 @@ TEST_F(MSFBuilderTest, UseDirectoryBlockHint) {
   EXPECT_THAT_ERROR(Msf.setDirectoryBlocksHint({B + 1}), Succeeded());
   EXPECT_THAT_EXPECTED(Msf.addStream(2048, {B + 2}), Succeeded());
 
-  auto ExpectedLayout = Msf.build();
+  auto ExpectedLayout = Msf.generateLayout();
   EXPECT_THAT_EXPECTED(ExpectedLayout, Succeeded());
   MSFLayout &L = *ExpectedLayout;
   EXPECT_EQ(msf::getMinimumBlockCount() + 2, L.SB->NumBlocks);
@@ -338,7 +338,7 @@ TEST_F(MSFBuilderTest, DirectoryBlockHintInsufficient) {
   uint32_t Size = 4096 * 4096 / 4;
   EXPECT_THAT_EXPECTED(Msf.addStream(Size), Succeeded());
 
-  auto ExpectedLayout = Msf.build();
+  auto ExpectedLayout = Msf.generateLayout();
   EXPECT_THAT_EXPECTED(ExpectedLayout, Succeeded());
   MSFLayout &L = *ExpectedLayout;
   EXPECT_EQ(2U, L.DirectoryBlocks.size());
@@ -356,7 +356,7 @@ TEST_F(MSFBuilderTest, DirectoryBlockHintOverestimated) {
 
   ASSERT_THAT_EXPECTED(Msf.addStream(2048), Succeeded());
 
-  auto ExpectedLayout = Msf.build();
+  auto ExpectedLayout = Msf.generateLayout();
   ASSERT_THAT_EXPECTED(ExpectedLayout, Succeeded());
   MSFLayout &L = *ExpectedLayout;
   EXPECT_EQ(1U, L.DirectoryBlocks.size());
@@ -376,7 +376,7 @@ TEST_F(MSFBuilderTest, StreamDoesntUseFpmBlocks) {
   Expected<uint32_t> SN = Msf.addStream(StreamSize);
   ASSERT_THAT_EXPECTED(SN, Succeeded());
 
-  auto ExpectedLayout = Msf.build();
+  auto ExpectedLayout = Msf.generateLayout();
   ASSERT_THAT_EXPECTED(ExpectedLayout, Succeeded());
   MSFLayout &L = *ExpectedLayout;
   auto BlocksRef = L.StreamMap[*SN];