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   // FIXME:  We will eventually need to handle pointers to other simple types,
69   // which are still simple types in the world of CodeView TypeIndexes.
70   if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
71     return 0;
72 
73   const auto Kind = Index.getSimpleKind();
74   const auto It = std::find_if(
75       std::begin(BuiltinTypes), std::end(BuiltinTypes),
76       [Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; });
77   if (It == std::end(BuiltinTypes))
78     return 0;
79   SymIndexId Id = Cache.size();
80   Cache.emplace_back(llvm::make_unique<NativeTypeBuiltin>(Session, Id, Mods,
81                                                           It->Type, It->Size));
82   TypeIndexToSymbolId[Index] = Id;
83   return Id;
84 }
85 
86 SymIndexId
87 SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
88                                          codeview::CVType CVT) {
89   ModifierRecord Record;
90   if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
91     consumeError(std::move(EC));
92     return 0;
93   }
94 
95   if (Record.ModifiedType.isSimple())
96     return createSimpleType(Record.ModifiedType, Record.Modifiers);
97 
98   auto Tpi = Session.getPDBFile().getPDBTpiStream();
99   if (!Tpi) {
100     consumeError(Tpi.takeError());
101     return 0;
102   }
103   codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
104 
105   codeview::CVType UnmodifiedType = Types.getType(Record.ModifiedType);
106 
107   switch (UnmodifiedType.kind()) {
108   case LF_ENUM: {
109     EnumRecord ER;
110     if (auto EC =
111             TypeDeserializer::deserializeAs<EnumRecord>(UnmodifiedType, ER)) {
112       consumeError(std::move(EC));
113       return 0;
114     }
115     return createSymbol<NativeTypeEnum>(Record.ModifiedType, std::move(Record),
116                                         std::move(ER));
117   }
118   case LF_STRUCTURE:
119   case LF_UNION:
120   case LF_CLASS:
121     // FIXME: Handle these
122     break;
123   default:
124     // No other types can be modified.  (LF_POINTER, for example, records
125     // its modifiers a different way.
126     assert(false && "Invalid LF_MODIFIER record");
127     break;
128   }
129   return createSymbolPlaceholder();
130 }
131 
132 SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
133   // First see if it's already in our cache.
134   const auto Entry = TypeIndexToSymbolId.find(Index);
135   if (Entry != TypeIndexToSymbolId.end())
136     return Entry->second;
137 
138   // Symbols for built-in types are created on the fly.
139   if (Index.isSimple())
140     return createSimpleType(Index, ModifierOptions::None);
141 
142   // We need to instantiate and cache the desired type symbol.
143   auto Tpi = Session.getPDBFile().getPDBTpiStream();
144   if (!Tpi) {
145     consumeError(Tpi.takeError());
146     return 0;
147   }
148   codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
149   codeview::CVType CVT = Types.getType(Index);
150   // TODO(amccarth):  Make this handle all types.
151   SymIndexId Id = 0;
152 
153   switch (CVT.kind()) {
154   case codeview::LF_ENUM:
155     Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
156     break;
157   case codeview::LF_POINTER:
158     Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
159                                                                std::move(CVT));
160     break;
161   case codeview::LF_MODIFIER:
162     Id = createSymbolForModifiedType(Index, std::move(CVT));
163     break;
164   default:
165     Id = createSymbolPlaceholder();
166     break;
167   }
168   if (Id != 0)
169     TypeIndexToSymbolId[Index] = Id;
170   return Id;
171 }
172 
173 std::unique_ptr<PDBSymbol>
174 SymbolCache::getSymbolById(SymIndexId SymbolId) const {
175   assert(SymbolId < Cache.size());
176 
177   // Id 0 is reserved.
178   if (SymbolId == 0)
179     return nullptr;
180 
181   // If the caller has a SymbolId, it'd better be in our SymbolCache.
182   return SymbolId < Cache.size() ? PDBSymbol::create(Session, *Cache[SymbolId])
183                                  : nullptr;
184 }
185 
186 NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
187   return *Cache[SymbolId];
188 }
189 
190 uint32_t SymbolCache::getNumCompilands() const {
191   if (!Dbi)
192     return 0;
193 
194   return Dbi->modules().getModuleCount();
195 }
196 
197 std::unique_ptr<PDBSymbolCompiland>
198 SymbolCache::getOrCreateCompiland(uint32_t Index) {
199   if (!Dbi)
200     return nullptr;
201 
202   if (Index >= Compilands.size())
203     return nullptr;
204 
205   if (Compilands[Index] == 0) {
206     const DbiModuleList &Modules = Dbi->modules();
207     Compilands[Index] =
208         createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
209   }
210 
211   return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
212 }
213