OSDN Git Service

[llvm-pdbdump] Support native ordering of subsections in raw mode.
authorZachary Turner <zturner@google.com>
Thu, 8 Jun 2017 23:49:01 +0000 (23:49 +0000)
committerZachary Turner <zturner@google.com>
Thu, 8 Jun 2017 23:49:01 +0000 (23:49 +0000)
This is the same change for the YAML Output style applied to the
raw output style.  Previously we would queue up all subsections
until every one had been read, and then output them in a pre-
determined order.  This was because some subsections need to be
read first in order to properly dump later subsections.  This
patch allows them to be dumped in the order they appear.

Differential Revision: https://reviews.llvm.org/D34015

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

12 files changed:
include/llvm/DebugInfo/CodeView/DebugStringTableSubsection.h
include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h
lib/DebugInfo/CodeView/DebugStringTableSubsection.cpp
lib/DebugInfo/CodeView/DebugSubsectionVisitor.cpp
lib/ObjectYAML/CodeViewYAMLDebugSections.cpp
test/DebugInfo/PDB/pdbdump-debug-subsections.test
test/DebugInfo/PDB/pdbdump-headers.test
tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp [deleted file]
tools/llvm-pdbdump/C13DebugFragmentVisitor.h [deleted file]
tools/llvm-pdbdump/CMakeLists.txt
tools/llvm-pdbdump/LLVMOutputStyle.cpp
tools/llvm-pdbdump/YAMLOutputStyle.cpp

index fbe39cb..ceb0054 100644 (file)
@@ -39,6 +39,7 @@ public:
   }
 
   Error initialize(BinaryStreamRef Contents);
+  Error initialize(BinaryStreamReader &Reader);
 
   Expected<StringRef> getString(uint32_t Offset) const;
 
index 6fa6244..db0bd56 100644 (file)
@@ -23,8 +23,59 @@ class DebugInlineeLinesSubsectionRef;
 class DebugCrossModuleExportsSubsectionRef;
 class DebugCrossModuleImportsSubsectionRef;
 class DebugLinesSubsectionRef;
+class DebugStringTableSubsectionRef;
 class DebugUnknownSubsectionRef;
 
+struct DebugSubsectionState {
+public:
+  // If no subsections are known about initially, we find as much as we can.
+  DebugSubsectionState();
+
+  // If only a string table subsection is given, we find a checksums subsection.
+  explicit DebugSubsectionState(const DebugStringTableSubsectionRef &Strings);
+
+  // If both subsections are given, we don't need to find anything.
+  DebugSubsectionState(const DebugStringTableSubsectionRef &Strings,
+                       const DebugChecksumsSubsectionRef &Checksums);
+
+  template <typename T> void initialize(T &&FragmentRange) {
+    for (const DebugSubsectionRecord &R : FragmentRange) {
+      if (Strings && Checksums)
+        return;
+      if (R.kind() == DebugSubsectionKind::FileChecksums) {
+        initializeChecksums(R);
+        continue;
+      }
+      if (R.kind() == DebugSubsectionKind::StringTable && !Strings) {
+        // While in practice we should never encounter a string table even
+        // though the string table is already initialized, in theory it's
+        // possible.  PDBs are supposed to have one global string table and
+        // then this subsection should not appear.  Whereas object files are
+        // supposed to have this subsection appear exactly once.  However,
+        // for testing purposes it's nice to be able to test this subsection
+        // independently of one format or the other, so for some tests we
+        // manually construct a PDB that contains this subsection in addition
+        // to a global string table.
+        initializeStrings(R);
+        continue;
+      }
+    }
+  }
+
+  const DebugStringTableSubsectionRef &strings() const { return *Strings; }
+  const DebugChecksumsSubsectionRef &checksums() const { return *Checksums; }
+
+private:
+  void initializeStrings(const DebugSubsectionRecord &SR);
+  void initializeChecksums(const DebugSubsectionRecord &FCR);
+
+  std::unique_ptr<DebugStringTableSubsectionRef> OwnedStrings;
+  std::unique_ptr<DebugChecksumsSubsectionRef> OwnedChecksums;
+
+  const DebugStringTableSubsectionRef *Strings = nullptr;
+  const DebugChecksumsSubsectionRef *Checksums = nullptr;
+};
+
 class DebugSubsectionVisitor {
 public:
   virtual ~DebugSubsectionVisitor() = default;
@@ -32,44 +83,61 @@ public:
   virtual Error visitUnknown(DebugUnknownSubsectionRef &Unknown) {
     return Error::success();
   }
-  virtual Error visitLines(DebugLinesSubsectionRef &Lines) {
-    return Error::success();
-  }
-
-  virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums) {
-    return Error::success();
-  }
-
-  virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees) {
-    return Error::success();
-  }
-
+  virtual Error visitLines(DebugLinesSubsectionRef &Lines,
+                           const DebugSubsectionState &State) = 0;
+  virtual Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
+                                   const DebugSubsectionState &State) = 0;
+  virtual Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
+                                  const DebugSubsectionState &State) = 0;
   virtual Error
-  visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE) {
-    return Error::success();
-  }
-
+  visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE,
+                          const DebugSubsectionState &State) = 0;
   virtual Error
