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