[pdb/lld] Write a valid FPM.

The PDB reserves certain blocks for the FPM that describe which
blocks in the file are allocated and which are free.  We weren't
filling that out at all, and in some cases we were even stomping
it with incorrect data.  This patch writes a correct FPM.

Differential Revision: https://reviews.llvm.org/D36235

llvm-svn: 309896
diff --git a/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp b/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp
index 2a200ed..f28f9441 100644
--- a/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp
+++ b/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp
@@ -11,6 +11,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/DebugInfo/MSF/MSFCommon.h"
+#include "llvm/Support/BinaryStreamWriter.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/MathExtras.h"
@@ -347,9 +348,27 @@
 std::unique_ptr<WritableMappedBlockStream>
 WritableMappedBlockStream::createFpmStream(const MSFLayout &Layout,
                                            WritableBinaryStreamRef MsfData,
-                                           BumpPtrAllocator &Allocator) {
-  MSFStreamLayout SL(getFpmStreamLayout(Layout));
-  return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator);
+                                           BumpPtrAllocator &Allocator,
+                                           bool AltFpm) {
+  // We only want to give the user a stream containing the bytes of the FPM that
+  // are actually valid, but we want to initialize all of the bytes, even those
+  // that come from reserved FPM blocks where the entire block is unused.  To do
+  // this, we first create the full layout, which gives us a stream with all
+  // bytes and all blocks, and initialize everything to 0xFF (all blocks in the
+  // file are unused).  Then we create the minimal layout (which contains only a
+  // subset of the bytes previously initialized), and return that to the user.
+  MSFStreamLayout MinLayout(getFpmStreamLayout(Layout, false, AltFpm));
+
+  MSFStreamLayout FullLayout(getFpmStreamLayout(Layout, true, AltFpm));
+  auto Result =
+      createStream(Layout.SB->BlockSize, FullLayout, MsfData, Allocator);
+  if (!Result)
+    return Result;
+  std::vector<uint8_t> InitData(Layout.SB->BlockSize, 0xFF);
+  BinaryStreamWriter Initializer(*Result);
+  while (Initializer.bytesRemaining() > 0)
+    cantFail(Initializer.writeBytes(InitData));
+  return createStream(Layout.SB->BlockSize, MinLayout, MsfData, Allocator);
 }
 
 Error WritableMappedBlockStream::readBytes(uint32_t Offset, uint32_t Size,