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