OSDN Git Service

Refactor Symbol visitor code.
authorZachary Turner <zturner@google.com>
Fri, 7 Oct 2016 21:34:46 +0000 (21:34 +0000)
committerZachary Turner <zturner@google.com>
Fri, 7 Oct 2016 21:34:46 +0000 (21:34 +0000)
Type visitor code had already been refactored previously to
decouple the visitor and the visitor callback interface.  This
was necessary for having the flexibility to visit in different
ways (for example, dumping to yaml, reading from yaml, dumping
to ScopedPrinter, etc).

This patch merely implements the same visitation pattern for
symbol records that has already been implemented for type records.

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

include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h
include/llvm/DebugInfo/CodeView/SymbolDeserializer.h [new file with mode: 0644]
include/llvm/DebugInfo/CodeView/SymbolDumper.h
include/llvm/DebugInfo/CodeView/SymbolRecord.h
include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h [new file with mode: 0644]
include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h [new file with mode: 0644]
lib/DebugInfo/CodeView/CMakeLists.txt
lib/DebugInfo/CodeView/CVSymbolVisitor.cpp [new file with mode: 0644]
lib/DebugInfo/CodeView/SymbolDumper.cpp
tools/llvm-pdbdump/LLVMOutputStyle.cpp
tools/llvm-readobj/COFFDumper.cpp

index 4dd911d..b2d3f5e 100644 (file)
 
 namespace llvm {
 namespace codeview {
+class SymbolVisitorCallbacks;
 
-template <typename Derived> class CVSymbolVisitor {
+class CVSymbolVisitor {
 public:
-  CVSymbolVisitor(SymbolVisitorDelegate *Delegate) : Delegate(Delegate) {}
+  CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks);
 
-  bool hadError() const { return HadError; }
-
-  template <typename T>
-  bool consumeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
-    if (Data.size() < sizeof(*Res)) {
-      HadError = true;
-      return false;
-    }
-    Res = reinterpret_cast<const T *>(Data.data());
-    Data = Data.drop_front(sizeof(*Res));
-    return true;
-  }
-
-/// Actions to take on known symbols. By default, they do nothing. Visit methods
-/// for member records take the FieldData by non-const reference and are
-/// expected to consume the trailing bytes used by the field.
-/// FIXME: Make the visitor interpret the trailing bytes so that clients don't
-/// need to.
-#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
-  void visit##Name(SymbolRecordKind Kind, Name &Record) {}
-#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "CVSymbolTypes.def"
-
-  void visitSymbolRecord(const CVRecord<SymbolKind> &Record) {
-    ArrayRef<uint8_t> Data = Record.content();
-    auto *DerivedThis = static_cast<Derived *>(this);
-    DerivedThis->visitSymbolBegin(Record.Type, Data);
-    uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
-    switch (Record.Type) {
-    default:
-      DerivedThis->visitUnknownSymbol(Record.Type, Data);
-      break;
-#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
-  case EnumName: {                                                             \
-    SymbolRecordKind RK = static_cast<SymbolRecordKind>(EnumName);             \
-    auto ExpectedResult = Name::deserialize(RK, RecordOffset, Data);           \
-    if (!ExpectedResult) {                                                     \
-      consumeError(ExpectedResult.takeError());                                \
-      return parseError();                                                     \
-    }                                                                          \
-    DerivedThis->visit##Name(Record.Type, *ExpectedResult);                    \
-    break;                                                                     \
-  }
-#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
-  SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
-#include "CVSymbolTypes.def"
-    }
-    DerivedThis->visitSymbolEnd(Record.Type, Record.content());
-  }
-
-  /// Visits the symbol records in Data. Sets the error flag on parse failures.
-  void visitSymbolStream(const CVSymbolArray &Symbols) {
-    for (const auto &I : Symbols) {
-      visitSymbolRecord(I);
-      if (hadError())
-        break;
-    }
-  }
-
-  /// Action to take on unknown symbols. By default, they are ignored.
-  void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data) {}
-
-  /// Paired begin/end actions for all symbols. Receives all record data,
-  /// including the fixed-length record prefix.
-  void visitSymbolBegin(SymbolKind Leaf, ArrayRef<uint8_t> RecordData) {}
-  void visitSymbolEnd(SymbolKind Leaf, ArrayRef<uint8_t> OriginalSymData) {}
-
-  /// Helper for returning from a void function when the stream is corrupted.
-  void parseError() { HadError = true; }
+  Error visitSymbolRecord(CVSymbol &Record);
+  Error visitSymbolStream(const CVSymbolArray &Symbols);
 
 private:
-  SymbolVisitorDelegate *Delegate;
-  /// Whether a symbol stream parsing error was encountered.
-  bool HadError = false;
+  SymbolVisitorCallbacks &Callbacks;
 };
 
 } // end namespace codeview
