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 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> 890b57cec5SDimitry Andric SymbolCache::createTypeEnumerator(TypeLeafKind Kind) { 900b57cec5SDimitry Andric return createTypeEnumerator(std::vector<TypeLeafKind>{Kind}); 910b57cec5SDimitry Andric } 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric std::unique_ptr<IPDBEnumSymbols> 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> 1060b57cec5SDimitry Andric SymbolCache::createGlobalsEnumerator(codeview::SymbolKind Kind) { 1070b57cec5SDimitry Andric return std::unique_ptr<IPDBEnumSymbols>( 1080b57cec5SDimitry Andric new NativeEnumGlobals(Session, {Kind})); 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric 1110b57cec5SDimitry 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 1270b57cec5SDimitry 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 158e8d8bef9SDimitry 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> 2470b57cec5SDimitry 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 2630b57cec5SDimitry Andric NativeRawSymbol &SymbolCache::getNativeSymbolById(SymIndexId SymbolId) const { 2640b57cec5SDimitry Andric return *Cache[SymbolId]; 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry 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 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 300e8d8bef9SDimitry 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> 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> 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> 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> 4485ffd83dbSDimitry 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> 5335ffd83dbSDimitry 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> 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> 6145ffd83dbSDimitry 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 621*0fca6ea1SDimitry Andric return std::make_unique<NativeSourceFile>(*SourceFiles[FileId].get()); 6225ffd83dbSDimitry Andric } 6235ffd83dbSDimitry Andric 6245ffd83dbSDimitry Andric SymIndexId 6255ffd83dbSDimitry Andric SymbolCache::getOrCreateSourceFile(const FileChecksumEntry &Checksums) const { 6265ffd83dbSDimitry Andric auto Iter = FileNameOffsetToId.find(Checksums.FileNameOffset); 6275ffd83dbSDimitry Andric if (Iter != FileNameOffsetToId.end()) 6285ffd83dbSDimitry Andric return Iter->second; 6295ffd83dbSDimitry Andric 6305ffd83dbSDimitry Andric SymIndexId Id = SourceFiles.size(); 6315ffd83dbSDimitry Andric auto SrcFile = std::make_unique<NativeSourceFile>(Session, Id, Checksums); 6325ffd83dbSDimitry Andric SourceFiles.push_back(std::move(SrcFile)); 6335ffd83dbSDimitry Andric FileNameOffsetToId[Checksums.FileNameOffset] = Id; 6345ffd83dbSDimitry Andric return Id; 6355ffd83dbSDimitry Andric } 6365ffd83dbSDimitry Andric 6375ffd83dbSDimitry Andric 638