|
10 | 10 |
|
11 | 11 | #include "llvm/DebugInfo/CodeView/CodeView.h"
|
12 | 12 | #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
|
| 13 | +#include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" |
13 | 14 | #include "llvm/DebugInfo/CodeView/SymbolVisitorCallbacks.h"
|
14 | 15 | #include "llvm/Support/BinaryStreamArray.h"
|
15 | 16 | #include "llvm/Support/ErrorHandling.h"
|
@@ -83,3 +84,74 @@ Error CVSymbolVisitor::visitSymbolStream(const CVSymbolArray &Symbols,
|
83 | 84 | }
|
84 | 85 | return Error::success();
|
85 | 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 = |
| 94 | + Filter.ParentRecursiveDepth ? *Filter.ParentRecursiveDepth : 0; |
| 95 | + uint32_t ChildrenRecurseDepth = |
| 96 | + Filter.ChildRecursiveDepth ? *Filter.ChildRecursiveDepth : 0; |
| 97 | + if (!Symbols.isOffsetValid(SymbolOffset)) |
| 98 | + return createStringError(inconvertibleErrorCode(), "Invalid symbol offset"); |
| 99 | + CVSymbol Sym = *Symbols.at(SymbolOffset); |
| 100 | + uint32_t SymEndOffset = |
| 101 | + symbolOpensScope(Sym.kind()) ? getScopeEndOffset(Sym) : 0; |
| 102 | + |
| 103 | + std::vector<uint32_t> ParentOffsets; |
| 104 | + std::vector<uint32_t> ParentEndOffsets; |
| 105 | + uint32_t ChildrenDepth = 0; |
| 106 | + for (auto Begin = Symbols.begin(), End = Symbols.end(); Begin != End; |
| 107 | + ++Begin) { |
| 108 | + uint32_t BeginOffset = Begin.offset(); |
| 109 | + CVSymbol BeginSym = *Begin; |
| 110 | + if (BeginOffset < SymbolOffset) { |
| 111 | + if (symbolOpensScope(Begin->kind())) { |
| 112 | + uint32_t EndOffset = getScopeEndOffset(BeginSym); |
| 113 | + if (SymbolOffset < EndOffset) { |
| 114 | + ParentOffsets.push_back(BeginOffset); |
| 115 | + ParentEndOffsets.push_back(EndOffset); |
| 116 | + } |
| 117 | + } |
| 118 | + } else if (BeginOffset == SymbolOffset) { |
| 119 | + // Found symbol at offset. Visit its parent up to ParentRecurseDepth. |
| 120 | + if (ParentRecurseDepth >= ParentOffsets.size()) |
| 121 | + ParentRecurseDepth = ParentOffsets.size(); |
| 122 | + uint32_t StartIndex = ParentOffsets.size() - ParentRecurseDepth; |
| 123 | + while (StartIndex < ParentOffsets.size()) { |
| 124 | + if (!Symbols.isOffsetValid(ParentOffsets[StartIndex])) |
| 125 | + break; |
| 126 | + CVSymbol Parent = *Symbols.at(ParentOffsets[StartIndex]); |
| 127 | + if (auto EC = visitSymbolRecord(Parent, ParentOffsets[StartIndex])) |
| 128 | + return EC; |
| 129 | + ++StartIndex; |
| 130 | + } |
| 131 | + if (auto EC = visitSymbolRecord(Sym, SymbolOffset)) |
| 132 | + return EC; |
| 133 | + } else if (BeginOffset <= SymEndOffset) { |
| 134 | + if (ChildrenRecurseDepth) { |
| 135 | + // Visit children. |
| 136 | + if (symbolEndsScope(Begin->kind())) |
| 137 | + --ChildrenDepth; |
| 138 | + if (ChildrenDepth < ChildrenRecurseDepth || |
| 139 | + BeginOffset == SymEndOffset) { |
| 140 | + if (auto EC = visitSymbolRecord(BeginSym, BeginOffset)) |
| 141 | + return EC; |
| 142 | + } |
| 143 | + if (symbolOpensScope(Begin->kind())) |
| 144 | + ++ChildrenDepth; |
| 145 | + } |
| 146 | + } else { |
| 147 | + // Visit parents' ends. |
| 148 | + if (ParentRecurseDepth && BeginOffset == ParentEndOffsets.back()) { |
| 149 | + if (auto EC = visitSymbolRecord(BeginSym, BeginOffset)) |
| 150 | + return EC; |
| 151 | + ParentEndOffsets.pop_back(); |
| 152 | + --ParentRecurseDepth; |
| 153 | + } |
| 154 | + } |
| 155 | + } |
| 156 | + return Error::success(); |
| 157 | +} |
0 commit comments