xref: /freebsd/contrib/llvm-project/llvm/lib/DebugInfo/PDB/Native/SymbolCache.cpp (revision 6966ac055c3b7a39266fb982493330df7a097997)
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 SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
65     : Session(Session), Dbi(Dbi) {
66   // Id 0 is reserved for the invalid symbol.
67   Cache.push_back(nullptr);
68 
69   if (Dbi)
70     Compilands.resize(Dbi->modules().getModuleCount());
71 }
72 
73 std::unique_ptr<IPDBEnumSymbols>
74 SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
75   return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
76 }
77 
78 std::unique_ptr<IPDBEnumSymbols>
79 SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
80   auto Tpi = Session.getPDBFile().getPDBTpiStream();
81   if (!Tpi) {
82     consumeError(Tpi.takeError());
83     return nullptr;
84   }
85   auto &Types = Tpi->typeCollection();
86   return std::unique_ptr<IPDBEnumSymbols>(
87       new NativeEnumTypes(Session, Types, std::move(Kinds)));
88 }
89 
90 std::unique_ptr<IPDBEnumSymbols>
91 SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
92   return std::unique_ptr<IPDBEnumSymbols>(
93       new NativeEnumGlobals(Session, {Kind}));
94 }
95 
96 SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
97                                          ModifierOptions Mods) {
98   if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
99     return createSymbol<NativeTypePointer>(Index);
100 
101   const auto Kind = Index.getSimpleKind();
102   const auto It = std::find_if(
103       std::begin(BuiltinTypes), std::end(BuiltinTypes),
104       [Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; });
105   if (It == std::end(BuiltinTypes))
106     return 0;
107   return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
108 }
109 
110 SymIndexId
111 SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
112                                          codeview::CVType CVT) {
113   ModifierRecord Record;
114   if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
115     consumeError(std::move(EC));
116     return 0;
117   }
118 
119   if (Record.ModifiedType.isSimple())
120     return createSimpleType(Record.ModifiedType, Record.Modifiers);
121 
122   // Make sure we create and cache a record for the unmodified type.
123   SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
124   NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
125 
126   switch (UnmodifiedNRS.getSymTag()) {
127   case PDB_SymType::Enum:
128     return createSymbol<NativeTypeEnum>(
129         static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
130   case PDB_SymType::UDT:
131     return createSymbol<NativeTypeUDT>(
132         static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
133   default:
134     // No other types can be modified.  (LF_POINTER, for example, records
135     // its modifiers a different way.
136     assert(false && "Invalid LF_MODIFIER record");
137     break;
138   }
139   return 0;
140 }
141 
142 SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
143   // First see if it's already in our cache.
144   const auto Entry = TypeIndexToSymbolId.find(Index);
145   if (Entry != TypeIndexToSymbolId.end())
146     return Entry->second;
147 
148   // Symbols for built-in types are created on the fly.
149   if (Index.isSimple()) {
150     SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
151     assert(TypeIndexToSymbolId.count(Index) == 0);
152     TypeIndexToSymbolId[Index] = Result;
153     return Result;
154   }
155 
156   // We need to instantiate and cache the desired type symbol.
157   auto Tpi = Session.getPDBFile().getPDBTpiStream();
158   if (!Tpi) {
159     consumeError(Tpi.takeError());
160     return 0;
161   }
162   codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
163   codeview::CVType CVT = Types.getType(Index);
164 
165   if (isUdtForwardRef(CVT)) {
166     Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
167 
168     if (!EFD)
169       consumeError(EFD.takeError());
170     else if (*EFD != Index) {
171       assert(!isUdtForwardRef(Types.getType(*EFD)));
172       SymIndexId Result = findSymbolByTypeIndex(*EFD);
173       // Record a mapping from ForwardRef -> SymIndex of complete type so that
174       // we'll take the fast path next time.
175       assert(TypeIndexToSymbolId.count(Index) == 0);
176       TypeIndexToSymbolId[Index] = Result;
177       return Result;
178     }
179   }
180 
181   // At this point if we still have a forward ref udt it means the full decl was
182   // not in the PDB.  We just have to deal with it and use the forward ref.
183   SymIndexId Id = 0;
184   switch (CVT.kind()) {
185   case codeview::LF_ENUM:
186     Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
187     break;
188   case codeview::LF_ARRAY:
189     Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
190                                                            std::move(CVT));
191     break;
192   case codeview::LF_CLASS:
193   case codeview::LF_STRUCTURE:
194   case codeview::LF_INTERFACE:
195     Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
196     break;
197   case codeview::LF_UNION:
198     Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
199     break;
200   case codeview::LF_POINTER:
201     Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
202                                                                std::move(CVT));
203     break;
204   case codeview::LF_MODIFIER:
205     Id = createSymbolForModifiedType(Index, std::move(CVT));
206     break;
207   case codeview::LF_PROCEDURE:
208     Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
209         Index, std::move(CVT));
210     break;
211   case codeview::LF_MFUNCTION:
212     Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
213         Index, std::move(CVT));
214     break;
215   case codeview::LF_VTSHAPE:
216     Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
217         Index, std::move(CVT));
218     break;
219   default:
220     Id = createSymbolPlaceholder();
221     break;
222   }
223   if (Id != 0) {
224     assert(TypeIndexToSymbolId.count(Index) == 0);
225     TypeIndexToSymbolId[Index] = Id;
226   }
227   return Id;
228 }
229 
230 std::unique_ptr<PDBSymbol>
231 SymbolCache::getSymbolById(SymIndexId SymbolId) const {
232   assert(SymbolId < Cache.size());
233 
234   // Id 0 is reserved.
235   if (SymbolId == 0 || SymbolId >= Cache.size())
236     return nullptr;
237 
238   // Make sure to handle the case where we've inserted a placeholder symbol
239   // for types we don't yet suppport.
240   NativeRawSymbol *NRS = Cache[SymbolId].get();
241   if (!NRS)
242     return nullptr;
243 
244   return PDBSymbol::create(Session, *NRS);
245 }
246 
247 NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
248   return *Cache[SymbolId];
249 }
250 
251 uint32_t SymbolCache::getNumCompilands() const {
252   if (!Dbi)
253     return 0;
254 
255   return Dbi->modules().getModuleCount();
256 }
257 
258 SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
259   auto Iter = GlobalOffsetToSymbolId.find(Offset);
260   if (Iter != GlobalOffsetToSymbolId.end())
261     return Iter->second;
262 
263   SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
264   CVSymbol CVS = SS.readRecord(Offset);
265   SymIndexId Id = 0;
266   switch (CVS.kind()) {
267   case SymbolKind::S_UDT: {
268     UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
269     Id = createSymbol<NativeTypeTypedef>(std::move(US));
270     break;
271   }
272   default:
273     Id = createSymbolPlaceholder();
274     break;
275   }
276   if (Id != 0) {
277     assert(GlobalOffsetToSymbolId.count(Offset) == 0);
278     GlobalOffsetToSymbolId[Offset] = Id;
279   }
280 
281   return Id;
282 }
283 
284 std::unique_ptr<PDBSymbolCompiland>
285 SymbolCache::getOrCreateCompiland(uint32_t Index) {
286   if (!Dbi)
287     return nullptr;
288 
289   if (Index >= Compilands.size())
290     return nullptr;
291 
292   if (Compilands[Index] == 0) {
293     const DbiModuleList &Modules = Dbi->modules();
294     Compilands[Index] =
295         createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
296   }
297 
298   return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
299 }
300