[pdbutil] Add a command to dump the FPM.

Recently problems have been discovered in the way we write the FPM
(free page map).  In order to fix this, we first need to establish
a baseline about what a correct FPM looks like using an MSVC
generated PDB, so that we can then make our own generated PDBs
match.  And in order to do this, the dumper needs a mode where it
can dump an FPM so that we can write tests for it.

This patch adds a command to dump the FPM, as well as a test against
a known-good PDB.

llvm-svn: 309894
diff --git a/llvm/lib/DebugInfo/MSF/MSFCommon.cpp b/llvm/lib/DebugInfo/MSF/MSFCommon.cpp
index 1facf5e..484e184 100644
--- a/llvm/lib/DebugInfo/MSF/MSFCommon.cpp
+++ b/llvm/lib/DebugInfo/MSF/MSFCommon.cpp
@@ -59,3 +59,18 @@
 
   return Error::success();
 }
+
+MSFStreamLayout llvm::msf::getFpmStreamLayout(const MSFLayout &Msf) {
+  MSFStreamLayout FL;
+  uint32_t NumFpmIntervals = getNumFpmIntervals(Msf);
+  support::ulittle32_t FpmBlock = Msf.SB->FreeBlockMapBlock;
+  assert(FpmBlock == 1 || FpmBlock == 2);
+  while (NumFpmIntervals > 0) {
+    FL.Blocks.push_back(FpmBlock);
+    FpmBlock += msf::getFpmIntervalLength(Msf);
+    --NumFpmIntervals;
+  }
+  FL.Length = getFullFpmByteSize(Msf);
+
+  return FL;
+}
diff --git a/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp b/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp
index e45f4ae..2a200ed 100644
--- a/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp
+++ b/llvm/lib/DebugInfo/MSF/MappedBlockStream.cpp
@@ -11,7 +11,6 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/DebugInfo/MSF/MSFCommon.h"
-#include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/MathExtras.h"
@@ -36,19 +35,6 @@
 
 } // end anonymous namespace
 
-static void initializeFpmStreamLayout(const MSFLayout &Layout,
-                                      MSFStreamLayout &FpmLayout) {
-  uint32_t NumFpmIntervals = msf::getNumFpmIntervals(Layout);
-  support::ulittle32_t FpmBlock = Layout.SB->FreeBlockMapBlock;
-  assert(FpmBlock == 1 || FpmBlock == 2);
-  while (NumFpmIntervals > 0) {
-    FpmLayout.Blocks.push_back(FpmBlock);
-    FpmBlock += msf::getFpmIntervalLength(Layout);
-    --NumFpmIntervals;
-  }
-  FpmLayout.Length = msf::getFullFpmByteSize(Layout);
-}
-
 using Interval = std::pair<uint32_t, uint32_t>;
 
 static Interval intersect(const Interval &I1, const Interval &I2) {
@@ -95,8 +81,7 @@
 MappedBlockStream::createFpmStream(const MSFLayout &Layout,
                                    BinaryStreamRef MsfData,
                                    BumpPtrAllocator &Allocator) {
-  MSFStreamLayout SL;
-  initializeFpmStreamLayout(Layout, SL);
+  MSFStreamLayout SL(getFpmStreamLayout(Layout));
   return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator);
 }
 
@@ -363,8 +348,7 @@
 WritableMappedBlockStream::createFpmStream(const MSFLayout &Layout,
                                            WritableBinaryStreamRef MsfData,
                                            BumpPtrAllocator &Allocator) {
-  MSFStreamLayout SL;
-  initializeFpmStreamLayout(Layout, SL);
+  MSFStreamLayout SL(getFpmStreamLayout(Layout));
   return createStream(Layout.SB->BlockSize, SL, MsfData, Allocator);
 }
 
diff --git a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
index f19e70e..e0bb460 100644
--- a/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
+++ b/llvm/lib/DebugInfo/PDB/Native/PDBFile.cpp
@@ -238,6 +238,10 @@
   return Result;
 }
 
+msf::MSFStreamLayout PDBFile::getFpmStreamLayout() const {
+  return msf::getFpmStreamLayout(ContainerLayout);
+}
+
 Expected<GlobalsStream &> PDBFile::getPDBGlobalsStream() {
   if (!Globals) {
     auto DbiS = getPDBDbiStream();