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