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