1 | //===- PDBSymbol.cpp - base class for user-facing symbol types --*- 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/PDB/PDBSymbol.h" |
10 | #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" |
11 | #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" |
12 | #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" |
13 | #include "llvm/DebugInfo/PDB/IPDBSession.h" |
14 | #include "llvm/DebugInfo/PDB/PDBExtras.h" |
15 | #include "llvm/DebugInfo/PDB/PDBSymbolAnnotation.h" |
16 | #include "llvm/DebugInfo/PDB/PDBSymbolBlock.h" |
17 | #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" |
18 | #include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h" |
19 | #include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h" |
20 | #include "llvm/DebugInfo/PDB/PDBSymbolCustom.h" |
21 | #include "llvm/DebugInfo/PDB/PDBSymbolData.h" |
22 | #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" |
23 | #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" |
24 | #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" |
25 | #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" |
26 | #include "llvm/DebugInfo/PDB/PDBSymbolLabel.h" |
27 | #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" |
28 | #include "llvm/DebugInfo/PDB/PDBSymbolThunk.h" |
29 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h" |
30 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h" |
31 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h" |
32 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h" |
33 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h" |
34 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" |
35 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h" |
36 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h" |
37 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h" |
38 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h" |
39 | #include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h" |
40 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" |
41 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" |
42 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h" |
43 | #include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h" |
44 | #include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h" |
45 | #include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h" |
46 | #include "llvm/DebugInfo/PDB/PDBTypes.h" |
47 | #include <memory> |
48 | |
49 | using namespace llvm; |
50 | using namespace llvm::pdb; |
51 | |
52 | PDBSymbol::PDBSymbol(const IPDBSession &PDBSession) : Session(PDBSession) {} |
53 | |
54 | PDBSymbol::PDBSymbol(PDBSymbol &&Other) |
55 | : Session(Other.Session), RawSymbol(std::move(Other.RawSymbol)) {} |
56 | |
57 | PDBSymbol::~PDBSymbol() = default; |
58 | |
59 | #define FACTORY_SYMTAG_CASE(Tag, Type) \ |
60 | case PDB_SymType::Tag: \ |
61 | return std::unique_ptr<PDBSymbol>(new Type(PDBSession)); |
62 | |
63 | std::unique_ptr<PDBSymbol> |
64 | PDBSymbol::createSymbol(const IPDBSession &PDBSession, PDB_SymType Tag) { |
65 | switch (Tag) { |
66 | FACTORY_SYMTAG_CASE(Exe, PDBSymbolExe) |
67 | FACTORY_SYMTAG_CASE(Compiland, PDBSymbolCompiland) |
68 | FACTORY_SYMTAG_CASE(CompilandDetails, PDBSymbolCompilandDetails) |
69 | FACTORY_SYMTAG_CASE(CompilandEnv, PDBSymbolCompilandEnv) |
70 | FACTORY_SYMTAG_CASE(Function, PDBSymbolFunc) |
71 | FACTORY_SYMTAG_CASE(Block, PDBSymbolBlock) |
72 | FACTORY_SYMTAG_CASE(Data, PDBSymbolData) |
73 | FACTORY_SYMTAG_CASE(Annotation, PDBSymbolAnnotation) |
74 | FACTORY_SYMTAG_CASE(Label, PDBSymbolLabel) |
75 | FACTORY_SYMTAG_CASE(PublicSymbol, PDBSymbolPublicSymbol) |
76 | FACTORY_SYMTAG_CASE(UDT, PDBSymbolTypeUDT) |
77 | FACTORY_SYMTAG_CASE(Enum, PDBSymbolTypeEnum) |
78 | FACTORY_SYMTAG_CASE(FunctionSig, PDBSymbolTypeFunctionSig) |
79 | FACTORY_SYMTAG_CASE(PointerType, PDBSymbolTypePointer) |
80 | FACTORY_SYMTAG_CASE(ArrayType, PDBSymbolTypeArray) |
81 | FACTORY_SYMTAG_CASE(BuiltinType, PDBSymbolTypeBuiltin) |
82 | FACTORY_SYMTAG_CASE(Typedef, PDBSymbolTypeTypedef) |
83 | FACTORY_SYMTAG_CASE(BaseClass, PDBSymbolTypeBaseClass) |
84 | FACTORY_SYMTAG_CASE(Friend, PDBSymbolTypeFriend) |
85 | FACTORY_SYMTAG_CASE(FunctionArg, PDBSymbolTypeFunctionArg) |
86 | FACTORY_SYMTAG_CASE(FuncDebugStart, PDBSymbolFuncDebugStart) |
87 | FACTORY_SYMTAG_CASE(FuncDebugEnd, PDBSymbolFuncDebugEnd) |
88 | FACTORY_SYMTAG_CASE(UsingNamespace, PDBSymbolUsingNamespace) |
89 | FACTORY_SYMTAG_CASE(VTableShape, PDBSymbolTypeVTableShape) |
90 | FACTORY_SYMTAG_CASE(VTable, PDBSymbolTypeVTable) |
91 | FACTORY_SYMTAG_CASE(Custom, PDBSymbolCustom) |
92 | FACTORY_SYMTAG_CASE(Thunk, PDBSymbolThunk) |
93 | FACTORY_SYMTAG_CASE(CustomType, PDBSymbolTypeCustom) |
94 | FACTORY_SYMTAG_CASE(ManagedType, PDBSymbolTypeManaged) |
95 | FACTORY_SYMTAG_CASE(Dimension, PDBSymbolTypeDimension) |
96 | default: |
97 | return std::unique_ptr<PDBSymbol>(new PDBSymbolUnknown(PDBSession)); |
98 | } |
99 | } |
100 | |
101 | std::unique_ptr<PDBSymbol> |
102 | PDBSymbol::create(const IPDBSession &PDBSession, |
103 | std::unique_ptr<IPDBRawSymbol> RawSymbol) { |
104 | auto SymbolPtr = createSymbol(PDBSession, Tag: RawSymbol->getSymTag()); |
105 | SymbolPtr->RawSymbol = RawSymbol.get(); |
106 | SymbolPtr->OwnedRawSymbol = std::move(RawSymbol); |
107 | return SymbolPtr; |
108 | } |
109 | |
110 | std::unique_ptr<PDBSymbol> PDBSymbol::create(const IPDBSession &PDBSession, |
111 | IPDBRawSymbol &RawSymbol) { |
112 | auto SymbolPtr = createSymbol(PDBSession, Tag: RawSymbol.getSymTag()); |
113 | SymbolPtr->RawSymbol = &RawSymbol; |
114 | return SymbolPtr; |
115 | } |
116 | |
117 | void PDBSymbol::defaultDump(raw_ostream &OS, int Indent, |
118 | PdbSymbolIdField ShowFlags, |
119 | PdbSymbolIdField RecurseFlags) const { |
120 | RawSymbol->dump(OS, Indent, ShowIdFields: ShowFlags, RecurseIdFields: RecurseFlags); |
121 | } |
122 | |
123 | void PDBSymbol::dumpProperties() const { |
124 | outs() << "\n" ; |
125 | defaultDump(OS&: outs(), Indent: 0, ShowFlags: PdbSymbolIdField::All, RecurseFlags: PdbSymbolIdField::None); |
126 | outs().flush(); |
127 | } |
128 | |
129 | void PDBSymbol::dumpChildStats() const { |
130 | TagStats Stats; |
131 | getChildStats(Stats); |
132 | outs() << "\n" ; |
133 | for (auto &Stat : Stats) { |
134 | outs() << Stat.first << ": " << Stat.second << "\n" ; |
135 | } |
136 | outs().flush(); |
137 | } |
138 | |
139 | PDB_SymType PDBSymbol::getSymTag() const { return RawSymbol->getSymTag(); } |
140 | uint32_t PDBSymbol::getSymIndexId() const { return RawSymbol->getSymIndexId(); } |
141 | |
142 | std::unique_ptr<IPDBEnumSymbols> PDBSymbol::findAllChildren() const { |
143 | return findAllChildren(Type: PDB_SymType::None); |
144 | } |
145 | |
146 | std::unique_ptr<IPDBEnumSymbols> |
147 | PDBSymbol::findAllChildren(PDB_SymType Type) const { |
148 | return RawSymbol->findChildren(Type); |
149 | } |
150 | |
151 | std::unique_ptr<IPDBEnumSymbols> |
152 | PDBSymbol::findChildren(PDB_SymType Type, StringRef Name, |
153 | PDB_NameSearchFlags Flags) const { |
154 | return RawSymbol->findChildren(Type, Name, Flags); |
155 | } |
156 | |
157 | std::unique_ptr<IPDBEnumSymbols> |
158 | PDBSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name, |
159 | PDB_NameSearchFlags Flags, uint32_t RVA) const { |
160 | return RawSymbol->findChildrenByRVA(Type, Name, Flags, RVA); |
161 | } |
162 | |
163 | std::unique_ptr<IPDBEnumSymbols> |
164 | PDBSymbol::findInlineFramesByVA(uint64_t VA) const { |
165 | return RawSymbol->findInlineFramesByVA(VA); |
166 | } |
167 | |
168 | std::unique_ptr<IPDBEnumSymbols> |
169 | PDBSymbol::findInlineFramesByRVA(uint32_t RVA) const { |
170 | return RawSymbol->findInlineFramesByRVA(RVA); |
171 | } |
172 | |
173 | std::unique_ptr<IPDBEnumLineNumbers> |
174 | PDBSymbol::findInlineeLinesByVA(uint64_t VA, uint32_t Length) const { |
175 | return RawSymbol->findInlineeLinesByVA(VA, Length); |
176 | } |
177 | |
178 | std::unique_ptr<IPDBEnumLineNumbers> |
179 | PDBSymbol::findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const { |
180 | return RawSymbol->findInlineeLinesByRVA(RVA, Length); |
181 | } |
182 | |
183 | std::string PDBSymbol::getName() const { return RawSymbol->getName(); } |
184 | |
185 | std::unique_ptr<IPDBEnumSymbols> |
186 | PDBSymbol::getChildStats(TagStats &Stats) const { |
187 | std::unique_ptr<IPDBEnumSymbols> Result(findAllChildren()); |
188 | if (!Result) |
189 | return nullptr; |
190 | Stats.clear(); |
191 | while (auto Child = Result->getNext()) { |
192 | ++Stats[Child->getSymTag()]; |
193 | } |
194 | Result->reset(); |
195 | return Result; |
196 | } |
197 | |
198 | std::unique_ptr<PDBSymbol> PDBSymbol::getSymbolByIdHelper(uint32_t Id) const { |
199 | return Session.getSymbolById(SymbolId: Id); |
200 | } |
201 | |
202 | void llvm::pdb::dumpSymbolIdField(raw_ostream &OS, StringRef Name, |
203 | SymIndexId Value, int Indent, |
204 | const IPDBSession &Session, |
205 | PdbSymbolIdField FieldId, |
206 | PdbSymbolIdField ShowFlags, |
207 | PdbSymbolIdField RecurseFlags) { |
208 | if ((FieldId & ShowFlags) == PdbSymbolIdField::None) |
209 | return; |
210 | |
211 | OS << "\n" ; |
212 | OS.indent(NumSpaces: Indent); |
213 | OS << Name << ": " << Value; |
214 | // Don't recurse unless the user requested it. |
215 | if ((FieldId & RecurseFlags) == PdbSymbolIdField::None) |
216 | return; |
217 | // And obviously don't recurse on the symbol itself. |
218 | if (FieldId == PdbSymbolIdField::SymIndexId) |
219 | return; |
220 | |
221 | auto Child = Session.getSymbolById(SymbolId: Value); |
222 | |
223 | // It could have been a placeholder symbol for a type we don't yet support, |
224 | // so just exit in that case. |
225 | if (!Child) |
226 | return; |
227 | |
228 | // Don't recurse more than once, so pass PdbSymbolIdField::None) for the |
229 | // recurse flags. |
230 | Child->defaultDump(OS, Indent: Indent + 2, ShowFlags, RecurseFlags: PdbSymbolIdField::None); |
231 | } |
232 | |