10b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/SymbolCache.h"
20b57cec5SDimitry Andric 
381ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
45ffd83dbSDimitry Andric #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
581ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
681ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
70b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
881ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
90b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
1081ad6265SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeRecord.h"
110b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"
1281ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
1381ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
140b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
1581ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
160b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeCompilandSymbol.h"
170b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeEnumGlobals.h"
185ffd83dbSDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h"
190b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeEnumTypes.h"
205ffd83dbSDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h"
21e8d8bef9SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h"
2281ad6265SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"
235ffd83dbSDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativePublicSymbol.h"
240b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
250b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeSession.h"
260b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeTypeArray.h"
270b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeTypeBuiltin.h"
280b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeTypeEnum.h"
290b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h"
300b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeTypePointer.h"
310b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h"
320b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeTypeUDT.h"
330b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h"
340b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h"
355ffd83dbSDimitry Andric #include "llvm/DebugInfo/PDB/Native/PublicsStream.h"
360b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/SymbolStream.h"
370b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h"
380b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbol.h"
390b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
400b57cec5SDimitry Andric 
410b57cec5SDimitry Andric using namespace llvm;
420b57cec5SDimitry Andric using namespace llvm::codeview;
430b57cec5SDimitry Andric using namespace llvm::pdb;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric // Maps codeview::SimpleTypeKind of a built-in type to the parameters necessary
460b57cec5SDimitry Andric // to instantiate a NativeBuiltinSymbol for that type.
470b57cec5SDimitry Andric static const struct BuiltinTypeEntry {
480b57cec5SDimitry Andric   codeview::SimpleTypeKind Kind;
490b57cec5SDimitry Andric   PDB_BuiltinType Type;
500b57cec5SDimitry Andric   uint32_t Size;
510b57cec5SDimitry Andric } BuiltinTypes[] = {
520b57cec5SDimitry Andric     {codeview::SimpleTypeKind::None, PDB_BuiltinType::None, 0},
530b57cec5SDimitry Andric     {codeview::SimpleTypeKind::Void, PDB_BuiltinType::Void, 0},
540b57cec5SDimitry Andric     {codeview::SimpleTypeKind::HResult, PDB_BuiltinType::HResult, 4},
550b57cec5SDimitry Andric     {codeview::SimpleTypeKind::Int16Short, PDB_BuiltinType::Int, 2},
560b57cec5SDimitry Andric     {codeview::SimpleTypeKind::UInt16Short, PDB_BuiltinType::UInt, 2},
570b57cec5SDimitry Andric     {codeview::SimpleTypeKind::Int32, PDB_BuiltinType::Int, 4},
580b57cec5SDimitry Andric     {codeview::SimpleTypeKind::UInt32, PDB_BuiltinType::UInt, 4},
590b57cec5SDimitry Andric     {codeview::SimpleTypeKind::Int32Long, PDB_BuiltinType::Int, 4},
600b57cec5SDimitry Andric     {codeview::SimpleTypeKind::UInt32Long, PDB_BuiltinType::UInt, 4},
610b57cec5SDimitry Andric     {codeview::SimpleTypeKind::Int64Quad, PDB_BuiltinType::Int, 8},
620b57cec5SDimitry Andric     {codeview::SimpleTypeKind::UInt64Quad, PDB_BuiltinType::UInt, 8},
630b57cec5SDimitry Andric     {codeview::SimpleTypeKind::NarrowCharacter, PDB_BuiltinType::Char, 1},
640b57cec5SDimitry Andric     {codeview::SimpleTypeKind::WideCharacter, PDB_BuiltinType::WCharT, 2},
650b57cec5SDimitry Andric     {codeview::SimpleTypeKind::Character16, PDB_BuiltinType::Char16, 2},
660b57cec5SDimitry Andric     {codeview::SimpleTypeKind::Character32, PDB_BuiltinType::Char32, 4},
6781ad6265SDimitry Andric     {codeview::SimpleTypeKind::Character8, PDB_BuiltinType::Char8, 1},
680b57cec5SDimitry Andric     {codeview::SimpleTypeKind::SignedCharacter, PDB_BuiltinType::Char, 1},
690b57cec5SDimitry Andric     {codeview::SimpleTypeKind::UnsignedCharacter, PDB_BuiltinType::UInt, 1},
700b57cec5SDimitry Andric     {codeview::SimpleTypeKind::Float32, PDB_BuiltinType::Float, 4},
710b57cec5SDimitry Andric     {codeview::SimpleTypeKind::Float64, PDB_BuiltinType::Float, 8},
720b57cec5SDimitry Andric     {codeview::SimpleTypeKind::Float80, PDB_BuiltinType::Float, 10},
730b57cec5SDimitry Andric     {codeview::SimpleTypeKind::Boolean8, PDB_BuiltinType::Bool, 1},
740b57cec5SDimitry Andric     // This table can be grown as necessary, but these are the only types we've
750b57cec5SDimitry Andric     // needed so far.
760b57cec5SDimitry Andric };
770b57cec5SDimitry Andric 
SymbolCache(NativeSession & Session,DbiStream * Dbi)780b57cec5SDimitry Andric SymbolCache::SymbolCache(NativeSession &Session, DbiStream *Dbi)
79e8d8bef9SDimitry Andric     : Session(Session), Dbi(Dbi) {
800b57cec5SDimitry Andric   // Id 0 is reserved for the invalid symbol.
810b57cec5SDimitry Andric   Cache.push_back(nullptr);
825ffd83dbSDimitry Andric   SourceFiles.push_back(nullptr);
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   if (Dbi)
850b57cec5SDimitry Andric     Compilands.resize(Dbi->modules().getModuleCount());
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric std::unique_ptr<IPDBEnumSymbols>
createTypeEnumerator(TypeLeafKind Kind)890b57cec5SDimitry Andric SymbolCache::createTypeEnumerator(TypeLeafKind Kind) {
900b57cec5SDimitry Andric   return createTypeEnumerator(std::vector<TypeLeafKind>{Kind});
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric std::unique_ptr<IPDBEnumSymbols>
createTypeEnumerator(std::vector<TypeLeafKind> Kinds)940b57cec5SDimitry Andric SymbolCache::createTypeEnumerator(std::vector<TypeLeafKind> Kinds) {
950b57cec5SDimitry Andric   auto Tpi = Session.getPDBFile().getPDBTpiStream();
960b57cec5SDimitry Andric   if (!Tpi) {
970b57cec5SDimitry Andric     consumeError(Tpi.takeError());
980b57cec5SDimitry Andric     return nullptr;
990b57cec5SDimitry Andric   }
1000b57cec5SDimitry Andric   auto &Types = Tpi->typeCollection();
1010b57cec5SDimitry Andric   return std::unique_ptr<IPDBEnumSymbols>(
1020b57cec5SDimitry Andric       new NativeEnumTypes(Session, Types, std::move(Kinds)));
1030b57cec5SDimitry Andric }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric std::unique_ptr<IPDBEnumSymbols>
createGlobalsEnumerator(codeview::SymbolKind Kind)1060b57cec5SDimitry Andric SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) {
1070b57cec5SDimitry Andric   return std::unique_ptr<IPDBEnumSymbols>(
1080b57cec5SDimitry Andric       new NativeEnumGlobals(Session, {Kind}));
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric 
createSimpleType(TypeIndex Index,ModifierOptions Mods) const1110b57cec5SDimitry Andric SymIndexId SymbolCache::createSimpleType(TypeIndex Index,
112e8d8bef9SDimitry Andric                                          ModifierOptions Mods) const {
1130b57cec5SDimitry Andric   if (Index.getSimpleMode() != codeview::SimpleTypeMode::Direct)
1140b57cec5SDimitry Andric     return createSymbol<NativeTypePointer>(Index);
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   const auto Kind = Index.getSimpleKind();
117e8d8bef9SDimitry Andric   const auto It =
118e8d8bef9SDimitry Andric       llvm::find_if(BuiltinTypes, [Kind](const BuiltinTypeEntry &Builtin) {
119e8d8bef9SDimitry Andric         return Builtin.Kind == Kind;
120e8d8bef9SDimitry Andric       });
1210b57cec5SDimitry Andric   if (It == std::end(BuiltinTypes))
1220b57cec5SDimitry Andric     return 0;
1230b57cec5SDimitry Andric   return createSymbol<NativeTypeBuiltin>(Mods, It->Type, It->Size);
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric SymIndexId
createSymbolForModifiedType(codeview::TypeIndex ModifierTI,codeview::CVType CVT) const1270b57cec5SDimitry Andric SymbolCache::createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
128e8d8bef9SDimitry Andric                                          codeview::CVType CVT) const {
1290b57cec5SDimitry Andric   ModifierRecord Record;
1300b57cec5SDimitry Andric   if (auto EC = TypeDeserializer::deserializeAs<ModifierRecord>(CVT, Record)) {
1310b57cec5SDimitry Andric     consumeError(std::move(EC));
1320b57cec5SDimitry Andric     return 0;
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric   if (Record.ModifiedType.isSimple())
1360b57cec5SDimitry Andric     return createSimpleType(Record.ModifiedType, Record.Modifiers);
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   // Make sure we create and cache a record for the unmodified type.
1390b57cec5SDimitry Andric   SymIndexId UnmodifiedId = findSymbolByTypeIndex(Record.ModifiedType);
1400b57cec5SDimitry Andric   NativeRawSymbol &UnmodifiedNRS = *Cache[UnmodifiedId];
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric   switch (UnmodifiedNRS.getSymTag()) {
1430b57cec5SDimitry Andric   case PDB_SymType::Enum:
1440b57cec5SDimitry Andric     return createSymbol<NativeTypeEnum>(
1450b57cec5SDimitry Andric         static_cast<NativeTypeEnum &>(UnmodifiedNRS), std::move(Record));
1460b57cec5SDimitry Andric   case PDB_SymType::UDT:
1470b57cec5SDimitry Andric     return createSymbol<NativeTypeUDT>(
1480b57cec5SDimitry Andric         static_cast<NativeTypeUDT &>(UnmodifiedNRS), std::move(Record));
1490b57cec5SDimitry Andric   default:
1500b57cec5SDimitry Andric     // No other types can be modified.  (LF_POINTER, for example, records
1510b57cec5SDimitry Andric     // its modifiers a different way.
1520b57cec5SDimitry Andric     assert(false && "Invalid LF_MODIFIER record");
1530b57cec5SDimitry Andric     break;
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric   return 0;
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric 
findSymbolByTypeIndex(codeview::TypeIndex Index) const158e8d8bef9SDimitry Andric SymIndexId SymbolCache::findSymbolByTypeIndex(codeview::TypeIndex Index) const {
1590b57cec5SDimitry Andric   // First see if it's already in our cache.
1600b57cec5SDimitry Andric   const auto Entry = TypeIndexToSymbolId.find(Index);
1610b57cec5SDimitry Andric   if (Entry != TypeIndexToSymbolId.end())
1620b57cec5SDimitry Andric     return Entry->second;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   // Symbols for built-in types are created on the fly.
1650b57cec5SDimitry Andric   if (Index.isSimple()) {
1660b57cec5SDimitry Andric     SymIndexId Result = createSimpleType(Index, ModifierOptions::None);
1670b57cec5SDimitry Andric     assert(TypeIndexToSymbolId.count(Index) == 0);
1680b57cec5SDimitry Andric     TypeIndexToSymbolId[Index] = Result;
1690b57cec5SDimitry Andric     return Result;
1700b57cec5SDimitry Andric   }
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   // We need to instantiate and cache the desired type symbol.
1730b57cec5SDimitry Andric   auto Tpi = Session.getPDBFile().getPDBTpiStream();
1740b57cec5SDimitry Andric   if (!Tpi) {
1750b57cec5SDimitry Andric     consumeError(Tpi.takeError());
1760b57cec5SDimitry Andric     return 0;
1770b57cec5SDimitry Andric   }
1780b57cec5SDimitry Andric   codeview::LazyRandomTypeCollection &Types = Tpi->typeCollection();
1790b57cec5SDimitry Andric   codeview::CVType CVT = Types.getType(Index);
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   if (isUdtForwardRef(CVT)) {
1820b57cec5SDimitry Andric     Expected<TypeIndex> EFD = Tpi->findFullDeclForForwardRef(Index);
1830b57cec5SDimitry Andric 
1840b57cec5SDimitry Andric     if (!EFD)
1850b57cec5SDimitry Andric       consumeError(EFD.takeError());
1860b57cec5SDimitry Andric     else if (*EFD != Index) {
1870b57cec5SDimitry Andric       assert(!isUdtForwardRef(Types.getType(*EFD)));
1880b57cec5SDimitry Andric       SymIndexId Result = findSymbolByTypeIndex(*EFD);
1890b57cec5SDimitry Andric       // Record a mapping from ForwardRef -> SymIndex of complete type so that
1900b57cec5SDimitry Andric       // we'll take the fast path next time.
1910b57cec5SDimitry Andric       assert(TypeIndexToSymbolId.count(Index) == 0);
1920b57cec5SDimitry Andric       TypeIndexToSymbolId[Index] = Result;
1930b57cec5SDimitry Andric       return Result;
1940b57cec5SDimitry Andric     }
1950b57cec5SDimitry Andric   }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   // At this point if we still have a forward ref udt it means the full decl was
1980b57cec5SDimitry Andric   // not in the PDB.  We just have to deal with it and use the forward ref.
1990b57cec5SDimitry Andric   SymIndexId Id = 0;
2000b57cec5SDimitry Andric   switch (CVT.kind()) {
2010b57cec5SDimitry Andric   case codeview::LF_ENUM:
2020b57cec5SDimitry Andric     Id = createSymbolForType<NativeTypeEnum, EnumRecord>(Index, std::move(CVT));
2030b57cec5SDimitry Andric     break;
2040b57cec5SDimitry Andric   case codeview::LF_ARRAY:
2050b57cec5SDimitry Andric     Id = createSymbolForType<NativeTypeArray, ArrayRecord>(Index,
2060b57cec5SDimitry Andric                                                            std::move(CVT));
2070b57cec5SDimitry Andric     break;
2080b57cec5SDimitry Andric   case codeview::LF_CLASS:
2090b57cec5SDimitry Andric   case codeview::LF_STRUCTURE:
2100b57cec5SDimitry Andric   case codeview::LF_INTERFACE:
2110b57cec5SDimitry Andric     Id = createSymbolForType<NativeTypeUDT, ClassRecord>(Index, std::move(CVT));
2120b57cec5SDimitry Andric     break;
2130b57cec5SDimitry Andric   case codeview::LF_UNION:
2140b57cec5SDimitry Andric     Id = createSymbolForType<NativeTypeUDT, UnionRecord>(Index, std::move(CVT));
2150b57cec5SDimitry Andric     break;
2160b57cec5SDimitry Andric   case codeview::LF_POINTER:
2170b57cec5SDimitry Andric     Id = createSymbolForType<NativeTypePointer, PointerRecord>(Index,
2180b57cec5SDimitry Andric                                                                std::move(CVT));
2190b57cec5SDimitry Andric     break;
2200b57cec5SDimitry Andric   case codeview::LF_MODIFIER:
2210b57cec5SDimitry Andric     Id = createSymbolForModifiedType(Index, std::move(CVT));
2220b57cec5SDimitry Andric     break;
2230b57cec5SDimitry Andric   case codeview::LF_PROCEDURE:
2240b57cec5SDimitry Andric     Id = createSymbolForType<NativeTypeFunctionSig, ProcedureRecord>(
2250b57cec5SDimitry Andric         Index, std::move(CVT));
2260b57cec5SDimitry Andric     break;
2270b57cec5SDimitry Andric   case codeview::LF_MFUNCTION:
2280b57cec5SDimitry Andric     Id = createSymbolForType<NativeTypeFunctionSig, MemberFunctionRecord>(
2290b57cec5SDimitry Andric         Index, std::move(CVT));
2300b57cec5SDimitry Andric     break;
2310b57cec5SDimitry Andric   case codeview::LF_VTSHAPE:
2320b57cec5SDimitry Andric     Id = createSymbolForType<NativeTypeVTShape, VFTableShapeRecord>(
2330b57cec5SDimitry Andric         Index, std::move(CVT));
2340b57cec5SDimitry Andric     break;
2350b57cec5SDimitry Andric   default:
2360b57cec5SDimitry Andric     Id = createSymbolPlaceholder();
2370b57cec5SDimitry Andric     break;
2380b57cec5SDimitry Andric   }
2390b57cec5SDimitry Andric   if (Id != 0) {
2400b57cec5SDimitry Andric     assert(TypeIndexToSymbolId.count(Index) == 0);
2410b57cec5SDimitry Andric     TypeIndexToSymbolId[Index] = Id;
2420b57cec5SDimitry Andric   }
2430b57cec5SDimitry Andric   return Id;
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric std::unique_ptr<PDBSymbol>
getSymbolById(SymIndexId SymbolId) const2470b57cec5SDimitry Andric SymbolCache::getSymbolById(SymIndexId SymbolId) const {
2480b57cec5SDimitry Andric   assert(SymbolId < Cache.size());
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric   // Id 0 is reserved.
2510b57cec5SDimitry Andric   if (SymbolId == 0 || SymbolId >= Cache.size())
2520b57cec5SDimitry Andric     return nullptr;
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   // Make sure to handle the case where we've inserted a placeholder symbol
255e8d8bef9SDimitry Andric   // for types we don't yet support.
2560b57cec5SDimitry Andric   NativeRawSymbol *NRS = Cache[SymbolId].get();
2570b57cec5SDimitry Andric   if (!NRS)
2580b57cec5SDimitry Andric     return nullptr;
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   return PDBSymbol::create(Session, *NRS);
2610b57cec5SDimitry Andric }
2620b57cec5SDimitry Andric 
getNativeSymbolById(SymIndexId SymbolId) const2630b57cec5SDimitry Andric NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const {
2640b57cec5SDimitry Andric   return *Cache[SymbolId];
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric 
getNumCompilands() const2670b57cec5SDimitry Andric uint32_t SymbolCache::getNumCompilands() const {
2680b57cec5SDimitry Andric   if (!Dbi)
2690b57cec5SDimitry Andric     return 0;
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   return Dbi->modules().getModuleCount();
2720b57cec5SDimitry Andric }
2730b57cec5SDimitry Andric 
getOrCreateGlobalSymbolByOffset(uint32_t Offset)2740b57cec5SDimitry Andric SymIndexId SymbolCache::getOrCreateGlobalSymbolByOffset(uint32_t Offset) {
2750b57cec5SDimitry Andric   auto Iter = GlobalOffsetToSymbolId.find(Offset);
2760b57cec5SDimitry Andric   if (Iter != GlobalOffsetToSymbolId.end())
2770b57cec5SDimitry Andric     return Iter->second;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   SymbolStream &SS = cantFail(Session.getPDBFile().getPDBSymbolStream());
2800b57cec5SDimitry Andric   CVSymbol CVS = SS.readRecord(Offset);
2810b57cec5SDimitry Andric   SymIndexId Id = 0;
2820b57cec5SDimitry Andric   switch (CVS.kind()) {
2830b57cec5SDimitry Andric   case SymbolKind::S_UDT: {
2840b57cec5SDimitry Andric     UDTSym US = cantFail(SymbolDeserializer::deserializeAs<UDTSym>(CVS));
2850b57cec5SDimitry Andric     Id = createSymbol<NativeTypeTypedef>(std::move(US));
2860b57cec5SDimitry Andric     break;
2870b57cec5SDimitry Andric   }
2880b57cec5SDimitry Andric   default:
2890b57cec5SDimitry Andric     Id = createSymbolPlaceholder();
2900b57cec5SDimitry Andric     break;
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric   if (Id != 0) {
2930b57cec5SDimitry Andric     assert(GlobalOffsetToSymbolId.count(Offset) == 0);
2940b57cec5SDimitry Andric     GlobalOffsetToSymbolId[Offset] = Id;
2950b57cec5SDimitry Andric   }
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   return Id;
2980b57cec5SDimitry Andric }
2990b57cec5SDimitry Andric 
getOrCreateInlineSymbol(InlineSiteSym Sym,uint64_t ParentAddr,uint16_t Modi,uint32_t RecordOffset) const300e8d8bef9SDimitry Andric SymIndexId SymbolCache::getOrCreateInlineSymbol(InlineSiteSym Sym,
301e8d8bef9SDimitry Andric                                                 uint64_t ParentAddr,
302e8d8bef9SDimitry Andric                                                 uint16_t Modi,
303e8d8bef9SDimitry Andric                                                 uint32_t RecordOffset) const {
304e8d8bef9SDimitry Andric   auto Iter = SymTabOffsetToSymbolId.find({Modi, RecordOffset});
305e8d8bef9SDimitry Andric   if (Iter != SymTabOffsetToSymbolId.end())
306e8d8bef9SDimitry Andric     return Iter->second;
3075ffd83dbSDimitry Andric 
308e8d8bef9SDimitry Andric   SymIndexId Id = createSymbol<NativeInlineSiteSymbol>(Sym, ParentAddr);
309e8d8bef9SDimitry Andric   SymTabOffsetToSymbolId.insert({{Modi, RecordOffset}, Id});
310e8d8bef9SDimitry Andric   return Id;
3115ffd83dbSDimitry Andric }
3125ffd83dbSDimitry Andric 
3135ffd83dbSDimitry Andric std::unique_ptr<PDBSymbol>
findSymbolBySectOffset(uint32_t Sect,uint32_t Offset,PDB_SymType Type)3145ffd83dbSDimitry Andric SymbolCache::findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
3155ffd83dbSDimitry Andric                                     PDB_SymType Type) {
3165ffd83dbSDimitry Andric   switch (Type) {
3175ffd83dbSDimitry Andric   case PDB_SymType::Function:
3185ffd83dbSDimitry Andric     return findFunctionSymbolBySectOffset(Sect, Offset);
3195ffd83dbSDimitry Andric   case PDB_SymType::PublicSymbol:
3205ffd83dbSDimitry Andric     return findPublicSymbolBySectOffset(Sect, Offset);
321e8d8bef9SDimitry Andric   case PDB_SymType::Compiland: {
322e8d8bef9SDimitry Andric     uint16_t Modi;
323e8d8bef9SDimitry Andric     if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
324e8d8bef9SDimitry Andric       return nullptr;
325e8d8bef9SDimitry Andric     return getOrCreateCompiland(Modi);
326e8d8bef9SDimitry Andric   }
3275ffd83dbSDimitry Andric   case PDB_SymType::None: {
328e8d8bef9SDimitry Andric     // FIXME: Implement for PDB_SymType::Data. The symbolizer calls this but
329e8d8bef9SDimitry Andric     // only uses it to find the symbol length.
3305ffd83dbSDimitry Andric     if (auto Sym = findFunctionSymbolBySectOffset(Sect, Offset))
3315ffd83dbSDimitry Andric       return Sym;
3325ffd83dbSDimitry Andric     return nullptr;
3335ffd83dbSDimitry Andric   }
3345ffd83dbSDimitry Andric   default:
3355ffd83dbSDimitry Andric     return nullptr;
3365ffd83dbSDimitry Andric   }
3375ffd83dbSDimitry Andric }
3385ffd83dbSDimitry Andric 
3395ffd83dbSDimitry Andric std::unique_ptr<PDBSymbol>
findFunctionSymbolBySectOffset(uint32_t Sect,uint32_t Offset)3405ffd83dbSDimitry Andric SymbolCache::findFunctionSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
341e8d8bef9SDimitry Andric   auto Iter = AddressToSymbolId.find({Sect, Offset});
342e8d8bef9SDimitry Andric   if (Iter != AddressToSymbolId.end())
3435ffd83dbSDimitry Andric     return getSymbolById(Iter->second);
3445ffd83dbSDimitry Andric 
3455ffd83dbSDimitry Andric   if (!Dbi)
3465ffd83dbSDimitry Andric     return nullptr;
3475ffd83dbSDimitry Andric 
348e8d8bef9SDimitry Andric   uint16_t Modi;
349e8d8bef9SDimitry Andric   if (!Session.moduleIndexForSectOffset(Sect, Offset, Modi))
3505ffd83dbSDimitry Andric     return nullptr;
3515ffd83dbSDimitry Andric 
352e8d8bef9SDimitry Andric   Expected<ModuleDebugStreamRef> ExpectedModS =
353e8d8bef9SDimitry Andric       Session.getModuleDebugStream(Modi);
3545ffd83dbSDimitry Andric   if (!ExpectedModS) {
3555ffd83dbSDimitry Andric     consumeError(ExpectedModS.takeError());
3565ffd83dbSDimitry Andric     return nullptr;
3575ffd83dbSDimitry Andric   }
3585ffd83dbSDimitry Andric   CVSymbolArray Syms = ExpectedModS->getSymbolArray();
3595ffd83dbSDimitry Andric 
3605ffd83dbSDimitry Andric   // Search for the symbol in this module.
3615ffd83dbSDimitry Andric   for (auto I = Syms.begin(), E = Syms.end(); I != E; ++I) {
3625ffd83dbSDimitry Andric     if (I->kind() != S_LPROC32 && I->kind() != S_GPROC32)
3635ffd83dbSDimitry Andric       continue;
3645ffd83dbSDimitry Andric     auto PS = cantFail(SymbolDeserializer::deserializeAs<ProcSym>(*I));
3655ffd83dbSDimitry Andric     if (Sect == PS.Segment && Offset >= PS.CodeOffset &&
3665ffd83dbSDimitry Andric         Offset < PS.CodeOffset + PS.CodeSize) {
367e8d8bef9SDimitry Andric       // Check if the symbol is already cached.
368e8d8bef9SDimitry Andric       auto Found = AddressToSymbolId.find({PS.Segment, PS.CodeOffset});
369e8d8bef9SDimitry Andric       if (Found != AddressToSymbolId.end())
370e8d8bef9SDimitry Andric         return getSymbolById(Found->second);
371e8d8bef9SDimitry Andric 
372e8d8bef9SDimitry Andric       // Otherwise, create a new symbol.
373e8d8bef9SDimitry Andric       SymIndexId Id = createSymbol<NativeFunctionSymbol>(PS, I.offset());
374e8d8bef9SDimitry Andric       AddressToSymbolId.insert({{PS.Segment, PS.CodeOffset}, Id});
3755ffd83dbSDimitry Andric       return getSymbolById(Id);
3765ffd83dbSDimitry Andric     }
3775ffd83dbSDimitry Andric 
3785ffd83dbSDimitry Andric     // Jump to the end of this ProcSym.
3795ffd83dbSDimitry Andric     I = Syms.at(PS.End);
3805ffd83dbSDimitry Andric   }
3815ffd83dbSDimitry Andric   return nullptr;
3825ffd83dbSDimitry Andric }
3835ffd83dbSDimitry Andric 
3845ffd83dbSDimitry Andric std::unique_ptr<PDBSymbol>
findPublicSymbolBySectOffset(uint32_t Sect,uint32_t Offset)3855ffd83dbSDimitry Andric SymbolCache::findPublicSymbolBySectOffset(uint32_t Sect, uint32_t Offset) {
3865ffd83dbSDimitry Andric   auto Iter = AddressToPublicSymId.find({Sect, Offset});
3875ffd83dbSDimitry Andric   if (Iter != AddressToPublicSymId.end())
3885ffd83dbSDimitry Andric     return getSymbolById(Iter->second);
3895ffd83dbSDimitry Andric 
3905ffd83dbSDimitry Andric   auto Publics = Session.getPDBFile().getPDBPublicsStream();
3915ffd83dbSDimitry Andric   if (!Publics)
3925ffd83dbSDimitry Andric     return nullptr;
3935ffd83dbSDimitry Andric 
3945ffd83dbSDimitry Andric   auto ExpectedSyms = Session.getPDBFile().getPDBSymbolStream();
3955ffd83dbSDimitry Andric   if (!ExpectedSyms)
3965ffd83dbSDimitry Andric     return nullptr;
3975ffd83dbSDimitry Andric   BinaryStreamRef SymStream =
3985ffd83dbSDimitry Andric       ExpectedSyms->getSymbolArray().getUnderlyingStream();
3995ffd83dbSDimitry Andric 
4005ffd83dbSDimitry Andric   // Use binary search to find the first public symbol with an address greater
4015ffd83dbSDimitry Andric   // than or equal to Sect, Offset.
4025ffd83dbSDimitry Andric   auto AddrMap = Publics->getAddressMap();
4035ffd83dbSDimitry Andric   auto First = AddrMap.begin();
4045ffd83dbSDimitry Andric   auto It = AddrMap.begin();
4055ffd83dbSDimitry Andric   size_t Count = AddrMap.size();
4065ffd83dbSDimitry Andric   size_t Half;
4075ffd83dbSDimitry Andric   while (Count > 0) {
4085ffd83dbSDimitry Andric     It = First;
4095ffd83dbSDimitry Andric     Half = Count / 2;
4105ffd83dbSDimitry Andric     It += Half;
4115ffd83dbSDimitry Andric     Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
4125ffd83dbSDimitry Andric     if (!Sym) {
4135ffd83dbSDimitry Andric       consumeError(Sym.takeError());
4145ffd83dbSDimitry Andric       return nullptr;
4155ffd83dbSDimitry Andric     }
4165ffd83dbSDimitry Andric 
4175ffd83dbSDimitry Andric     auto PS =
4185ffd83dbSDimitry Andric         cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
4195ffd83dbSDimitry Andric     if (PS.Segment < Sect || (PS.Segment == Sect && PS.Offset <= Offset)) {
4205ffd83dbSDimitry Andric       First = ++It;
4215ffd83dbSDimitry Andric       Count -= Half + 1;
4225ffd83dbSDimitry Andric     } else
4235ffd83dbSDimitry Andric       Count = Half;
4245ffd83dbSDimitry Andric   }
4255ffd83dbSDimitry Andric   if (It == AddrMap.begin())
4265ffd83dbSDimitry Andric     return nullptr;
4275ffd83dbSDimitry Andric   --It;
4285ffd83dbSDimitry Andric 
4295ffd83dbSDimitry Andric   Expected<CVSymbol> Sym = readSymbolFromStream(SymStream, *It);
4305ffd83dbSDimitry Andric   if (!Sym) {
4315ffd83dbSDimitry Andric     consumeError(Sym.takeError());
4325ffd83dbSDimitry Andric     return nullptr;
4335ffd83dbSDimitry Andric   }
434e8d8bef9SDimitry Andric 
435e8d8bef9SDimitry Andric   // Check if the symbol is already cached.
4365ffd83dbSDimitry Andric   auto PS = cantFail(SymbolDeserializer::deserializeAs<PublicSym32>(Sym.get()));
437e8d8bef9SDimitry Andric   auto Found = AddressToPublicSymId.find({PS.Segment, PS.Offset});
438e8d8bef9SDimitry Andric   if (Found != AddressToPublicSymId.end())
439e8d8bef9SDimitry Andric     return getSymbolById(Found->second);
440e8d8bef9SDimitry Andric 
441e8d8bef9SDimitry Andric   // Otherwise, create a new symbol.
4425ffd83dbSDimitry Andric   SymIndexId Id = createSymbol<NativePublicSymbol>(PS);
443e8d8bef9SDimitry Andric   AddressToPublicSymId.insert({{PS.Segment, PS.Offset}, Id});
4445ffd83dbSDimitry Andric   return getSymbolById(Id);
4455ffd83dbSDimitry Andric }
4465ffd83dbSDimitry Andric 
4475ffd83dbSDimitry Andric std::vector<SymbolCache::LineTableEntry>
findLineTable(uint16_t Modi) const4485ffd83dbSDimitry Andric SymbolCache::findLineTable(uint16_t Modi) const {
4495ffd83dbSDimitry Andric   // Check if this module has already been added.
4505ffd83dbSDimitry Andric   auto LineTableIter = LineTable.find(Modi);
4515ffd83dbSDimitry Andric   if (LineTableIter != LineTable.end())
4525ffd83dbSDimitry Andric     return LineTableIter->second;
4535ffd83dbSDimitry Andric 
4545ffd83dbSDimitry Andric   std::vector<LineTableEntry> &ModuleLineTable = LineTable[Modi];
4555ffd83dbSDimitry Andric 
4565ffd83dbSDimitry Andric   // If there is an error or there are no lines, just return the
4575ffd83dbSDimitry Andric   // empty vector.
458e8d8bef9SDimitry Andric   Expected<ModuleDebugStreamRef> ExpectedModS =
459e8d8bef9SDimitry Andric       Session.getModuleDebugStream(Modi);
4605ffd83dbSDimitry Andric   if (!ExpectedModS) {
4615ffd83dbSDimitry Andric     consumeError(ExpectedModS.takeError());
4625ffd83dbSDimitry Andric     return ModuleLineTable;
4635ffd83dbSDimitry Andric   }
4645ffd83dbSDimitry Andric 
4655ffd83dbSDimitry Andric   std::vector<std::vector<LineTableEntry>> EntryList;
4665ffd83dbSDimitry Andric   for (const auto &SS : ExpectedModS->getSubsectionsArray()) {
4675ffd83dbSDimitry Andric     if (SS.kind() != DebugSubsectionKind::Lines)
4685ffd83dbSDimitry Andric       continue;
4695ffd83dbSDimitry Andric 
4705ffd83dbSDimitry Andric     DebugLinesSubsectionRef Lines;
4715ffd83dbSDimitry Andric     BinaryStreamReader Reader(SS.getRecordData());
4725ffd83dbSDimitry Andric     if (auto EC = Lines.initialize(Reader)) {
4735ffd83dbSDimitry Andric       consumeError(std::move(EC));
4745ffd83dbSDimitry Andric       continue;
4755ffd83dbSDimitry Andric     }
4765ffd83dbSDimitry Andric 
4775ffd83dbSDimitry Andric     uint32_t RelocSegment = Lines.header()->RelocSegment;
4785ffd83dbSDimitry Andric     uint32_t RelocOffset = Lines.header()->RelocOffset;
4795ffd83dbSDimitry Andric     for (const LineColumnEntry &Group : Lines) {
4805ffd83dbSDimitry Andric       if (Group.LineNumbers.empty())
4815ffd83dbSDimitry Andric         continue;
4825ffd83dbSDimitry Andric 
4835ffd83dbSDimitry Andric       std::vector<LineTableEntry> Entries;
4845ffd83dbSDimitry Andric 
4855ffd83dbSDimitry Andric       // If there are column numbers, then they should be in a parallel stream
4865ffd83dbSDimitry Andric       // to the line numbers.
4875ffd83dbSDimitry Andric       auto ColIt = Group.Columns.begin();
4885ffd83dbSDimitry Andric       auto ColsEnd = Group.Columns.end();
4895ffd83dbSDimitry Andric 
490e8d8bef9SDimitry Andric       // Add a line to mark the beginning of this section.
491e8d8bef9SDimitry Andric       uint64_t StartAddr =
492e8d8bef9SDimitry Andric           Session.getVAFromSectOffset(RelocSegment, RelocOffset);
493e8d8bef9SDimitry Andric       LineInfo FirstLine(Group.LineNumbers.front().Flags);
494e8d8bef9SDimitry Andric       uint32_t ColNum =
495e8d8bef9SDimitry Andric           (Lines.hasColumnInfo()) ? Group.Columns.front().StartColumn : 0;
496e8d8bef9SDimitry Andric       Entries.push_back({StartAddr, FirstLine, ColNum, Group.NameIndex, false});
497e8d8bef9SDimitry Andric 
4985ffd83dbSDimitry Andric       for (const LineNumberEntry &LN : Group.LineNumbers) {
4995ffd83dbSDimitry Andric         uint64_t VA =
5005ffd83dbSDimitry Andric             Session.getVAFromSectOffset(RelocSegment, RelocOffset + LN.Offset);
5015ffd83dbSDimitry Andric         LineInfo Line(LN.Flags);
502e8d8bef9SDimitry Andric         ColNum = 0;
5035ffd83dbSDimitry Andric 
5045ffd83dbSDimitry Andric         if (Lines.hasColumnInfo() && ColIt != ColsEnd) {
5055ffd83dbSDimitry Andric           ColNum = ColIt->StartColumn;
5065ffd83dbSDimitry Andric           ++ColIt;
5075ffd83dbSDimitry Andric         }
5085ffd83dbSDimitry Andric         Entries.push_back({VA, Line, ColNum, Group.NameIndex, false});
5095ffd83dbSDimitry Andric       }
5105ffd83dbSDimitry Andric 
5115ffd83dbSDimitry Andric       // Add a terminal entry line to mark the end of this subsection.
512e8d8bef9SDimitry Andric       uint64_t EndAddr = StartAddr + Lines.header()->CodeSize;
5135ffd83dbSDimitry Andric       LineInfo LastLine(Group.LineNumbers.back().Flags);
514e8d8bef9SDimitry Andric       ColNum = (Lines.hasColumnInfo()) ? Group.Columns.back().StartColumn : 0;
515e8d8bef9SDimitry Andric       Entries.push_back({EndAddr, LastLine, ColNum, Group.NameIndex, true});
5165ffd83dbSDimitry Andric 
5175ffd83dbSDimitry Andric       EntryList.push_back(Entries);
5185ffd83dbSDimitry Andric     }
5195ffd83dbSDimitry Andric   }
5205ffd83dbSDimitry Andric 
5215ffd83dbSDimitry Andric   // Sort EntryList, and add flattened contents to the line table.
522e8d8bef9SDimitry Andric   llvm::sort(EntryList, [](const std::vector<LineTableEntry> &LHS,
5235ffd83dbSDimitry Andric                            const std::vector<LineTableEntry> &RHS) {
5245ffd83dbSDimitry Andric     return LHS[0].Addr < RHS[0].Addr;
5255ffd83dbSDimitry Andric   });
5260eae32dcSDimitry Andric   for (std::vector<LineTableEntry> &I : EntryList)
5270eae32dcSDimitry Andric     llvm::append_range(ModuleLineTable, I);
5285ffd83dbSDimitry Andric 
5295ffd83dbSDimitry Andric   return ModuleLineTable;
5305ffd83dbSDimitry Andric }
5315ffd83dbSDimitry Andric 
5325ffd83dbSDimitry Andric std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbersByVA(uint64_t VA,uint32_t Length) const5335ffd83dbSDimitry Andric SymbolCache::findLineNumbersByVA(uint64_t VA, uint32_t Length) const {
534e8d8bef9SDimitry Andric   uint16_t Modi;
535e8d8bef9SDimitry Andric   if (!Session.moduleIndexForVA(VA, Modi))
5365ffd83dbSDimitry Andric     return nullptr;
5375ffd83dbSDimitry Andric 
5385ffd83dbSDimitry Andric   std::vector<LineTableEntry> Lines = findLineTable(Modi);
5395ffd83dbSDimitry Andric   if (Lines.empty())
5405ffd83dbSDimitry Andric     return nullptr;
5415ffd83dbSDimitry Andric 
5425ffd83dbSDimitry Andric   // Find the first line in the line table whose address is not greater than
5435ffd83dbSDimitry Andric   // the one we are searching for.
5445ffd83dbSDimitry Andric   auto LineIter = llvm::partition_point(Lines, [&](const LineTableEntry &E) {
5455ffd83dbSDimitry Andric     return (E.Addr < VA || (E.Addr == VA && E.IsTerminalEntry));
5465ffd83dbSDimitry Andric   });
5475ffd83dbSDimitry Andric 
5485ffd83dbSDimitry Andric   // Try to back up if we've gone too far.
5495ffd83dbSDimitry Andric   if (LineIter == Lines.end() || LineIter->Addr > VA) {
5505ffd83dbSDimitry Andric     if (LineIter == Lines.begin() || std::prev(LineIter)->IsTerminalEntry)
5515ffd83dbSDimitry Andric       return nullptr;
5525ffd83dbSDimitry Andric     --LineIter;
5535ffd83dbSDimitry Andric   }
5545ffd83dbSDimitry Andric 
555e8d8bef9SDimitry Andric   Expected<ModuleDebugStreamRef> ExpectedModS =
556e8d8bef9SDimitry Andric       Session.getModuleDebugStream(Modi);
5575ffd83dbSDimitry Andric   if (!ExpectedModS) {
5585ffd83dbSDimitry Andric     consumeError(ExpectedModS.takeError());
5595ffd83dbSDimitry Andric     return nullptr;
5605ffd83dbSDimitry Andric   }
5615ffd83dbSDimitry Andric   Expected<DebugChecksumsSubsectionRef> ExpectedChecksums =
5625ffd83dbSDimitry Andric       ExpectedModS->findChecksumsSubsection();
5635ffd83dbSDimitry Andric   if (!ExpectedChecksums) {
5645ffd83dbSDimitry Andric     consumeError(ExpectedChecksums.takeError());
5655ffd83dbSDimitry Andric     return nullptr;
5665ffd83dbSDimitry Andric   }
5675ffd83dbSDimitry Andric 
5685ffd83dbSDimitry Andric   // Populate a vector of NativeLineNumbers that have addresses in the given
5695ffd83dbSDimitry Andric   // address range.
5705ffd83dbSDimitry Andric   std::vector<NativeLineNumber> LineNumbers;
571e8d8bef9SDimitry Andric   while (LineIter != Lines.end()) {
5725ffd83dbSDimitry Andric     if (LineIter->IsTerminalEntry) {
5735ffd83dbSDimitry Andric       ++LineIter;
5745ffd83dbSDimitry Andric       continue;
5755ffd83dbSDimitry Andric     }
5765ffd83dbSDimitry Andric 
5775ffd83dbSDimitry Andric     // If the line is still within the address range, create a NativeLineNumber
5785ffd83dbSDimitry Andric     // and add to the list.
5795ffd83dbSDimitry Andric     if (LineIter->Addr > VA + Length)
5805ffd83dbSDimitry Andric       break;
5815ffd83dbSDimitry Andric 
5825ffd83dbSDimitry Andric     uint32_t LineSect, LineOff;
5835ffd83dbSDimitry Andric     Session.addressForVA(LineIter->Addr, LineSect, LineOff);
5845ffd83dbSDimitry Andric     uint32_t LineLength = std::next(LineIter)->Addr - LineIter->Addr;
5855ffd83dbSDimitry Andric     auto ChecksumIter =
5865ffd83dbSDimitry Andric         ExpectedChecksums->getArray().at(LineIter->FileNameIndex);
5875ffd83dbSDimitry Andric     uint32_t SrcFileId = getOrCreateSourceFile(*ChecksumIter);
5885ffd83dbSDimitry Andric     NativeLineNumber LineNum(Session, LineIter->Line, LineIter->ColumnNumber,
589e8d8bef9SDimitry Andric                              LineSect, LineOff, LineLength, SrcFileId, Modi);
5905ffd83dbSDimitry Andric     LineNumbers.push_back(LineNum);
5915ffd83dbSDimitry Andric     ++LineIter;
5925ffd83dbSDimitry Andric   }
5935ffd83dbSDimitry Andric   return std::make_unique<NativeEnumLineNumbers>(std::move(LineNumbers));
5945ffd83dbSDimitry Andric }
5955ffd83dbSDimitry Andric 
5960b57cec5SDimitry Andric std::unique_ptr<PDBSymbolCompiland>
getOrCreateCompiland(uint32_t Index)5970b57cec5SDimitry Andric SymbolCache::getOrCreateCompiland(uint32_t Index) {
5980b57cec5SDimitry Andric   if (!Dbi)
5990b57cec5SDimitry Andric     return nullptr;
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric   if (Index >= Compilands.size())
6020b57cec5SDimitry Andric     return nullptr;
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric   if (Compilands[Index] == 0) {
6050b57cec5SDimitry Andric     const DbiModuleList &Modules = Dbi->modules();
6060b57cec5SDimitry Andric     Compilands[Index] =
6070b57cec5SDimitry Andric         createSymbol<NativeCompilandSymbol>(Modules.getModuleDescriptor(Index));
6080b57cec5SDimitry Andric   }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   return Session.getConcreteSymbolById<PDBSymbolCompiland>(Compilands[Index]);
6110b57cec5SDimitry Andric }
6125ffd83dbSDimitry Andric 
6135ffd83dbSDimitry Andric std::unique_ptr<IPDBSourceFile>
getSourceFileById(SymIndexId FileId) const6145ffd83dbSDimitry Andric SymbolCache::getSourceFileById(SymIndexId FileId) const {
6155ffd83dbSDimitry Andric   assert(FileId < SourceFiles.size());
6165ffd83dbSDimitry Andric 
6175ffd83dbSDimitry Andric   // Id 0 is reserved.
6185ffd83dbSDimitry Andric   if (FileId == 0)
6195ffd83dbSDimitry Andric     return nullptr;
6205ffd83dbSDimitry Andric 
6215ffd83dbSDimitry Andric   return std::unique_ptr<NativeSourceFile>(
6225ffd83dbSDimitry Andric       new NativeSourceFile(*SourceFiles[FileId].get()));
6235ffd83dbSDimitry Andric }
6245ffd83dbSDimitry Andric 
6255ffd83dbSDimitry Andric SymIndexId
getOrCreateSourceFile(const FileChecksumEntry & Checksums) const6265ffd83dbSDimitry Andric SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const {
6275ffd83dbSDimitry Andric   auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset);
6285ffd83dbSDimitry Andric   if (Iter != FileNameOffsetToId.end())
6295ffd83dbSDimitry Andric     return Iter->second;
6305ffd83dbSDimitry Andric 
6315ffd83dbSDimitry Andric   SymIndexId Id = SourceFiles.size();
6325ffd83dbSDimitry Andric   auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums);
6335ffd83dbSDimitry Andric   SourceFiles.push_back(std::move(SrcFile));
6345ffd83dbSDimitry Andric   FileNameOffsetToId[Checksums.FileNameOffset] = Id;
6355ffd83dbSDimitry Andric   return Id;
6365ffd83dbSDimitry Andric }
6375ffd83dbSDimitry Andric 
6385ffd83dbSDimitry Andric 
639