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 22namespace llvm { 23namespace codeview { 24class SymbolVisitorDelegate; 25class SymbolDeserializer : public SymbolVisitorCallbacks { 26 struct MappingInfo { 27 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 36public: 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 } 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 56 explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate, 57 CodeViewContainer Container) 58 : Delegate(Delegate), Container(Container) {} 59 60 Error visitSymbolBegin(CVSymbol &Record, uint32_t Offset) override { 61 return visitSymbolBegin(Record); 62 } 63 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 } 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 83private: 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