Factor out the checking of string tables.
[oota-llvm.git] / tools / llvm-pdbdump / llvm-pdbdump.cpp
index 1254a53a8d1aa42823e6fa66ec1ec35616ee530c..4a4c64b80cc18aa0cfe41ab9032cfee4782f14a6 100644 (file)
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm-pdbdump.h"
+#include "CompilandDumper.h"
+#include "ExternalSymbolDumper.h"
+#include "FunctionDumper.h"
+#include "LinePrinter.h"
+#include "TypeDumper.h"
+#include "VariableDumper.h"
+
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Config/config.h"
 #include "llvm/DebugInfo/PDB/IPDBSession.h"
 #include "llvm/DebugInfo/PDB/PDB.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/PrettyStackTrace.h"
 #include "llvm/Support/Process.h"
-#include "llvm/Support/Signals.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Signals.h"
 
 #if defined(HAVE_DIA_SDK)
 #include <Windows.h>
@@ -45,96 +57,181 @@ cl::list<std::string> InputFilenames(cl::Positional,
                                      cl::desc("<input PDB files>"),
                                      cl::OneOrMore);
 
-cl::opt<bool> DumpHidden(
-    "hidden",
-    cl::desc("Attempt to find hidden symbols.  This can find additional\n"
-             "symbols that cannot be found otherwise.  For example, vtables\n"
-             "can only be found with an exhaustive search such as this.  Be\n"
-             "warned that the performance can be prohibitive on large PDB "
-             "files."));
-
-cl::opt<bool> DumpAll(
-    "all",
-    cl::desc("Specifies all other options except -hidden and -group-by"));
-cl::opt<bool> DumpObjFiles("compilands", cl::desc("Display object files"));
-cl::opt<bool> DumpFuncs("functions", cl::desc("Display function information"));
-cl::opt<bool> DumpData(
-    "data",
-    cl::desc("Display global, class, and constant variable information."));
-cl::opt<bool> DumpLabels("labels", cl::desc("Display labels"));
-cl::opt<bool> DumpPublic("public", cl::desc("Display public symbols"));
-cl::opt<bool> DumpClasses("classes", cl::desc("Display class type information"));
-cl::opt<bool> DumpEnums("enums", cl::desc("Display enum information"));
-cl::opt<bool> DumpFuncsigs("funcsigs",
-                           cl::desc("Display unique function signatures"));
-cl::opt<bool> DumpTypedefs("typedefs", cl::desc("Display typedefs"));
-cl::opt<bool> DumpThunks("thunks", cl::desc("Display thunks"));
-cl::opt<bool> DumpVtables(
-    "vtables",
-    cl::desc("Display virtual function tables (only with --exhaustive)"));
-
-static cl::opt<PDB_DumpType> DumpMode(
-    "group-by", cl::init(PDB_DumpType::ByType), cl::desc("Dump mode:"),
-    cl::values(
-        clEnumValN(PDB_DumpType::ByType, "type",
-                   "(Default) Display symbols grouped by type"),
-        clEnumValN(PDB_DumpType::ByObjFile, "compiland",
-                   "Display symbols grouped under their containing object "
-                   "file."),
-        clEnumValN(
-            PDB_DumpType::Both, "both",
-            "Display symbols grouped by type, and then by object file.")));
-}
+cl::OptionCategory TypeCategory("Symbol Type Options");
+cl::OptionCategory FilterCategory("Filtering Options");
+cl::OptionCategory OtherOptions("Other Options");
 