-  visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE) {
-    return Error::success();
-  }
-
-  virtual Error finished() { return Error::success(); }
+  visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSE,
+                          const DebugSubsectionState &State) = 0;
 };
 
 Error visitDebugSubsection(const DebugSubsectionRecord &R,
-                           DebugSubsectionVisitor &V);
+                           DebugSubsectionVisitor &V,
+                           const DebugSubsectionState &State);
 
+namespace detail {
 template <typename T>
-Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) {
+Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
+                            DebugSubsectionState &State) {
+  State.initialize(std::forward<T>(FragmentRange));
+
   for (const auto &L : FragmentRange) {
-    if (auto EC = visitDebugSubsection(L, V))
+    if (auto EC = visitDebugSubsection(L, V, State))
       return EC;
   }
-  if (auto EC = V.finished())
-    return EC;
   return Error::success();
 }
+} // namespace detail
+
+template <typename T>
+Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V) {
+  DebugSubsectionState State;
+  return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V,
+                                       State);
+}
+
+template <typename T>
+Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
+                            const DebugStringTableSubsectionRef &Strings) {
+  DebugSubsectionState State(Strings);
+  return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V,
+                                       State);
+}
+
+template <typename T>
+Error visitDebugSubsections(T &&FragmentRange, DebugSubsectionVisitor &V,
+                            const DebugStringTableSubsectionRef &Strings,
+                            const DebugChecksumsSubsectionRef &Checksums) {
+  DebugSubsectionState State(Strings, Checksums);
+  return detail::visitDebugSubsections(std::forward<T>(FragmentRange), V,
+                                       State);
+}
 
 } // end namespace codeview
 
index 2e72242..7b972a1 100644 (file)
@@ -23,6 +23,9 @@ Error DebugStringTableSubsectionRef::initialize(BinaryStreamRef Contents) {
   Stream = Contents;
   return Error::success();
 }
