]> granicus.if.org Git - llvm/commitdiff
[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 fbe39cb16f090aa51f517953c3cb5cc90bcdd6a6..ceb0054f4453a6cb529eaad2820256487a9c8153 100644 (file)
@@ -39,6 +39,7 @@ public:
   }
 
   Error initialize(BinaryStreamRef Contents);
+  Error initialize(BinaryStreamReader &Reader);
 
   Expected<StringRef> getString(uint32_t Offset) const;
 
index 6fa62441e0446055b06710883cbdf25eff72bbc3..db0bd56e6ecaadb92b0d134c7842a4f3e110319f 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 2e72242181b0aa14dfd3a47831f2f9d591febf8e..7b972a1a2770a9b6424d70950ec83041939aef2b 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 93fe4e1914b8377f8a687ec7807d19cc381a3441..ee769d3970f02b72a6fe5b6bd99ac13259b180c9 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 fc3d0ceaa15b304f7095bc896d4379a9c3b5929a..baf98d1b0831895c1c0fd39e1f278a409774a1bc 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 5b09158c3201d687ea94081dddb02281c4c4674e..d95def71068dea69cded95845a4e42e0ac6e985c 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 5266f215bcbd5dd72f5a5cbcd33829c70e365cf7..0a9c48ca1b26cc372c7777e1d8c5f88848f61e40 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 a1f54a3bff6a32f9c98cf89c56edfc4729fcfa58..020331e6550cc71e223dd044161c657de303a451 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 cd4645ec0ee8271a761413b07eeee0d625b32c2a..8e861e96c5df421883cb8f878df1afb868f8b5f9 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 105b3ca2a07fd45d9dd9ff8ecb4165465f4ddae2..26891e6b79d849867dfd27ae9fec00e224086a0c 100644 (file)
@@ -9,7 +9,6 @@
 
 #include "YAMLOutputStyle.h"
 
-#include "C13DebugFragmentVisitor.h"
 #include "PdbYaml.h"
 #include "llvm-pdbdump.h"