Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
35271 views
//===- CVSymbolVisitor.cpp --------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DebugInfo/CodeView/CVSymbolVisitor.h"910#include "llvm/DebugInfo/CodeView/CodeView.h"11#include "llvm/DebugInfo/CodeView/SymbolRecord.h"12#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h"13#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"14#include "llvm/Support/BinaryStreamArray.h"15#include "llvm/Support/ErrorHandling.h"1617using namespace llvm;18using namespace llvm::codeview;1920CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks)21: Callbacks(Callbacks) {}2223template <typename T>24static Error visitKnownRecord(CVSymbol &Record,25SymbolVisitorCallbacks &Callbacks) {26SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.kind());27T KnownRecord(RK);28if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))29return EC;30return Error::success();31}3233static Error finishVisitation(CVSymbol &Record,34SymbolVisitorCallbacks &Callbacks) {35switch (Record.kind()) {36default:37if (auto EC = Callbacks.visitUnknownSymbol(Record))38return EC;39break;40#define SYMBOL_RECORD(EnumName, EnumVal, Name) \41case EnumName: { \42if (auto EC = visitKnownRecord<Name>(Record, Callbacks)) \43return EC; \44break; \45}46#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \47SYMBOL_RECORD(EnumVal, EnumVal, AliasName)48#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"49}5051if (auto EC = Callbacks.visitSymbolEnd(Record))52return EC;5354return Error::success();55}5657Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {58if (auto EC = Callbacks.visitSymbolBegin(Record))59return EC;60return finishVisitation(Record, Callbacks);61}6263Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record, uint32_t Offset) {64if (auto EC = Callbacks.visitSymbolBegin(Record, Offset))65return EC;66return finishVisitation(Record, Callbacks);67}6869Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {70for (auto I : Symbols) {71if (auto EC = visitSymbolRecord(I))72return EC;73}74return Error::success();75}7677Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols,78uint32_t InitialOffset) {79for (auto I : Symbols) {80if (auto EC = visitSymbolRecord(I, InitialOffset + Symbols.skew()))81return EC;82InitialOffset += I.length();83}84return Error::success();85}8687Error CVSymbolVisitor::visitSymbolStreamFiltered(const CVSymbolArray &Symbols,88const FilterOptions &Filter) {89if (!Filter.SymbolOffset)90return visitSymbolStream(Symbols);91uint32_t SymbolOffset = *Filter.SymbolOffset;92uint32_t ParentRecurseDepth = Filter.ParentRecursiveDepth.value_or(0);93uint32_t ChildrenRecurseDepth = Filter.ChildRecursiveDepth.value_or(0);94if (!Symbols.isOffsetValid(SymbolOffset))95return createStringError(inconvertibleErrorCode(), "Invalid symbol offset");96CVSymbol Sym = *Symbols.at(SymbolOffset);97uint32_t SymEndOffset =98symbolOpensScope(Sym.kind()) ? getScopeEndOffset(Sym) : 0;99100std::vector<uint32_t> ParentOffsets;101std::vector<uint32_t> ParentEndOffsets;102uint32_t ChildrenDepth = 0;103for (auto Begin = Symbols.begin(), End = Symbols.end(); Begin != End;104++Begin) {105uint32_t BeginOffset = Begin.offset();106CVSymbol BeginSym = *Begin;107if (BeginOffset < SymbolOffset) {108if (symbolOpensScope(Begin->kind())) {109uint32_t EndOffset = getScopeEndOffset(BeginSym);110if (SymbolOffset < EndOffset) {111ParentOffsets.push_back(BeginOffset);112ParentEndOffsets.push_back(EndOffset);113}114}115} else if (BeginOffset == SymbolOffset) {116// Found symbol at offset. Visit its parent up to ParentRecurseDepth.117if (ParentRecurseDepth >= ParentOffsets.size())118ParentRecurseDepth = ParentOffsets.size();119uint32_t StartIndex = ParentOffsets.size() - ParentRecurseDepth;120while (StartIndex < ParentOffsets.size()) {121if (!Symbols.isOffsetValid(ParentOffsets[StartIndex]))122break;123CVSymbol Parent = *Symbols.at(ParentOffsets[StartIndex]);124if (auto EC = visitSymbolRecord(Parent, ParentOffsets[StartIndex]))125return EC;126++StartIndex;127}128if (auto EC = visitSymbolRecord(Sym, SymbolOffset))129return EC;130} else if (BeginOffset <= SymEndOffset) {131if (ChildrenRecurseDepth) {132// Visit children.133if (symbolEndsScope(Begin->kind()))134--ChildrenDepth;135if (ChildrenDepth < ChildrenRecurseDepth ||136BeginOffset == SymEndOffset) {137if (auto EC = visitSymbolRecord(BeginSym, BeginOffset))138return EC;139}140if (symbolOpensScope(Begin->kind()))141++ChildrenDepth;142}143} else {144// Visit parents' ends.145if (ParentRecurseDepth && BeginOffset == ParentEndOffsets.back()) {146if (auto EC = visitSymbolRecord(BeginSym, BeginOffset))147return EC;148ParentEndOffsets.pop_back();149--ParentRecurseDepth;150}151}152}153return Error::success();154}155156157