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   auto &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
73   Tpi.buildHashMap();
74 }
75 
76 std::unique_ptr<IPDBEnumSymbols>
77 SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
78   return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
79 }
80 
81 std::unique_ptr<IPDBEnumSymbols>
82 SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
83   auto Tpi = Session.getPDBFile().getPDBTpiStream();
84   if (!Tpi) {
85     consumeError(Tpi.takeError());
86     return nullptr;
87   }
88   auto &Types = Tpi->typeCollection();
89   return std::unique_ptr<IPDBEnumSymbols>(
90       new NativeEnumTypes(Session, Types, std::move(Kinds)));
91 }
92 
93 std::unique_ptr<IPDBEnumSymbols>
94 SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
95   return std::unique_ptr<IPDBEnumSymbols>(
96       new NativeEnumGlobals(Session, {Kind}));
97 }
98 
99 SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
100                                          ModifierOptions Mods) {
101   if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
102     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   if (It == std::end(BuiltinTypes))
109     return 0;
110   return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
111 }
112 
113 SymIndexId
114 SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
115                                          codeview::CVType CVT) {
116   ModifierRecord Record;
117   if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
118     consumeError(std::move(EC));
119     return 0;
120   }
121 
122   if (Record.ModifiedType.isSimple())
123     return createSimpleType(Record.ModifiedType, Record.Modifiers);
124 
125   // Make sure we create and cache a record for the unmodified type.
126   SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
127   NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
128 
129   switch (UnmodifiedNRS.getSymTag()) {
130   case PDB_SymType::Enum:
131     return createSymbol<NativeTypeEnum>(
132         static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
133   case PDB_SymType::UDT:
134     return createSymbol<NativeTypeUDT>(
135         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 SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
146   // First see if it's already in our cache.
147   const auto Entry = TypeIndexToSymbolId.find(Index);
148   if (Entry != TypeIndexToSymbolId.end())
149     return Entry->second;
150 
151   // Symbols for built-in types are created on the fly.
152   if (Index.isSimple()) {
153     SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
154     assert(TypeIndexToSymbolId.count(Index) == 0);
155     TypeIndexToSymbolId[Index] = Result;
156     return Result;
157   }
158 
159   // We need to instantiate and cache the desired type symbol.
160   auto Tpi = Session.getPDBFile().getPDBTpiStream();
161   if (!Tpi) {
162     consumeError(Tpi.takeError());
163     return 0;
164   }
165   codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
166   codeview::CVType CVT = Types.getType(Index);
167 
168   if (isUdtForwardRef(CVT)) {
169     Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
170 
171     if (!EFD)
172       consumeError(EFD.takeError());
173     else if (*EFD != Index) {
174       assert(!isUdtForwardRef(Types.getType(*EFD)));
175       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       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   switch (CVT.kind()) {
188   case codeview::LF_ENUM:
189     Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
190     break;
191   case codeview::LF_ARRAY:
192     Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
193                                                            std::move(CVT));
194     break;
195   case codeview::LF_CLASS:
196   case codeview::LF_STRUCTURE:
197   case codeview::LF_INTERFACE:
198     Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
199     break;
200   case codeview::LF_UNION:
201     Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
202     break;
203   case codeview::LF_POINTER:
204     Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
205                                                                std::move(CVT));
206     break;
207   case codeview::LF_MODIFIER:
208     Id = createSymbolForModifiedType(Index, std::move(CVT));
209     break;
210   case codeview::LF_PROCEDURE:
211     Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
212         Index, std::move(CVT));
213     break;
214   case codeview::LF_MFUNCTION:
215     Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
216         Index, std::move(CVT));
217     break;
218   case codeview::LF_VTSHAPE:
219     Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
220         Index, std::move(CVT));
221     break;
222   default:
223     Id = createSymbolPlaceholder();
224     break;
225   }
226   if (Id != 0) {
227     assert(TypeIndexToSymbolId.count(Index) == 0);
228     TypeIndexToSymbolId[Index] = Id;
229   }
230   return Id;
231 }
232 
233 std::unique_ptr<PDBSymbol>
234 SymbolCache::getSymbolById(SymIndexId SymbolId) const {
235   assert(SymbolId < Cache.size());
236 
237   // Id 0 is reserved.
238   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   if (!NRS)
245     return nullptr;
246 
247   return PDBSymbol::create(Session, *NRS);
248 }
249 
250 NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
251   return *Cache[SymbolId];
252 }
253 
254 uint32_t SymbolCache::getNumCompilands() const {
255   if (!Dbi)
256     return 0;
257 
258   return Dbi->modules().getModuleCount();
259 }
260 
261 SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
262   auto Iter = GlobalOffsetToSymbolId.find(Offset);
263   if (Iter != GlobalOffsetToSymbolId.end())
264     return Iter->second;
265 
266   SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
267   CVSymbol CVS = SS.readRecord(Offset);
268   SymIndexId Id = 0;
269   switch (CVS.kind()) {
270   case SymbolKind::S_UDT: {
271     UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
272     Id = createSymbol<NativeTypeTypedef>(std::move(US));
273     break;
274   }
275   default:
276     Id = createSymbolPlaceholder();
277     break;
278   }
279   if (Id != 0) {
280     assert(GlobalOffsetToSymbolId.count(Offset) == 0);
281     GlobalOffsetToSymbolId[Offset] = Id;
282   }
283 
284   return Id;
285 }
286 
287 std::unique_ptr<PDBSymbolCompiland>
288 SymbolCache::getOrCreateCompiland(uint32_t Index) {
289   if (!Dbi)
290     return nullptr;
291 
292   if (Index >= Compilands.size())
293     return nullptr;
294 
295   if (Compilands[Index] == 0) {
296     const DbiModuleList &Modules = Dbi->modules();
297     Compilands[Index] =
298         createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
299   }
300 
301   return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
302 }
303