blob: b5479db97a1508dbe8fb199df6bf4c78d9ab7de7 [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- 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