llvm-pdbdump: Add flags controlling the type of values to dump.

llvm-svn: 229330
diff --git a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
index 2baf3df..5ed1624 100644
--- a/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
@@ -352,7 +352,7 @@
   enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
 
   CComPtr<IDiaEnumSymbols> DiaEnumerator;
-  if (S_OK != Symbol->findChildren(EnumVal, nullptr, nsNone, &DiaEnumerator))
+  if (S_OK != Symbol->findChildrenEx(EnumVal, nullptr, nsNone, &DiaEnumerator))
     return nullptr;
 
   return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
@@ -370,7 +370,7 @@
 
   CComPtr<IDiaEnumSymbols> DiaEnumerator;
   if (S_OK !=
-      Symbol->findChildren(EnumVal, Name16Str, CompareFlags, &DiaEnumerator))
+      Symbol->findChildrenEx(EnumVal, Name16Str, CompareFlags, &DiaEnumerator))
     return nullptr;
 
   return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp
index 5fcc602..c965d1d9 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp
@@ -20,4 +20,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolAnnotation::dump(raw_ostream &OS, int Indent,
-                               PDB_DumpLevel Level) const {}
+                               PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp
index f92bfca..2e350ad 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp
@@ -20,4 +20,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolBlock::dump(raw_ostream &OS, int Indent,
-                          PDB_DumpLevel Level) const {}
+                          PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp
index 0ea0b18..f014b39 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp
@@ -28,75 +28,43 @@
                                        std::unique_ptr<IPDBRawSymbol> Symbol)
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
+#define SKIP_SYMBOL_IF_FLAG_UNSET(Tag, Flag) \
+  case PDB_SymType::Tag: \
+    if ((Flags & Flag) == 0) \
+      continue;   \
+    break;
+
 void PDBSymbolCompiland::dump(raw_ostream &OS, int Indent,
-                              PDB_DumpLevel Level) const {
+                              PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   if (Level == PDB_DumpLevel::Detailed) {
     std::string FullName = getName();
-    StringRef Name = llvm::sys::path::filename(StringRef(FullName.c_str()));
-
-    OS.indent(Indent);
-    OS << "Compiland: " << Name << "\n";
-
-    std::string Source = getSourceFileName();
-    std::string Library = getLibraryName();
-    if (!Source.empty())
-      OS << stream_indent(Indent + 2) << "Source: " << this->getSourceFileName()
-         << "\n";
-    if (!Library.empty())
-      OS << stream_indent(Indent + 2) << "Library: " << this->getLibraryName()
-         << "\n";
-
-    TagStats Stats;
-    auto ChildrenEnum = getChildStats(Stats);
-    OS << stream_indent(Indent + 2) << "Children: " << Stats << "\n";
-    if (Level >= PDB_DumpLevel::Detailed) {
-      while (auto Child = ChildrenEnum->getNext()) {
-        if (llvm::isa<PDBSymbolCompilandDetails>(*Child))
-          continue;
-        if (llvm::isa<PDBSymbolCompilandEnv>(*Child))
-          continue;
-        PDB_DumpLevel ChildLevel = (Level == PDB_DumpLevel::Detailed)
-                                       ? PDB_DumpLevel::Normal
-                                       : PDB_DumpLevel::Compact;
-        Child->dump(OS, Indent + 4, ChildLevel);
-        OS << "\n";
+    OS << stream_indent(Indent) << FullName;
+    if (Flags & PDB_DF_Children) {
+      if (Level >= PDB_DumpLevel::Detailed) {
+        auto ChildrenEnum = findAllChildren();
+        while (auto Child = ChildrenEnum->getNext()) {
+          switch (Child->getSymTag()) {
+            SKIP_SYMBOL_IF_FLAG_UNSET(Function, PDB_DF_Functions)
+            SKIP_SYMBOL_IF_FLAG_UNSET(Data, PDB_DF_Data)
+            SKIP_SYMBOL_IF_FLAG_UNSET(Label, PDB_DF_Labels)
+            SKIP_SYMBOL_IF_FLAG_UNSET(PublicSymbol, PDB_DF_PublicSyms)
+            SKIP_SYMBOL_IF_FLAG_UNSET(UDT, PDB_DF_Classes)
+            SKIP_SYMBOL_IF_FLAG_UNSET(Enum, PDB_DF_Enums)
+            SKIP_SYMBOL_IF_FLAG_UNSET(FunctionSig, PDB_DF_Funcsigs)
+            SKIP_SYMBOL_IF_FLAG_UNSET(VTable, PDB_DF_VTables)
+            SKIP_SYMBOL_IF_FLAG_UNSET(Thunk, PDB_DF_Thunks)
+            SKIP_SYMBOL_IF_FLAG_UNSET(Compiland, PDB_DF_ObjFiles)
+            default:
+              continue;
+          }
+          PDB_DumpLevel ChildLevel = (Level == PDB_DumpLevel::Detailed)
+                                         ? PDB_DumpLevel::Normal
+                                         : PDB_DumpLevel::Compact;
+          OS << "\n";
+          Child->dump(OS, Indent + 2, ChildLevel, PDB_DF_Children);
+        }
       }
     }
-
-    auto DetailsEnum(findAllChildren<PDBSymbolCompilandDetails>());
-    if (auto CD = DetailsEnum->getNext()) {
-      VersionInfo FE;
-      VersionInfo BE;
-      CD->getFrontEndVersion(FE);
-      CD->getBackEndVersion(BE);
-      OS << stream_indent(Indent + 2) << "Compiler: " << CD->getCompilerName()
-         << "\n";
-      OS << stream_indent(Indent + 2) << "Version: " << FE << ", " << BE
-         << "\n";
-
-      OS << stream_indent(Indent + 2) << "Lang: " << CD->getLanguage() << "\n";
-      OS << stream_indent(Indent + 2) << "Attributes: ";
-      if (CD->hasDebugInfo())
-        OS << "DebugInfo ";
-      if (CD->isDataAligned())
-        OS << "DataAligned ";
-      if (CD->isLTCG())
-        OS << "LTCG ";
-      if (CD->hasSecurityChecks())
-        OS << "SecurityChecks ";
-      if (CD->isHotpatchable())
-        OS << "HotPatchable";
-
-      auto Files(Session.getSourceFilesForCompiland(*this));
-      OS << "\n";
-      OS << stream_indent(Indent + 2) << Files->getChildCount()
-         << " source files";
-    }
-    uint32_t Count = DetailsEnum->getChildCount();
-    if (Count > 1) {
-      OS << "\n";
-      OS << stream_indent(Indent + 2) << "(" << Count - 1 << " more omitted)";
-    }
   } else {
     std::string FullName = getName();
     OS << stream_indent(Indent) << "Compiland: " << FullName;
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp
index ebda161..9194376 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp
@@ -20,4 +20,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolCompilandDetails::dump(raw_ostream &OS, int Indent,
-                                     PDB_DumpLevel Level) const {}
+                                     PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp
index e4955e2..b44dc57 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp
@@ -26,4 +26,4 @@
 }
 
 void PDBSymbolCompilandEnv::dump(raw_ostream &OS, int Indent,
-                                 PDB_DumpLevel Level) const {}
+                                 PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp
index 4bddf56..68f2b45 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp
@@ -25,4 +25,4 @@
 }
 
 void PDBSymbolCustom::dump(raw_ostream &OS, int Indent,
-                           PDB_DumpLevel Level) const {}
\ No newline at end of file
+                           PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
\ No newline at end of file
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp
index 516b87e..9a04ecd 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp
@@ -24,58 +24,56 @@
     : PDBSymbol(PDBSession, std::move(DataSymbol)) {}
 
 void PDBSymbolData::dump(raw_ostream &OS, int Indent,
-                         PDB_DumpLevel Level) const {
+                         PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
   PDB_LocType Loc = getLocationType();
   PDB_DataKind Kind = getDataKind();
-  if (Level >= PDB_DumpLevel::Normal) {
-    switch (Loc) {
-    case PDB_LocType::Static: {
-      uint32_t RVA = getRelativeVirtualAddress();
-      OS << Kind << " data[";
-      if (RVA != 0)
-        OS << format_hex(RVA, 10);
-      else
-        OS << "???";
-      break;
-    }
-    case PDB_LocType::TLS:
-      OS << "threadlocal " << Kind << " data[";
-      OS << getAddressSection() << ":" << format_hex(getAddressOffset(), 10);
-      break;
-    case PDB_LocType::RegRel:
-      OS << "regrel " << Kind << " data[";
-      OS << getRegisterId() << " + " << getOffset();
-      break;
-    case PDB_LocType::ThisRel: {
-      uint32_t Offset = getOffset();
-      OS << Kind << " data[this + " << format_hex(Offset, 4);
-      break;
-    }
-    case PDB_LocType::Enregistered:
-      OS << "register " << Kind << " data[" << getRegisterId();
-      break;
-    case PDB_LocType::BitField: {
-      OS << "bitfield data[this + ";
-      uint32_t Offset = getOffset();
-      uint32_t BitPos = getBitPosition();
-      uint32_t Length = getLength();
-      OS << format_hex(Offset, 4) << ":" << BitPos << "," << Length;
-      break;
-    }
-    case PDB_LocType::Slot:
-      OS << getSlot();
-      break;
-    case PDB_LocType::Constant: {
-      OS << "constant data[";
-      OS << getValue();
-      break;
-    }
-    case PDB_LocType::IlRel:
-    case PDB_LocType::MetaData:
-    default:
+  switch (Loc) {
+  case PDB_LocType::Static: {
+    uint32_t RVA = getRelativeVirtualAddress();
+    OS << Kind << " data[";
+    if (RVA != 0)
+      OS << format_hex(RVA, 10);
+    else
       OS << "???";
-    }
+    break;
+  }
+  case PDB_LocType::TLS:
+    OS << "threadlocal " << Kind << " data[";
+    OS << getAddressSection() << ":" << format_hex(getAddressOffset(), 10);
+    break;
+  case PDB_LocType::RegRel:
+    OS << "regrel " << Kind << " data[";
+    OS << getRegisterId() << " + " << getOffset();
+    break;
+  case PDB_LocType::ThisRel: {
+    uint32_t Offset = getOffset();
+    OS << Kind << " data[this + " << format_hex(Offset, 4);
+    break;
+  }
+  case PDB_LocType::Enregistered:
+    OS << "register " << Kind << " data[" << getRegisterId();
+    break;
+  case PDB_LocType::BitField: {
+    OS << "bitfield data[this + ";
+    uint32_t Offset = getOffset();
+    uint32_t BitPos = getBitPosition();
+    uint32_t Length = getLength();
+    OS << format_hex(Offset, 4) << ":" << BitPos << "," << Length;
+    break;
+  }
+  case PDB_LocType::Slot:
+    OS << getSlot();
+    break;
+  case PDB_LocType::Constant: {
+    OS << "constant data[";
+    OS << getValue();
+    break;
+  }
+  case PDB_LocType::IlRel:
+  case PDB_LocType::MetaData:
+  default:
+    OS << "???";
   }
 
   OS << "] ";
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp
index 6555b81..5d3da21 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp
@@ -21,12 +21,18 @@
 
 using namespace llvm;
 
+#define SKIP_SYMBOL_IF_FLAG_UNSET(Tag, Flag)                                   \
+  case PDB_SymType::Tag:                                                       \
+    if ((Flags & Flag) == 0)                                                   \
+      continue;                                                                \
+    break;
+
 PDBSymbolExe::PDBSymbolExe(const IPDBSession &PDBSession,
                            std::unique_ptr<IPDBRawSymbol> Symbol)
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolExe::dump(raw_ostream &OS, int Indent,
-                        PDB_DumpLevel Level) const {
+                        PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   std::string FileName(getSymbolsFileName());
 
   OS << stream_indent(Indent) << "Summary for " << FileName << "\n";
@@ -46,25 +52,76 @@
     OS << "HasPrivateSymbols ";
   OS << "\n";
 
-  auto ChildrenEnum = findAllChildren();
-  OS << stream_indent(Indent + 2) << ChildrenEnum->getChildCount()
-     << " children\n";
-#if 0
-  dumpChildren(OS, PDB_SymType::None, Indent+4);
-#else
-  dumpChildren(OS, "Compilands", PDB_SymType::Compiland, Indent + 4);
-  dumpChildren(OS, "Functions", PDB_SymType::Function, Indent + 4);
-  dumpChildren(OS, "Blocks", PDB_SymType::Block, Indent + 4);
-  dumpChildren(OS, "Data", PDB_SymType::Data, Indent + 4);
-  dumpChildren(OS, "Labels", PDB_SymType::Label, Indent + 4);
-  dumpChildren(OS, "Public Symbols", PDB_SymType::PublicSymbol, Indent + 4);
-  dumpChildren(OS, "UDTs", PDB_SymType::UDT, Indent + 4);
-  dumpChildren(OS, "Enums", PDB_SymType::Enum, Indent + 4);
-  dumpChildren(OS, "Function Signatures", PDB_SymType::FunctionSig, Indent + 4);
-  dumpChildren(OS, "Typedefs", PDB_SymType::Typedef, Indent + 4);
-  dumpChildren(OS, "VTables", PDB_SymType::VTable, Indent + 4);
-  dumpChildren(OS, "Thunks", PDB_SymType::Thunk, Indent + 4);
-#endif
+  if (Flags & PDB_DF_Children) {
+    if (Flags & PDB_DF_Hidden) {
+      // For some reason, for each SymTag T, this dumps more items of type T
+      // than are dumped by calling dumpChildren(T).  In other words, there are
+      // "hidden" symbols.  For example, it causes functions to be dumped which
+      // have no address information, whereas specifically dumping only
+      // functions will not find those symbols.
+      //
+      // My suspicion is that in the underlying DIA call, when you call
+      // findChildren, passing a value of SymTagNone means all children
+      // recursively, whereas passing a concrete tag value means only immediate
+      // children of the global scope.  So perhaps we need to find these
+      // mysterious missing values by recursing through the hierarchy.
+      //
+      // On the other hand, there may just be some symbols that DIA tries to
+      // hide from you because it thinks you don't care about them.  However
+      // experimentation shows that even vtables, for example, can't be found
+      // without an exhaustive search.
+      auto ChildrenEnum = findAllChildren();
+      OS << stream_indent(Indent + 2) << ChildrenEnum->getChildCount()
+         << " symbols";
+
+      while (auto Child = ChildrenEnum->getNext()) {
+        switch (Child->getSymTag()) {
+          SKIP_SYMBOL_IF_FLAG_UNSET(Function, PDB_DF_Functions)
+          SKIP_SYMBOL_IF_FLAG_UNSET(Data, PDB_DF_Data)
+          SKIP_SYMBOL_IF_FLAG_UNSET(Label, PDB_DF_Labels)
+          SKIP_SYMBOL_IF_FLAG_UNSET(PublicSymbol, PDB_DF_PublicSyms)
+          SKIP_SYMBOL_IF_FLAG_UNSET(UDT, PDB_DF_Classes)
+          SKIP_SYMBOL_IF_FLAG_UNSET(Enum, PDB_DF_Enums)
+          SKIP_SYMBOL_IF_FLAG_UNSET(FunctionSig, PDB_DF_Funcsigs)
+          SKIP_SYMBOL_IF_FLAG_UNSET(VTable, PDB_DF_VTables)
+          SKIP_SYMBOL_IF_FLAG_UNSET(Thunk, PDB_DF_Thunks)
+          SKIP_SYMBOL_IF_FLAG_UNSET(Compiland, PDB_DF_ObjFiles)
+        default:
+          continue;
+        }
+        PDB_DumpLevel ChildLevel = (Level == PDB_DumpLevel::Detailed)
+                                       ? PDB_DumpLevel::Normal
+                                       : PDB_DumpLevel::Compact;
+        OS << "\n";
+        Child->dump(OS, Indent + 4, ChildLevel, PDB_DF_Children);
+      }
+    } else {
+      if (Flags & PDB_DF_ObjFiles)
+        dumpChildren(OS, "Compilands", PDB_SymType::Compiland, Indent + 4);
+      if (Flags & PDB_DF_Functions)
+        dumpChildren(OS, "Functions", PDB_SymType::Function, Indent + 4);
+      if (Flags & PDB_DF_Data)
+        dumpChildren(OS, "Data", PDB_SymType::Data, Indent + 4);
+      if (Flags & PDB_DF_Labels)
+        dumpChildren(OS, "Labels", PDB_SymType::Label, Indent + 4);
+      if (Flags & PDB_DF_PublicSyms)
+        dumpChildren(OS, "Public Symbols", PDB_SymType::PublicSymbol,
+                     Indent + 4);
+      if (Flags & PDB_DF_Classes)
+        dumpChildren(OS, "UDTs", PDB_SymType::UDT, Indent + 4);
+      if (Flags & PDB_DF_Enums)
+        dumpChildren(OS, "Enums", PDB_SymType::Enum, Indent + 4);
+      if (Flags & PDB_DF_Funcsigs)
+        dumpChildren(OS, "Function Signatures", PDB_SymType::FunctionSig,
+                     Indent + 4);
+      if (Flags & PDB_DF_Typedefs)
+        dumpChildren(OS, "Typedefs", PDB_SymType::Typedef, Indent + 4);
+      if (Flags & PDB_DF_VTables)
+        dumpChildren(OS, "VTables", PDB_SymType::VTable, Indent + 4);
+      if (Flags & PDB_DF_Thunks)
+        dumpChildren(OS, "Thunks", PDB_SymType::Thunk, Indent + 4);
+    }
+  }
 }
 
 void PDBSymbolExe::dumpChildren(raw_ostream &OS, StringRef Label,
@@ -73,7 +130,7 @@
   OS << stream_indent(Indent) << Label << ": (" << ChildrenEnum->getChildCount()
      << " items)\n";
   while (auto Child = ChildrenEnum->getNext()) {
-    Child->dump(OS, Indent + 2, PDB_DumpLevel::Normal);
+    Child->dump(OS, Indent + 2, PDB_DumpLevel::Normal, PDB_DF_None);
     OS << "\n";
   }
 }
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
index 817279b..cd01423 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
@@ -29,66 +29,58 @@
 }
 
 void PDBSymbolFunc::dump(raw_ostream &OS, int Indent,
-                         PDB_DumpLevel Level) const {
+                         PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
+  uint32_t FuncStart = getRelativeVirtualAddress();
+  uint32_t FuncEnd = FuncStart + getLength();
   OS << stream_indent(Indent);
-  // if (getName() == "__crtCreateThreadpoolWait") {
-  //  RawSymbol->dump(OS, Indent+2, Level);
-  //  OS.flush();
-  //}
-  if (Level >= PDB_DumpLevel::Normal) {
-    uint32_t FuncStart = getRelativeVirtualAddress();
-    uint32_t FuncEnd = FuncStart + getLength();
-    if (FuncStart == 0 && FuncEnd == 0) {
-      OS << "func [???] ";
-    } else {
-      OS << "func ";
-      OS << "[" << format_hex(FuncStart, 8);
-      if (auto DebugStart = findOneChild<PDBSymbolFuncDebugStart>())
-        OS << "+" << DebugStart->getRelativeVirtualAddress() - FuncStart;
-      OS << " - " << format_hex(FuncEnd, 8);
-      if (auto DebugEnd = findOneChild<PDBSymbolFuncDebugEnd>())
-        OS << "-" << FuncEnd - DebugEnd->getRelativeVirtualAddress();
-      OS << "] ";
-    }
-
-    PDB_RegisterId Reg = getLocalBasePointerRegisterId();
-    if (Reg == PDB_RegisterId::VFrame)
-      OS << "(VFrame)";
-    else if (hasFramePointer())
-      OS << "(" << Reg << ")";
-    else
-      OS << "(FPO)";
-
-    OS << " ";
-    if (auto FuncSig = getSignature()) {
-      // If we have a signature, dump the name with the signature.
-      if (auto ReturnType = FuncSig->getReturnType()) {
-        ReturnType->dump(OS, 0, PDB_DumpLevel::Compact);
-        OS << " ";
-      }
-
-      OS << FuncSig->getCallingConvention() << " ";
-
-      if (auto ClassParent = FuncSig->getClassParent()) {
-        ClassParent->dump(OS, 0, PDB_DumpLevel::Compact);
-        OS << "::";
-      }
-
-      OS << getName();
-      FuncSig->dumpArgList(OS);
-    } else {
-      uint32_t ClassId = getClassParentId();
-      if (ClassId != 0) {
-        if (auto Class = Session.getSymbolById(ClassId)) {
-          if (auto UDT = dyn_cast<PDBSymbolTypeUDT>(Class.get()))
-            OS << UDT->getName() << "::";
-          else
-            OS << "{class " << Class->getSymTag() << "}::";
-        }
-      }
-      OS << getName();
-    }
+  if (FuncStart == 0 && FuncEnd == 0) {
+    OS << "func [???] ";
   } else {
+    OS << "func ";
+    OS << "[" << format_hex(FuncStart, 8);
+    if (auto DebugStart = findOneChild<PDBSymbolFuncDebugStart>())
+      OS << "+" << DebugStart->getRelativeVirtualAddress() - FuncStart;
+    OS << " - " << format_hex(FuncEnd, 8);
+    if (auto DebugEnd = findOneChild<PDBSymbolFuncDebugEnd>())
+      OS << "-" << FuncEnd - DebugEnd->getRelativeVirtualAddress();
+    OS << "] ";
+  }
+
+  PDB_RegisterId Reg = getLocalBasePointerRegisterId();
+  if (Reg == PDB_RegisterId::VFrame)
+    OS << "(VFrame)";
+  else if (hasFramePointer())
+    OS << "(" << Reg << ")";
+  else
+    OS << "(FPO)";
+
+  OS << " ";
+  if (isVirtual() || isPureVirtual())
+    OS << "virtual ";
+
+  if (auto FuncSig = getSignature()) {
+    // If we have a signature, dump the name with the signature.
+    if (auto ReturnType = FuncSig->getReturnType()) {
+      ReturnType->dump(OS, 0, PDB_DumpLevel::Compact, PDB_DF_Children);
+      OS << " ";
+    }
+
+    OS << FuncSig->getCallingConvention() << " ";
+
+    OS << getName();
+    FuncSig->dumpArgList(OS);
+    if (isPureVirtual())
+      OS << " = 0";
+  } else {
+    uint32_t ClassId = getClassParentId();
+    if (ClassId != 0) {
+      if (auto Class = Session.getSymbolById(ClassId)) {
+        if (auto UDT = dyn_cast<PDBSymbolTypeUDT>(Class.get()))
+          OS << UDT->getName() << "::";
+        else
+          OS << "{class " << Class->getSymTag() << "}::";
+      }
+    }
     OS << getName();
   }
 }
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp
index bd4d888..8658be9 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp
@@ -20,4 +20,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolFuncDebugEnd::dump(raw_ostream &OS, int Indent,
-                                 PDB_DumpLevel Level) const {}
+                                 PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp
index 704e7ca..64cd3e3 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp
@@ -20,4 +20,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolFuncDebugStart::dump(raw_ostream &OS, int Indent,
-                                   PDB_DumpLevel Level) const {}
+                                   PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp
index 5f2dedf..abb5163 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp
@@ -21,7 +21,7 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolLabel::dump(raw_ostream &OS, int Indent,
-                          PDB_DumpLevel Level) const {
+                          PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
   OS << "label [" << format_hex(getRelativeVirtualAddress(), 10) << "] "
      << getName();
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp
index 5d53a3a..a2cea8b 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp
@@ -20,7 +20,7 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolPublicSymbol::dump(raw_ostream &OS, int Indent,
-                                 PDB_DumpLevel Level) const {
+                                 PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
   OS << "public symbol: " << getName();
 }
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp
index 985b87e..c62c96b 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp
@@ -21,7 +21,7 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolThunk::dump(raw_ostream &OS, int Indent,
-                          PDB_DumpLevel Level) const {
+                          PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS.indent(Indent);
   OS << "thunk ";
   PDB_ThunkOrdinal Ordinal = getThunkOrdinal();
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp
index ef6bb13..b418e33 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp
@@ -21,10 +21,10 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeArray::dump(raw_ostream &OS, int Indent,
-                              PDB_DumpLevel Level) const {
+                              PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
   if (auto ElementType = Session.getSymbolById(getTypeId()))
-    ElementType->dump(OS, 0, PDB_DumpLevel::Compact);
+    ElementType->dump(OS, 0, PDB_DumpLevel::Compact, PDB_DF_Children);
   else
     OS << "<unknown-element-type>";
   OS << "[" << getLength() << "]";
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp
index c312d9f..532e8b8 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp
@@ -20,7 +20,7 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeBaseClass::dump(raw_ostream &OS, int Indent,
-                                  PDB_DumpLevel Level) const {
+                                  PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
   OS << "<base class> " << getName();
 }
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp
index d51f653..b7afdcd 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp
@@ -20,7 +20,7 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeBuiltin::dump(raw_ostream &OS, int Indent,
-                                PDB_DumpLevel Level) const {
+                                PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
   PDB_BuiltinType Type = getBuiltinType();
   OS << Type;
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp
index f09d0a0..0bfa8eb 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp
@@ -20,4 +20,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeCustom::dump(raw_ostream &OS, int Indent,
-                               PDB_DumpLevel Level) const {}
+                               PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp
index d36d0cf..84f48ea 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp
@@ -21,4 +21,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeDimension::dump(raw_ostream &OS, int Indent,
-                                  PDB_DumpLevel Level) const {}
+                                  PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp
index a44acc0..512b602 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp
@@ -21,7 +21,7 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeEnum::dump(raw_ostream &OS, int Indent,
-                             PDB_DumpLevel Level) const {
+                             PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
   if (Level >= PDB_DumpLevel::Normal)
     OS << "enum ";
@@ -29,7 +29,7 @@
   uint32_t ClassId = getClassParentId();
   if (ClassId != 0) {
     if (auto ClassParent = Session.getSymbolById(ClassId)) {
-      ClassParent->dump(OS, 0, Level);
+      ClassParent->dump(OS, 0, Level, PDB_DF_Children);
       OS << "::";
     }
   }
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp
index 405f49a..236304e 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp
@@ -20,4 +20,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeFriend::dump(raw_ostream &OS, int Indent,
-                               PDB_DumpLevel Level) const {}
+                               PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp
index 30db55a..4b8cc26 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp
@@ -21,10 +21,10 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeFunctionArg::dump(raw_ostream &OS, int Indent,
-                                    PDB_DumpLevel Level) const {
+                                    PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
   uint32_t TypeId = getTypeId();
   if (auto Type = Session.getSymbolById(TypeId)) {
-    Type->dump(OS, 0, Level);
+    Type->dump(OS, 0, Level, PDB_DF_Children);
   }
 }
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
index f9a1bbf..13b89b2 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
@@ -87,7 +87,7 @@
   if (auto ChildEnum = getArguments()) {
     uint32_t Index = 0;
     while (auto Arg = ChildEnum->getNext()) {
-      Arg->dump(OS, 0, PDB_DumpLevel::Compact);
+      Arg->dump(OS, 0, PDB_DumpLevel::Compact, PDB_DF_Children);
       if (++Index < ChildEnum->getChildCount())
         OS << ", ";
     }
@@ -100,18 +100,18 @@
 }
 
 void PDBSymbolTypeFunctionSig::dump(raw_ostream &OS, int Indent,
-                                    PDB_DumpLevel Level) const {
+                                    PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
 
   if (auto ReturnType = getReturnType()) {
-    ReturnType->dump(OS, 0, PDB_DumpLevel::Compact);
+    ReturnType->dump(OS, 0, PDB_DumpLevel::Compact, PDB_DF_Children);
     OS << " ";
   }
 
   OS << getCallingConvention() << " ";
   if (auto ClassParent = getClassParent()) {
     OS << "(";
-    ClassParent->dump(OS, 0, PDB_DumpLevel::Compact);
+    ClassParent->dump(OS, 0, PDB_DumpLevel::Compact, PDB_DF_Children);
     OS << "::*)";
   }
 
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp
index 4cce8e1..32602dc 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp
@@ -20,4 +20,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeManaged::dump(raw_ostream &OS, int Indent,
-                                PDB_DumpLevel Level) const {}
+                                PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp
index 0a4dd23..3461928 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp
@@ -22,7 +22,7 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypePointer::dump(raw_ostream &OS, int Indent,
-                                PDB_DumpLevel Level) const {
+                                PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
   if (isConstType())
     OS << "const ";
@@ -34,12 +34,12 @@
     // the middle of the signature.
     if (auto FuncSig = dyn_cast<PDBSymbolTypeFunctionSig>(PointeeType.get())) {
       if (auto ReturnType = FuncSig->getReturnType())
-        ReturnType->dump(OS, 0, PDB_DumpLevel::Compact);
+        ReturnType->dump(OS, 0, PDB_DumpLevel::Compact, PDB_DF_Children);
       OS << " (" << FuncSig->getCallingConvention() << " ";
       OS << ((isReference()) ? "&" : "*") << ")";
       FuncSig->dumpArgList(OS);
     } else {
-      PointeeType->dump(OS, 0, PDB_DumpLevel::Compact);
+      PointeeType->dump(OS, 0, PDB_DumpLevel::Compact, PDB_DF_Children);
       OS << ((isReference()) ? "&" : "*");
     }
   }
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp
index 32e5446..9554d70 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp
@@ -22,7 +22,7 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeTypedef::dump(raw_ostream &OS, int Indent,
-                                PDB_DumpLevel Level) const {
+                                PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS.indent(Indent);
   if (Level >= PDB_DumpLevel::Normal) {
     std::string Name = getName();
@@ -30,7 +30,7 @@
     std::string TargetTypeName;
     uint32_t TargetId = getTypeId();
     if (auto TypeSymbol = Session.getSymbolById(TargetId)) {
-      TypeSymbol->dump(OS, 0, PDB_DumpLevel::Compact);
+      TypeSymbol->dump(OS, 0, PDB_DumpLevel::Compact, PDB_DF_Children);
     }
     OS << TargetTypeName;
   } else {
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
index 96786a2..ea884bd 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
@@ -21,7 +21,7 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeUDT::dump(raw_ostream &OS, int Indent,
-                            PDB_DumpLevel Level) const {
+                            PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
   if (Level >= PDB_DumpLevel::Normal)
     OS << "class ";
@@ -30,7 +30,7 @@
     uint32_t ClassId = getClassParentId();
     if (ClassId != 0) {
       if (auto ClassParent = Session.getSymbolById(ClassId)) {
-        ClassParent->dump(OS, 0, Level);
+        ClassParent->dump(OS, 0, Level, PDB_DF_Children);
         OS << "::";
       }
     }
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp
index 7002008..4c1f05e 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp
@@ -23,11 +23,11 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeVTable::dump(raw_ostream &OS, int Indent,
-                               PDB_DumpLevel Level) const {
+                               PDB_DumpLevel Level, PDB_DumpFlags Flags) const {
   OS << stream_indent(Indent);
   uint32_t ClassId = getClassParentId();
   if (auto ClassParent = Session.getSymbolById(ClassId)) {
-    ClassParent->dump(OS, 0, PDB_DumpLevel::Compact);
+    ClassParent->dump(OS, 0, PDB_DumpLevel::Compact, PDB_DF_Children);
     OS << "::";
   }
   OS << "<vtbl> ";
@@ -38,5 +38,4 @@
                 VtblPointer->getTypeId()))
       OS << "(" << VtblShape->getCount() << " entries)";
   }
-  OS.flush();
 }
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp
index 7ea4da2..cff0d03 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp
@@ -20,4 +20,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolTypeVTableShape::dump(raw_ostream &OS, int Indent,
-                                    PDB_DumpLevel Level) const {}
+                                    PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp
index 97e4a91..b7b4c38 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp
@@ -20,4 +20,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolUnknown::dump(raw_ostream &OS, int Indent,
-                            PDB_DumpLevel Level) const {}
+                            PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}
diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp
index fea9844..077d2b3 100644
--- a/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp
+++ b/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp
@@ -20,4 +20,4 @@
     : PDBSymbol(PDBSession, std::move(Symbol)) {}
 
 void PDBSymbolUsingNamespace::dump(raw_ostream &OS, int Indent,
-                                   PDB_DumpLevel Level) const {}
+                                   PDB_DumpLevel Level, PDB_DumpFlags Flags) const {}