Line data Source code
1 : #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
2 :
3 : #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
4 : #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
5 : #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
6 : #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
7 : #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
8 : #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
9 : #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
10 : #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
11 : #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
12 : #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
13 : #include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
14 : #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
15 : #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
16 : #include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
17 : #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
18 : #include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
19 : #include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
20 : #include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
21 : #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
22 : #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
23 : #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
24 : #include "llvm/DebugInfo/PDB/PDBSymbol.h"
25 : #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
26 : #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
27 :
28 : using namespace llvm;
29 : using namespace llvm::codeview;
30 : using namespace llvm::pdb;
31 :
32 : // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
33 : // to instantiate a NativeBuiltinSymbol for that type.
34 : static const struct BuiltinTypeEntry {
35 : codeview::SimpleTypeKind Kind;
36 : PDB_BuiltinType Type;
37 : uint32_t Size;
38 : } BuiltinTypes[] = {
39 : {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0},
40 : {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},
41 : {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4},
42 : {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
43 : {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
44 : {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
45 : {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
46 : {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
47 : {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
48 : {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
49 : {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
50 : {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
51 : {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},
52 : {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},
53 : {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},
54 : {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
55 : {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
56 : {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4},
57 : {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8},
58 : {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10},
59 : {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1},
60 : // This table can be grown as necessary, but these are the only types we've
61 : // needed so far.
62 : };
63 :
64 127 : SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
65 254 : : Session(Session), Dbi(Dbi) {
66 : // Id 0 is reserved for the invalid symbol.
67 127 : Cache.push_back(nullptr);
68 :
69 127 : if (Dbi)
70 122 : Compilands.resize(Dbi->modules().getModuleCount());
71 :
72 127 : auto &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
73 127 : Tpi.buildHashMap();
74 127 : }
75 :
76 : std::unique_ptr<IPDBEnumSymbols>
77 4 : SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
78 4 : return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
79 : }
80 :
81 : std::unique_ptr<IPDBEnumSymbols>
82 8 : SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
83 16 : auto Tpi = Session.getPDBFile().getPDBTpiStream();
84 8 : if (!Tpi) {
85 0 : consumeError(Tpi.takeError());
86 : return nullptr;
87 : }
88 : auto &Types = Tpi->typeCollection();
89 : return std::unique_ptr<IPDBEnumSymbols>(
90 16 : new NativeEnumTypes(Session, Types, std::move(Kinds)));
91 : }
92 :
93 : std::unique_ptr<IPDBEnumSymbols>
94 2 : SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
95 : return std::unique_ptr<IPDBEnumSymbols>(
96 2 : new NativeEnumGlobals(Session, {Kind}));
97 : }
98 :
99 52 : SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
100 : ModifierOptions Mods) {
101 52 : if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
102 5 : return createSymbol<NativeTypePointer>(Index);
103 :
104 : const auto Kind = Index.getSimpleKind();
105 : const auto It = std::find_if(
106 : std::begin(BuiltinTypes), std::end(BuiltinTypes),
107 : [Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; });
108 47 : if (It == std::end(BuiltinTypes))
109 : return 0;
110 47 : return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
111 : }
112 :
113 : SymIndexId
114 34 : SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
115 : codeview::CVType CVT) {
116 : ModifierRecord Record;
117 68 : if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
118 0 : consumeError(std::move(EC));
119 : return 0;
120 : }
121 :
122 34 : if (Record.ModifiedType.isSimple())
123 12 : return createSimpleType(Record.ModifiedType, Record.Modifiers);
124 :
125 : // Make sure we create and cache a record for the unmodified type.
126 22 : SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
127 22 : NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
128 :
129 22 : switch (UnmodifiedNRS.getSymTag()) {
130 : case PDB_SymType::Enum:
131 2 : return createSymbol<NativeTypeEnum>(
132 2 : static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
133 : case PDB_SymType::UDT:
134 20 : return createSymbol<NativeTypeUDT>(
135 20 : static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
136 : default:
137 : // No other types can be modified. (LF_POINTER, for example, records
138 : // its modifiers a different way.
139 : assert(false && "Invalid LF_MODIFIER record");
140 : break;
141 : }
142 : return 0;
143 : }
144 :
145 1088 : SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
146 : // First see if it's already in our cache.
147 1088 : const auto Entry = TypeIndexToSymbolId.find(Index);
148 1088 : if (Entry != TypeIndexToSymbolId.end())
149 651 : return Entry->second;
150 :
151 : // Symbols for built-in types are created on the fly.
152 437 : if (Index.isSimple()) {
153 40 : SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
154 : assert(TypeIndexToSymbolId.count(Index) == 0);
155 40 : TypeIndexToSymbolId[Index] = Result;
156 40 : return Result;
157 : }
158 :
159 : // We need to instantiate and cache the desired type symbol.
160 794 : auto Tpi = Session.getPDBFile().getPDBTpiStream();
161 397 : if (!Tpi) {
162 0 : consumeError(Tpi.takeError());
163 0 : return 0;
164 : }
165 : codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
166 397 : codeview::CVType CVT = Types.getType(Index);
167 :
168 397 : if (isUdtForwardRef(CVT)) {
169 40 : Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
170 :
171 40 : if (!EFD)
172 0 : consumeError(EFD.takeError());
173 40 : else if (*EFD != Index) {
174 : assert(!isUdtForwardRef(Types.getType(*EFD)));
175 40 : SymIndexId Result = findSymbolByTypeIndex(*EFD);
176 : // Record a mapping from ForwardRef -> SymIndex of complete type so that
177 : // we'll take the fast path next time.
178 : assert(TypeIndexToSymbolId.count(Index) == 0);
179 40 : TypeIndexToSymbolId[Index] = Result;
180 : return Result;
181 : }
182 : }
183 :
184 : // At this point if we still have a forward ref udt it means the full decl was
185 : // not in the PDB. We just have to deal with it and use the forward ref.
186 : SymIndexId Id = 0;
187 357 : switch (CVT.kind()) {
188 : case codeview::LF_ENUM:
189 50 : Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
190 50 : break;
191 : case codeview::LF_ARRAY:
192 2 : Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
193 : std::move(CVT));
194 2 : break;
195 : case codeview::LF_CLASS:
196 : case codeview::LF_STRUCTURE:
197 : case codeview::LF_INTERFACE:
198 74 : Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
199 74 : break;
200 : case codeview::LF_UNION:
201 2 : Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
202 2 : break;
203 : case codeview::LF_POINTER:
204 73 : Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
205 : std::move(CVT));
206 73 : break;
207 : case codeview::LF_MODIFIER:
208 34 : Id = createSymbolForModifiedType(Index, std::move(CVT));
209 34 : break;
210 : case codeview::LF_PROCEDURE:
211 36 : Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
212 : Index, std::move(CVT));
213 36 : break;
214 : case codeview::LF_MFUNCTION:
215 86 : Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
216 : Index, std::move(CVT));
217 86 : break;
218 : case codeview::LF_VTSHAPE:
219 0 : Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
220 : Index, std::move(CVT));
221 0 : break;
222 0 : default:
223 0 : Id = createSymbolPlaceholder();
224 0 : break;
225 : }
226 357 : if (Id != 0) {
227 : assert(TypeIndexToSymbolId.count(Index) == 0);
228 357 : TypeIndexToSymbolId[Index] = Id;
229 : }
230 : return Id;
231 : }
232 :
233 : std::unique_ptr<PDBSymbol>
234 926 : SymbolCache::getSymbolById(SymIndexId SymbolId) const {
235 : assert(SymbolId < Cache.size());
236 :
237 : // Id 0 is reserved.
238 926 : if (SymbolId == 0 || SymbolId >= Cache.size())
239 : return nullptr;
240 :
241 : // Make sure to handle the case where we've inserted a placeholder symbol
242 : // for types we don't yet suppport.
243 : NativeRawSymbol *NRS = Cache[SymbolId].get();
244 851 : if (!NRS)
245 : return nullptr;
246 :
247 851 : return PDBSymbol::create(Session, *NRS);
248 : }
249 :
250 198 : NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
251 396 : return *Cache[SymbolId];
252 : }
253 :
254 71 : uint32_t SymbolCache::getNumCompilands() const {
255 71 : if (!Dbi)
256 : return 0;
257 :
258 71 : return Dbi->modules().getModuleCount();
259 : }
260 :
261 6 : SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
262 6 : auto Iter = GlobalOffsetToSymbolId.find(Offset);
263 6 : if (Iter != GlobalOffsetToSymbolId.end())
264 0 : return Iter->second;
265 :
266 12 : SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
267 6 : CVSymbol CVS = SS.readRecord(Offset);
268 : SymIndexId Id = 0;
269 6 : switch (CVS.kind()) {
270 : case SymbolKind::S_UDT: {
271 6 : UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
272 6 : Id = createSymbol<NativeTypeTypedef>(std::move(US));
273 : break;
274 : }
275 0 : default:
276 0 : Id = createSymbolPlaceholder();
277 0 : break;
278 : }
279 6 : if (Id != 0) {
280 : assert(GlobalOffsetToSymbolId.count(Offset) == 0);
281 6 : GlobalOffsetToSymbolId[Offset] = Id;
282 : }
283 :
284 : return Id;
285 : }
286 :
287 : std::unique_ptr<PDBSymbolCompiland>
288 62 : SymbolCache::getOrCreateCompiland(uint32_t Index) {
289 62 : if (!Dbi)
290 : return nullptr;
291 :
292 124 : if (Index >= Compilands.size())
293 : return nullptr;
294 :
295 62 : if (Compilands[Index] == 0) {
296 56 : const DbiModuleList &Modules = Dbi->modules();
297 56 : Compilands[Index] =
298 56 : createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
299 : }
300 :
301 124 : return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
302 : }
|