18ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
28ab7dd60SZachary Turner 
3eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
4641ae73fSAmy Huang #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
5eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
6eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
7a5e3e026SZachary Turner #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
8eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
94d68951eSZachary Turner #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
10eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/CodeView/TypeRecord.h"
11355ffb00SZachary Turner #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
12eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
13eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
148ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
15eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
168ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
17a5e3e026SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
18f8170d87SAmy Huang #include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
198ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
20641ae73fSAmy Huang #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
21bc980340SAmy Huang #include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"
22eb4c8608Sserge-sans-paille #include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"
23641ae73fSAmy Huang #include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
248ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
258ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
26518cb2d5SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
275d629966SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
285d629966SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
296345e84dSZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
30da4b63abSZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
31a5e3e026SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
32355ffb00SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
335c1873b2SZachary Turner #include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
348ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
35641ae73fSAmy Huang #include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
36a5e3e026SZachary Turner #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
378ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
388ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbol.h"
398ab7dd60SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
408ab7dd60SZachary Turner 
418ab7dd60SZachary Turner using namespace llvm;
424d68951eSZachary Turner using namespace llvm::codeview;
438ab7dd60SZachary Turner using namespace llvm::pdb;
448ab7dd60SZachary Turner 
458ab7dd60SZachary Turner // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
468ab7dd60SZachary Turner // to instantiate a NativeBuiltinSymbol for that type.
478ab7dd60SZachary Turner static const struct BuiltinTypeEntry {
488ab7dd60SZachary Turner   codeview::SimpleTypeKind Kind;
498ab7dd60SZachary Turner   PDB_BuiltinType Type;
508ab7dd60SZachary Turner   uint32_t Size;
518ab7dd60SZachary Turner } BuiltinTypes[] = {
525907a780SZachary Turner     {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0},
536345e84dSZachary Turner     {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},
545c1873b2SZachary Turner     {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4},
55bdf0381eSZachary Turner     {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
56bdf0381eSZachary Turner     {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
578ab7dd60SZachary Turner     {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
588ab7dd60SZachary Turner     {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
59bdf0381eSZachary Turner     {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
608ab7dd60SZachary Turner     {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
61bdf0381eSZachary Turner     {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
628ab7dd60SZachary Turner     {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
638ab7dd60SZachary Turner     {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
645c1873b2SZachary Turner     {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},
655c1873b2SZachary Turner     {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},
665c1873b2SZachary Turner     {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},
67*5c9e20d7SZequan Wu     {codeview::SimpleTypeKind::Character8, PDB_BuiltinType::Char8, 1},
688ab7dd60SZachary Turner     {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
698ab7dd60SZachary Turner     {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
705c1873b2SZachary Turner     {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4},
715c1873b2SZachary Turner     {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8},
725c1873b2SZachary Turner     {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10},
735c1873b2SZachary Turner     {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1},
748ab7dd60SZachary Turner     // This table can be grown as necessary, but these are the only types we've
758ab7dd60SZachary Turner     // needed so far.
768ab7dd60SZachary Turner };
778ab7dd60SZachary Turner 
SymbolCache(NativeSession & Session,DbiStream * Dbi)788ab7dd60SZachary Turner SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
79bc980340SAmy Huang     : Session(Session), Dbi(Dbi) {
808ab7dd60SZachary Turner   // Id 0 is reserved for the invalid symbol.
818ab7dd60SZachary Turner   Cache.push_back(nullptr);
82f8170d87SAmy Huang   SourceFiles.push_back(nullptr);
838ab7dd60SZachary Turner 
848ab7dd60SZachary Turner   if (Dbi)
858ab7dd60SZachary Turner     Compilands.resize(Dbi->modules().getModuleCount());
868ab7dd60SZachary Turner }
878ab7dd60SZachary Turner 
888ab7dd60SZachary Turner std::unique_ptr<IPDBEnumSymbols>
createTypeEnumerator(TypeLeafKind Kind)89355ffb00SZachary Turner SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
90355ffb00SZachary Turner   return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
91355ffb00SZachary Turner }
92355ffb00SZachary Turner 
93355ffb00SZachary Turner std::unique_ptr<IPDBEnumSymbols>
createTypeEnumerator(std::vector<TypeLeafKind> Kinds)94355ffb00SZachary Turner SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
958ab7dd60SZachary Turner   auto Tpi = Session.getPDBFile().getPDBTpiStream();
968ab7dd60SZachary Turner   if (!Tpi) {
978ab7dd60SZachary Turner     consumeError(Tpi.takeError());
988ab7dd60SZachary Turner     return nullptr;
998ab7dd60SZachary Turner   }
1008ab7dd60SZachary Turner   auto &Types = Tpi->typeCollection();
1018ab7dd60SZachary Turner   return std::unique_ptr<IPDBEnumSymbols>(
102355ffb00SZachary Turner       new NativeEnumTypes(Session, Types, std::move(Kinds)));
1038ab7dd60SZachary Turner }
1048ab7dd60SZachary Turner 
105a5e3e026SZachary Turner std::unique_ptr<IPDBEnumSymbols>
createGlobalsEnumerator(codeview::SymbolKind Kind)106a5e3e026SZachary Turner SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
107a5e3e026SZachary Turner   return std::unique_ptr<IPDBEnumSymbols>(
108a5e3e026SZachary Turner       new NativeEnumGlobals(Session, {Kind}));
109a5e3e026SZachary Turner }
110a5e3e026SZachary Turner 
createSimpleType(TypeIndex Index,ModifierOptions Mods) const1114727ac23SZachary Turner SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
112bc980340SAmy Huang                                          ModifierOptions Mods) const {
1136345e84dSZachary Turner   if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
1146345e84dSZachary Turner     return createSymbol<NativeTypePointer>(Index);
1154727ac23SZachary Turner 
1164727ac23SZachary Turner   const auto Kind = Index.getSimpleKind();
1179850d3b1SKazu Hirata   const auto It =
1189850d3b1SKazu Hirata       llvm::find_if(BuiltinTypes, [Kind](const BuiltinTypeEntry &Builtin) {
1199850d3b1SKazu Hirata         return Builtin.Kind == Kind;
1209850d3b1SKazu Hirata       });
1214727ac23SZachary Turner   if (It == std::end(BuiltinTypes))
1224727ac23SZachary Turner     return 0;
1236345e84dSZachary Turner   return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
1244727ac23SZachary Turner }
1254727ac23SZachary Turner 
1264727ac23SZachary Turner SymIndexId
createSymbolForModifiedType(codeview::TypeIndex ModifierTI,codeview::CVType CVT) const1274727ac23SZachary Turner SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
128bc980340SAmy Huang                                          codeview::CVType CVT) const {
1294727ac23SZachary Turner   ModifierRecord Record;
1304727ac23SZachary Turner   if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
1314727ac23SZachary Turner     consumeError(std::move(EC));
1324727ac23SZachary Turner     return 0;
1334727ac23SZachary Turner   }
1344727ac23SZachary Turner 
1354727ac23SZachary Turner   if (Record.ModifiedType.isSimple())
1364727ac23SZachary Turner     return createSimpleType(Record.ModifiedType, Record.Modifiers);
1374727ac23SZachary Turner 
138355ffb00SZachary Turner   // Make sure we create and cache a record for the unmodified type.
139355ffb00SZachary Turner   SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
140355ffb00SZachary Turner   NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
1414727ac23SZachary Turner 
142355ffb00SZachary Turner   switch (UnmodifiedNRS.getSymTag()) {
143355ffb00SZachary Turner   case PDB_SymType::Enum:
144355ffb00SZachary Turner     return createSymbol<NativeTypeEnum>(
145355ffb00SZachary Turner         static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
146355ffb00SZachary Turner   case PDB_SymType::UDT:
147355ffb00SZachary Turner     return createSymbol<NativeTypeUDT>(
148355ffb00SZachary Turner         static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
1494727ac23SZachary Turner   default:
1504727ac23SZachary Turner     // No other types can be modified.  (LF_POINTER, for example, records
1514727ac23SZachary Turner     // its modifiers a different way.
1524727ac23SZachary Turner     assert(false && "Invalid LF_MODIFIER record");
1534727ac23SZachary Turner     break;
1544727ac23SZachary Turner   }
155355ffb00SZachary Turner   return 0;
1564727ac23SZachary Turner }
1574727ac23SZachary Turner 
findSymbolByTypeIndex(codeview::TypeIndex Index) const158bc980340SAmy Huang SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) const {
1598ab7dd60SZachary Turner   // First see if it's already in our cache.
1608ab7dd60SZachary Turner   const auto Entry = TypeIndexToSymbolId.find(Index);
1618ab7dd60SZachary Turner   if (Entry != TypeIndexToSymbolId.end())
1628ab7dd60SZachary Turner     return Entry->second;
1638ab7dd60SZachary Turner 
1648ab7dd60SZachary Turner   // Symbols for built-in types are created on the fly.
1656345e84dSZachary Turner   if (Index.isSimple()) {
1666345e84dSZachary Turner     SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
1676345e84dSZachary Turner     assert(TypeIndexToSymbolId.count(Index) == 0);
1686345e84dSZachary Turner     TypeIndexToSymbolId[Index] = Result;
1696345e84dSZachary Turner     return Result;
1706345e84dSZachary Turner   }
1718ab7dd60SZachary Turner 
1728ab7dd60SZachary Turner   // We need to instantiate and cache the desired type symbol.
1738ab7dd60SZachary Turner   auto Tpi = Session.getPDBFile().getPDBTpiStream();
1748ab7dd60SZachary Turner   if (!Tpi) {
1758ab7dd60SZachary Turner     consumeError(Tpi.takeError());
1768ab7dd60SZachary Turner     return 0;
1778ab7dd60SZachary Turner   }
1788ab7dd60SZachary Turner   codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
1794d68951eSZachary Turner   codeview::CVType CVT = Types.getType(Index);
1804727ac23SZachary Turner 
181355ffb00SZachary Turner   if (isUdtForwardRef(CVT)) {
182355ffb00SZachary Turner     Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
183355ffb00SZachary Turner 
184355ffb00SZachary Turner     if (!EFD)
185355ffb00SZachary Turner       consumeError(EFD.takeError());
186355ffb00SZachary Turner     else if (*EFD != Index) {
187355ffb00SZachary Turner       assert(!isUdtForwardRef(Types.getType(*EFD)));
188355ffb00SZachary Turner       SymIndexId Result = findSymbolByTypeIndex(*EFD);
189355ffb00SZachary Turner       // Record a mapping from ForwardRef -> SymIndex of complete type so that
190355ffb00SZachary Turner       // we'll take the fast path next time.
1916345e84dSZachary Turner       assert(TypeIndexToSymbolId.count(Index) == 0);
192355ffb00SZachary Turner       TypeIndexToSymbolId[Index] = Result;
193355ffb00SZachary Turner       return Result;
194355ffb00SZachary Turner     }
195355ffb00SZachary Turner   }
196355ffb00SZachary Turner 
197355ffb00SZachary Turner   // At this point if we still have a forward ref udt it means the full decl was
198355ffb00SZachary Turner   // not in the PDB.  We just have to deal with it and use the forward ref.
199355ffb00SZachary Turner   SymIndexId Id = 0;
2008ab7dd60SZachary Turner   switch (CVT.kind()) {
2018ab7dd60SZachary Turner   case codeview::LF_ENUM:
2024d68951eSZachary Turner     Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
2038ab7dd60SZachary Turner     break;
204518cb2d5SZachary Turner   case codeview::LF_ARRAY:
205518cb2d5SZachary Turner     Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
206518cb2d5SZachary Turner                                                            std::move(CVT));
207518cb2d5SZachary Turner     break;
208355ffb00SZachary Turner   case codeview::LF_CLASS:
209355ffb00SZachary Turner   case codeview::LF_STRUCTURE:
210355ffb00SZachary Turner   case codeview::LF_INTERFACE:
211355ffb00SZachary Turner     Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
212355ffb00SZachary Turner     break;
213355ffb00SZachary Turner   case codeview::LF_UNION:
214355ffb00SZachary Turner     Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
215355ffb00SZachary Turner     break;
216da4b63abSZachary Turner   case codeview::LF_POINTER:
2174d68951eSZachary Turner     Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
2184d68951eSZachary Turner                                                                std::move(CVT));
219da4b63abSZachary Turner     break;
2204727ac23SZachary Turner   case codeview::LF_MODIFIER:
2214727ac23SZachary Turner     Id = createSymbolForModifiedType(Index, std::move(CVT));
2224727ac23SZachary Turner     break;
2236345e84dSZachary Turner   case codeview::LF_PROCEDURE:
2246345e84dSZachary Turner     Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
2256345e84dSZachary Turner         Index, std::move(CVT));
2266345e84dSZachary Turner     break;
2276345e84dSZachary Turner   case codeview::LF_MFUNCTION:
2286345e84dSZachary Turner     Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
2296345e84dSZachary Turner         Index, std::move(CVT));
2306345e84dSZachary Turner     break;
2315c1873b2SZachary Turner   case codeview::LF_VTSHAPE:
2325c1873b2SZachary Turner     Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
2335c1873b2SZachary Turner         Index, std::move(CVT));
2345c1873b2SZachary Turner     break;
2358ab7dd60SZachary Turner   default:
236da4b63abSZachary Turner     Id = createSymbolPlaceholder();
237da4b63abSZachary Turner     break;
2388ab7dd60SZachary Turner   }
2396345e84dSZachary Turner   if (Id != 0) {
2406345e84dSZachary Turner     assert(TypeIndexToSymbolId.count(Index) == 0);
2418ab7dd60SZachary Turner     TypeIndexToSymbolId[Index] = Id;
2426345e84dSZachary Turner   }
2438ab7dd60SZachary Turner   return Id;
2448ab7dd60SZachary Turner }
2458ab7dd60SZachary Turner 
2468ab7dd60SZachary Turner std::unique_ptr<PDBSymbol>
getSymbolById(SymIndexId SymbolId) const2478ab7dd60SZachary Turner SymbolCache::getSymbolById(SymIndexId SymbolId) const {
248bdf0381eSZachary Turner   assert(SymbolId < Cache.size());
249bdf0381eSZachary Turner 
250da4b63abSZachary Turner   // Id 0 is reserved.
251c41ce835SZachary Turner   if (SymbolId == 0 || SymbolId >= Cache.size())
252da4b63abSZachary Turner     return nullptr;
253da4b63abSZachary Turner 
254c41ce835SZachary Turner   // Make sure to handle the case where we've inserted a placeholder symbol
255cf16437eSNico Weber   // for types we don't yet support.
256c41ce835SZachary Turner   NativeRawSymbol *NRS = Cache[SymbolId].get();
257c41ce835SZachary Turner   if (!NRS)
258c41ce835SZachary Turner     return nullptr;
259c41ce835SZachary Turner 
260c41ce835SZachary Turner   return PDBSymbol::create(Session, *NRS);
2618ab7dd60SZachary Turner }
2628ab7dd60SZachary Turner 
getNativeSymbolById(SymIndexId SymbolId) const2638ab7dd60SZachary Turner NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
2648ab7dd60SZachary Turner   return *Cache[SymbolId];
2658ab7dd60SZachary Turner }
2668ab7dd60SZachary Turner 
getNumCompilands() const2678ab7dd60SZachary Turner uint32_t SymbolCache::getNumCompilands() const {
2688ab7dd60SZachary Turner   if (!Dbi)
2698ab7dd60SZachary Turner     return 0;
2708ab7dd60SZachary Turner 
2718ab7dd60SZachary Turner   return Dbi->modules().getModuleCount();
2728ab7dd60SZachary Turner }
2738ab7dd60SZachary Turner 
getOrCreateGlobalSymbolByOffset(uint32_t Offset)274a5e3e026SZachary Turner SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
275a5e3e026SZachary Turner   auto Iter = GlobalOffsetToSymbolId.find(Offset);
276a5e3e026SZachary Turner   if (Iter != GlobalOffsetToSymbolId.end())
277a5e3e026SZachary Turner     return Iter->second;
278a5e3e026SZachary Turner 
279a5e3e026SZachary Turner   SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
280a5e3e026SZachary Turner   CVSymbol CVS = SS.readRecord(Offset);
281a5e3e026SZachary Turner   SymIndexId Id = 0;
282a5e3e026SZachary Turner   switch (CVS.kind()) {
283a5e3e026SZachary Turner   case SymbolKind::S_UDT: {
284a5e3e026SZachary Turner     UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
285a5e3e026SZachary Turner     Id = createSymbol<NativeTypeTypedef>(std::move(US));
286a5e3e026SZachary Turner     break;
287a5e3e026SZachary Turner   }
288a5e3e026SZachary Turner   default:
289a5e3e026SZachary Turner     Id = createSymbolPlaceholder();
290a5e3e026SZachary Turner     break;
291a5e3e026SZachary Turner   }
292a5e3e026SZachary Turner   if (Id != 0) {
293a5e3e026SZachary Turner     assert(GlobalOffsetToSymbolId.count(Offset) == 0);
294a5e3e026SZachary Turner     GlobalOffsetToSymbolId[Offset] = Id;
295a5e3e026SZachary Turner   }
296a5e3e026SZachary Turner 
297a5e3e026SZachary Turner   return Id;
298a5e3e026SZachary Turner }
299a5e3e026SZachary Turner 
getOrCreateInlineSymbol(InlineSiteSym Sym,uint64_t ParentAddr,uint16_t Modi,uint32_t RecordOffset) const300bc980340SAmy Huang SymIndexId SymbolCache::getOrCreateInlineSymbol(InlineSiteSym Sym,
301bc980340SAmy Huang                                                 uint64_t ParentAddr,
302bc980340SAmy Huang                                                 uint16_t Modi,
303bc980340SAmy Huang                                                 uint32_t RecordOffset) const {
304bc980340SAmy Huang   auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
305bc980340SAmy Huang   if (Iter != SymTabOffsetToSymbolId.end())
306bc980340SAmy Huang     return Iter->second;
307f8170d87SAmy Huang 
308bc980340SAmy Huang   SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(Sym, ParentAddr);
309bc980340SAmy Huang   SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
310bc980340SAmy Huang   return Id;
311f8170d87SAmy Huang }
312f8170d87SAmy Huang 
313641ae73fSAmy Huang std::unique_ptr<PDBSymbol>
findSymbolBySectOffset(uint32_t Sect,uint32_t Offset,PDB_SymType Type)314641ae73fSAmy Huang SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
315641ae73fSAmy Huang                                     PDB_SymType Type) {
316641ae73fSAmy Huang   switch (Type) {
317641ae73fSAmy Huang   case PDB_SymType::Function:
318641ae73fSAmy Huang     return findFunctionSymbolBySectOffset(Sect, Offset);
319641ae73fSAmy Huang   case PDB_SymType::PublicSymbol:
320641ae73fSAmy Huang     return findPublicSymbolBySectOffset(Sect, Offset);
3210881d0beSAmy Huang   case PDB_SymType::Compiland: {
322bc980340SAmy Huang     uint16_t Modi;
323bc980340SAmy Huang     if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
3240881d0beSAmy Huang       return nullptr;
325bc980340SAmy Huang     return getOrCreateCompiland(Modi);
3260881d0beSAmy Huang   }
327641ae73fSAmy Huang   case PDB_SymType::None: {
3280881d0beSAmy Huang     // FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but
3290881d0beSAmy Huang     // only uses it to find the symbol length.
330641ae73fSAmy Huang     if (auto Sym = findFunctionSymbolBySectOffset(Sect, Offset))
331641ae73fSAmy Huang       return Sym;
332641ae73fSAmy Huang     return nullptr;
333641ae73fSAmy Huang   }
334641ae73fSAmy Huang   default:
335641ae73fSAmy Huang     return nullptr;
336641ae73fSAmy Huang   }
337641ae73fSAmy Huang }
338641ae73fSAmy Huang 
339641ae73fSAmy Huang std::unique_ptr<PDBSymbol>
findFunctionSymbolBySectOffset(uint32_t Sect,uint32_t Offset)340641ae73fSAmy Huang SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
3410881d0beSAmy Huang   auto Iter = AddressToSymbolId.find({Sect, Offset});
3420881d0beSAmy Huang   if (Iter != AddressToSymbolId.end())
343641ae73fSAmy Huang     return getSymbolById(Iter->second);
344641ae73fSAmy Huang 
345641ae73fSAmy Huang   if (!Dbi)
346641ae73fSAmy Huang     return nullptr;
347641ae73fSAmy Huang 
348bc980340SAmy Huang   uint16_t Modi;
349bc980340SAmy Huang   if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
350641ae73fSAmy Huang     return nullptr;
351641ae73fSAmy Huang 
352bc980340SAmy Huang   Expected<ModuleDebugStreamRef> ExpectedModS =
353bc980340SAmy Huang       Session.getModuleDebugStream(Modi);
354f8170d87SAmy Huang   if (!ExpectedModS) {
355f8170d87SAmy Huang     consumeError(ExpectedModS.takeError());
356641ae73fSAmy Huang     return nullptr;
357641ae73fSAmy Huang   }
358f8170d87SAmy Huang   CVSymbolArray Syms = ExpectedModS->getSymbolArray();
359641ae73fSAmy Huang 
360641ae73fSAmy Huang   // Search for the symbol in this module.
361641ae73fSAmy Huang   for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
362641ae73fSAmy Huang     if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32)
363641ae73fSAmy Huang       continue;
364641ae73fSAmy Huang     auto PS = cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*I));
365641ae73fSAmy Huang     if (Sect == PS.Segment && Offset >= PS.CodeOffset &&
366641ae73fSAmy Huang         Offset < PS.CodeOffset + PS.CodeSize) {
3670881d0beSAmy Huang       // Check if the symbol is already cached.
3680881d0beSAmy Huang       auto Found = AddressToSymbolId.find({PS.Segment, PS.CodeOffset});
3690881d0beSAmy Huang       if (Found != AddressToSymbolId.end())
3700881d0beSAmy Huang         return getSymbolById(Found->second);
3710881d0beSAmy Huang 
3720881d0beSAmy Huang       // Otherwise, create a new symbol.
373bc980340SAmy Huang       SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS, I.offset());
3740881d0beSAmy Huang       AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id});
375641ae73fSAmy Huang       return getSymbolById(Id);
376641ae73fSAmy Huang     }
377641ae73fSAmy Huang 
378641ae73fSAmy Huang     // Jump to the end of this ProcSym.
379641ae73fSAmy Huang     I = Syms.at(PS.End);
380641ae73fSAmy Huang   }
381641ae73fSAmy Huang   return nullptr;
382641ae73fSAmy Huang }
383641ae73fSAmy Huang 
384641ae73fSAmy Huang std::unique_ptr<PDBSymbol>
findPublicSymbolBySectOffset(uint32_t Sect,uint32_t Offset)385641ae73fSAmy Huang SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
386641ae73fSAmy Huang   auto Iter = AddressToPublicSymId.find({Sect, Offset});
387641ae73fSAmy Huang   if (Iter != AddressToPublicSymId.end())
388641ae73fSAmy Huang     return getSymbolById(Iter->second);
389641ae73fSAmy Huang 
390641ae73fSAmy Huang   auto Publics = Session.getPDBFile().getPDBPublicsStream();
391641ae73fSAmy Huang   if (!Publics)
392641ae73fSAmy Huang     return nullptr;
393641ae73fSAmy Huang 
394641ae73fSAmy Huang   auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();
395641ae73fSAmy Huang   if (!ExpectedSyms)
396641ae73fSAmy Huang     return nullptr;
397641ae73fSAmy Huang   BinaryStreamRef SymStream =
398641ae73fSAmy Huang       ExpectedSyms->getSymbolArray().getUnderlyingStream();
399641ae73fSAmy Huang 
400641ae73fSAmy Huang   // Use binary search to find the first public symbol with an address greater
401641ae73fSAmy Huang   // than or equal to Sect, Offset.
402641ae73fSAmy Huang   auto AddrMap = Publics->getAddressMap();
403641ae73fSAmy Huang   auto First = AddrMap.begin();
404641ae73fSAmy Huang   auto It = AddrMap.begin();
405641ae73fSAmy Huang   size_t Count = AddrMap.size();
406641ae73fSAmy Huang   size_t Half;
407641ae73fSAmy Huang   while (Count > 0) {
408641ae73fSAmy Huang     It = First;
409641ae73fSAmy Huang     Half = Count / 2;
410641ae73fSAmy Huang     It += Half;
411641ae73fSAmy Huang     Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
412641ae73fSAmy Huang     if (!Sym) {
413641ae73fSAmy Huang       consumeError(Sym.takeError());
414641ae73fSAmy Huang       return nullptr;
415641ae73fSAmy Huang     }
416641ae73fSAmy Huang 
417641ae73fSAmy Huang     auto PS =
418641ae73fSAmy Huang         cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
419641ae73fSAmy Huang     if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) {
420641ae73fSAmy Huang       First = ++It;
421641ae73fSAmy Huang       Count -= Half + 1;
422641ae73fSAmy Huang     } else
423641ae73fSAmy Huang       Count = Half;
424641ae73fSAmy Huang   }
425f8170d87SAmy Huang   if (It == AddrMap.begin())
426f8170d87SAmy Huang     return nullptr;
427641ae73fSAmy Huang   --It;
428641ae73fSAmy Huang 
429641ae73fSAmy Huang   Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
430641ae73fSAmy Huang   if (!Sym) {
431641ae73fSAmy Huang     consumeError(Sym.takeError());
432641ae73fSAmy Huang     return nullptr;
433641ae73fSAmy Huang   }
4340881d0beSAmy Huang 
4350881d0beSAmy Huang   // Check if the symbol is already cached.
436641ae73fSAmy Huang   auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
4370881d0beSAmy Huang   auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});
4380881d0beSAmy Huang   if (Found != AddressToPublicSymId.end())
4390881d0beSAmy Huang     return getSymbolById(Found->second);
4400881d0beSAmy Huang 
4410881d0beSAmy Huang   // Otherwise, create a new symbol.
442641ae73fSAmy Huang   SymIndexId Id = createSymbol<NativePublicSymbol>(PS);
4430881d0beSAmy Huang   AddressToPublicSymId.insert({{PS.Segment, PS.Offset}, Id});
444641ae73fSAmy Huang   return getSymbolById(Id);
445641ae73fSAmy Huang }
446641ae73fSAmy Huang 
447f8170d87SAmy Huang std::vector<SymbolCache::LineTableEntry>
findLineTable(uint16_t Modi) const448f8170d87SAmy Huang SymbolCache::findLineTable(uint16_t Modi) const {
449f8170d87SAmy Huang   // Check if this module has already been added.
450f8170d87SAmy Huang   auto LineTableIter = LineTable.find(Modi);
451f8170d87SAmy Huang   if (LineTableIter != LineTable.end())
452f8170d87SAmy Huang     return LineTableIter->second;
453f8170d87SAmy Huang 
454f8170d87SAmy Huang   std::vector<LineTableEntry> &ModuleLineTable = LineTable[Modi];
455f8170d87SAmy Huang 
456f8170d87SAmy Huang   // If there is an error or there are no lines, just return the
457f8170d87SAmy Huang   // empty vector.
458bc980340SAmy Huang   Expected<ModuleDebugStreamRef> ExpectedModS =
459bc980340SAmy Huang       Session.getModuleDebugStream(Modi);
460f8170d87SAmy Huang   if (!ExpectedModS) {
461f8170d87SAmy Huang     consumeError(ExpectedModS.takeError());
462f8170d87SAmy Huang     return ModuleLineTable;
463f8170d87SAmy Huang   }
464f8170d87SAmy Huang 
465f8170d87SAmy Huang   std::vector<std::vector<LineTableEntry>> EntryList;
466f8170d87SAmy Huang   for (const auto &SS : ExpectedModS->getSubsectionsArray()) {
467f8170d87SAmy Huang     if (SS.kind() != DebugSubsectionKind::Lines)
468f8170d87SAmy Huang       continue;
469f8170d87SAmy Huang 
470f8170d87SAmy Huang     DebugLinesSubsectionRef Lines;
471f8170d87SAmy Huang     BinaryStreamReader Reader(SS.getRecordData());
472f8170d87SAmy Huang     if (auto EC = Lines.initialize(Reader)) {
473f8170d87SAmy Huang       consumeError(std::move(EC));
474f8170d87SAmy Huang       continue;
475f8170d87SAmy Huang     }
476f8170d87SAmy Huang 
477f8170d87SAmy Huang     uint32_t RelocSegment = Lines.header()->RelocSegment;
478f8170d87SAmy Huang     uint32_t RelocOffset = Lines.header()->RelocOffset;
479f8170d87SAmy Huang     for (const LineColumnEntry &Group : Lines) {
480f8170d87SAmy Huang       if (Group.LineNumbers.empty())
481f8170d87SAmy Huang         continue;
482f8170d87SAmy Huang 
483f8170d87SAmy Huang       std::vector<LineTableEntry> Entries;
4849ee90a49SAmy Huang 
4859ee90a49SAmy Huang       // If there are column numbers, then they should be in a parallel stream
4869ee90a49SAmy Huang       // to the line numbers.
4879ee90a49SAmy Huang       auto ColIt = Group.Columns.begin();
4889ee90a49SAmy Huang       auto ColsEnd = Group.Columns.end();
4899ee90a49SAmy Huang 
4907e13694aSAmy Huang       // Add a line to mark the beginning of this section.
4917e13694aSAmy Huang       uint64_t StartAddr =
4927e13694aSAmy Huang           Session.getVAFromSectOffset(RelocSegment, RelocOffset);
4937e13694aSAmy Huang       LineInfo FirstLine(Group.LineNumbers.front().Flags);
4947e13694aSAmy Huang       uint32_t ColNum =
4957e13694aSAmy Huang           (Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;
4967e13694aSAmy Huang       Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex, false});
4977e13694aSAmy Huang 
498f8170d87SAmy Huang       for (const LineNumberEntry &LN : Group.LineNumbers) {
499f8170d87SAmy Huang         uint64_t VA =
500f8170d87SAmy Huang             Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset);
5019ee90a49SAmy Huang         LineInfo Line(LN.Flags);
5027e13694aSAmy Huang         ColNum = 0;
5039ee90a49SAmy Huang 
5049ee90a49SAmy Huang         if (Lines.hasColumnInfo() && ColIt != ColsEnd) {
5059ee90a49SAmy Huang           ColNum = ColIt->StartColumn;
5069ee90a49SAmy Huang           ++ColIt;
5079ee90a49SAmy Huang         }
5089ee90a49SAmy Huang         Entries.push_back({VA, Line, ColNum, Group.NameIndex, false});
509f8170d87SAmy Huang       }
510f8170d87SAmy Huang 
511f8170d87SAmy Huang       // Add a terminal entry line to mark the end of this subsection.
5127e13694aSAmy Huang       uint64_t EndAddr = StartAddr + Lines.header()->CodeSize;
5139ee90a49SAmy Huang       LineInfo LastLine(Group.LineNumbers.back().Flags);
5147e13694aSAmy Huang       ColNum = (Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0;
5157e13694aSAmy Huang       Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex, true});
5169ee90a49SAmy Huang 
517f8170d87SAmy Huang       EntryList.push_back(Entries);
518f8170d87SAmy Huang     }
519f8170d87SAmy Huang   }
520f8170d87SAmy Huang 
521f8170d87SAmy Huang   // Sort EntryList, and add flattened contents to the line table.
522352fcfc6SKazu Hirata   llvm::sort(EntryList, [](const std::vector<LineTableEntry> &LHS,
523f8170d87SAmy Huang                            const std::vector<LineTableEntry> &RHS) {
524f8170d87SAmy Huang     return LHS[0].Addr < RHS[0].Addr;
525f8170d87SAmy Huang   });
526c23ebf17SKazu Hirata   for (std::vector<LineTableEntry> &I : EntryList)
527c23ebf17SKazu Hirata     llvm::append_range(ModuleLineTable, I);
528f8170d87SAmy Huang 
529f8170d87SAmy Huang   return ModuleLineTable;
530f8170d87SAmy Huang }
531f8170d87SAmy Huang 
532f8170d87SAmy Huang std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByVA(uint64_t VA,uint32_t Length) const533f8170d87SAmy Huang SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
534bc980340SAmy Huang   uint16_t Modi;
535bc980340SAmy Huang   if (!Session.moduleIndexForVA(VA, Modi))
536f8170d87SAmy Huang     return nullptr;
537f8170d87SAmy Huang 
538f8170d87SAmy Huang   std::vector<LineTableEntry> Lines = findLineTable(Modi);
539f8170d87SAmy Huang   if (Lines.empty())
540f8170d87SAmy Huang     return nullptr;
541f8170d87SAmy Huang 
542f8170d87SAmy Huang   // Find the first line in the line table whose address is not greater than
543f8170d87SAmy Huang   // the one we are searching for.
544f8170d87SAmy Huang   auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) {
545f8170d87SAmy Huang     return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
546f8170d87SAmy Huang   });
547f8170d87SAmy Huang 
548f8170d87SAmy Huang   // Try to back up if we've gone too far.
549f8170d87SAmy Huang   if (LineIter == Lines.end() || LineIter->Addr > VA) {
550f8170d87SAmy Huang     if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
551f8170d87SAmy Huang       return nullptr;
552f8170d87SAmy Huang     --LineIter;
553f8170d87SAmy Huang   }
554f8170d87SAmy Huang 
555bc980340SAmy Huang   Expected<ModuleDebugStreamRef> ExpectedModS =
556bc980340SAmy Huang       Session.getModuleDebugStream(Modi);
557f8170d87SAmy Huang   if (!ExpectedModS) {
558f8170d87SAmy Huang     consumeError(ExpectedModS.takeError());
559f8170d87SAmy Huang     return nullptr;
560f8170d87SAmy Huang   }
561f8170d87SAmy Huang   Expected<DebugChecksumsSubsectionRef> ExpectedChecksums =
562f8170d87SAmy Huang       ExpectedModS->findChecksumsSubsection();
563f8170d87SAmy Huang   if (!ExpectedChecksums) {
564f8170d87SAmy Huang     consumeError(ExpectedChecksums.takeError());
565f8170d87SAmy Huang     return nullptr;
566f8170d87SAmy Huang   }
567f8170d87SAmy Huang 
568f8170d87SAmy Huang   // Populate a vector of NativeLineNumbers that have addresses in the given
569f8170d87SAmy Huang   // address range.
570f8170d87SAmy Huang   std::vector<NativeLineNumber> LineNumbers;
571bc980340SAmy Huang   while (LineIter != Lines.end()) {
572f8170d87SAmy Huang     if (LineIter->IsTerminalEntry) {
573f8170d87SAmy Huang       ++LineIter;
574f8170d87SAmy Huang       continue;
575f8170d87SAmy Huang     }
576f8170d87SAmy Huang 
577f8170d87SAmy Huang     // If the line is still within the address range, create a NativeLineNumber
578f8170d87SAmy Huang     // and add to the list.
579f8170d87SAmy Huang     if (LineIter->Addr > VA + Length)
580f8170d87SAmy Huang       break;
581f8170d87SAmy Huang 
582f8170d87SAmy Huang     uint32_t LineSect, LineOff;
583f8170d87SAmy Huang     Session.addressForVA(LineIter->Addr, LineSect, LineOff);
584f8170d87SAmy Huang     uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
585f8170d87SAmy Huang     auto ChecksumIter =
586f8170d87SAmy Huang         ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
587f8170d87SAmy Huang     uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter);
5889ee90a49SAmy Huang     NativeLineNumber LineNum(Session, LineIter->Line, LineIter->ColumnNumber,
5890881d0beSAmy Huang                              LineSect, LineOff, LineLength, SrcFileId, Modi);
590f8170d87SAmy Huang     LineNumbers.push_back(LineNum);
591f8170d87SAmy Huang     ++LineIter;
592f8170d87SAmy Huang   }
593f8170d87SAmy Huang   return std::make_unique<NativeEnumLineNumbers>(std::move(LineNumbers));
594f8170d87SAmy Huang }
595f8170d87SAmy Huang 
5968ab7dd60SZachary Turner std::unique_ptr<PDBSymbolCompiland>
getOrCreateCompiland(uint32_t Index)5978ab7dd60SZachary Turner SymbolCache::getOrCreateCompiland(uint32_t Index) {
5988ab7dd60SZachary Turner   if (!Dbi)
5998ab7dd60SZachary Turner     return nullptr;
6008ab7dd60SZachary Turner 
6018ab7dd60SZachary Turner   if (Index >= Compilands.size())
6028ab7dd60SZachary Turner     return nullptr;
6038ab7dd60SZachary Turner 
6048ab7dd60SZachary Turner   if (Compilands[Index] == 0) {
6058ab7dd60SZachary Turner     const DbiModuleList &Modules = Dbi->modules();
6068ab7dd60SZachary Turner     Compilands[Index] =
6078ab7dd60SZachary Turner         createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
6088ab7dd60SZachary Turner   }
6098ab7dd60SZachary Turner 
6108ab7dd60SZachary Turner   return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
6118ab7dd60SZachary Turner }
612641ae73fSAmy Huang 
613f8170d87SAmy Huang std::unique_ptr<IPDBSourceFile>
getSourceFileById(SymIndexId FileId) const614f8170d87SAmy Huang SymbolCache::getSourceFileById(SymIndexId FileId) const {
615f8170d87SAmy Huang   assert(FileId < SourceFiles.size());
616f8170d87SAmy Huang 
617f8170d87SAmy Huang   // Id 0 is reserved.
618f8170d87SAmy Huang   if (FileId == 0)
619f8170d87SAmy Huang     return nullptr;
620f8170d87SAmy Huang 
621f8170d87SAmy Huang   return std::unique_ptr<NativeSourceFile>(
622f8170d87SAmy Huang       new NativeSourceFile(*SourceFiles[FileId].get()));
623f8170d87SAmy Huang }
624f8170d87SAmy Huang 
625f8170d87SAmy Huang SymIndexId
getOrCreateSourceFile(const FileChecksumEntry & Checksums) const626f8170d87SAmy Huang SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {
627f8170d87SAmy Huang   auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset);
628f8170d87SAmy Huang   if (Iter != FileNameOffsetToId.end())
629f8170d87SAmy Huang     return Iter->second;
630f8170d87SAmy Huang 
631f8170d87SAmy Huang   SymIndexId Id = SourceFiles.size();
632f8170d87SAmy Huang   auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
633f8170d87SAmy Huang   SourceFiles.push_back(std::move(SrcFile));
634f8170d87SAmy Huang   FileNameOffsetToId[Checksums.FileNameOffset] = Id;
635f8170d87SAmy Huang   return Id;
636f8170d87SAmy Huang }
637f8170d87SAmy Huang 
638641ae73fSAmy Huang 
639