diff --git a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
new file mode 100644 (file)
index 0000000..ae50974
--- /dev/null
@@ -0,0 +1,60 @@
+//===- SymbolDeserializer.h -------------------------------------*- 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_SYMBOLDESERIALIZER_H
+#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDESERIALIZER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+class SymbolVisitorDelegate;
+class SymbolDeserializer : public SymbolVisitorCallbacks {
+public:
+  explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate)
+      : Delegate(Delegate) {}
+
+#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
+  Error visitKnownRecord(CVSymbol &CVR, Name &Record) override {               \
+    return defaultVisitKnownRecord(CVR, Record);                               \
+  }
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "CVSymbolTypes.def"
+
+protected:
+  template <typename T>
+  Error deserializeRecord(ArrayRef<uint8_t> &Data, SymbolKind Kind,
+                          T &Record) const {
+    uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
+    SymbolRecordKind RK = static_cast<SymbolRecordKind>(Kind);
+    auto ExpectedRecord = T::deserialize(RK, RecordOffset, Data);
+    if (!ExpectedRecord)
+      return ExpectedRecord.takeError();
+    Record = std::move(*ExpectedRecord);
+    return Error::success();
+  }
+
+private:
+  template <typename T>
+  Error defaultVisitKnownRecord(CVSymbol &CVR, T &Record) {
+    ArrayRef<uint8_t> RD = CVR.content();
+    if (auto EC = deserializeRecord(RD, CVR.Type, Record))
+      return EC;
+    return Error::success();
+  }
+
+  SymbolVisitorDelegate *Delegate;
+};
+}
+}
+
+#endif
index 648e40f..eb63f78 100644 (file)
@@ -35,11 +35,11 @@ public:
   /// and true otherwise.  This should be called in order, since the dumper
   /// maintains state about previous records which are necessary for cross
   /// type references.
-  bool dump(const CVRecord<SymbolKind> &Record);
+  Error dump(CVRecord<SymbolKind> &Record);
 
   /// Dumps the type records in Data. Returns false if there was a type stream
   /// parse error, and true otherwise.
-  bool dump(const CVSymbolArray &Symbols);
+  Error dump(const CVSymbolArray &Symbols);
 
 private:
   ScopedPrinter &W;
index afa6f24..4eecda0 100644 (file)
@@ -56,6 +56,7 @@ public:
                    // Name: The null-terminated name follows.
   };
 
+  explicit ProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ProcSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
           StringRef Name)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
@@ -95,6 +96,7 @@ public:
                  // Variant portion of thunk
   };
 
+  explicit Thunk32Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
              StringRef Name, ArrayRef<uint8_t> VariantData)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name),
@@ -130,6 +132,7 @@ public:
     ulittle16_t TargetSection;
   };
 
+  explicit TrampolineSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   TrampolineSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H) {}
 
@@ -160,6 +163,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit SectionSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
              StringRef Name)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
@@ -192,6 +196,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit CoffGroupSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *H,
                StringRef Name)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*H), Name(Name) {
@@ -215,6 +220,7 @@ public:
 
 class ScopeEndSym : public SymbolRecord {
 public:
+  explicit ScopeEndSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
       : SymbolRecord(Kind), RecordOffset(RecordOffset) {}
 
@@ -232,6 +238,7 @@ public:
     ulittle32_t Count;
   };
 
+  explicit CallerSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   CallerSym(SymbolRecordKind Kind, uint32_t RecordOffset, const Hdr *Header,
             ArrayRef<TypeIndex> Indices)
       : SymbolRecord(Kind), RecordOffset(RecordOffset), Header(*Header),
@@ -441,6 +448,7 @@ public:
     // BinaryAnnotations
   };
 
+  explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   InlineSiteSym(uint32_t RecordOffset, const Hdr *H,
                 ArrayRef<uint8_t> Annotations)
       : SymbolRecord(SymbolRecordKind::InlineSiteSym),
@@ -478,6 +486,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit PublicSym32(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   PublicSym32(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::PublicSym32), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -506,6 +515,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   RegisterSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::RegisterSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -535,6 +545,7 @@ public:
                            // Name:  The null-terminated name follows.
   };
 
+  explicit ProcRefSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ProcRefSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -563,6 +574,7 @@ public:
                        // Name: The null-terminated name follows.
   };
 
+  explicit LocalSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   LocalSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -604,6 +616,7 @@ public:
     // LocalVariableAddrGap Gaps[];
   };
 
+  explicit DefRangeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   DefRangeSym(uint32_t RecordOffset, const Hdr *H,
               ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeSym), RecordOffset(RecordOffset),
@@ -637,6 +650,7 @@ public:
     LocalVariableAddrRange Range;
     // LocalVariableAddrGap Gaps[];
   };
+  explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   DefRangeSubfieldSym(uint32_t RecordOffset, const Hdr *H,
                       ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
@@ -671,6 +685,7 @@ public:
     // LocalVariableAddrGap Gaps[];
   };
 
+  explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   DefRangeRegisterSym(uint32_t RecordOffset, const Hdr *H,
                       ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
@@ -715,6 +730,8 @@ public:
     // LocalVariableAddrGap Gaps[];
   };
 
+  explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
+      : SymbolRecord(Kind) {}
   DefRangeSubfieldRegisterSym(uint32_t RecordOffset, const Hdr *H,
                               ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
@@ -759,6 +776,8 @@ public:
     // LocalVariableAddrGap Gaps[];
   };
 
+  explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
+      : SymbolRecord(Kind) {}
   DefRangeFramePointerRelSym(uint32_t RecordOffset, const Hdr *H,
                              ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
@@ -794,6 +813,7 @@ public:
     // LocalVariableAddrGap Gaps[];
   };
 
+  explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   DefRangeRegisterRelSym(uint32_t RecordOffset, const Hdr *H,
                          ArrayRef<LocalVariableAddrGap> Gaps)
       : SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
@@ -848,6 +868,8 @@ public:
     little32_t Offset; // Offset from the frame pointer register
   };
 
+  explicit DefRangeFramePointerRelFullScopeSym(SymbolRecordKind Kind)
+      : SymbolRecord(Kind) {}
   DefRangeFramePointerRelFullScopeSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -877,6 +899,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit BlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   BlockSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::BlockSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -910,6 +933,7 @@ public:
                    // Name: The null-terminated name follows.
   };
 
+  explicit LabelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   LabelSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::LabelSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -941,6 +965,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ObjNameSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -968,6 +993,7 @@ public:
     // Sequence of zero terminated strings.
   };
 
