blob: 40b352a844cdf7d084eb998b7c6585b1c9df9fa5 [file] [log] [blame]
Zachary Turner8ab7dd602018-09-07 00:12:34 +00001#include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
2
Zachary Turner4d689512018-09-14 21:03:57 +00003#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
Zachary Turner355ffb02018-09-21 22:36:04 +00004#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
Zachary Turner8ab7dd602018-09-07 00:12:34 +00005#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
6#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
Zachary Turner8ab7dd602018-09-07 00:12:34 +00007#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
8#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
9#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
Zachary Turner518cb2d2018-09-30 16:19:18 +000010#include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
Zachary Turner5d629962018-09-07 00:12:56 +000011#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
12#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
Zachary Turner6345e842018-09-21 22:36:28 +000013#include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
Zachary Turnerda4b63a2018-09-07 23:21:33 +000014#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
Zachary Turner355ffb02018-09-21 22:36:04 +000015#include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
Zachary Turner8ab7dd602018-09-07 00:12:34 +000016#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
22using namespace llvm;
Zachary Turner4d689512018-09-14 21:03:57 +000023using namespace llvm::codeview;
Zachary Turner8ab7dd602018-09-07 00:12:34 +000024using 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.
28static const struct BuiltinTypeEntry {
29 codeview::SimpleTypeKind Kind;
30 PDB_BuiltinType Type;
31 uint32_t Size;
32} BuiltinTypes[] = {
Zachary Turner5907a782018-09-20 16:12:05 +000033 {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0},
Zachary Turner6345e842018-09-21 22:36:28 +000034 {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},
Zachary Turnerbdf03812018-09-17 21:08:11 +000035 {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
36 {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
Zachary Turner8ab7dd602018-09-07 00:12:34 +000037 {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
38 {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
Zachary Turnerbdf03812018-09-17 21:08:11 +000039 {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
Zachary Turner8ab7dd602018-09-07 00:12:34 +000040 {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
Zachary Turnerbdf03812018-09-17 21:08:11 +000041 {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
Zachary Turner8ab7dd602018-09-07 00:12:34 +000042 {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},
Zachary Turner8ab7dd602018-09-07 00:12:34 +000046 {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
51SymbolCache::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());
Zachary Turner355ffb02018-09-21 22:36:04 +000058
59 auto &Tpi = cantFail(Session.getPDBFile().getPDBTpiStream());
60 Tpi.buildHashMap();
Zachary Turner8ab7dd602018-09-07 00:12:34 +000061}
62
Zachary Turner8ab7dd602018-09-07 00:12:34 +000063std::unique_ptr<IPDBEnumSymbols>
Zachary Turner355ffb02018-09-21 22:36:04 +000064SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
65 return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
66}
67
68std::unique_ptr<IPDBEnumSymbols>
69SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
Zachary Turner8ab7dd602018-09-07 00:12:34 +000070 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>(
Zachary Turner355ffb02018-09-21 22:36:04 +000077 new NativeEnumTypes(Session, Types, std::move(Kinds)));
Zachary Turner8ab7dd602018-09-07 00:12:34 +000078}
79
Zachary Turner4727ac22018-09-17 21:07:48 +000080SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
81 ModifierOptions Mods) {
Zachary Turner6345e842018-09-21 22:36:28 +000082 if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
83 return createSymbol<NativeTypePointer>(Index);
Zachary Turner4727ac22018-09-17 21:07:48 +000084
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;
Zachary Turner6345e842018-09-21 22:36:28 +000091 return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
Zachary Turner4727ac22018-09-17 21:07:48 +000092}
93
94SymIndexId
95SymbolCache::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
Zachary Turner355ffb02018-09-21 22:36:04 +0000106 // Make sure we create and cache a record for the unmodified type.
107 SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
108 NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
Zachary Turner4727ac22018-09-17 21:07:48 +0000109
Zachary Turner355ffb02018-09-21 22:36:04 +0000110 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));
Zachary Turner4727ac22018-09-17 21:07:48 +0000117 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 }
Zachary Turner355ffb02018-09-21 22:36:04 +0000123 return 0;
Zachary Turner4727ac22018-09-17 21:07:48 +0000124}
125
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000126SymIndexId 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.
Zachary Turner6345e842018-09-21 22:36:28 +0000133 if (Index.isSimple()) {
134 SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
135 assert(TypeIndexToSymbolId.count(Index) == 0);
136 TypeIndexToSymbolId[Index] = Result;
137 return Result;
138 }
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000139
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();
Zachary Turner4d689512018-09-14 21:03:57 +0000147 codeview::CVType CVT = Types.getType(Index);
Zachary Turner4727ac22018-09-17 21:07:48 +0000148
Zachary Turner355ffb02018-09-21 22:36:04 +0000149 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.
Zachary Turner6345e842018-09-21 22:36:28 +0000159 assert(TypeIndexToSymbolId.count(Index) == 0);
Zachary Turner355ffb02018-09-21 22:36:04 +0000160 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;
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000168 switch (CVT.kind()) {
169 case codeview::LF_ENUM:
Zachary Turner4d689512018-09-14 21:03:57 +0000170 Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000171 break;
Zachary Turner518cb2d2018-09-30 16:19:18 +0000172 case codeview::LF_ARRAY:
173 Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
174 std::move(CVT));
175 break;
Zachary Turner355ffb02018-09-21 22:36:04 +0000176 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;
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000184 case codeview::LF_POINTER:
Zachary Turner4d689512018-09-14 21:03:57 +0000185 Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
186 std::move(CVT));
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000187 break;
Zachary Turner4727ac22018-09-17 21:07:48 +0000188 case codeview::LF_MODIFIER:
189 Id = createSymbolForModifiedType(Index, std::move(CVT));
190 break;
Zachary Turner6345e842018-09-21 22:36:28 +0000191 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;
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000199 default:
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000200 Id = createSymbolPlaceholder();
201 break;
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000202 }
Zachary Turner6345e842018-09-21 22:36:28 +0000203 if (Id != 0) {
204 assert(TypeIndexToSymbolId.count(Index) == 0);
Zachary Turner4d689512018-09-14 21:03:57 +0000205 TypeIndexToSymbolId[Index] = Id;
Zachary Turner6345e842018-09-21 22:36:28 +0000206 }
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000207 return Id;
208}
209
210std::unique_ptr<PDBSymbol>
211SymbolCache::getSymbolById(SymIndexId SymbolId) const {
Zachary Turnerbdf03812018-09-17 21:08:11 +0000212 assert(SymbolId < Cache.size());
213
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000214 // Id 0 is reserved.
Zachary Turnerc41ce832018-09-18 16:35:05 +0000215 if (SymbolId == 0 || SymbolId >= Cache.size())
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000216 return nullptr;
217
Zachary Turnerc41ce832018-09-18 16:35:05 +0000218 // 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);
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000225}
226
227NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
228 return *Cache[SymbolId];
229}
230
231uint32_t SymbolCache::getNumCompilands() const {
232 if (!Dbi)
233 return 0;
234
235 return Dbi->modules().getModuleCount();
236}
237
238std::unique_ptr<PDBSymbolCompiland>
239SymbolCache::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}