]> granicus.if.org Git - llvm/commitdiff
[llvm-pdbdump] Add a compact dump mode.
authorZachary Turner <zturner@google.com>
Thu, 12 Jan 2017 22:28:15 +0000 (22:28 +0000)
committerZachary Turner <zturner@google.com>
Thu, 12 Jan 2017 22:28:15 +0000 (22:28 +0000)
Differential Revision: https://reviews.llvm.org/D28545

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@291849 91177308-0d34-0410-b5e6-96231b3b80d8

tools/llvm-pdbdump/CMakeLists.txt
tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp [new file with mode: 0644]
tools/llvm-pdbdump/CompactTypeDumpVisitor.h [new file with mode: 0644]
tools/llvm-pdbdump/LLVMOutputStyle.cpp
tools/llvm-pdbdump/llvm-pdbdump.cpp
tools/llvm-pdbdump/llvm-pdbdump.h

index 7c46171941f7d3bc4efd9fb3199b99a0681d1a3e..cb6abb1326de73d19aa12ff7ee02ad80438c1e13 100644 (file)
@@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS
   )
 
 add_llvm_tool(llvm-pdbdump
+  CompactTypeDumpVisitor.cpp
   llvm-pdbdump.cpp
   YamlSymbolDumper.cpp
   YamlTypeDumper.cpp
diff --git a/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp b/tools/llvm-pdbdump/CompactTypeDumpVisitor.cpp
new file mode 100644 (file)
index 0000000..1fc8dd5
--- /dev/null
@@ -0,0 +1,57 @@
+//===-- CompactTypeDumpVisitor.cpp - CodeView type info dumper --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CompactTypeDumpVisitor.h"
+#include "llvm/DebugInfo/CodeView/TypeDatabase.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/ScopedPrinter.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+using namespace llvm::pdb;
+
+static const EnumEntry<TypeLeafKind> LeafTypeNames[] = {
+#define CV_TYPE(enum, val) {#enum, enum},
+#include "llvm/DebugInfo/CodeView/TypeRecords.def"
+};
+
+static StringRef getLeafName(TypeLeafKind K) {
+  for (const auto &E : LeafTypeNames) {
+    if (E.Value == K)
+      return E.Name;
+  }
+  return StringRef();
+}
+
+CompactTypeDumpVisitor::CompactTypeDumpVisitor(TypeDatabase &TypeDB,
+                                               ScopedPrinter *W)
+    : W(W), TI(TypeIndex::None()), Offset(0), TypeDB(TypeDB) {}
+
+Error CompactTypeDumpVisitor::visitTypeBegin(CVType &Record) {
+  if (TI == TypeIndex::None())
+    TI.setIndex(TypeIndex::FirstNonSimpleIndex);
+  else
+    TI.setIndex(TI.getIndex() + 1);
+
+  return Error::success();
+}
+
+Error CompactTypeDumpVisitor::visitTypeEnd(CVType &Record) {
+  uint32_t I = TI.getIndex();
+  StringRef Leaf = getLeafName(Record.Type);
+  StringRef Name = TypeDB.getTypeName(TI);
+  W->printString(
+      llvm::formatv("Index: {0:x} ({1:N} bytes, offset {2:N}) {3} \"{4}\"", I,
+                    Record.length(), Offset, Leaf, Name)
+          .str());
+
+  Offset += Record.length();
+
+  return Error::success();
+}
diff --git a/tools/llvm-pdbdump/CompactTypeDumpVisitor.h b/tools/llvm-pdbdump/CompactTypeDumpVisitor.h
new file mode 100644 (file)
index 0000000..180eea7
--- /dev/null
@@ -0,0 +1,47 @@
+//===-- CompactTypeDumpVisitor.h - CodeView type info dumper ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_COMPACTTYPEDUMPVISITOR_H
+#define LLVM_DEBUGINFO_CODEVIEW_COMPACTTYPEDUMPVISITOR_H
+
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+
+namespace llvm {
+class ScopedPrinter;
+namespace codeview {
+class TypeDatabase;
+}
+
+namespace pdb {
+
+/// Dumper for CodeView type streams found in COFF object files and PDB files.
+/// Dumps records on a single line, and ignores member records.
+class CompactTypeDumpVisitor : public codeview::TypeVisitorCallbacks {
+public:
+  CompactTypeDumpVisitor(codeview::TypeDatabase &TypeDB, ScopedPrinter *W);
+
+  /// Paired begin/end actions for all types. Receives all record data,
+  /// including the fixed-length record prefix.
+  Error visitTypeBegin(codeview::CVType &Record) override;
+  Error visitTypeEnd(codeview::CVType &Record) override;
+
+private:
+  ScopedPrinter *W;
+
+  codeview::TypeIndex TI;
+  uint32_t Offset;
+  codeview::TypeDatabase &TypeDB;
+};
+
+} // end namespace pdb
+} // end namespace llvm
+
+#endif
index 629ba40b113c560cee14b91e8abefdc2058550d7..f3508d6961cb6c26e3262bbd85f4c3d878cfa5e5 100644 (file)
@@ -9,7 +9,9 @@
 
 #include "LLVMOutputStyle.h"
 
+#include "CompactTypeDumpVisitor.h"
 #include "llvm-pdbdump.h"
+
 #include "llvm/DebugInfo/CodeView/CVTypeDumper.h"
 #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
 #include "llvm/DebugInfo/CodeView/EnumTables.h"
@@ -34,6 +36,7 @@
 #include "llvm/DebugInfo/PDB/Raw/RawError.h"
 #include "llvm/DebugInfo/PDB/Raw/TpiStream.h"
 #include "llvm/Object/COFF.h"
+#include "llvm/Support/FormatVariadic.h"
 
 #include <unordered_map>
 
@@ -524,22 +527,40 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
   if (!Tpi)
     return Tpi.takeError();
 
-  CVTypeDumper Dumper(TypeDB);
+  // Even if the user doesn't want to dump type records, we still need to
+  // iterate them in order to build the type database. So when they want to
+  // dump symbols but not types, don't stick a dumper on the end, just build
+  // the type database.
+  TypeDatabaseVisitor DBV(TypeDB);
+  CompactTypeDumpVisitor CTDV(TypeDB, &P);
+  TypeDumpVisitor TDV(TypeDB, &P, false);
+  TypeDeserializer Deserializer;
+  TypeVisitorCallbackPipeline Pipeline;
+  Pipeline.addCallbackToPipeline(Deserializer);
+  Pipeline.addCallbackToPipeline(DBV);
+
+  CVTypeVisitor Visitor(Pipeline);
+
   if (DumpRecords || DumpRecordBytes) {
     DictScope D(P, Label);
 
     P.printNumber(VerLabel, Tpi->getTpiVersion());
     P.printNumber("Record count", Tpi->NumTypeRecords());
-
     ListScope L(P, "Records");
 
     bool HadError = false;
-    for (auto &Type : Tpi->types(&HadError)) {
-      DictScope DD(P, "");
+    if (opts::raw::CompactRecords)
+      Pipeline.addCallbackToPipeline(CTDV);
+    else
+      Pipeline.addCallbackToPipeline(TDV);
+
+    for (auto Type : Tpi->types(&HadError)) {
+      std::unique_ptr<DictScope> Scope;
+      if (!opts::raw::CompactRecords)
+        Scope.reset(new DictScope(P, ""));
 
       if (DumpRecords) {
-        TypeDumpVisitor TDV(TypeDB, &P, false);
-        if (auto EC = Dumper.dump(Type, TDV))
+        if (auto EC = Visitor.visitTypeRecord(Type))
           return EC;
       }
 
@@ -550,18 +571,16 @@ Error LLVMOutputStyle::dumpTpiStream(uint32_t StreamIdx) {
     if (HadError)
       return make_error<RawError>(raw_error_code::corrupt_file,
                                   "TPI stream contained corrupt record");
+    {
+      ListScope L(P, "TypeIndexOffsets");
+      for (const auto &IO : Tpi->getTypeIndexOffsets()) {
+        P.printString(formatv("Index: {0:x}, Offset: {1:N}", IO.Type.getIndex(),
+                              (uint32_t)IO.Offset)
+                          .str());
+      }
+    }
+
   } else if (opts::raw::DumpModuleSyms) {
-    // Even if the user doesn't want to dump type records, we still need to
-    // iterate them in order to build the type database. So when they want to
-    // dump symbols but not types, don't stick a dumper on the end, just build
-    // the type database.
-    TypeDatabaseVisitor DBV(TypeDB);
-    TypeDeserializer Deserializer;
-    TypeVisitorCallbackPipeline Pipeline;
-    Pipeline.addCallbackToPipeline(Deserializer);
-    Pipeline.addCallbackToPipeline(DBV);
-
-    CVTypeVisitor Visitor(Pipeline);
 
     bool HadError = false;
     for (auto Type : Tpi->types(&HadError)) {
index d3495e524abcf8733d67cc0dd9e0ab13b7251325..cce0a04399774497115ee9a6545ced1fa43c7c3e 100644 (file)
@@ -186,6 +186,11 @@ cl::list<uint32_t>
                    cl::cat(MsfOptions), cl::sub(RawSubcommand));
 
 // TYPE OPTIONS
+cl::opt<bool>
+    CompactRecords("compact-records",
+                   cl::desc("Dump type and symbol records with less detail"),
+                   cl::cat(TypeOptions), cl::sub(RawSubcommand));
+
 cl::opt<bool>
     DumpTpiRecords("tpi-records",
                    cl::desc("dump CodeView type records from TPI stream"),
@@ -556,24 +561,33 @@ int main(int argc_, const char *argv_[]) {
     }
   }
 
-  if (opts::RawSubcommand && opts::raw::RawAll) {
-    opts::raw::DumpHeaders = true;
-    opts::raw::DumpModules = true;
-    opts::raw::DumpModuleFiles = true;
-    opts::raw::DumpModuleSyms = true;
-    opts::raw::DumpGlobals = true;
-    opts::raw::DumpPublics = true;
-    opts::raw::DumpSectionHeaders = true;
-    opts::raw::DumpStreamSummary = true;
-    opts::raw::DumpPageStats = true;
-    opts::raw::DumpStreamBlocks = true;
-    opts::raw::DumpTpiRecords = true;
-    opts::raw::DumpTpiHash = true;
-    opts::raw::DumpIpiRecords = true;
-    opts::raw::DumpSectionMap = true;
-    opts::raw::DumpSectionContribs = true;
-    opts::raw::DumpLineInfo = true;
-    opts::raw::DumpFpo = true;
+  if (opts::RawSubcommand) {
+    if (opts::raw::RawAll) {
+      opts::raw::DumpHeaders = true;
+      opts::raw::DumpModules = true;
+      opts::raw::DumpModuleFiles = true;
+      opts::raw::DumpModuleSyms = true;
+      opts::raw::DumpGlobals = true;
+      opts::raw::DumpPublics = true;
+      opts::raw::DumpSectionHeaders = true;
+      opts::raw::DumpStreamSummary = true;
+      opts::raw::DumpPageStats = true;
+      opts::raw::DumpStreamBlocks = true;
+      opts::raw::DumpTpiRecords = true;
+      opts::raw::DumpTpiHash = true;
+      opts::raw::DumpIpiRecords = true;
+      opts::raw::DumpSectionMap = true;
+      opts::raw::DumpSectionContribs = true;
+      opts::raw::DumpLineInfo = true;
+      opts::raw::DumpFpo = true;
+    }
+
+    if (opts::raw::CompactRecords &&
+        (opts::raw::DumpTpiRecordBytes || opts::raw::DumpIpiRecordBytes)) {
+      errs() << "-compact-records is incompatible with -tpi-record-bytes and "
+                "-ipi-record-bytes.\n";
+      exit(1);
+    }
   }
 
   llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
index 42d847a23fcc99244c22d347cbcc9241c10e2424..869ebf2eec443e58a41d0b90781f413d58ab2bc7 100644 (file)
@@ -43,6 +43,7 @@ struct BlockRange {
 extern llvm::Optional<BlockRange> DumpBlockRange;
 extern llvm::cl::list<uint32_t> DumpStreamData;
 
+extern llvm::cl::opt<bool> CompactRecords;
 extern llvm::cl::opt<bool> DumpGlobals;
 extern llvm::cl::opt<bool> DumpHeaders;
 extern llvm::cl::opt<bool> DumpStreamBlocks;