-#define SET_DUMP_FLAG_FROM_OPT(Var, Flag, Opt) \
-  if (opts::Opt) \
-    Var |= Flag;
-
-PDB_DumpFlags CalculateDumpFlags() {
-  PDB_DumpFlags Flags = PDB_DF_None;
-
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Hidden, DumpHidden)
-
-  if (opts::DumpAll)
-    return Flags | PDB_DF_All;
-
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_ObjFiles, DumpObjFiles)
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Functions, DumpFuncs)
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Data, DumpData)
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Labels, DumpLabels)
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_PublicSyms, DumpPublic)
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Classes, DumpClasses)
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Enums, DumpEnums)
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Funcsigs, DumpFuncsigs)
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Typedefs, DumpTypedefs)
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_Thunks, DumpThunks)
-  SET_DUMP_FLAG_FROM_OPT(Flags, PDB_DF_VTables, DumpVtables)
-  return Flags;
+cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
+                         cl::cat(TypeCategory));
+cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
+                      cl::cat(TypeCategory));
+cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
+                      cl::cat(TypeCategory));
+cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
+                        cl::cat(TypeCategory));
+cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory));
+cl::opt<bool>
+    All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
+        cl::cat(TypeCategory));
+
+cl::opt<uint64_t> LoadAddress(
+    "load-address",
+    cl::desc("Assume the module is loaded at the specified address"),
+    cl::cat(OtherOptions));
+
+cl::list<std::string>
+    ExcludeTypes("exclude-types",
+                 cl::desc("Exclude types by regular expression"),
+                 cl::ZeroOrMore, cl::cat(FilterCategory));
+cl::list<std::string>
+    ExcludeSymbols("exclude-symbols",
+                   cl::desc("Exclude symbols by regular expression"),
+                   cl::ZeroOrMore, cl::cat(FilterCategory));
+cl::list<std::string>
+    ExcludeCompilands("exclude-compilands",
+                      cl::desc("Exclude compilands by regular expression"),
+                      cl::ZeroOrMore, cl::cat(FilterCategory));
+cl::opt<bool> ExcludeCompilerGenerated(
+    "no-compiler-generated",
+    cl::desc("Don't show compiler generated types and symbols"),
+    cl::cat(FilterCategory));
+cl::opt<bool>
+    ExcludeSystemLibraries("no-system-libs",
+                           cl::desc("Don't show symbols from system libraries"),
+                           cl::cat(FilterCategory));
+cl::opt<bool> NoClassDefs("no-class-definitions",
+                          cl::desc("Don't display full class definitions"),
+                          cl::cat(FilterCategory));
+cl::opt<bool> NoEnumDefs("no-enum-definitions",
+                         cl::desc("Don't display full enum definitions"),
+                         cl::cat(FilterCategory));
 }
 
 static void dumpInput(StringRef Path) {
-  std::unique_ptr<IPDBSession> Session(
-      llvm::createPDBReader(PDB_ReaderType::DIA, Path));
-  if (!Session) {
-    outs() << "Unable to create PDB reader.  Check that a valid implementation";
-    outs() << " is available for your platform.";
+  std::unique_ptr<IPDBSession> Session;
+  PDB_ErrorCode Error =
+      llvm::loadDataForPDB(PDB_ReaderType::DIA, Path, Session);
+  switch (Error) {
+  case PDB_ErrorCode::Success:
+    break;
+  case PDB_ErrorCode::NoPdbImpl:
+    outs() << "Reading PDBs is not supported on this platform.\n";
+    return;
+  case PDB_ErrorCode::InvalidPath:
+    outs() << "Unable to load PDB at '" << Path
+           << "'.  Check that the file exists and is readable.\n";
+    return;
+  case PDB_ErrorCode::InvalidFileFormat:
+    outs() << "Unable to load PDB at '" << Path
+           << "'.  The file has an unrecognized format.\n";
+    return;
+  default:
+    outs() << "Unable to load PDB at '" << Path
+           << "'.  An unknown error occured.\n";
     return;
   }
-  PDB_DumpFlags Flags = CalculateDumpFlags();
+  if (opts::LoadAddress)
+    Session->setLoadAddress(opts::LoadAddress);
+
+  LinePrinter Printer(2, outs());
 
-  if (opts::DumpMode != opts::PDB_DumpType::ByObjFile)
-    Flags |= PDB_DF_Children;
   auto GlobalScope(Session->getGlobalScope());
-  GlobalScope->dump(outs(), 0, PDB_DumpLevel::Normal, Flags);
-  outs() << "\n";
+  std::string FileName(GlobalScope->getSymbolsFileName());
+
+  WithColor(Printer, PDB_ColorItem::None).get() << "Summary for ";
+  WithColor(Printer, PDB_ColorItem::Path).get() << FileName;
+  Printer.Indent();
+  uint64_t FileSize = 0;
+
+  Printer.NewLine();
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Size";
+  if (!llvm::sys::fs::file_size(FileName, FileSize)) {
+    Printer << ": " << FileSize << " bytes";
+  } else {
+    Printer << ": (Unable to obtain file size)";
+  }
+
+  Printer.NewLine();
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Guid";
+  Printer << ": " << GlobalScope->getGuid();
+
+  Printer.NewLine();
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Age";
+  Printer << ": " << GlobalScope->getAge();
 
-  if (opts::DumpMode != opts::PDB_DumpType::ByType) {
+  Printer.NewLine();
+  WithColor(Printer, PDB_ColorItem::Identifier).get() << "Attributes";
+  Printer << ": ";
+  if (GlobalScope->hasCTypes())
+    outs() << "HasCTypes ";
+  if (GlobalScope->hasPrivateSymbols())
+    outs() << "HasPrivateSymbols ";
+  Printer.Unindent();
+
+  if (opts::Compilands) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get()
+        << "---COMPILANDS---";
+    Printer.Indent();
     auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
-    while (auto Compiland = Compilands->getNext()) {
-      Compiland->dump(outs(), 0, PDB_DumpLevel::Detailed,
-                      Flags | PDB_DF_Children);
-      outs() << "\n";
+    CompilandDumper Dumper(Printer);
+    while (auto Compiland = Compilands->getNext())
+      Dumper.start(*Compiland, false);
+    Printer.Unindent();
+  }
+
+  if (opts::Types) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
+    Printer.Indent();
+    TypeDumper Dumper(Printer);
+    Dumper.start(*GlobalScope);
+    Printer.Unindent();
+  }
+
+  if (opts::Symbols) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
+    Printer.Indent();
+    auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
+    CompilandDumper Dumper(Printer);
+    while (auto Compiland = Compilands->getNext())
+      Dumper.start(*Compiland, true);
+    Printer.Unindent();
+  }
+
+  if (opts::Globals) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
+    Printer.Indent();
+    {
+      FunctionDumper Dumper(Printer);
+      auto Functions = GlobalScope->findAllChildren<PDBSymbolFunc>();
+      while (auto Function = Functions->getNext()) {
+        Printer.NewLine();
+        Dumper.start(*Function, FunctionDumper::PointerType::None);
+      }
+    }
+    {
+      auto Vars = GlobalScope->findAllChildren<PDBSymbolData>();
+      VariableDumper Dumper(Printer);
+      while (auto Var = Vars->getNext())
+        Dumper.start(*Var);
     }
+    {
+      auto Thunks = GlobalScope->findAllChildren<PDBSymbolThunk>();
+      CompilandDumper Dumper(Printer);
+      while (auto Thunk = Thunks->getNext())
+        Dumper.dump(*Thunk);
+    }
+    Printer.Unindent();
+  }
+  if (opts::Externals) {
+    Printer.NewLine();
+    WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
+    Printer.Indent();
+    ExternalSymbolDumper Dumper(Printer);
+    Dumper.start(*GlobalScope);
   }
   outs().flush();
 }
@@ -156,6 +253,21 @@ int main(int argc_, const char *argv_[]) {
   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
 
   cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
+  if (opts::All) {
+    opts::Compilands = true;
+    opts::Symbols = true;
+    opts::Globals = true;
+    opts::Types = true;
+    opts::Externals = true;
+  }
+  if (opts::ExcludeCompilerGenerated) {
+    opts::ExcludeTypes.push_back("__vc_attributes");
+    opts::ExcludeCompilands.push_back("* Linker *");
+  }
+  if (opts::ExcludeSystemLibraries) {
+    opts::ExcludeCompilands.push_back(
+        "f:\\binaries\\Intermediate\\vctools\\crt_bld");
+  }
 
 #if defined(HAVE_DIA_SDK)
   CoInitializeEx(nullptr, COINIT_MULTITHREADED);