+  explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   EnvBlockSym(uint32_t RecordOffset, const Hdr *H,
               const std::vector<StringRef> &Fields)
       : SymbolRecord(SymbolRecordKind::EnvBlockSym), RecordOffset(RecordOffset),
@@ -997,6 +1023,7 @@ public:
                        // Name: The null-terminated name follows.
   };
 
+  explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ExportSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -1026,6 +1053,7 @@ public:
                                    // Name: The null-terminated name follows.
   };
 
+  explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   FileStaticSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::FileStaticSym),
         RecordOffset(RecordOffset), Header(*H), Name(Name) {}
@@ -1062,6 +1090,7 @@ public:
     // Optional block of zero terminated strings terminated with a double zero.
   };
 
+  explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   Compile2Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
       : SymbolRecord(SymbolRecordKind::Compile2Sym), RecordOffset(RecordOffset),
         Header(*H), Version(Version) {}
@@ -1099,6 +1128,7 @@ public:
     // VersionString: The null-terminated version string follows.
   };
 
+  explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   Compile3Sym(uint32_t RecordOffset, const Hdr *H, StringRef Version)
       : SymbolRecord(SymbolRecordKind::Compile3Sym), RecordOffset(RecordOffset),
         Header(*H), Version(Version) {}
@@ -1131,6 +1161,7 @@ public:
     ulittle32_t Flags;
   };
 
+  explicit FrameProcSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   FrameProcSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::FrameProcSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -1158,6 +1189,7 @@ public:
     TypeIndex Type;
   };
 
+  explicit CallSiteInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   CallSiteInfoSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::CallSiteInfoSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -1189,6 +1221,7 @@ public:
     TypeIndex Type;
   };
 
+  explicit HeapAllocationSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   HeapAllocationSiteSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::HeapAllocationSiteSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -1220,6 +1253,7 @@ public:
     uint8_t Flags;
   };
 
+  explicit FrameCookieSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   FrameCookieSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::FrameCookieSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -1249,6 +1283,7 @@ public:
                     // Name: The null-terminated name follows.
   };
 
+  explicit UDTSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   UDTSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::UDTSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -1275,6 +1310,7 @@ public:
     ulittle32_t BuildId;
   };
 
+  explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   BuildInfoSym(uint32_t RecordOffset, const Hdr *H)
       : SymbolRecord(SymbolRecordKind::BuildInfoSym),
         RecordOffset(RecordOffset), Header(*H) {}
@@ -1301,6 +1337,7 @@ public:
                        // Name: The null-terminated name follows.
   };
 
+  explicit BPRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   BPRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::BPRelativeSym),
         RecordOffset(RecordOffset), Header(*H), Name(Name) {}
@@ -1330,6 +1367,7 @@ public:
                           // Name: The null-terminated name follows.
   };
 
+  explicit RegRelativeSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   RegRelativeSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::RegRelativeSym),
         RecordOffset(RecordOffset), Header(*H), Name(Name) {}
@@ -1358,6 +1396,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ConstantSym(uint32_t RecordOffset, const Hdr *H, const APSInt &Value,
               StringRef Name)
       : SymbolRecord(SymbolRecordKind::ConstantSym), RecordOffset(RecordOffset),
@@ -1390,6 +1429,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   DataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset),
         Header(*H), Name(Name) {}
@@ -1423,6 +1463,7 @@ public:
     // Name: The null-terminated name follows.
   };
 
+  explicit ThreadLocalDataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
   ThreadLocalDataSym(uint32_t RecordOffset, const Hdr *H, StringRef Name)
       : SymbolRecord(SymbolRecordKind::ThreadLocalDataSym),
         RecordOffset(RecordOffset), Header(*H), Name(Name) {}
