1 //===- CVSymbolVisitor.cpp --------------------------------------*- 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 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"
11 
12 #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
14 #include "llvm/DebugInfo/MSF/ByteStream.h"
15 
16 using namespace llvm;
17 using namespace llvm::codeview;
18 
19 template <typename T>
20 static Error takeObject(ArrayRef<uint8_t> &Data, const T *&Res) {
21   if (Data.size() < sizeof(*Res))
22     return llvm::make_error<CodeViewError>(cv_error_code::insufficient_buffer);
23   Res = reinterpret_cast<const T *>(Data.data());
24   Data = Data.drop_front(sizeof(*Res));
25   return Error::success();
26 }
27 
28 CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks)
29     : Callbacks(Callbacks) {}
30 
31 template <typename T>
32 static Error visitKnownRecord(CVSymbol &Record,
33                               SymbolVisitorCallbacks &Callbacks) {
34   SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.Type);
35   T KnownRecord(RK);
36   if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
37     return EC;
38   return Error::success();
39 }
40 
41 Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
42   if (auto EC = Callbacks.visitSymbolBegin(Record))
43     return EC;
44 
45   switch (Record.Type) {
46   default:
47     if (auto EC = Callbacks.visitUnknownSymbol(Record))
48       return EC;
49     break;
50 #define SYMBOL_RECORD(EnumName, EnumVal, Name)                                 \
51   case EnumName: {                                                             \
52     if (auto EC = visitKnownRecord<Name>(Record, Callbacks))                   \
53       return EC;                                                               \
54     break;                                                                     \
55   }
56 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)                \
57   SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
58 #include "llvm/DebugInfo/CodeView/CVSymbolTypes.def"
59   }
60 
61   if (auto EC = Callbacks.visitSymbolEnd(Record))
62     return EC;
63 
64   return Error::success();
65 }
66 
67 Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
68   for (auto I : Symbols) {
69     if (auto EC = visitSymbolRecord(I))
70       return EC;
71   }
72   return Error::success();
73 }
74