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