[PDB] Fix an issue writing the publics stream.

In the refactor to merge the publics and globals stream, a bug
was introduced that wrote the wrong value for one of the fields
of the PublicsStreamHeader.  This caused debugging in WinDbg
to break.

We had no way of dumping any of these fields, so in addition to
fixing the bug I've added dumping support for them along with a
test that verifies the correct value is written.

llvm-svn: 310439
diff --git a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
index 73e4a14..bc0bb08 100644
--- a/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -896,6 +896,13 @@
   auto &Publics = Err(File.getPDBPublicsStream());
 
   const GSIHashTable &PublicsTable = Publics.getPublicsTable();
+  if (opts::dump::DumpPublicExtras) {
+    P.printLine("Publics Header");
+    AutoIndent Indent(P);
+    P.formatLine("sym hash = {0}, thunk table addr = {1}", Publics.getSymHash(),
+                 formatSegmentOffset(Publics.getThunkTableSection(),
+                                     Publics.getThunkTableOffset()));
+  }
   Err(dumpSymbolsFromGSI(PublicsTable, opts::dump::DumpPublicExtras));
 
   // Skip the rest if we aren't dumping extras.
@@ -941,30 +948,42 @@
   auto ExpectedIds = initializeTypes(StreamIPI);
   if (!ExpectedIds)
     return ExpectedIds.takeError();
-  SymbolVisitorCallbackPipeline Pipeline;
-  SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
-  MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, *ExpectedIds,
-                             *ExpectedTypes);
 
-  Pipeline.addCallbackToPipeline(Deserializer);
-  Pipeline.addCallbackToPipeline(Dumper);
-  CVSymbolVisitor Visitor(Pipeline);
+  if (HashExtras) {
+    P.printLine("GSI Header");
+    AutoIndent Indent(P);
+    P.formatLine("sig = {0:X}, hdr = {1:X}, hr size = {2}, num buckets = {3}",
+                 Table.getVerSignature(), Table.getVerHeader(),
+                 Table.getHashRecordSize(), Table.getNumBuckets());
+  }
 
-  BinaryStreamRef SymStream =
-      ExpectedSyms->getSymbolArray().getUnderlyingStream();
-  for (uint32_t PubSymOff : Table) {
-    Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
-    if (!Sym)
-      return Sym.takeError();
-    if (auto E = Visitor.visitSymbolRecord(*Sym, PubSymOff))
-      return E;
+  {
+    P.printLine("Records");
+    SymbolVisitorCallbackPipeline Pipeline;
+    SymbolDeserializer Deserializer(nullptr, CodeViewContainer::Pdb);
+    MinimalSymbolDumper Dumper(P, opts::dump::DumpSymRecordBytes, *ExpectedIds,
+                               *ExpectedTypes);
+
+    Pipeline.addCallbackToPipeline(Deserializer);
+    Pipeline.addCallbackToPipeline(Dumper);
+    CVSymbolVisitor Visitor(Pipeline);
+
+    BinaryStreamRef SymStream =
+        ExpectedSyms->getSymbolArray().getUnderlyingStream();
+    for (uint32_t PubSymOff : Table) {
+      Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, PubSymOff);
+      if (!Sym)
+        return Sym.takeError();
+      if (auto E = Visitor.visitSymbolRecord(*Sym, PubSymOff))
+        return E;
+    }
   }
 
   // Return early if we aren't dumping public hash table and address map info.
   if (!HashExtras)
     return Error::success();
 
-  P.formatLine("Hash Records");
+  P.formatLine("Hash Entries");
   {
     AutoIndent Indent2(P);
     for (const PSHashRecord &HR : Table.HashRecords)