1 //===- SymbolDeserializer.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_SYMBOLDESERIALIZER_H 11 #define LLVM_DEBUGINFO_CODEVIEW_SYMBOLDESERIALIZER_H 12 13 #include "llvm/ADT/ArrayRef.h" 14 #include "llvm/DebugInfo/CodeView/SymbolRecord.h" 15 #include "llvm/DebugInfo/CodeView/SymbolRecordMapping.h" 16 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" 17 #include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h" 18 #include "llvm/Support/BinaryByteStream.h" 19 #include "llvm/Support/BinaryStreamReader.h" 20 #include "llvm/Support/Error.h" 21 22 namespace llvm { 23 namespace codeview { 24 class SymbolVisitorDelegate; 25 class SymbolDeserializer : public SymbolVisitorCallbacks { 26 struct MappingInfo { MappingInfoMappingInfo27 MappingInfo(ArrayRef<uint8_t> RecordData, CodeViewContainer Container) 28 : Stream(RecordData, llvm::support::little), Reader(Stream), 29 Mapping(Reader, Container) {} 30 31 BinaryByteStream Stream; 32 BinaryStreamReader Reader; 33 SymbolRecordMapping Mapping; 34 }; 35 36 public: deserializeAs(CVSymbol Symbol,T & Record)37 template <typename T> static Error deserializeAs(CVSymbol Symbol, T &Record) { 38 // If we're just deserializing one record, then don't worry about alignment 39 // as there's nothing that comes after. 40 SymbolDeserializer S(nullptr, CodeViewContainer::ObjectFile); 41 if (auto EC = S.visitSymbolBegin(Symbol)) 42 return EC; 43 if (auto EC = S.visitKnownRecord(Symbol, Record)) 44 return EC; 45 if (auto EC = S.visitSymbolEnd(Symbol)) 46 return EC; 47 return Error::success(); 48 } deserializeAs(CVSymbol Symbol)49 template <typename T> static Expected<T> deserializeAs(CVSymbol Symbol) { 50 T Record(Symbol.kind()); 51 if (auto EC = deserializeAs<T>(Symbol, Record)) 52 return std::move(EC); 53 return Record; 54 } 55 SymbolDeserializer(SymbolVisitorDelegate * Delegate,CodeViewContainer Container)56 explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate, 57 CodeViewContainer Container) 58 : Delegate(Delegate), Container(Container) {} 59 visitSymbolBegin(CVSymbol & Record,uint32_t Offset)60 Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override { 61 return visitSymbolBegin(Record); 62 } 63 visitSymbolBegin(CVSymbol & Record)64 Error visitSymbolBegin(CVSymbol &Record) override { 65 assert(!Mapping && "Already in a symbol mapping!"); 66 Mapping = llvm::make_unique<MappingInfo>(Record.content(), Container); 67 return Mapping->Mapping.visitSymbolBegin(Record); 68 } visitSymbolEnd(CVSymbol & Record)69 Error visitSymbolEnd(CVSymbol &Record) override { 70 assert(Mapping && "Not in a symbol mapping!"); 71 auto EC = Mapping->Mapping.visitSymbolEnd(Record); 72 Mapping.reset(); 73 return EC; 74 } 75 76 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ 77 Error visitKnownRecord(CVSymbol &CVR, Name &Record) override { \ 78 return visitKnownRecordImpl(CVR, Record); \ 79 } 80 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) 81 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 82 83 private: visitKnownRecordImpl(CVSymbol & CVR,T & Record)84 template <typename T> Error visitKnownRecordImpl(CVSymbol &CVR, T &Record) { 85 86 Record.RecordOffset = 87 Delegate ? Delegate->getRecordOffset(Mapping->Reader) : 0; 88 if (auto EC = Mapping->Mapping.visitKnownRecord(CVR, Record)) 89 return EC; 90 return Error::success(); 91 } 92 93 SymbolVisitorDelegate *Delegate; 94 CodeViewContainer Container; 95 std::unique_ptr<MappingInfo> Mapping; 96 }; 97 } 98 } 99 100 #endif 101