diff --git a/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h b/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h
new file mode 100644 (file)
index 0000000..ef34bcf
--- /dev/null
@@ -0,0 +1,69 @@
+//===- SymbolVisitorCallbackPipeline.h ------------------------ *- 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_SYMBOLVISITORCALLBACKPIPELINE_H
+#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKPIPELINE_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+class SymbolVisitorCallbackPipeline : public SymbolVisitorCallbacks {
+public:
+  SymbolVisitorCallbackPipeline() {}
+
+  virtual Error visitUnknownSymbol(CVSymbol &Record) override {
+    for (auto Visitor : Pipeline) {
+      if (auto EC = Visitor->visitUnknownSymbol(Record))
+        return EC;
+    }
+    return Error::success();
+  }
+
+  virtual Error visitSymbolBegin(CVSymbol &Record) override {
+    for (auto Visitor : Pipeline) {
+      if (auto EC = Visitor->visitSymbolBegin(Record))
+        return EC;
+    }
+    return Error::success();
+  }
+  virtual Error visitSymbolEnd(CVSymbol &Record) override {
+    for (auto Visitor : Pipeline) {
+      if (auto EC = Visitor->visitSymbolEnd(Record))
+        return EC;
+    }
+    return Error::success();
+  }
+
+  void addCallbackToPipeline(SymbolVisitorCallbacks &Callbacks) {
+    Pipeline.push_back(&Callbacks);
+  }
+
+#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
+  Error visitKnownRecord(CVSymbol &CVR, Name &Record) override {               \
+    for (auto Visitor : Pipeline) {                                            \
+      if (auto EC = Visitor->visitKnownRecord(CVR, Record))                    \
+        return EC;                                                             \
+    }                                                                          \
+    return Error::success();                                                   \
+  }
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
+
+private:
+  std::vector<SymbolVisitorCallbacks *> Pipeline;
+};
+}
+}
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h b/include/llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h
new file mode 100644 (file)
index 0000000..9c0df11
--- /dev/null
@@ -0,0 +1,49 @@
+//===- SymbolVisitorCallbacks.h ---------------------------------*- 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_SYMBOLVISITORCALLBACKS_H
+#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLVISITORCALLBACKS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace codeview {
+class SymbolVisitorCallbacks {
+  friend class CVSymbolVisitor;
+
+public:
+  virtual ~SymbolVisitorCallbacks() {}
+
+  /// Action to take on unknown symbols. By default, they are ignored.
+  virtual Error visitUnknownSymbol(CVSymbol &Record) {
+    return Error::success();
+  }
+
+  /// Paired begin/end actions for all symbols. Receives all record data,
+  /// including the fixed-length record prefix.  visitSymbolBegin() should
+  /// return
+  /// the type of the Symbol, or an error if it cannot be determined.
+  virtual Error visitSymbolBegin(CVSymbol &Record) { return Error::success(); }
+  virtual Error visitSymbolEnd(CVSymbol &Record) { return Error::success(); }
+
+#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
+  virtual Error visitKnownRecord(CVSymbol &CVR, Name &Record) {                \
+    return Error::success();                                                   \
+  }
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
+#include "CVSymbolTypes.def"
+};
+}
+}
+
+#endif
index d8c2195..a070080 100644 (file)
@@ -1,5 +1,6 @@
 add_llvm_library(LLVMDebugInfoCodeView
   CodeViewError.cpp
+  CVSymbolVisitor.cpp
   CVTypeVisitor.cpp
   EnumTables.cpp
   FieldListRecordBuilder.cpp
diff --git a/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp b/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
new file mode 100644 (file)
index 0000000..75cfd0d
--- /dev/null
@@ -0,0 +1,73 @@
+//===- CVSymbolVisitor.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
+
+#include "llvm/DebugInfo/CodeView/CodeViewError.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
+#include "llvm/DebugInfo/MSF/ByteStream.h"
+
+using namespace llvm;
+using namespace llvm::codeview;
+
+template <typename T>
+static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
+  if (Data.size() < sizeof(*Res))
+    return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
+  Res = reinterpret_cast<const T *>(Data.data());
+  Data = Data.drop_front(sizeof(*Res));
+  return Error::success();
+}
+
+CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks)
+    : Callbacks(Callbacks) {}
+
+template <typename T>
+static Error visitKnownRecord(CVSymbol &Record,
+                              SymbolVisitorCallbacks &Callbacks) {
+  SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.Type);
+  T KnownRecord(RK);
+  if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
+    return EC;
+  return Error::success();
+}
+
+Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
+  if (auto EC = Callbacks.visitSymbolBegin(Record))
+    return EC;
+
+  switch (Record.Type) {
+  default:
+    if (auto EC = Callbacks.visitUnknownSymbol(Record))
+      return EC;
+    break;
+#define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
+  case EnumName: {                                                             \
+    if (auto EC = visitKnownRecord<Name>(Record, Callbacks))                   \
+      return EC;                                                               \
+    break;                                                                     \
+  }
+#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
+  SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
+#include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
+  }
+
+  if (auto EC = Callbacks.visitSymbolEnd(Record))
+    return EC;
+
+  return Error::success();
+}
+
+Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
+  for (auto I : Symbols) {
+    if (auto EC = visitSymbolRecord(I))
+      return EC;
+  }
+  return Error::success();
+}
index 6763c3d..19a2552 100644 (file)
 #include "llvm/ADT/SmallString.h"
 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
 #include "llvm/DebugInfo/CodeView/EnumTables.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbackPipeline.h"
+#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
 #include "llvm/DebugInfo/CodeView/TypeDumper.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/ScopedPrinter.h"
 
 #include <system_error>
