Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/DebugInfo/CodeView/CVSymbolVisitor.cpp
35271 views
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/SymbolRecordHelpers.h"
14
#include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
15
#include "llvm/Support/BinaryStreamArray.h"
16
#include "llvm/Support/ErrorHandling.h"
17
18
using namespace llvm;
19
using namespace llvm::codeview;
20
21
CVSymbolVisitor::CVSymbolVisitor(SymbolVisitorCallbacks &Callbacks)
22
: Callbacks(Callbacks) {}
23
24
template <typename T>
25
static Error visitKnownRecord(CVSymbol &Record,
26
SymbolVisitorCallbacks &Callbacks) {
27
SymbolRecordKind RK = static_cast<SymbolRecordKind>(Record.kind());
28
T KnownRecord(RK);
29
if (auto EC = Callbacks.visitKnownRecord(Record, KnownRecord))
30
return EC;
31
return Error::success();
32
}
33
34
static Error finishVisitation(CVSymbol &Record,
35
SymbolVisitorCallbacks &Callbacks) {
36
switch (Record.kind()) {
37
default:
38
if (auto EC = Callbacks.visitUnknownSymbol(Record))
39
return EC;
40
break;
41
#define SYMBOL_RECORD(EnumName, EnumVal, Name) \
42
case EnumName: { \
43
if (auto EC = visitKnownRecord<Name>(Record, Callbacks)) \
44
return EC; \
45
break; \
46
}
47
#define SYMBOL_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName) \
48
SYMBOL_RECORD(EnumVal, EnumVal, AliasName)
49
#include "llvm/DebugInfo/CodeView/CodeViewSymbols.def"
50
}
51
52
if (auto EC = Callbacks.visitSymbolEnd(Record))
53
return EC;
54
55
return Error::success();
56
}
57
58
Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record) {
59
if (auto EC = Callbacks.visitSymbolBegin(Record))
60
return EC;
61
return finishVisitation(Record, Callbacks);
62
}
63
64
Error CVSymbolVisitor::visitSymbolRecord(CVSymbol &Record, uint32_t Offset) {
65
if (auto EC = Callbacks.visitSymbolBegin(Record, Offset))
66
return EC;
67
return finishVisitation(Record, Callbacks);
68
}
69
70
Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols) {
71
for (auto I : Symbols) {
72
if (auto EC = visitSymbolRecord(I))
73
return EC;
74
}
75
return Error::success();
76
}
77
78
Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols,
79
uint32_t InitialOffset) {
80
for (auto I : Symbols) {
81
if (auto EC = visitSymbolRecord(I, InitialOffset + Symbols.skew()))
82
return EC;
83
InitialOffset += I.length();
84
}
85
return Error::success();
86
}
87
88
Error CVSymbolVisitor::visitSymbolStreamFiltered(const CVSymbolArray &Symbols,
89
const FilterOptions &Filter) {
90
if (!Filter.SymbolOffset)
91
return visitSymbolStream(Symbols);
92
uint32_t SymbolOffset = *Filter.SymbolOffset;
93
uint32_t ParentRecurseDepth = Filter.ParentRecursiveDepth.value_or(0);
94
uint32_t ChildrenRecurseDepth = Filter.ChildRecursiveDepth.value_or(0);
95
if (!Symbols.isOffsetValid(SymbolOffset))
96
return createStringError(inconvertibleErrorCode(), "Invalid symbol offset");
97
CVSymbol Sym = *Symbols.at(SymbolOffset);
98
uint32_t SymEndOffset =
99
symbolOpensScope(Sym.kind()) ? getScopeEndOffset(Sym) : 0;
100
101
std::vector<uint32_t> ParentOffsets;
102
std::vector<uint32_t> ParentEndOffsets;
103
uint32_t ChildrenDepth = 0;
104
for (auto Begin = Symbols.begin(), End = Symbols.end(); Begin != End;
105
++Begin) {
106
uint32_t BeginOffset = Begin.offset();
107
CVSymbol BeginSym = *Begin;
108
if (BeginOffset < SymbolOffset) {
109
if (symbolOpensScope(Begin->kind())) {
110
uint32_t EndOffset = getScopeEndOffset(BeginSym);
111
if (SymbolOffset < EndOffset) {
112
ParentOffsets.push_back(BeginOffset);
113
ParentEndOffsets.push_back(EndOffset);
114
}
115
}
116
} else if (BeginOffset == SymbolOffset) {
117
// Found symbol at offset. Visit its parent up to ParentRecurseDepth.
118
if (ParentRecurseDepth >= ParentOffsets.size())
119
ParentRecurseDepth = ParentOffsets.size();
120
uint32_t StartIndex = ParentOffsets.size() - ParentRecurseDepth;
121
while (StartIndex < ParentOffsets.size()) {
122
if (!Symbols.isOffsetValid(ParentOffsets[StartIndex]))
123
break;
124
CVSymbol Parent = *Symbols.at(ParentOffsets[StartIndex]);
125
if (auto EC = visitSymbolRecord(Parent, ParentOffsets[StartIndex]))
126
return EC;
127
++StartIndex;
128
}
129
if (auto EC = visitSymbolRecord(Sym, SymbolOffset))
130
return EC;
131
} else if (BeginOffset <= SymEndOffset) {
132
if (ChildrenRecurseDepth) {
133
// Visit children.
134
if (symbolEndsScope(Begin->kind()))
135
--ChildrenDepth;
136
if (ChildrenDepth < ChildrenRecurseDepth ||
137
BeginOffset == SymEndOffset) {
138
if (auto EC = visitSymbolRecord(BeginSym, BeginOffset))
139
return EC;
140
}
141
if (symbolOpensScope(Begin->kind()))
142
++ChildrenDepth;
143
}
144
} else {
145
// Visit parents' ends.
146
if (ParentRecurseDepth && BeginOffset == ParentEndOffsets.back()) {
147
if (auto EC = visitSymbolRecord(BeginSym, BeginOffset))
148
return EC;
149
ParentEndOffsets.pop_back();
150
--ParentRecurseDepth;
151
}
152
}
153
}
154
return Error::success();
155
}
156
157