1 #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
2 
3 #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
4 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
5 #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
6 #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
7 #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
8 #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
9 #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
10 #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
11 #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
12 #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
13 #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
14 #include "llvm/DebugInfo/PDB/PDBSymbol.h"
15 #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
16 #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
17 
18 using namespace llvm;
19 using namespace llvm::codeview;
20 using namespace llvm::pdb;
21 
22 // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
23 // to instantiate a NativeBuiltinSymbol for that type.
24 static const struct BuiltinTypeEntry {
25   codeview::SimpleTypeKind Kind;
26   PDB_BuiltinType Type;
27   uint32_t Size;
28 } BuiltinTypes[] = {
29     {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
30     {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
31     {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
32     {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
33     {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
34     {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
35     {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
36     {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
37     {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
38     {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
39     {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
40     {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
41     // This table can be grown as necessary, but these are the only types we've
42     // needed so far.
43 };
44 
45 SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
46     : Session(Session), Dbi(Dbi) {
47   // Id 0 is reserved for the invalid symbol.
48   Cache.push_back(nullptr);
49 
50   if (Dbi)
51     Compilands.resize(Dbi->modules().getModuleCount());
52 }
53 
54 std::unique_ptr<IPDBEnumSymbols>
55 SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) {
56   auto Tpi = Session.getPDBFile().getPDBTpiStream();
57   if (!Tpi) {
58     consumeError(Tpi.takeError());
59     return nullptr;
60   }
61   auto &Types = Tpi->typeCollection();
62   return std::unique_ptr<IPDBEnumSymbols>(
63       new NativeEnumTypes(Session, Types, Kind));
64 }
65 
66 SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
67                                          ModifierOptions Mods) {
68   if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct) {
69     SymIndexId Id = Cache.size();
70     Cache.emplace_back(
71         llvm::make_unique<NativeTypePointer>(Session, Id, Index));
72     return Id;
73   }
74 
75   SymIndexId Id = Cache.size();
76   const auto Kind = Index.getSimpleKind();
77   const auto It = std::find_if(
78       std::begin(BuiltinTypes), std::end(BuiltinTypes),
79       [Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; });
80   if (It == std::end(BuiltinTypes))
81     return 0;
82   Cache.emplace_back(llvm::make_unique<NativeTypeBuiltin>(Session, Id, Mods,
83                                                           It->Type, It->Size));
84   TypeIndexToSymbolId[Index] = Id;
85   return Id;
86 }
87 
88 SymIndexId
89 SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
90                                          codeview::CVType CVT) {
91   ModifierRecord Record;
92   if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
93     consumeError(std::move(EC));
94     return 0;
95   }
96 
97   if (Record.ModifiedType.isSimple())
98     return createSimpleType(Record.ModifiedType, Record.Modifiers);
99 
100   auto Tpi = Session.getPDBFile().getPDBTpiStream();
101   if (!Tpi) {
102     consumeError(Tpi.takeError());
103     return 0;
104   }
105   codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
106 
107   codeview::CVType UnmodifiedType = Types.getType(Record.ModifiedType);
108 
109   switch (UnmodifiedType.kind()) {
110   case LF_ENUM: {
111     EnumRecord ER;
112     if (auto EC =
113             TypeDeserializer::deserializeAs<EnumRecord>(UnmodifiedType, ER)) {
114       consumeError(std::move(EC));
115       return 0;
116     }
117     return createSymbol<NativeTypeEnum>(Record.ModifiedType, std::move(Record),
118                                         std::move(ER));
119   }
120   case LF_STRUCTURE:
121   case LF_UNION:
122   case LF_CLASS:
123     // FIXME: Handle these
124     break;
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 createSymbolPlaceholder();
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     return createSimpleType(Index, ModifierOptions::None);
143 
144   // We need to instantiate and cache the desired type symbol.
145   auto Tpi = Session.getPDBFile().getPDBTpiStream();
146   if (!Tpi) {
147     consumeError(Tpi.takeError());
148     return 0;
149   }
150   codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
151   codeview::CVType CVT = Types.getType(Index);
152   // TODO(amccarth):  Make this handle all types.
153   SymIndexId Id = 0;
154 
155   switch (CVT.kind()) {
156   case codeview::LF_ENUM:
157     Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
158     break;
159   case codeview::LF_POINTER:
160     Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
161                                                                std::move(CVT));
162     break;
163   case codeview::LF_MODIFIER:
164     Id = createSymbolForModifiedType(Index, std::move(CVT));
165     break;
166   default:
167     Id = createSymbolPlaceholder();
168     break;
169   }
170   if (Id != 0)
171     TypeIndexToSymbolId[Index] = Id;
172   return Id;
173 }
174 
175 std::unique_ptr<PDBSymbol>
176 SymbolCache::getSymbolById(SymIndexId SymbolId) const {
177   assert(SymbolId < Cache.size());
178 
179   // Id 0 is reserved.
180   if (SymbolId == 0 || SymbolId >= Cache.size())
181     return nullptr;
182 
183   // Make sure to handle the case where we've inserted a placeholder symbol
184   // for types we don't yet suppport.
185   NativeRawSymbol *NRS = Cache[SymbolId].get();
186   if (!NRS)
187     return nullptr;
188 
189   return PDBSymbol::create(Session, *NRS);
190 }
191 
192 NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
193   return *Cache[SymbolId];
194 }
195 
196 uint32_t SymbolCache::getNumCompilands() const {
197   if (!Dbi)
198     return 0;
199 
200   return Dbi->modules().getModuleCount();
201 }
202 
203 std::unique_ptr<PDBSymbolCompiland>
204 SymbolCache::getOrCreateCompiland(uint32_t Index) {
205   if (!Dbi)
206     return nullptr;
207 
208   if (Index >= Compilands.size())
209     return nullptr;
210 
211   if (Compilands[Index] == 0) {
212     const DbiModuleList &Modules = Dbi->modules();
213     Compilands[Index] =
214         createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
215   }
216 
217   return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
218 }
219