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