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