1 //===- CVSymbolVisitor.cpp --------------------------------------*- 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 #include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h" 10 11 #include "llvm/DebugInfo/CodeView/CodeViewError.h" 12 #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h" 13 14 using namespace llvm; 15 using namespace llvm::codeview; 16 17 CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks) 18 : Callbacks(Callbacks) {} 19 20 template <typename T> 21 static Error visitKnownRecord(CVSymbol &Record, 22 SymbolVisitorCallbacks &Callbacks) { 23 SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.kind()); 24 T KnownRecord(RK); 25 if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord)) 26 return EC; 27 return Error::success(); 28 } 29 30 static Error finishVisitation(CVSymbol &Record, 31 SymbolVisitorCallbacks &Callbacks) { 32 switch (Record.kind()) { 33 default: 34 if (auto EC = Callbacks.visitUnknownSymbol(Record)) 35 return EC; 36 break; 37 #define SYMBOL_RECORD(EnumName, EnumVal, Name) \ 38 case EnumName: { \ 39 if (auto EC = visitKnownRecord<Name>(Record, Callbacks)) \ 40 return EC; \ 41 break; \ 42 } 43 #define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \ 44 SYMBOL_RECORD(EnumVal, EnumVal, AliasName) 45 #include "llvm/DebugInfo/CodeView/CodeViewSymbols.def" 46 } 47 48 if (auto EC = Callbacks.visitSymbolEnd(Record)) 49 return EC; 50 51 return Error::success(); 52 } 53 54 Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) { 55 if (auto EC = Callbacks.visitSymbolBegin(Record)) 56 return EC; 57 return finishVisitation(Record, Callbacks); 58 } 59 60 Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record, uint32_t Offset) { 61 if (auto EC = Callbacks.visitSymbolBegin(Record, Offset)) 62 return EC; 63 return finishVisitation(Record, Callbacks); 64 } 65 66 Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) { 67 for (auto I : Symbols) { 68 if (auto EC = visitSymbolRecord(I)) 69 return EC; 70 } 71 return Error::success(); 72 } 73 74 Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols, 75 uint32_t InitialOffset) { 76 for (auto I : Symbols) { 77 if (auto EC = visitSymbolRecord(I, InitialOffset + Symbols.skew())) 78 return EC; 79 InitialOffset += I.length(); 80 } 81 return Error::success(); 82 } 83