@@ -26,22 +30,22 @@ using namespace llvm::codeview;
 namespace {
 /// Use this private dumper implementation to keep implementation details about
 /// the visitor out of SymbolDumper.h.
-class CVSymbolDumperImpl : public CVSymbolVisitor<CVSymbolDumperImpl> {
+class CVSymbolDumperImpl : public SymbolVisitorCallbacks {
 public:
   CVSymbolDumperImpl(CVTypeDumper &CVTD, SymbolDumpDelegate *ObjDelegate,
                      ScopedPrinter &W, bool PrintRecordBytes)
-      : CVSymbolVisitor(ObjDelegate), CVTD(CVTD), ObjDelegate(ObjDelegate),
-        W(W), PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
+      : CVTD(CVTD), ObjDelegate(ObjDelegate), W(W),
+        PrintRecordBytes(PrintRecordBytes), InFunctionScope(false) {}
 
 /// CVSymbolVisitor overrides.
 #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
-  void visit##Name(SymbolKind Kind, Name &Record);
+  Error visitKnownRecord(CVSymbol &CVR, Name &Record) override;
 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
 #include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
 
-  void visitSymbolBegin(SymbolKind Kind, ArrayRef<uint8_t> Data);
-  void visitSymbolEnd(SymbolKind Kind, ArrayRef<uint8_t> OriginalSymData);
-  void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data);
+  Error visitSymbolBegin(CVSymbol &Record) override;
+  Error visitSymbolEnd(CVSymbol &Record) override;
+  Error visitUnknownSymbol(CVSymbol &Record) override;
 
 private:
   void printLocalVariableAddrRange(const LocalVariableAddrRange &Range,
@@ -76,16 +80,17 @@ void CVSymbolDumperImpl::printLocalVariableAddrGap(
   }
 }
 
-void CVSymbolDumperImpl::visitSymbolBegin(SymbolKind Kind,
-                                          ArrayRef<uint8_t> Data) {}
+Error CVSymbolDumperImpl::visitSymbolBegin(CVSymbol &CVR) {
+  return Error::success();
+}
 
-void CVSymbolDumperImpl::visitSymbolEnd(SymbolKind Kind,
-                                        ArrayRef<uint8_t> OriginalSymData) {
+Error CVSymbolDumperImpl::visitSymbolEnd(CVSymbol &CVR) {
   if (PrintRecordBytes && ObjDelegate)
-    ObjDelegate->printBinaryBlockWithRelocs("SymData", OriginalSymData);
+    ObjDelegate->printBinaryBlockWithRelocs("SymData", CVR.content());
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
   DictScope S(W, "BlockStart");
 
   StringRef LinkageName;
@@ -99,9 +104,10 @@ void CVSymbolDumperImpl::visitBlockSym(SymbolKind Kind, BlockSym &Block) {
   W.printHex("Segment", Block.Header.Segment);
   W.printString("BlockName", Block.Name);
   W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
   DictScope S(W, "Thunk32");
   W.printNumber("Parent", Thunk.Header.Parent);
   W.printNumber("End", Thunk.Header.End);
@@ -110,10 +116,11 @@ void CVSymbolDumperImpl::visitThunk32Sym(SymbolKind Kind, Thunk32Sym &Thunk) {
   W.printNumber("Seg", Thunk.Header.Seg);
   W.printNumber("Len", Thunk.Header.Len);
   W.printEnum("Ordinal", Thunk.Header.Ord, getThunkOrdinalNames());
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind,
-                                            TrampolineSym &Tramp) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           TrampolineSym &Tramp) {
   DictScope S(W, "Trampoline");
   W.printEnum("Type", Tramp.Header.Type, getTrampolineNames());
   W.printNumber("Size", Tramp.Header.Size);
@@ -121,9 +128,10 @@ void CVSymbolDumperImpl::visitTrampolineSym(SymbolKind Kind,
   W.printNumber("TargetOff", Tramp.Header.TargetOff);
   W.printNumber("ThunkSection", Tramp.Header.ThunkSection);
   W.printNumber("TargetSection", Tramp.Header.TargetSection);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, SectionSym &Section) {
   DictScope S(W, "Section");
   W.printNumber("SectionNumber", Section.Header.SectionNumber);
   W.printNumber("Alignment", Section.Header.Alignment);
@@ -135,9 +143,10 @@ void CVSymbolDumperImpl::visitSectionSym(SymbolKind Kind, SectionSym &Section) {
                COFF::SectionCharacteristics(0x00F00000));
 
   W.printString("Name", Section.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
                                            CoffGroupSym &CoffGroup) {
   DictScope S(W, "COFF Group");
   W.printNumber("Size", CoffGroup.Header.Size);
@@ -147,26 +156,29 @@ void CVSymbolDumperImpl::visitCoffGroupSym(SymbolKind Kind,
   W.printNumber("Offset", CoffGroup.Header.Offset);
   W.printNumber("Segment", CoffGroup.Header.Segment);
   W.printString("Name", CoffGroup.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitBPRelativeSym(SymbolKind Kind,
-                                            BPRelativeSym &BPRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           BPRelativeSym &BPRel) {
   DictScope S(W, "BPRelativeSym");
 
   W.printNumber("Offset", BPRel.Header.Offset);
   CVTD.printTypeIndex("Type", BPRel.Header.Type);
   W.printString("VarName", BPRel.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitBuildInfoSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
                                            BuildInfoSym &BuildInfo) {
   DictScope S(W, "BuildInfo");
 
   W.printNumber("BuildId", BuildInfo.Header.BuildId);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind,
-                                              CallSiteInfoSym &CallSiteInfo) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           CallSiteInfoSym &CallSiteInfo) {
   DictScope S(W, "CallSiteInfo");
 
   StringRef LinkageName;
@@ -180,10 +192,11 @@ void CVSymbolDumperImpl::visitCallSiteInfoSym(SymbolKind Kind,
   CVTD.printTypeIndex("Type", CallSiteInfo.Header.Type);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind,
-                                          EnvBlockSym &EnvBlock) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           EnvBlockSym &EnvBlock) {
   DictScope S(W, "EnvBlock");
 
   W.printNumber("Reserved", EnvBlock.Header.Reserved);
@@ -191,26 +204,29 @@ void CVSymbolDumperImpl::visitEnvBlockSym(SymbolKind Kind,
   for (auto Entry : EnvBlock.Fields) {
     W.printString(Entry);
   }
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitFileStaticSym(SymbolKind Kind,
-                                            FileStaticSym &FileStatic) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           FileStaticSym &FileStatic) {
   DictScope S(W, "FileStatic");
   W.printNumber("Index", FileStatic.Header.Index);
   W.printNumber("ModFilenameOffset", FileStatic.Header.ModFilenameOffset);
   W.printFlags("Flags", uint16_t(FileStatic.Header.Flags), getLocalFlagNames());
   W.printString("Name", FileStatic.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitExportSym(SymbolKind Kind, ExportSym &Export) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
   DictScope S(W, "Export");
   W.printNumber("Ordinal", Export.Header.Ordinal);
   W.printFlags("Flags", Export.Header.Flags, getExportSymFlagNames());
   W.printString("Name", Export.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind,
-                                          Compile2Sym &Compile2) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           Compile2Sym &Compile2) {
   DictScope S(W, "CompilerFlags2");
 
   W.printEnum("Language", Compile2.Header.getLanguage(),
@@ -235,10 +251,11 @@ void CVSymbolDumperImpl::visitCompile2Sym(SymbolKind Kind,
   W.printString("FrontendVersion", FrontendVersion);
   W.printString("BackendVersion", BackendVersion);
   W.printString("VersionName", Compile2.Version);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind,
-                                          Compile3Sym &Compile3) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           Compile3Sym &Compile3) {
   DictScope S(W, "CompilerFlags3");
 
   W.printEnum("Language", Compile3.Header.getLanguage(),
@@ -265,21 +282,23 @@ void CVSymbolDumperImpl::visitCompile3Sym(SymbolKind Kind,
   W.printString("FrontendVersion", FrontendVersion);
   W.printString("BackendVersion", BackendVersion);
   W.printString("VersionName", Compile3.Version);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitConstantSym(SymbolKind Kind,
-                                          ConstantSym &Constant) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           ConstantSym &Constant) {
   DictScope S(W, "Constant");
 
   CVTD.printTypeIndex("Type", Constant.Header.Type);
   W.printNumber("Value", Constant.Value);
   W.printString("Name", Constant.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
   DictScope S(W, "DataSym");
 
-  W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
+  W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
   StringRef LinkageName;
   if (ObjDelegate) {
     ObjDelegate->printRelocatedField("DataOffset", Data.getRelocationOffset(),
@@ -289,27 +308,30 @@ void CVSymbolDumperImpl::visitDataSym(SymbolKind Kind, DataSym &Data) {
   W.printString("DisplayName", Data.Name);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeFramePointerRelFullScopeSym(
-    SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR,
     DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
   DictScope S(W, "DefRangeFramePointerRelFullScope");
   W.printNumber("Offset", DefRangeFramePointerRelFullScope.Header.Offset);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeFramePointerRelSym(
-    SymbolKind Kind, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
   DictScope S(W, "DefRangeFramePointerRel");
 
   W.printNumber("Offset", DefRangeFramePointerRel.Header.Offset);
   printLocalVariableAddrRange(DefRangeFramePointerRel.Header.Range,
                               DefRangeFramePointerRel.getRelocationOffset());
   printLocalVariableAddrGap(DefRangeFramePointerRel.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
-    SymbolKind Kind, DefRangeRegisterRelSym &DefRangeRegisterRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
   DictScope S(W, "DefRangeRegisterRel");
 
   W.printNumber("BaseRegister", DefRangeRegisterRel.Header.BaseRegister);
@@ -321,10 +343,11 @@ void CVSymbolDumperImpl::visitDefRangeRegisterRelSym(
   printLocalVariableAddrRange(DefRangeRegisterRel.Header.Range,
                               DefRangeRegisterRel.getRelocationOffset());
   printLocalVariableAddrGap(DefRangeRegisterRel.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeRegisterSym(
-    SymbolKind Kind, DefRangeRegisterSym &DefRangeRegister) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
   DictScope S(W, "DefRangeRegister");
 
   W.printNumber("Register", DefRangeRegister.Header.Register);
@@ -332,10 +355,11 @@ void CVSymbolDumperImpl::visitDefRangeRegisterSym(
   printLocalVariableAddrRange(DefRangeRegister.Header.Range,
                               DefRangeRegister.getRelocationOffset());
   printLocalVariableAddrGap(DefRangeRegister.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
-    SymbolKind Kind, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
   DictScope S(W, "DefRangeSubfieldRegister");
 
   W.printNumber("Register", DefRangeSubfieldRegister.Header.Register);
@@ -345,17 +369,19 @@ void CVSymbolDumperImpl::visitDefRangeSubfieldRegisterSym(
   printLocalVariableAddrRange(DefRangeSubfieldRegister.Header.Range,
                               DefRangeSubfieldRegister.getRelocationOffset());
   printLocalVariableAddrGap(DefRangeSubfieldRegister.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
-    SymbolKind Kind, DefRangeSubfieldSym &DefRangeSubfield) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
   DictScope S(W, "DefRangeSubfield");
 
   if (ObjDelegate) {
     StringRef StringTable = ObjDelegate->getStringTable();
     auto ProgramStringTableOffset = DefRangeSubfield.Header.Program;
     if (ProgramStringTableOffset >= StringTable.size())
-      return parseError();
+      return llvm::make_error<CodeViewError>(
+          "String table offset outside of bounds of String Table!");
     StringRef Program =
         StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
     W.printString("Program", Program);
@@ -364,17 +390,19 @@ void CVSymbolDumperImpl::visitDefRangeSubfieldSym(
   printLocalVariableAddrRange(DefRangeSubfield.Header.Range,
                               DefRangeSubfield.getRelocationOffset());
   printLocalVariableAddrGap(DefRangeSubfield.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
-                                          DefRangeSym &DefRange) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           DefRangeSym &DefRange) {
   DictScope S(W, "DefRange");
 
   if (ObjDelegate) {
     StringRef StringTable = ObjDelegate->getStringTable();
     auto ProgramStringTableOffset = DefRange.Header.Program;
     if (ProgramStringTableOffset >= StringTable.size())
-      return parseError();
+      return llvm::make_error<CodeViewError>(
+          "String table offset outside of bounds of String Table!");
     StringRef Program =
         StringTable.drop_front(ProgramStringTableOffset).split('\0').first;
     W.printString("Program", Program);
@@ -382,10 +410,11 @@ void CVSymbolDumperImpl::visitDefRangeSym(SymbolKind Kind,
   printLocalVariableAddrRange(DefRange.Header.Range,
                               DefRange.getRelocationOffset());
   printLocalVariableAddrGap(DefRange.Gaps);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
-                                             FrameCookieSym &FrameCookie) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           FrameCookieSym &FrameCookie) {
   DictScope S(W, "FrameCookie");
 
   StringRef LinkageName;
@@ -398,9 +427,10 @@ void CVSymbolDumperImpl::visitFrameCookieSym(SymbolKind Kind,
   W.printEnum("CookieKind", uint16_t(FrameCookie.Header.CookieKind),
               getFrameCookieKindNames());
   W.printHex("Flags", FrameCookie.Header.Flags);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
                                            FrameProcSym &FrameProc) {
   DictScope S(W, "FrameProc");
 
@@ -414,10 +444,11 @@ void CVSymbolDumperImpl::visitFrameProcSym(SymbolKind Kind,
   W.printHex("SectionIdOfExceptionHandler",
              FrameProc.Header.SectionIdOfExceptionHandler);
   W.printFlags("Flags", FrameProc.Header.Flags, getFrameProcSymFlagNames());
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
-    SymbolKind Kind, HeapAllocationSiteSym &HeapAllocSite) {
+Error CVSymbolDumperImpl::visitKnownRecord(
+    CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
   DictScope S(W, "HeapAllocationSite");
 
   StringRef LinkageName;
@@ -431,10 +462,11 @@ void CVSymbolDumperImpl::visitHeapAllocationSiteSym(
   CVTD.printTypeIndex("Type", HeapAllocSite.Header.Type);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
-                                            InlineSiteSym &InlineSite) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           InlineSiteSym &InlineSite) {
   DictScope S(W, "InlineSite");
 
   W.printHex("PtrParent", InlineSite.Header.PtrParent);
@@ -445,7 +477,8 @@ void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
   for (auto &Annotation : InlineSite.annotations()) {
     switch (Annotation.OpCode) {
     case BinaryAnnotationsOpCode::Invalid:
-      return parseError();
+      return llvm::make_error<CodeViewError>(
+          "Invalid binary annotation opcode!");
     case BinaryAnnotationsOpCode::CodeOffset:
     case BinaryAnnotationsOpCode::ChangeCodeOffset:
     case BinaryAnnotationsOpCode::ChangeCodeLength:
@@ -486,34 +519,37 @@ void CVSymbolDumperImpl::visitInlineSiteSym(SymbolKind Kind,
     }
     }
   }
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitRegisterSym(SymbolKind Kind,
-                                          RegisterSym &Register) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           RegisterSym &Register) {
   DictScope S(W, "RegisterSym");
   W.printNumber("Type", Register.Header.Index);
   W.printEnum("Seg", uint16_t(Register.Header.Register), getRegisterNames());
   W.printString("Name", Register.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitPublicSym32(SymbolKind Kind,
-                                          PublicSym32 &Public) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, PublicSym32 &Public) {
   DictScope S(W, "PublicSym");
   W.printNumber("Type", Public.Header.Index);
   W.printNumber("Seg", Public.Header.Seg);
   W.printNumber("Off", Public.Header.Off);
   W.printString("Name", Public.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitProcRefSym(SymbolKind Kind, ProcRefSym &ProcRef) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcRefSym &ProcRef) {
   DictScope S(W, "ProcRef");
   W.printNumber("SumName", ProcRef.Header.SumName);
   W.printNumber("SymOffset", ProcRef.Header.SymOffset);
   W.printNumber("Mod", ProcRef.Header.Mod);
   W.printString("Name", ProcRef.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
   DictScope S(W, "Label");
 
   StringRef LinkageName;
@@ -527,33 +563,37 @@ void CVSymbolDumperImpl::visitLabelSym(SymbolKind Kind, LabelSym &Label) {
   W.printString("DisplayName", Label.Name);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitLocalSym(SymbolKind Kind, LocalSym &Local) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
   DictScope S(W, "Local");
 
   CVTD.printTypeIndex("Type", Local.Header.Type);
   W.printFlags("Flags", uint16_t(Local.Header.Flags), getLocalFlagNames());
   W.printString("VarName", Local.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitObjNameSym(SymbolKind Kind, ObjNameSym &ObjName) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ObjNameSym &ObjName) {
   DictScope S(W, "ObjectName");
 
   W.printHex("Signature", ObjName.Header.Signature);
   W.printString("ObjectName", ObjName.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
   DictScope S(W, "ProcStart");
 
   if (InFunctionScope)
-    return parseError();
+    return llvm::make_error<CodeViewError>(
+        "Visiting a ProcSym while inside function scope!");
 
   InFunctionScope = true;
 
   StringRef LinkageName;
-  W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
+  W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
   W.printHex("PtrParent", Proc.Header.PtrParent);
   W.printHex("PtrEnd", Proc.Header.PtrEnd);
   W.printHex("PtrNext", Proc.Header.PtrNext);
@@ -571,38 +611,42 @@ void CVSymbolDumperImpl::visitProcSym(SymbolKind Kind, ProcSym &Proc) {
   W.printString("DisplayName", Proc.Name);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitScopeEndSym(SymbolKind Kind,
-                                          ScopeEndSym &ScopeEnd) {
-  if (Kind == SymbolKind::S_END)
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           ScopeEndSym &ScopeEnd) {
+  if (CVR.kind() == SymbolKind::S_END)
     DictScope S(W, "BlockEnd");
-  else if (Kind == SymbolKind::S_PROC_ID_END)
+  else if (CVR.kind() == SymbolKind::S_PROC_ID_END)
     DictScope S(W, "ProcEnd");
-  else if (Kind == SymbolKind::S_INLINESITE_END)
+  else if (CVR.kind() == SymbolKind::S_INLINESITE_END)
     DictScope S(W, "InlineSiteEnd");
 
   InFunctionScope = false;
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitCallerSym(SymbolKind Kind, CallerSym &Caller) {
-  ListScope S(W, Kind == S_CALLEES ? "Callees" : "Callers");
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
+  ListScope S(W, CVR.kind() == S_CALLEES ? "Callees" : "Callers");
   for (auto FuncID : Caller.Indices)
     CVTD.printTypeIndex("FuncID", FuncID);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitRegRelativeSym(SymbolKind Kind,
-                                             RegRelativeSym &RegRel) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           RegRelativeSym &RegRel) {
   DictScope S(W, "RegRelativeSym");
 
   W.printHex("Offset", RegRel.Header.Offset);
   CVTD.printTypeIndex("Type", RegRel.Header.Type);
   W.printHex("Register", RegRel.Header.Register);
   W.printString("VarName", RegRel.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
-                                                 ThreadLocalDataSym &Data) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR,
+                                           ThreadLocalDataSym &Data) {
   DictScope S(W, "ThreadLocalDataSym");
 
   StringRef LinkageName;
@@ -614,29 +658,41 @@ void CVSymbolDumperImpl::visitThreadLocalDataSym(SymbolKind Kind,
   W.printString("DisplayName", Data.Name);
   if (!LinkageName.empty())
     W.printString("LinkageName", LinkageName);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitUDTSym(SymbolKind Kind, UDTSym &UDT) {
+Error CVSymbolDumperImpl::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
   DictScope S(W, "UDT");
   CVTD.printTypeIndex("Type", UDT.Header.Type);
   W.printString("UDTName", UDT.Name);
+  return Error::success();
 }
 
-void CVSymbolDumperImpl::visitUnknownSymbol(SymbolKind Kind,
-                                            ArrayRef<uint8_t> Data) {
+Error CVSymbolDumperImpl::visitUnknownSymbol(CVSymbol &CVR) {
   DictScope S(W, "UnknownSym");
-  W.printEnum("Kind", uint16_t(Kind), getSymbolTypeNames());
-  W.printNumber("Length", uint32_t(Data.size()));
+  W.printEnum("Kind", uint16_t(CVR.kind()), getSymbolTypeNames());
+  W.printNumber("Length", CVR.length());
+  return Error::success();
 }
 
-bool CVSymbolDumper::dump(const CVRecord<SymbolKind> &Record) {
+Error CVSymbolDumper::dump(CVRecord<SymbolKind> &Record) {
+  SymbolVisitorCallbackPipeline Pipeline;
+  SymbolDeserializer Deserializer(ObjDelegate.get());
   CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
-  Dumper.visitSymbolRecord(Record);
-  return !Dumper.hadError();
+
+  Pipeline.addCallbackToPipeline(Deserializer);
+  Pipeline.addCallbackToPipeline(Dumper);
+  CVSymbolVisitor Visitor(Pipeline);
+  return Visitor.visitSymbolRecord(Record);
 }
 
-bool CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
+Error CVSymbolDumper::dump(const CVSymbolArray &Symbols) {
+  SymbolVisitorCallbackPipeline Pipeline;
+  SymbolDeserializer Deserializer(ObjDelegate.get());
   CVSymbolDumperImpl Dumper(CVTD, ObjDelegate.get(), W, PrintRecordBytes);
-  Dumper.visitSymbolStream(Symbols);
-  return !Dumper.hadError();
+
+  Pipeline.addCallbackToPipeline(Deserializer);
+  Pipeline.addCallbackToPipeline(Dumper);
+  CVSymbolVisitor Visitor(Pipeline);
+  return Visitor.visitSymbolStream(Symbols);
 }
index 69438b3..db39dae 100644 (file)
@@ -598,11 +598,15 @@ Error LLVMOutputStyle::dumpDbiStream() {
           ListScope SS(P, "Symbols");
           codeview::CVSymbolDumper SD(P, Dumper, nullptr, false);
           bool HadError = false;
-          for (const auto &S : ModS.symbols(&HadError)) {
-            DictScope DD(P, "");
-
-            if (opts::raw::DumpModuleSyms)
-              SD.dump(S);
+          for (auto S : ModS.symbols(&HadError)) {
+            DictScope LL(P, "");
+            if (opts::raw::DumpModuleSyms) {
+              if (auto EC = SD.dump(S)) {
+                llvm::consumeError(std::move(EC));
+                HadError = true;
+                break;
+              }
+            }
             if (opts::raw::DumpSymRecordBytes)
               P.printBinaryBlock("Bytes", S.content());
           }
@@ -811,7 +815,10 @@ Error LLVMOutputStyle::dumpPublicsStream() {
   for (auto S : Publics->getSymbols(&HadError)) {
     DictScope DD(P, "");
 
-    SD.dump(S);
+    if (auto EC = SD.dump(S)) {
+      HadError = true;
+      break;
+    }
     if (opts::raw::DumpSymRecordBytes)
       P.printBinaryBlock("Bytes", S.content());
   }
index bf6a103..2b45d1d 100644 (file)
@@ -26,6 +26,7 @@
 #include "llvm/DebugInfo/CodeView/Line.h"
 #include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
 #include "llvm/DebugInfo/CodeView/RecordSerialization.h"
+#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
 #include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
 #include "llvm/DebugInfo/CodeView/SymbolDumper.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
@@ -965,9 +966,9 @@ void COFFDumper::printCodeViewSymbolsSubsection(StringRef Subsection,
     error(object_error::parse_failed);
   }
 
-  if (!CVSD.dump(Symbols)) {
+  if (auto EC = CVSD.dump(Symbols)) {
     W.flush();
-    error(object_error::parse_failed);
+    error(std::move(EC));
   }
   W.flush();
 }