• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- CVSymbolVisitor.h ----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
11 #define LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
12 
13 #include "llvm/DebugInfo/CodeView/CVRecord.h"
14 #include "llvm/DebugInfo/CodeView/CodeView.h"
15 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
16 #include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h"
17 #include "llvm/Support/ErrorOr.h"
18 
19 namespace llvm {
20 namespace codeview {
21 
22 template <typename Derived> class CVSymbolVisitor {
23 public:
CVSymbolVisitor(SymbolVisitorDelegate * Delegate)24   CVSymbolVisitor(SymbolVisitorDelegate *Delegate) : Delegate(Delegate) {}
25 
hadError()26   bool hadError() const { return HadError; }
27 
28   template <typename T>
consumeObject(ArrayRef<uint8_t> & Data,const T * & Res)29   bool consumeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
30     if (Data.size() < sizeof(*Res)) {
31       HadError = true;
32       return false;
33     }
34     Res = reinterpret_cast<const T *>(Data.data());
35     Data = Data.drop_front(sizeof(*Res));
36     return true;
37   }
38 
39 /// Actions to take on known symbols. By default, they do nothing. Visit methods
40 /// for member records take the FieldData by non-const reference and are
41 /// expected to consume the trailing bytes used by the field.
42 /// FIXME: Make the visitor interpret the trailing bytes so that clients don't
43 /// need to.
44 #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
45   void visit##Name(SymbolRecordKind Kind, Name &Record) {}
46 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
47 #include "CVSymbolTypes.def"
48 
visitSymbolRecord(const CVRecord<SymbolKind> & Record)49   void visitSymbolRecord(const CVRecord<SymbolKind> &Record) {
50     ArrayRef<uint8_t> Data = Record.Data;
51     auto *DerivedThis = static_cast<Derived *>(this);
52     DerivedThis->visitSymbolBegin(Record.Type, Data);
53     uint32_t RecordOffset = Delegate ? Delegate->getRecordOffset(Data) : 0;
54     switch (Record.Type) {
55     default:
56       DerivedThis->visitUnknownSymbol(Record.Type, Data);
57       break;
58 #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
59   case EnumName: {                                                             \
60     SymbolRecordKind RK = static_cast<SymbolRecordKind>(EnumName);             \
61     auto Result = Name::deserialize(RK, RecordOffset, Data);                   \
62     if (Result.getError())                                                     \
63       return parseError();                                                     \
64     DerivedThis->visit##Name(Record.Type, *Result);                            \
65     break;                                                                     \
66   }
67 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
68   SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
69 #include "CVSymbolTypes.def"
70     }
71     DerivedThis->visitSymbolEnd(Record.Type, Record.Data);
72   }
73 
74   /// Visits the symbol records in Data. Sets the error flag on parse failures.
visitSymbolStream(const CVSymbolArray & Symbols)75   void visitSymbolStream(const CVSymbolArray &Symbols) {
76     for (const auto &I : Symbols) {
77       visitSymbolRecord(I);
78       if (hadError())
79         break;
80     }
81   }
82 
83   /// Action to take on unknown symbols. By default, they are ignored.
visitUnknownSymbol(SymbolKind Kind,ArrayRef<uint8_t> Data)84   void visitUnknownSymbol(SymbolKind Kind, ArrayRef<uint8_t> Data) {}
85 
86   /// Paired begin/end actions for all symbols. Receives all record data,
87   /// including the fixed-length record prefix.
visitSymbolBegin(SymbolKind Leaf,ArrayRef<uint8_t> RecordData)88   void visitSymbolBegin(SymbolKind Leaf, ArrayRef<uint8_t> RecordData) {}
visitSymbolEnd(SymbolKind Leaf,ArrayRef<uint8_t> OriginalSymData)89   void visitSymbolEnd(SymbolKind Leaf, ArrayRef<uint8_t> OriginalSymData) {}
90 
91   /// Helper for returning from a void function when the stream is corrupted.
parseError()92   void parseError() { HadError = true; }
93 
94 private:
95   SymbolVisitorDelegate *Delegate;
96   /// Whether a symbol stream parsing error was encountered.
97   bool HadError = false;
98 };
99 
100 } // end namespace codeview
101 } // end namespace llvm
102 
103 #endif // LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
104