+Error DebugStringTableSubsectionRef::initialize(BinaryStreamReader &Reader) {
+  return Reader.readStreamRef(Stream, Reader.bytesRemaining());
+}
 
 Expected<StringRef>
 DebugStringTableSubsectionRef::getString(uint32_t Offset) const {
index 93fe4e1..ee769d3 100644 (file)
@@ -14,6 +14,7 @@
 #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
 #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
 #include "llvm/DebugInfo/CodeView/DebugUnknownSubsection.h"
 #include "llvm/Support/BinaryStreamReader.h"
 using namespace llvm;
 using namespace llvm::codeview;
 
+DebugSubsectionState::DebugSubsectionState() {}
+
+DebugSubsectionState::DebugSubsectionState(
+    const DebugStringTableSubsectionRef &Strings)
+    : Strings(&Strings) {}
+
+DebugSubsectionState::DebugSubsectionState(
+    const DebugStringTableSubsectionRef &Strings,
+    const DebugChecksumsSubsectionRef &Checksums)
+    : Strings(&Strings), Checksums(&Checksums) {}
+
+void DebugSubsectionState::initializeStrings(const DebugSubsectionRecord &SR) {
+  assert(SR.kind() == DebugSubsectionKind::StringTable);
+  assert(!Strings && "Found a string table even though we already have one!");
+
+  OwnedStrings = llvm::make_unique<DebugStringTableSubsectionRef>();
+  consumeError(OwnedStrings->initialize(SR.getRecordData()));
+  Strings = OwnedStrings.get();
+}
+
+void DebugSubsectionState::initializeChecksums(
+    const DebugSubsectionRecord &FCR) {
+  assert(FCR.kind() == DebugSubsectionKind::FileChecksums);
+  if (Checksums)
+    return;
+
+  OwnedChecksums = llvm::make_unique<DebugChecksumsSubsectionRef>();
+  consumeError(OwnedChecksums->initialize(FCR.getRecordData()));
+  Checksums = OwnedChecksums.get();
+}
+
 Error llvm::codeview::visitDebugSubsection(const DebugSubsectionRecord &R,
-                                           DebugSubsectionVisitor &V) {
+                                           DebugSubsectionVisitor &V,
+                                           const DebugSubsectionState &State) {
   BinaryStreamReader Reader(R.getRecordData());
   switch (R.kind()) {
   case DebugSubsectionKind::Lines: {
@@ -31,32 +64,32 @@ Error llvm::codeview::visitDebugSubsection(const DebugSubsectionRecord &R,
     if (auto EC = Fragment.initialize(Reader))
       return EC;
 
-    return V.visitLines(Fragment);
+    return V.visitLines(Fragment, State);
   }
   case DebugSubsectionKind::FileChecksums: {
     DebugChecksumsSubsectionRef Fragment;
     if (auto EC = Fragment.initialize(Reader))
       return EC;
 
-    return V.visitFileChecksums(Fragment);
+    return V.visitFileChecksums(Fragment, State);
   }
   case DebugSubsectionKind::InlineeLines: {
     DebugInlineeLinesSubsectionRef Fragment;
     if (auto EC = Fragment.initialize(Reader))
       return EC;
-    return V.visitInlineeLines(Fragment);
+    return V.visitInlineeLines(Fragment, State);
   }
   case DebugSubsectionKind::CrossScopeExports: {
     DebugCrossModuleExportsSubsectionRef Section;
     if (auto EC = Section.initialize(Reader))
       return EC;
-    return V.visitCrossModuleExports(Section);
+    return V.visitCrossModuleExports(Section, State);
   }
   case DebugSubsectionKind::CrossScopeImports: {
     DebugCrossModuleImportsSubsectionRef Section;
     if (auto EC = Section.initialize(Reader))
       return EC;
-    return V.visitCrossModuleImports(Section);
+    return V.visitCrossModuleImports(Section, State);
   }
   default: {
     DebugUnknownSubsectionRef Fragment(R.kind(), R.getRecordData());
index fc3d0ce..baf98d1 100644 (file)
@@ -533,25 +533,21 @@ llvm::CodeViewYAML::convertSubsectionList(
 
 namespace {
 struct SubsectionConversionVisitor : public DebugSubsectionVisitor {
-  explicit SubsectionConversionVisitor(
-      const DebugStringTableSubsectionRef &Strings,
-      const DebugChecksumsSubsectionRef &Checksums)
-      : Strings(Strings), Checksums(Checksums) {}
+  SubsectionConversionVisitor() {}
 
   Error visitUnknown(DebugUnknownSubsectionRef &Unknown) override;
-  Error visitLines(DebugLinesSubsectionRef &Lines) override;
-  Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums) override;
-  Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees) override;
-  Error visitCrossModuleExports(
-      DebugCrossModuleExportsSubsectionRef &Checksums) override;
-  Error visitCrossModuleImports(
-      DebugCrossModuleImportsSubsectionRef &Inlinees) override;
+  Error visitLines(DebugLinesSubsectionRef &Lines,
+                   const DebugSubsectionState &State) override;
+  Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
+                           const DebugSubsectionState &State) override;
+  Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
+                          const DebugSubsectionState &State) override;
+  Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &Checksums,
+                                const DebugSubsectionState &State) override;
+  Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &Inlinees,
+                                const DebugSubsectionState &State) override;
 
   YAMLDebugSubsection Subsection;
-
-private:
-  const DebugStringTableSubsectionRef &Strings;
-  const DebugChecksumsSubsectionRef &Checksums;
 };
 
 Error SubsectionConversionVisitor::visitUnknown(
@@ -559,9 +555,10 @@ Error SubsectionConversionVisitor::visitUnknown(
   return make_error<CodeViewError>(cv_error_code::operation_unsupported);
 }
 
-Error SubsectionConversionVisitor::visitLines(DebugLinesSubsectionRef &Lines) {
-  auto Result =
-      YAMLLinesSubsection::fromCodeViewSubsection(Strings, Checksums, Lines);
+Error SubsectionConversionVisitor::visitLines(
+    DebugLinesSubsectionRef &Lines, const DebugSubsectionState &State) {
+  auto Result = YAMLLinesSubsection::fromCodeViewSubsection(
+      State.strings(), State.checksums(), Lines);
   if (!Result)
     return Result.takeError();
   Subsection.Subsection = *Result;
@@ -569,9 +566,9 @@ Error SubsectionConversionVisitor::visitLines(DebugLinesSubsectionRef &Lines) {
 }
 
 Error SubsectionConversionVisitor::visitFileChecksums(
-    DebugChecksumsSubsectionRef &Checksums) {
-  auto Result =
-      YAMLChecksumsSubsection::fromCodeViewSubsection(Strings, Checksums);
+    DebugChecksumsSubsectionRef &Checksums, const DebugSubsectionState &State) {
+  auto Result = YAMLChecksumsSubsection::fromCodeViewSubsection(State.strings(),
+                                                                Checksums);
   if (!Result)
     return Result.takeError();
   Subsection.Subsection = *Result;
@@ -579,9 +576,10 @@ Error SubsectionConversionVisitor::visitFileChecksums(
 }
 
 Error SubsectionConversionVisitor::visitInlineeLines(
-    DebugInlineeLinesSubsectionRef &Inlinees) {
+    DebugInlineeLinesSubsectionRef &Inlinees,
+    const DebugSubsectionState &State) {
   auto Result = YAMLInlineeLinesSubsection::fromCodeViewSubsection(
-      Strings, Checksums, Inlinees);
+      State.strings(), State.checksums(), Inlinees);
   if (!Result)
     return Result.takeError();
   Subsection.Subsection = *Result;
@@ -589,7 +587,8 @@ Error SubsectionConversionVisitor::visitInlineeLines(
 }
 
 Error SubsectionConversionVisitor::visitCrossModuleExports(
-    DebugCrossModuleExportsSubsectionRef &Exports) {
+    DebugCrossModuleExportsSubsectionRef &Exports,
+    const DebugSubsectionState &State) {
   auto Result =
       YAMLCrossModuleExportsSubsection::fromCodeViewSubsection(Exports);
   if (!Result)
@@ -599,9 +598,10 @@ Error SubsectionConversionVisitor::visitCrossModuleExports(
 }
 
 Error SubsectionConversionVisitor::visitCrossModuleImports(
-    DebugCrossModuleImportsSubsectionRef &Imports) {
+    DebugCrossModuleImportsSubsectionRef &Imports,
+    const DebugSubsectionState &State) {
   auto Result = YAMLCrossModuleImportsSubsection::fromCodeViewSubsection(
-      Strings, Imports);
+      State.strings(), Imports);
   if (!Result)
     return Result.takeError();
   Subsection.Subsection = *Result;
@@ -613,8 +613,9 @@ Expected<YAMLDebugSubsection> YAMLDebugSubsection::fromCodeViewSubection(
     const DebugStringTableSubsectionRef &Strings,
     const DebugChecksumsSubsectionRef &Checksums,
     const DebugSubsectionRecord &SS) {
-  SubsectionConversionVisitor V(Strings, Checksums);
-  if (auto EC = visitDebugSubsection(SS, V))
+  DebugSubsectionState State(Strings, Checksums);
+  SubsectionConversionVisitor V;
+  if (auto EC = visitDebugSubsection(SS, V, State))
     return std::move(EC);
 
   return V.Subsection;
index 5b09158..d95def7 100644 (file)
@@ -73,27 +73,37 @@ RAW:        Modules [
 RAW-NEXT:     {
 RAW-NEXT:       Name: Foo.obj
 RAW:            Subsections [
-RAW-NEXT:         CrossModuleExports {
-RAW-NEXT:           Local: 0x12F4
-RAW-NEXT:           Global: 0x2443
-RAW-NEXT:           Local: 0x80001083
-RAW-NEXT:           Global: 0x23A3
-RAW-NEXT:         }
+RAW-NEXT:         CrossModuleExports [
+RAW-NEXT:           Export {
+RAW-NEXT:             Local: 0x12F4
+RAW-NEXT:             Global: 0x2443
+RAW-NEXT:           }
+RAW-NEXT:           Export {
+RAW-NEXT:             Local: 0x80001083
+RAW-NEXT:             Global: 0x23A3
+RAW-NEXT:           }
+RAW-NEXT:         ]
 RAW-NEXT:       ]
 RAW-NEXT:     }
 RAW-NEXT:     {
 RAW-NEXT:       Name: Bar.obj
 RAW:            Subsections [
-RAW-NEXT:         CrossModuleExports {
-RAW-NEXT:           Local: 0x10A9
-RAW-NEXT:           Global: 0x17D1
-RAW-NEXT:           Local: 0x10C9
-RAW-NEXT:           Global: 0x1245
-RAW-NEXT:         }
-RAW-NEXT:         CrossModuleImports {
-RAW-NEXT:           Module: Foo.obj
-RAW-NEXT:           Imports: [0x12F4, 0x80001083]
-RAW-NEXT:         }
+RAW-NEXT:         CrossModuleExports [
+RAW-NEXT:           Export {
+RAW-NEXT:             Local: 0x10A9
+RAW-NEXT:             Global: 0x17D1
+RAW-NEXT:           }
+RAW-NEXT:           Export {
+RAW-NEXT:             Local: 0x10C9
+RAW-NEXT:             Global: 0x1245
+RAW-NEXT:           }
+RAW-NEXT:         ]
+RAW-NEXT:         CrossModuleImports [
+RAW-NEXT:           ModuleImport {
+RAW-NEXT:             Module: Foo.obj
+RAW-NEXT:             Imports: [0x12F4, 0x80001083]
+RAW-NEXT:           }
+RAW-NEXT:         ]
 RAW-NEXT:       ]
 RAW-NEXT:     }
 RAW-NEXT:    {
@@ -116,31 +126,29 @@ RAW-NEXT:            )
 RAW-NEXT:          }
 RAW-NEXT:        }
 RAW-NEXT:        Lines {
-RAW-NEXT:          Block {
-RAW-NEXT:            RelocSegment: 1
-RAW-NEXT:            RelocOffset: 16
-RAW-NEXT:            CodeSize: 10
-RAW-NEXT:            HasColumns: No
-RAW-NEXT:            Lines {
-RAW-NEXT:              FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-RAW-NEXT:              Line {
-RAW-NEXT:                Offset: 0
-RAW-NEXT:                LineNumberStart: 5
-RAW-NEXT:                EndDelta: 0
-RAW-NEXT:                IsStatement: Yes
-RAW-NEXT:              }
-RAW-NEXT:              Line {
-RAW-NEXT:                Offset: 3
-RAW-NEXT:                LineNumberStart: 6
-RAW-NEXT:                EndDelta: 0
-RAW-NEXT:                IsStatement: Yes
-RAW-NEXT:              }
-RAW-NEXT:              Line {
-RAW-NEXT:                Offset: 8
-RAW-NEXT:                LineNumberStart: 7
-RAW-NEXT:                EndDelta: 0
-RAW-NEXT:                IsStatement: Yes
-RAW-NEXT:              }
+RAW-NEXT:          RelocSegment: 1
+RAW-NEXT:          RelocOffset: 16
+RAW-NEXT:          CodeSize: 10
+RAW-NEXT:          HasColumns: No
+RAW-NEXT:          FileEntry {
+RAW-NEXT:            FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
+RAW-NEXT:            Line {
+RAW-NEXT:              Offset: 0
+RAW-NEXT:              LineNumberStart: 5
+RAW-NEXT:              EndDelta: 0
+RAW-NEXT:              IsStatement: Yes
+RAW-NEXT:            }
+RAW-NEXT:            Line {
+RAW-NEXT:              Offset: 3
+RAW-NEXT:              LineNumberStart: 6
+RAW-NEXT:              EndDelta: 0
+RAW-NEXT:              IsStatement: Yes
+RAW-NEXT:            }
+RAW-NEXT:            Line {
+RAW-NEXT:              Offset: 8
+RAW-NEXT:              LineNumberStart: 7
+RAW-NEXT:              EndDelta: 0
+RAW-NEXT:              IsStatement: Yes
 RAW-NEXT:            }
 RAW-NEXT:          }
 RAW-NEXT:        }
index 5266f21..0a9c48c 100644 (file)
 ; EMPTY-NEXT:         }
 ; EMPTY-NEXT:       ]
 ; EMPTY-NEXT:       Subsections [
+; EMPTY-NEXT:         Lines {
+; EMPTY-NEXT:           RelocSegment: 1
+; EMPTY-NEXT:           RelocOffset: 16
+; EMPTY-NEXT:           CodeSize: 10
+; EMPTY-NEXT:           HasColumns: No
+; EMPTY-NEXT:           FileEntry {
+; EMPTY-NEXT:             FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
+; EMPTY-NEXT:             Line {
+; EMPTY-NEXT:               Offset: 0
+; EMPTY-NEXT:               LineNumberStart: 5
+; EMPTY-NEXT:               EndDelta: 0
+; EMPTY-NEXT:               IsStatement: Yes
+; EMPTY-NEXT:             }
+; EMPTY-NEXT:             Line {
+; EMPTY-NEXT:               Offset: 3
+; EMPTY-NEXT:               LineNumberStart: 6
+; EMPTY-NEXT:               EndDelta: 0
+; EMPTY-NEXT:               IsStatement: Yes
+; EMPTY-NEXT:             }
+; EMPTY-NEXT:             Line {
+; EMPTY-NEXT:               Offset: 8
+; EMPTY-NEXT:               LineNumberStart: 7
+; EMPTY-NEXT:               EndDelta: 0
+; EMPTY-NEXT:               IsStatement: Yes
+; EMPTY-NEXT:             }
+; EMPTY-NEXT:           }
+; EMPTY-NEXT:         }
 ; EMPTY-NEXT:         FileChecksums {
 ; EMPTY-NEXT:           Checksum {
 ; EMPTY-NEXT:             FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
 ; EMPTY-NEXT:             )
 ; EMPTY-NEXT:           }
 ; EMPTY-NEXT:         }
-; EMPTY-NEXT:         Lines {
-; EMPTY-NEXT:           Block {
-; EMPTY-NEXT:             RelocSegment: 1
-; EMPTY-NEXT:             RelocOffset: 16
-; EMPTY-NEXT:             CodeSize: 10
-; EMPTY-NEXT:             HasColumns: No
-; EMPTY-NEXT:             Lines {
-; EMPTY-NEXT:               FileName: d:\src\llvm\test\debuginfo\pdb\inputs\empty.cpp
-; EMPTY-NEXT:               Line {
-; EMPTY-NEXT:                 Offset: 0
-; EMPTY-NEXT:                 LineNumberStart: 5
-; EMPTY-NEXT:                 EndDelta: 0
-; EMPTY-NEXT:                 IsStatement: Yes
-; EMPTY-NEXT:               }
-; EMPTY-NEXT:               Line {
-; EMPTY-NEXT:                 Offset: 3
-; EMPTY-NEXT:                 LineNumberStart: 6
-; EMPTY-NEXT:                 EndDelta: 0
-; EMPTY-NEXT:                 IsStatement: Yes
-; EMPTY-NEXT:               }
-; EMPTY-NEXT:               Line {
-; EMPTY-NEXT:                 Offset: 8
-; EMPTY-NEXT:                 LineNumberStart: 7
-; EMPTY-NEXT:                 EndDelta: 0
-; EMPTY-NEXT:                 IsStatement: Yes
-; EMPTY-NEXT:               }
-; EMPTY-NEXT:             }
-; EMPTY-NEXT:           }
-; EMPTY-NEXT:         }
 ; EMPTY-NEXT:       ]
 ; EMPTY-NEXT:     }
 ; EMPTY-NEXT:     {
diff --git a/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp b/tools/llvm-pdbdump/C13DebugFragmentVisitor.cpp
deleted file mode 100644 (file)
index 3113a32..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-//===- C13DebugFragmentVisitor.cpp -------------------------------*- C++-*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "C13DebugFragmentVisitor.h"
-
-#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugCrossExSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugInlineeLinesSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
-#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
-#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
-#include "llvm/DebugInfo/PDB/Native/RawError.h"
-
-using namespace llvm;
-using namespace llvm::codeview;
-using namespace llvm::pdb;
-
-C13DebugFragmentVisitor::C13DebugFragmentVisitor(PDBFile &F) : F(F) {}
-
-C13DebugFragmentVisitor::~C13DebugFragmentVisitor() {}
-
-Error C13DebugFragmentVisitor::visitUnknown(
-    codeview::DebugUnknownSubsectionRef &Fragment) {
-  return Error::success();
-}
-
-Error C13DebugFragmentVisitor::visitFileChecksums(
-    codeview::DebugChecksumsSubsectionRef &Checksums) {
-  assert(!this->Checksums.hasValue());
-  this->Checksums = Checksums;
-  return Error::success();
-}
-
-Error C13DebugFragmentVisitor::visitLines(
-    codeview::DebugLinesSubsectionRef &Lines) {
-  this->Lines.push_back(Lines);
-  return Error::success();
-}
-
-Error C13DebugFragmentVisitor::visitInlineeLines(
-    codeview::DebugInlineeLinesSubsectionRef &Lines) {
-  this->InlineeLines.push_back(Lines);
-  return Error::success();
-}
-
-Error C13DebugFragmentVisitor::visitCrossModuleExports(
-    codeview::DebugCrossModuleExportsSubsectionRef &Exports) {
-  this->CrossExports.push_back(Exports);
-  return Error::success();
-}
-
-Error C13DebugFragmentVisitor::visitCrossModuleImports(
-    codeview::DebugCrossModuleImportsSubsectionRef &Imports) {
-  this->CrossImports.push_back(Imports);
-  return Error::success();
-}
-
-Error C13DebugFragmentVisitor::finished() {
-  if (Checksums.hasValue()) {
-    if (auto EC = handleFileChecksums())
-      return EC;
-
-    if (auto EC = handleLines())
-      return EC;
-
-    if (auto EC = handleInlineeLines())
-      return EC;
-  }
-
-  if (auto EC = handleCrossModuleExports())
-    return EC;
-
-  if (auto EC = handleCrossModuleImports())
-    return EC;
-
-  return Error::success();
-}
-
-Expected<StringRef>
-C13DebugFragmentVisitor::getNameFromStringTable(uint32_t Offset) {
-  auto ST = F.getStringTable();
-  if (!ST)
-    return ST.takeError();
-
-  return ST->getStringForID(Offset);
-}
-
-Expected<StringRef>
-C13DebugFragmentVisitor::getNameFromChecksumsBuffer(uint32_t Offset) {
-  assert(Checksums.hasValue());
-
-  auto Array = Checksums->getArray();
-  auto ChecksumIter = Array.at(Offset);
-  if (ChecksumIter == Array.end())
-    return make_error<RawError>(raw_error_code::invalid_format);
-  const auto &Entry = *ChecksumIter;
-  return getNameFromStringTable(Entry.FileNameOffset);
-}
diff --git a/tools/llvm-pdbdump/C13DebugFragmentVisitor.h b/tools/llvm-pdbdump/C13DebugFragmentVisitor.h
deleted file mode 100644 (file)
index 1865295..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-//===- C13DebugFragmentVisitor.h - Visitor for CodeView Info ----*- C++ -*-===//
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_LLVMPDBDUMP_C13DEBUGFRAGMENTVISITOR_H
-#define LLVM_TOOLS_LLVMPDBDUMP_C13DEBUGFRAGMENTVISITOR_H
-
-#include "llvm/ADT/Optional.h"
-#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
-#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
-#include "llvm/Support/Error.h"
-
-#include <vector>
-
-namespace llvm {
-
-namespace pdb {
-
-class PDBFile;
-
-class C13DebugFragmentVisitor : public codeview::DebugSubsectionVisitor {
-public:
-  C13DebugFragmentVisitor(PDBFile &F);
-  ~C13DebugFragmentVisitor();
-
-  Error visitUnknown(codeview::DebugUnknownSubsectionRef &Fragment) final;
-
-  Error
-  visitFileChecksums(codeview::DebugChecksumsSubsectionRef &Checksums) final;
-
-  Error visitLines(codeview::DebugLinesSubsectionRef &Lines) final;
-
-  Error
-  visitInlineeLines(codeview::DebugInlineeLinesSubsectionRef &Lines) final;
-
-  Error visitCrossModuleExports(
-      codeview::DebugCrossModuleExportsSubsectionRef &Lines) final;
-
-  Error visitCrossModuleImports(
-      codeview::DebugCrossModuleImportsSubsectionRef &Imports) final;
-
-  Error finished() final;
-
-protected:
-  virtual Error handleFileChecksums() { return Error::success(); }
-  virtual Error handleLines() { return Error::success(); }
-  virtual Error handleInlineeLines() { return Error::success(); }
-  virtual Error handleCrossModuleExports() { return Error::success(); }
-  virtual Error handleCrossModuleImports() { return Error::success(); }
-
-  Expected<StringRef> getNameFromStringTable(uint32_t Offset);
-  Expected<StringRef> getNameFromChecksumsBuffer(uint32_t Offset);
-
-  Optional<codeview::DebugChecksumsSubsectionRef> Checksums;
-  std::vector<codeview::DebugInlineeLinesSubsectionRef> InlineeLines;
-  std::vector<codeview::DebugLinesSubsectionRef> Lines;
-  std::vector<codeview::DebugCrossModuleExportsSubsectionRef> CrossExports;
-  std::vector<codeview::DebugCrossModuleImportsSubsectionRef> CrossImports;
-
-  PDBFile &F;
-};
-}
-}
-
-#endif
index a1f54a3..020331e 100644 (file)
@@ -9,7 +9,6 @@ set(LLVM_LINK_COMPONENTS
 
 add_llvm_tool(llvm-pdbdump
   Analyze.cpp
-  C13DebugFragmentVisitor.cpp
   CompactTypeDumpVisitor.cpp
   Diff.cpp
   llvm-pdbdump.cpp
index cd4645e..8e861e9 100644 (file)
@@ -9,7 +9,6 @@
 
 #include "LLVMOutputStyle.h"
 
-#include "C13DebugFragmentVisitor.h"
 #include "CompactTypeDumpVisitor.h"
 #include "StreamUtil.h"
 #include "llvm-pdbdump.h"
@@ -83,64 +82,61 @@ struct PageStats {
   BitVector UseAfterFreePages;
 };
 
-class C13RawVisitor : public C13DebugFragmentVisitor {
+class C13RawVisitor : public DebugSubsectionVisitor {
 public:
-  C13RawVisitor(ScopedPrinter &P, PDBFile &F, LazyRandomTypeCollection &IPI)
-      : C13DebugFragmentVisitor(F), P(P), IPI(IPI) {}
+  C13RawVisitor(ScopedPrinter &P, LazyRandomTypeCollection &IPI)
+      : P(P), IPI(IPI) {}
 
-  Error handleLines() override {
-    if (Lines.empty() ||
-        !opts::checkModuleSubsection(opts::ModuleSubsection::Lines))
+  Error visitLines(DebugLinesSubsectionRef &Lines,
+                   const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::Lines))
       return Error::success();
 
     DictScope DD(P, "Lines");
 
-    for (const auto &Fragment : Lines) {
-      DictScope DDD(P, "Block");
-      P.printNumber("RelocSegment", Fragment.header()->RelocSegment);
-      P.printNumber("RelocOffset", Fragment.header()->RelocOffset);
-      P.printNumber("CodeSize", Fragment.header()->CodeSize);
-      P.printBoolean("HasColumns", Fragment.hasColumnInfo());
+    P.printNumber("RelocSegment", Lines.header()->RelocSegment);
+    P.printNumber("RelocOffset", Lines.header()->RelocOffset);
+    P.printNumber("CodeSize", Lines.header()->CodeSize);
+    P.printBoolean("HasColumns", Lines.hasColumnInfo());
 
-      for (const auto &L : Fragment) {
-        DictScope DDDD(P, "Lines");
+    for (const auto &L : Lines) {
+      DictScope DDDD(P, "FileEntry");
 
-        if (auto EC = printFileName("FileName", L.NameIndex))
-          return EC;
+      if (auto EC = printFileName("FileName", L.NameIndex, State))
+        return EC;
 
-        for (const auto &N : L.LineNumbers) {
-          DictScope DDD(P, "Line");
-          LineInfo LI(N.Flags);
-          P.printNumber("Offset", N.Offset);
-          if (LI.isAlwaysStepInto())
-            P.printString("StepInto", StringRef("Always"));
-          else if (LI.isNeverStepInto())
-            P.printString("StepInto", StringRef("Never"));
-          else
-            P.printNumber("LineNumberStart", LI.getStartLine());
-          P.printNumber("EndDelta", LI.getLineDelta());
-          P.printBoolean("IsStatement", LI.isStatement());
-        }
-        for (const auto &C : L.Columns) {
-          DictScope DDD(P, "Column");
-          P.printNumber("Start", C.StartColumn);
-          P.printNumber("End", C.EndColumn);
-        }
+      for (const auto &N : L.LineNumbers) {
+        DictScope DDD(P, "Line");
+        LineInfo LI(N.Flags);
+        P.printNumber("Offset", N.Offset);
+        if (LI.isAlwaysStepInto())
+          P.printString("StepInto", StringRef("Always"));
+        else if (LI.isNeverStepInto())
+          P.printString("StepInto", StringRef("Never"));
+        else
+          P.printNumber("LineNumberStart", LI.getStartLine());
+        P.printNumber("EndDelta", LI.getLineDelta());
+        P.printBoolean("IsStatement", LI.isStatement());
+      }
+      for (const auto &C : L.Columns) {
+        DictScope DDD(P, "Column");
+        P.printNumber("Start", C.StartColumn);
+        P.printNumber("End", C.EndColumn);
       }
     }
 
     return Error::success();
   }
 
-  Error handleFileChecksums() override {
-    if (!Checksums.hasValue() ||
-        !opts::checkModuleSubsection(opts::ModuleSubsection::FileChecksums))
+  Error visitFileChecksums(DebugChecksumsSubsectionRef &Checksums,
+                           const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::FileChecksums))
       return Error::success();
 
     DictScope DD(P, "FileChecksums");
-    for (const auto &CS : *Checksums) {
+    for (const auto &CS : Checksums) {
       DictScope DDD(P, "Checksum");
-      if (auto Result = getNameFromStringTable(CS.FileNameOffset))
+      if (auto Result = getNameFromStringTable(CS.FileNameOffset, State))
         P.printString("FileName", *Result);
       else
         return Result.takeError();
@@ -150,65 +146,60 @@ public:
     return Error::success();
   }
 
-  Error handleInlineeLines() override {
-    if (InlineeLines.empty() ||
-        !opts::checkModuleSubsection(opts::ModuleSubsection::InlineeLines))
+  Error visitInlineeLines(DebugInlineeLinesSubsectionRef &Inlinees,
+                          const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::InlineeLines))
       return Error::success();
 
     DictScope D(P, "InlineeLines");
-    for (const auto &IL : InlineeLines) {
-      P.printBoolean("HasExtraFiles", IL.hasExtraFiles());
-      ListScope LS(P, "Lines");
-      for (const auto &L : IL) {
-        DictScope DDD(P, "Inlinee");
-        if (auto EC = printFileName("FileName", L.Header->FileID))
-          return EC;
+    P.printBoolean("HasExtraFiles", Inlinees.hasExtraFiles());
+    ListScope LS(P, "Lines");
+    for (const auto &L : Inlinees) {
+      DictScope DDD(P, "Inlinee");
+      if (auto EC = printFileName("FileName", L.Header->FileID, State))
+        return EC;
 
-        if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee))
-          return EC;
-        P.printNumber("SourceLine", L.Header->SourceLineNum);
-        if (IL.hasExtraFiles()) {
-          ListScope DDDD(P, "ExtraFiles");
-          for (const auto &EF : L.ExtraFiles) {
-            if (auto EC = printFileName("File", EF))
-              return EC;
-          }
+      if (auto EC = dumpTypeRecord("Function", L.Header->Inlinee))
+        return EC;
+      P.printNumber("SourceLine", L.Header->SourceLineNum);
+      if (Inlinees.hasExtraFiles()) {
+        ListScope DDDD(P, "ExtraFiles");
+        for (const auto &EF : L.ExtraFiles) {
+          if (auto EC = printFileName("File", EF, State))
+            return EC;
         }
       }
     }
     return Error::success();
   }
 
-  Error handleCrossModuleExports() override {
-    if (CrossExports.empty() ||
-        !opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeExports))
+  Error visitCrossModuleExports(DebugCrossModuleExportsSubsectionRef &CSE,
+                                const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeExports))
       return Error::success();
 
-    for (const auto &M : CrossExports) {
-      DictScope D(P, "CrossModuleExports");
-      for (const auto &E : M) {
-        P.printHex("Local", E.Local);
-        P.printHex("Global", E.Global);
-      }
+    ListScope D(P, "CrossModuleExports");
+    for (const auto &M : CSE) {
+      DictScope D(P, "Export");
+      P.printHex("Local", M.Local);
+      P.printHex("Global", M.Global);
     }
     return Error::success();
   }
 
-  Error handleCrossModuleImports() override {
-    if (CrossImports.empty() ||
-        !opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeImports))
+  Error visitCrossModuleImports(DebugCrossModuleImportsSubsectionRef &CSI,
+                                const DebugSubsectionState &State) override {
+    if (!opts::checkModuleSubsection(opts::ModuleSubsection::CrossScopeImports))
       return Error::success();
 
-    for (const auto &M : CrossImports) {
-      DictScope D(P, "CrossModuleImports");
-      for (const auto &ImportGroup : M) {
-        auto Name =
-            getNameFromStringTable(ImportGroup.Header->ModuleNameOffset);
-        if (!Name)
-          return Name.takeError();
-        P.printString("Module", *Name);
-        P.printHexList("Imports", ImportGroup.Imports);
-      }
+    ListScope L(P, "CrossModuleImports");
+    for (const auto &M : CSI) {
+      DictScope D(P, "ModuleImport");
+      auto Name = getNameFromStringTable(M.Header->ModuleNameOffset, State);
+      if (!Name)
+        return Name.takeError();
+      P.printString("Module", *Name);
+      P.printHexList("Imports", M.Imports);
     }
     return Error::success();
   }
@@ -228,14 +219,31 @@ private:
     }
     return Error::success();
   }
-  Error printFileName(StringRef Label, uint32_t Offset) {
-    if (auto Result = getNameFromChecksumsBuffer(Offset)) {
+  Error printFileName(StringRef Label, uint32_t Offset,
+                      const DebugSubsectionState &State) {
+    if (auto Result = getNameFromChecksumsBuffer(Offset, State)) {
       P.printString(Label, *Result);
       return Error::success();
     } else
       return Result.takeError();
   }
 
+  Expected<StringRef>
+  getNameFromStringTable(uint32_t Offset, const DebugSubsectionState &State) {
+    return State.strings().getString(Offset);
+  }
+
+  Expected<StringRef>
+  getNameFromChecksumsBuffer(uint32_t Offset,
+                             const DebugSubsectionState &State) {
+    auto Array = State.checksums().getArray();
+    auto ChecksumIter = Array.at(Offset);
+    if (ChecksumIter == Array.end())
+      return make_error<RawError>(raw_error_code::invalid_format);
+    const auto &Entry = *ChecksumIter;
+    return getNameFromStringTable(Entry.FileNameOffset, State);
+  }
+
   ScopedPrinter &P;
   LazyRandomTypeCollection &IPI;
 };
@@ -872,8 +880,16 @@ Error LLVMOutputStyle::dumpDbiStream() {
           if (!ExpectedTypes)
             return ExpectedTypes.takeError();
           auto &IpiItems = *ExpectedTypes;
-          C13RawVisitor V(P, File, IpiItems);
-          if (auto EC = codeview::visitDebugSubsections(ModS.subsections(), V))
+          auto ExpectedStrings = File.getStringTable();
+          if (!ExpectedStrings)
+            return joinErrors(
+                make_error<RawError>(raw_error_code::no_stream,
+                                     "Could not get string table!"),
+                std::move(ExpectedStrings.takeError()));
+
+          C13RawVisitor V(P, IpiItems);
+          if (auto EC = codeview::visitDebugSubsections(
+                  ModS.subsections(), V, ExpectedStrings->getStringTable()))
             return EC;
         }
       }
index 105b3ca..26891e6 100644 (file)
@@ -9,7 +9,6 @@
 
 #include "YAMLOutputStyle.h"
 
-#include "C13DebugFragmentVisitor.h"
 #include "PdbYaml.h"
 #include "llvm-pdbdump.h"