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