blob: a661227f9b64dbfc5a0f260c9bedba622b3b2666 [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[] = {
Zachary Turnerbdf03812018-09-17 21:08:11 +000029 {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
30 {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
Zachary Turner8ab7dd602018-09-07 00:12:34 +000031 {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
32 {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
Zachary Turnerbdf03812018-09-17 21:08:11 +000033 {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
Zachary Turner8ab7dd602018-09-07 00:12:34 +000034 {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
Zachary Turnerbdf03812018-09-17 21:08:11 +000035 {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
Zachary Turner8ab7dd602018-09-07 00:12:34 +000036 {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},
Zachary Turner8ab7dd602018-09-07 00:12:34 +000040 {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
45SymbolCache::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
Zachary Turner8ab7dd602018-09-07 00:12:34 +000054std::unique_ptr<IPDBEnumSymbols>
55SymbolCache::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>(
Zachary Turnerda4b63a2018-09-07 23:21:33 +000063 new NativeEnumTypes(Session, Types, Kind));
Zachary Turner8ab7dd602018-09-07 00:12:34 +000064}
65
Zachary Turner4727ac22018-09-17 21:07:48 +000066SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
67 ModifierOptions Mods) {
Zachary Turnerc41ce832018-09-18 16:35:05 +000068 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 }
Zachary Turner4727ac22018-09-17 21:07:48 +000074
Zachary Turnerc41ce832018-09-18 16:35:05 +000075 SymIndexId Id = Cache.size();
Zachary Turner4727ac22018-09-17 21:07:48 +000076 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;
Zachary Turner4727ac22018-09-17 21:07:48 +000082 Cache.emplace_back(llvm::make_unique<NativeTypeBuiltin>(Session, Id, Mods,
83 It->Type, It->Size));
84 TypeIndexToSymbolId[Index] = Id;
85 return Id;
86}
87
88SymIndexId
89SymbolCache::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
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000134SymIndexId 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.
Zachary Turner4727ac22018-09-17 21:07:48 +0000141 if (Index.isSimple())
142 return createSimpleType(Index, ModifierOptions::None);
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000143
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();
Zachary Turner4d689512018-09-14 21:03:57 +0000151 codeview::CVType CVT = Types.getType(Index);
152 // TODO(amccarth): Make this handle all types.
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000153 SymIndexId Id = 0;
Zachary Turner4727ac22018-09-17 21:07:48 +0000154
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000155 switch (CVT.kind()) {
156 case codeview::LF_ENUM:
Zachary Turner4d689512018-09-14 21:03:57 +0000157 Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000158 break;
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000159 case codeview::LF_POINTER:
Zachary Turner4d689512018-09-14 21:03:57 +0000160 Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
161 std::move(CVT));
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000162 break;
Zachary Turner4727ac22018-09-17 21:07:48 +0000163 case codeview::LF_MODIFIER:
164 Id = createSymbolForModifiedType(Index, std::move(CVT));
165 break;
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000166 default:
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000167 Id = createSymbolPlaceholder();
168 break;
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000169 }
Zachary Turner4d689512018-09-14 21:03:57 +0000170 if (Id != 0)
171 TypeIndexToSymbolId[Index] = Id;
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000172 return Id;
173}
174
175std::unique_ptr<PDBSymbol>
176SymbolCache::getSymbolById(SymIndexId SymbolId) const {
Zachary Turnerbdf03812018-09-17 21:08:11 +0000177 assert(SymbolId < Cache.size());
178
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000179 // Id 0 is reserved.
Zachary Turnerc41ce832018-09-18 16:35:05 +0000180 if (SymbolId == 0 || SymbolId >= Cache.size())
Zachary Turnerda4b63a2018-09-07 23:21:33 +0000181 return nullptr;
182
Zachary Turnerc41ce832018-09-18 16:35:05 +0000183 // 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);
Zachary Turner8ab7dd602018-09-07 00:12:34 +0000190}
191
192NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
193 return *Cache[SymbolId];
194}
195
196uint32_t SymbolCache::getNumCompilands() const {
197 if (!Dbi)
198 return 0;
199
200 return Dbi->modules().getModuleCount();
201}
202
203std::unique_ptr<PDBSymbolCompiland>
204SymbolCache::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}