LLVM  8.0.1
SymbolCache.cpp
Go to the documentation of this file.
2 
27 
28 using namespace llvm;
29 using namespace llvm::codeview;
30 using namespace llvm::pdb;
31 
32 // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
33 // to instantiate a NativeBuiltinSymbol for that type.
34 static const struct BuiltinTypeEntry {
38 } BuiltinTypes[] = {
43  {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
45  {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
47  {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
49  {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
50  {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
51  {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},
52  {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},
53  {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},
54  {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
55  {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
60  // This table can be grown as necessary, but these are the only types we've
61  // needed so far.
62 };
63 
64 SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
65  : Session(Session), Dbi(Dbi) {
66  // Id 0 is reserved for the invalid symbol.
67  Cache.push_back(nullptr);
68 
69  if (Dbi)
70  Compilands.resize(Dbi->modules().getModuleCount());
71 }
72 
73 std::unique_ptr<IPDBEnumSymbols>
75  return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
76 }
77 
78 std::unique_ptr<IPDBEnumSymbols>
79 SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
80  auto Tpi = Session.getPDBFile().getPDBTpiStream();
81  if (!Tpi) {
82  consumeError(Tpi.takeError());
83  return nullptr;
84  }
85  auto &Types = Tpi->typeCollection();
86  return std::unique_ptr<IPDBEnumSymbols>(
87  new NativeEnumTypes(Session, Types, std::move(Kinds)));
88 }
89 
90 std::unique_ptr<IPDBEnumSymbols>
92  return std::unique_ptr<IPDBEnumSymbols>(
93  new NativeEnumGlobals(Session, {Kind}));
94 }
95 
96 SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
97  ModifierOptions Mods) {
99  return createSymbol<NativeTypePointer>(Index);
100 
101  const auto Kind = Index.getSimpleKind();
102  const auto It = std::find_if(
104  [Kind](const BuiltinTypeEntry &Builtin) { return Builtin.Kind == Kind; });
105  if (It == std::end(BuiltinTypes))
106  return 0;
107  return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
108 }
109 
111 SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
112  codeview::CVType CVT) {
114  if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
115  consumeError(std::move(EC));
116  return 0;
117  }
118 
119  if (Record.ModifiedType.isSimple())
120  return createSimpleType(Record.ModifiedType, Record.Modifiers);
121 
122  // Make sure we create and cache a record for the unmodified type.
123  SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
124  NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
125 
126  switch (UnmodifiedNRS.getSymTag()) {
127  case PDB_SymType::Enum:
128  return createSymbol<NativeTypeEnum>(
129  static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
130  case PDB_SymType::UDT:
131  return createSymbol<NativeTypeUDT>(
132  static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
133  default:
134  // No other types can be modified. (LF_POINTER, for example, records
135  // its modifiers a different way.
136  assert(false && "Invalid LF_MODIFIER record");
137  break;
138  }
139  return 0;
140 }
141 
143  // First see if it's already in our cache.
144  const auto Entry = TypeIndexToSymbolId.find(Index);
145  if (Entry != TypeIndexToSymbolId.end())
146  return Entry->second;
147 
148  // Symbols for built-in types are created on the fly.
149  if (Index.isSimple()) {
150  SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
151  assert(TypeIndexToSymbolId.count(Index) == 0);
152  TypeIndexToSymbolId[Index] = Result;
153  return Result;
154  }
155 
156  // We need to instantiate and cache the desired type symbol.
157  auto Tpi = Session.getPDBFile().getPDBTpiStream();
158  if (!Tpi) {
159  consumeError(Tpi.takeError());
160  return 0;
161  }
162  codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
163  codeview::CVType CVT = Types.getType(Index);
164 
165  if (isUdtForwardRef(CVT)) {
166  Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
167 
168  if (!EFD)
169  consumeError(EFD.takeError());
170  else if (*EFD != Index) {
171  assert(!isUdtForwardRef(Types.getType(*EFD)));
172  SymIndexId Result = findSymbolByTypeIndex(*EFD);
173  // Record a mapping from ForwardRef -> SymIndex of complete type so that
174  // we'll take the fast path next time.
175  assert(TypeIndexToSymbolId.count(Index) == 0);
176  TypeIndexToSymbolId[Index] = Result;
177  return Result;
178  }
179  }
180 
181  // At this point if we still have a forward ref udt it means the full decl was
182  // not in the PDB. We just have to deal with it and use the forward ref.
183  SymIndexId Id = 0;
184  switch (CVT.kind()) {
185  case codeview::LF_ENUM:
186  Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
187  break;
188  case codeview::LF_ARRAY:
189  Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
190  std::move(CVT));
191  break;
192  case codeview::LF_CLASS:
193  case codeview::LF_STRUCTURE:
194  case codeview::LF_INTERFACE:
195  Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
196  break;
197  case codeview::LF_UNION:
198  Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
199  break;
200  case codeview::LF_POINTER:
201  Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
202  std::move(CVT));
203  break;
204  case codeview::LF_MODIFIER:
205  Id = createSymbolForModifiedType(Index, std::move(CVT));
206  break;
207  case codeview::LF_PROCEDURE:
208  Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
209  Index, std::move(CVT));
210  break;
211  case codeview::LF_MFUNCTION:
212  Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
213  Index, std::move(CVT));
214  break;
215  case codeview::LF_VTSHAPE:
216  Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
217  Index, std::move(CVT));
218  break;
219  default:
220  Id = createSymbolPlaceholder();
221  break;
222  }
223  if (Id != 0) {
224  assert(TypeIndexToSymbolId.count(Index) == 0);
225  TypeIndexToSymbolId[Index] = Id;
226  }
227  return Id;
228 }
229 
230 std::unique_ptr<PDBSymbol>
232  assert(SymbolId < Cache.size());
233 
234  // Id 0 is reserved.
235  if (SymbolId == 0 || SymbolId >= Cache.size())
236  return nullptr;
237 
238  // Make sure to handle the case where we've inserted a placeholder symbol
239  // for types we don't yet suppport.
240  NativeRawSymbol *NRS = Cache[SymbolId].get();
241  if (!NRS)
242  return nullptr;
243 
244  return PDBSymbol::create(Session, *NRS);
245 }
246 
248  return *Cache[SymbolId];
249 }
250 
252  if (!Dbi)
253  return 0;
254 
255  return Dbi->modules().getModuleCount();
256 }
257 
259  auto Iter = GlobalOffsetToSymbolId.find(Offset);
260  if (Iter != GlobalOffsetToSymbolId.end())
261  return Iter->second;
262 
264  CVSymbol CVS = SS.readRecord(Offset);
265  SymIndexId Id = 0;
266  switch (CVS.kind()) {
267  case SymbolKind::S_UDT: {
268  UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
269  Id = createSymbol<NativeTypeTypedef>(std::move(US));
270  break;
271  }
272  default:
273  Id = createSymbolPlaceholder();
274  break;
275  }
276  if (Id != 0) {
277  assert(GlobalOffsetToSymbolId.count(Offset) == 0);
278  GlobalOffsetToSymbolId[Offset] = Id;
279  }
280 
281  return Id;
282 }
283 
284 std::unique_ptr<PDBSymbolCompiland>
286  if (!Dbi)
287  return nullptr;
288 
289  if (Index >= Compilands.size())
290  return nullptr;
291 
292  if (Compilands[Index] == 0) {
293  const DbiModuleList &Modules = Dbi->modules();
294  Compilands[Index] =
295  createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
296  }
297 
298  return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
299 }
void cantFail(Error Err, const char *Msg=nullptr)
Report a fatal error if Err is a failure value.
Definition: Error.h:704
std::unique_ptr< IPDBEnumSymbols > createGlobalsEnumerator(codeview::SymbolKind Kind)
Definition: SymbolCache.cpp:91
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:259
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:250
Kind kind() const
Definition: CVRecord.h:37
This class represents lattice values for constants.
Definition: AllocatorList.h:24
TypeLeafKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:34
std::unique_ptr< IPDBEnumSymbols > createTypeEnumerator(codeview::TypeLeafKind Kind)
Definition: SymbolCache.cpp:74
codeview::SimpleTypeKind Kind
Definition: SymbolCache.cpp:35
SimpleTypeKind getSimpleKind() const
Definition: TypeIndex.h:127
DbiModuleDescriptor getModuleDescriptor(uint32_t Modi) const
Error takeError()
Take ownership of the stored error.
Definition: Error.h:553
bool isUdtForwardRef(CVType CVT)
Given an arbitrary codeview type, determine if it is an LF_STRUCTURE, LF_CLASS, LF_INTERFACE, LF_UNION, or LF_ENUM with the forward ref class option.
Expected< TpiStream & > getPDBTpiStream()
Definition: PDBFile.cpp:300
static const struct BuiltinTypeEntry BuiltinTypes[]
SimpleTypeMode getSimpleMode() const
Definition: TypeIndex.h:132
uint32_t getModuleCount() const
std::unique_ptr< PDBSymbol > getSymbolById(SymIndexId SymbolId) const
Tagged union holding either a T or a Error.
Definition: CachePruning.h:23
PDB_BuiltinType Type
Definition: SymbolCache.cpp:36
std::unique_ptr< PDBSymbolCompiland > getOrCreateCompiland(uint32_t Index)
ModifierOptions
Equivalent to CV_modifier_t.
Definition: CodeView.h:299
A 32-bit type reference.
Definition: TypeIndex.h:96
* if(!EatIfPresent(lltok::kw_thread_local)) return false
ParseOptionalThreadLocal := /*empty.
Expected< SymbolStream & > getPDBSymbolStream()
Definition: PDBFile.cpp:347
const DbiModuleList & modules() const
Definition: DbiStream.cpp:208
auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range))
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1214
std::unique_ptr< T > getConcreteSymbolById(SymIndexId SymbolId) const
Definition: IPDBSession.h:42
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:982
SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset)
NativeRawSymbol & getNativeSymbolById(SymIndexId SymbolId) const
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI)
PDB_SymType getSymTag() const override
uint32_t getNumCompilands() const
SymbolKind
Duplicate copy of the above enum, but using the official CV names.
Definition: CodeView.h:48
PDB_BuiltinType
These values correspond to the Basictype enumeration, and are documented here: https://msdn.microsoft.com/en-us/library/4szdtzc3.aspx.
Definition: PDBTypes.h:275
const unsigned Kind
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static std::unique_ptr< PDBSymbol > create(const IPDBSession &PDBSession, std::unique_ptr< IPDBRawSymbol > RawSymbol)
Definition: PDBSymbol.cpp:103
Provides amortized O(1) random access to a CodeView type stream.