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