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