blob: d8b4d591a97cfcffd24d8e75ca8bf0fa070d2f61 [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 Turner8ab7dd602018-09-07 00:12:34 +00004#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
5#include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
Zachary Turner8ab7dd602018-09-07 00:12:34 +00006#include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
7#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
8#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
Zachary Turner5d629962018-09-07 00:12:56 +00009#include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
10#include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
Zachary Turnerda4b63a2018-09-07 23:21:33 +000011#include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
Zachary Turner8ab7dd602018-09-07 00:12:34 +000012#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
18using namespace llvm;
Zachary Turner4d689512018-09-14 21:03:57 +000019using namespace llvm::codeview;
Zachary Turner8ab7dd602018-09-07 00:12:34 +000020using 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.
24static const struct BuiltinTypeEntry {
25 codeview::SimpleTypeKind Kind;
26 PDB_BuiltinType Type;
27 uint32_t Size;
28} BuiltinTypes[] = {
29 {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
30 {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
31 {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
32 {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
33 {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
34 {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
35 {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
36 {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
37 {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1}
38 // This table can be grown as necessary, but these are the only types we've
39 // needed so far.
40};
41
42SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
43 : Session(Session), Dbi(Dbi) {
44 // Id 0 is reserved for the invalid symbol.
45 Cache.push_back(nullptr);
46
47 if (Dbi)
48 Compilands.resize(Dbi->modules().getModuleCount());
49}
50
Zachary Turner8ab7dd602018-09-07 00:12:34 +000051std::unique_ptr<IPDBEnumSymbols>
52SymbolCache::createTypeEnumerator(codeview::TypeLeafKind Kind) {
53 auto Tpi = Session.getPDBFile().getPDBTpiStream();
54 if (!Tpi) {
55 consumeError(Tpi.takeError());
56 return nullptr;
57 }
58 auto &Types = Tpi->typeCollection();
59 return std::unique_ptr<IPDBEnumSymbols>(
Zachary Turnerda4b63a2018-09-07 23:21:33 +000060 new NativeEnumTypes(Session, Types, Kind));
Zachary Turner8ab7dd602018-09-07 00:12:34 +000061}
62
Zachary Turner4727ac22018-09-17 21:07:48 +000063SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
64 ModifierOptions Mods) {
65 // FIXME: We will eventually need to handle pointers to other simple types,
66 // which are still simple types in the world of CodeView TypeIndexes.
67 if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
68 return 0;
69
70 const auto Kind = Index.getSimpleKind();
71 const auto It = std::find_if(
72 std::begin(BuiltinTypes), std::end(BuiltinTypes),
73 [Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; });
74 if (It == std::end(BuiltinTypes))
75 return 0;
76 SymIndexId Id = Cache.size();
77 Cache.emplace_back(llvm::make_unique<NativeTypeBuiltin>(Session, Id, Mods,
78 It->Type, It->Size));
79 TypeIndexToSymbolId[Index] = Id;
80 return Id;
81}
82
83SymIndexId
84SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
85 codeview::CVType CVT) {
86 ModifierRecord Record;
87 if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
88 consumeError(std::move(EC));
89 return 0;
90 }
91
92 if (Record.ModifiedType.isSimple())
93 return createSimpleType(Record.ModifiedType, Record.Modifiers);
94
95 auto Tpi = Session.getPDBFile().getPDBTpiStream();
96 if (!Tpi) {
97 consumeError(Tpi.takeError());
98 return 0;
99 }
100 codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
101
102 codeview::CVType UnmodifiedType = Types.getType(Record.ModifiedType);
103
104 switch (UnmodifiedType.kind()) {
105 case LF_ENUM: {
106 EnumRecord ER;
107 if (auto EC =
108 TypeDeserializer::deserializeAs<EnumRecord>(UnmodifiedType, ER)) {
109 consumeError(std::move(EC));
110 return 0;
111 }
112 return createSymbol<NativeTypeEnum>(Record.ModifiedType, std::move(Record),
113 std::move(ER));
114 }
115 case LF_STRUCTURE:
116 case LF_UNION:
117 case LF_CLASS:
118 // FIXME: Handle these
119 break;
120 default:
121 // No other types can be modified. (LF_POINTER, for example, records
122 // its modifiers a different way.
123 assert(false && "Invalid LF_MODIFIER record");
124 break;
125 }
126 return createSymbolPlaceholder();
127}
128
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000129SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) {
130 // First see if it's already in our cache.
131 const auto Entry = TypeIndexToSymbolId.find(Index);
132 if (Entry != TypeIndexToSymbolId.end())
133 return Entry->second;
134
135 // Symbols for built-in types are created on the fly.
Zachary Turner4727ac22018-09-17 21:07:48 +0000136 if (Index.isSimple())
137 return createSimpleType(Index, ModifierOptions::None);
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000138
139 // We need to instantiate and cache the desired type symbol.
140 auto Tpi = Session.getPDBFile().getPDBTpiStream();
141 if (!Tpi) {
142 consumeError(Tpi.takeError());
143 return 0;
144 }
145 codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
Zachary Turner4d689512018-09-14 21:03:57 +0000146 codeview::CVType CVT = Types.getType(Index);
147 // TODO(amccarth): Make this handle all types.
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000148 SymIndexId Id = 0;
Zachary Turner4727ac22018-09-17 21:07:48 +0000149
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000150 switch (CVT.kind()) {
151 case codeview::LF_ENUM:
Zachary Turner4d689512018-09-14 21:03:57 +0000152 Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000153 break;
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000154 case codeview::LF_POINTER:
Zachary Turner4d689512018-09-14 21:03:57 +0000155 Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
156 std::move(CVT));
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000157 break;
Zachary Turner4727ac22018-09-17 21:07:48 +0000158 case codeview::LF_MODIFIER:
159 Id = createSymbolForModifiedType(Index, std::move(CVT));
160 break;
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000161 default:
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000162 Id = createSymbolPlaceholder();
163 break;
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000164 }
Zachary Turner4d689512018-09-14 21:03:57 +0000165 if (Id != 0)
166 TypeIndexToSymbolId[Index] = Id;
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000167 return Id;
168}
169
170std::unique_ptr<PDBSymbol>
171SymbolCache::getSymbolById(SymIndexId SymbolId) const {
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000172 // Id 0 is reserved.
173 if (SymbolId == 0)
174 return nullptr;
175
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000176 // If the caller has a SymbolId, it'd better be in our SymbolCache.
177 return SymbolId < Cache.size() ? PDBSymbol::create(Session, *Cache[SymbolId])
178 : nullptr;
179}
180
181NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
182 return *Cache[SymbolId];
183}
184
185uint32_t SymbolCache::getNumCompilands() const {
186 if (!Dbi)
187 return 0;
188
189 return Dbi->modules().getModuleCount();
190}
191
192std::unique_ptr<PDBSymbolCompiland>
193SymbolCache::getOrCreateCompiland(uint32_t Index) {
194 if (!Dbi)
195 return nullptr;
196
197 if (Index >= Compilands.size())
198 return nullptr;
199
200 if (Compilands[Index] == 0) {
201 const DbiModuleList &Modules = Dbi->modules();
202 Compilands[Index] =
203 createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
204 }
205
206 return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
207}