15ffd83dbSDimitry Andric //===-- SymbolFileNativePDB.cpp -------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "SymbolFileNativePDB.h" 100b57cec5SDimitry Andric 115ffd83dbSDimitry Andric #include "Plugins/ExpressionParser/Clang/ClangUtil.h" 120b57cec5SDimitry Andric #include "Plugins/Language/CPlusPlus/MSVCUndecoratedNameParser.h" 13e8d8bef9SDimitry Andric #include "Plugins/ObjectFile/PDB/ObjectFilePDB.h" 145ffd83dbSDimitry Andric #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" 150b57cec5SDimitry Andric #include "lldb/Core/Module.h" 160b57cec5SDimitry Andric #include "lldb/Core/PluginManager.h" 170b57cec5SDimitry Andric #include "lldb/Core/StreamBuffer.h" 180b57cec5SDimitry Andric #include "lldb/Core/StreamFile.h" 190b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h" 200b57cec5SDimitry Andric #include "lldb/Symbol/LineTable.h" 210b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 220b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h" 230b57cec5SDimitry Andric #include "lldb/Symbol/SymbolVendor.h" 240b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h" 250b57cec5SDimitry Andric #include "lldb/Symbol/VariableList.h" 2681ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 279dba64beSDimitry Andric #include "lldb/Utility/Log.h" 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CVRecord.h" 300b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" 310b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" 320b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" 330b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/RecordName.h" 340b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 350b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" 360b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 370b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 380b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" 390b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStream.h" 400b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" 41e8d8bef9SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 420b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 430b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/SymbolStream.h" 440b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 45e8d8bef9SDimitry Andric #include "llvm/DebugInfo/PDB/PDB.h" 460b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBTypes.h" 470b57cec5SDimitry Andric #include "llvm/Demangle/MicrosoftDemangle.h" 480b57cec5SDimitry Andric #include "llvm/Object/COFF.h" 490b57cec5SDimitry Andric #include "llvm/Support/Allocator.h" 500b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h" 510b57cec5SDimitry Andric #include "llvm/Support/Error.h" 520b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h" 530b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric #include "DWARFLocationExpression.h" 560b57cec5SDimitry Andric #include "PdbSymUid.h" 570b57cec5SDimitry Andric #include "PdbUtil.h" 580b57cec5SDimitry Andric #include "UdtRecordCompleter.h" 59bdd1243dSDimitry Andric #include <optional> 6006c3fb27SDimitry Andric #include <string_view> 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric using namespace lldb; 630b57cec5SDimitry Andric using namespace lldb_private; 640b57cec5SDimitry Andric using namespace npdb; 650b57cec5SDimitry Andric using namespace llvm::codeview; 660b57cec5SDimitry Andric using namespace llvm::pdb; 670b57cec5SDimitry Andric 68480093f4SDimitry Andric char SymbolFileNativePDB::ID; 69480093f4SDimitry Andric 700b57cec5SDimitry Andric static lldb::LanguageType TranslateLanguage(PDB_Lang lang) { 710b57cec5SDimitry Andric switch (lang) { 720b57cec5SDimitry Andric case PDB_Lang::Cpp: 730b57cec5SDimitry Andric return lldb::LanguageType::eLanguageTypeC_plus_plus; 740b57cec5SDimitry Andric case PDB_Lang::C: 750b57cec5SDimitry Andric return lldb::LanguageType::eLanguageTypeC; 760b57cec5SDimitry Andric case PDB_Lang::Swift: 770b57cec5SDimitry Andric return lldb::LanguageType::eLanguageTypeSwift; 7881ad6265SDimitry Andric case PDB_Lang::Rust: 7981ad6265SDimitry Andric return lldb::LanguageType::eLanguageTypeRust; 8006c3fb27SDimitry Andric case PDB_Lang::ObjC: 8106c3fb27SDimitry Andric return lldb::LanguageType::eLanguageTypeObjC; 8206c3fb27SDimitry Andric case PDB_Lang::ObjCpp: 8306c3fb27SDimitry Andric return lldb::LanguageType::eLanguageTypeObjC_plus_plus; 840b57cec5SDimitry Andric default: 850b57cec5SDimitry Andric return lldb::LanguageType::eLanguageTypeUnknown; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric static std::unique_ptr<PDBFile> 900b57cec5SDimitry Andric loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) { 910b57cec5SDimitry Andric // Try to find a matching PDB for an EXE. 920b57cec5SDimitry Andric using namespace llvm::object; 930b57cec5SDimitry Andric auto expected_binary = createBinary(exe_path); 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric // If the file isn't a PE/COFF executable, fail. 960b57cec5SDimitry Andric if (!expected_binary) { 970b57cec5SDimitry Andric llvm::consumeError(expected_binary.takeError()); 980b57cec5SDimitry Andric return nullptr; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric OwningBinary<Binary> binary = std::move(*expected_binary); 1010b57cec5SDimitry Andric 1029dba64beSDimitry Andric // TODO: Avoid opening the PE/COFF binary twice by reading this information 1039dba64beSDimitry Andric // directly from the lldb_private::ObjectFile. 1040b57cec5SDimitry Andric auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary()); 1050b57cec5SDimitry Andric if (!obj) 1060b57cec5SDimitry Andric return nullptr; 1070b57cec5SDimitry Andric const llvm::codeview::DebugInfo *pdb_info = nullptr; 1080b57cec5SDimitry Andric 1090b57cec5SDimitry Andric // If it doesn't have a debug directory, fail. 1100b57cec5SDimitry Andric llvm::StringRef pdb_file; 1115ffd83dbSDimitry Andric if (llvm::Error e = obj->getDebugPDBInfo(pdb_info, pdb_file)) { 1125ffd83dbSDimitry Andric consumeError(std::move(e)); 1130b57cec5SDimitry Andric return nullptr; 1145ffd83dbSDimitry Andric } 1150b57cec5SDimitry Andric 116e8d8bef9SDimitry Andric // If the file doesn't exist, perhaps the path specified at build time 117e8d8bef9SDimitry Andric // doesn't match the PDB's current location, so check the location of the 118e8d8bef9SDimitry Andric // executable. 119e8d8bef9SDimitry Andric if (!FileSystem::Instance().Exists(pdb_file)) { 120e8d8bef9SDimitry Andric const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent(); 121e8d8bef9SDimitry Andric const auto pdb_name = FileSpec(pdb_file).GetFilename().GetCString(); 122bdd1243dSDimitry Andric pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetPathAsConstString().GetStringRef(); 123e8d8bef9SDimitry Andric } 124e8d8bef9SDimitry Andric 125e8d8bef9SDimitry Andric // If the file is not a PDB or if it doesn't have a matching GUID, fail. 126e8d8bef9SDimitry Andric auto pdb = ObjectFilePDB::loadPDBFile(std::string(pdb_file), allocator); 1270b57cec5SDimitry Andric if (!pdb) 1280b57cec5SDimitry Andric return nullptr; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric auto expected_info = pdb->getPDBInfoStream(); 1310b57cec5SDimitry Andric if (!expected_info) { 1320b57cec5SDimitry Andric llvm::consumeError(expected_info.takeError()); 1330b57cec5SDimitry Andric return nullptr; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric llvm::codeview::GUID guid; 1360b57cec5SDimitry Andric memcpy(&guid, pdb_info->PDB70.Signature, 16); 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric if (expected_info->getGuid() != guid) 1390b57cec5SDimitry Andric return nullptr; 1400b57cec5SDimitry Andric return pdb; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric static bool IsFunctionPrologue(const CompilandIndexItem &cci, 1440b57cec5SDimitry Andric lldb::addr_t addr) { 1450b57cec5SDimitry Andric // FIXME: Implement this. 1460b57cec5SDimitry Andric return false; 1470b57cec5SDimitry Andric } 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric static bool IsFunctionEpilogue(const CompilandIndexItem &cci, 1500b57cec5SDimitry Andric lldb::addr_t addr) { 1510b57cec5SDimitry Andric // FIXME: Implement this. 1520b57cec5SDimitry Andric return false; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) { 1560b57cec5SDimitry Andric switch (kind) { 1570b57cec5SDimitry Andric case SimpleTypeKind::Boolean128: 1580b57cec5SDimitry Andric case SimpleTypeKind::Boolean16: 1590b57cec5SDimitry Andric case SimpleTypeKind::Boolean32: 1600b57cec5SDimitry Andric case SimpleTypeKind::Boolean64: 1610b57cec5SDimitry Andric case SimpleTypeKind::Boolean8: 1620b57cec5SDimitry Andric return "bool"; 1630b57cec5SDimitry Andric case SimpleTypeKind::Byte: 1640b57cec5SDimitry Andric case SimpleTypeKind::UnsignedCharacter: 1650b57cec5SDimitry Andric return "unsigned char"; 1660b57cec5SDimitry Andric case SimpleTypeKind::NarrowCharacter: 1670b57cec5SDimitry Andric return "char"; 1680b57cec5SDimitry Andric case SimpleTypeKind::SignedCharacter: 1690b57cec5SDimitry Andric case SimpleTypeKind::SByte: 1700b57cec5SDimitry Andric return "signed char"; 1710b57cec5SDimitry Andric case SimpleTypeKind::Character16: 1720b57cec5SDimitry Andric return "char16_t"; 1730b57cec5SDimitry Andric case SimpleTypeKind::Character32: 1740b57cec5SDimitry Andric return "char32_t"; 17581ad6265SDimitry Andric case SimpleTypeKind::Character8: 17681ad6265SDimitry Andric return "char8_t"; 1770b57cec5SDimitry Andric case SimpleTypeKind::Complex80: 1780b57cec5SDimitry Andric case SimpleTypeKind::Complex64: 1790b57cec5SDimitry Andric case SimpleTypeKind::Complex32: 1800b57cec5SDimitry Andric return "complex"; 1810b57cec5SDimitry Andric case SimpleTypeKind::Float128: 1820b57cec5SDimitry Andric case SimpleTypeKind::Float80: 1830b57cec5SDimitry Andric return "long double"; 1840b57cec5SDimitry Andric case SimpleTypeKind::Float64: 1850b57cec5SDimitry Andric return "double"; 1860b57cec5SDimitry Andric case SimpleTypeKind::Float32: 1870b57cec5SDimitry Andric return "float"; 1880b57cec5SDimitry Andric case SimpleTypeKind::Float16: 1890b57cec5SDimitry Andric return "single"; 1900b57cec5SDimitry Andric case SimpleTypeKind::Int128: 1910b57cec5SDimitry Andric return "__int128"; 1920b57cec5SDimitry Andric case SimpleTypeKind::Int64: 1930b57cec5SDimitry Andric case SimpleTypeKind::Int64Quad: 1940b57cec5SDimitry Andric return "int64_t"; 1950b57cec5SDimitry Andric case SimpleTypeKind::Int32: 1960b57cec5SDimitry Andric return "int"; 1970b57cec5SDimitry Andric case SimpleTypeKind::Int16: 1980b57cec5SDimitry Andric return "short"; 1990b57cec5SDimitry Andric case SimpleTypeKind::UInt128: 2000b57cec5SDimitry Andric return "unsigned __int128"; 2010b57cec5SDimitry Andric case SimpleTypeKind::UInt64: 2020b57cec5SDimitry Andric case SimpleTypeKind::UInt64Quad: 2030b57cec5SDimitry Andric return "uint64_t"; 2040b57cec5SDimitry Andric case SimpleTypeKind::HResult: 2050b57cec5SDimitry Andric return "HRESULT"; 2060b57cec5SDimitry Andric case SimpleTypeKind::UInt32: 2070b57cec5SDimitry Andric return "unsigned"; 2080b57cec5SDimitry Andric case SimpleTypeKind::UInt16: 2090b57cec5SDimitry Andric case SimpleTypeKind::UInt16Short: 2100b57cec5SDimitry Andric return "unsigned short"; 2110b57cec5SDimitry Andric case SimpleTypeKind::Int32Long: 2120b57cec5SDimitry Andric return "long"; 2130b57cec5SDimitry Andric case SimpleTypeKind::UInt32Long: 2140b57cec5SDimitry Andric return "unsigned long"; 2150b57cec5SDimitry Andric case SimpleTypeKind::Void: 2160b57cec5SDimitry Andric return "void"; 2170b57cec5SDimitry Andric case SimpleTypeKind::WideCharacter: 2180b57cec5SDimitry Andric return "wchar_t"; 2190b57cec5SDimitry Andric default: 2200b57cec5SDimitry Andric return ""; 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric static bool IsClassRecord(TypeLeafKind kind) { 2250b57cec5SDimitry Andric switch (kind) { 2260b57cec5SDimitry Andric case LF_STRUCTURE: 2270b57cec5SDimitry Andric case LF_CLASS: 2280b57cec5SDimitry Andric case LF_INTERFACE: 2290b57cec5SDimitry Andric return true; 2300b57cec5SDimitry Andric default: 2310b57cec5SDimitry Andric return false; 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 235bdd1243dSDimitry Andric static std::optional<CVTagRecord> 236bdd1243dSDimitry Andric GetNestedTagDefinition(const NestedTypeRecord &Record, 237bdd1243dSDimitry Andric const CVTagRecord &parent, TpiStream &tpi) { 238bdd1243dSDimitry Andric // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it 239bdd1243dSDimitry Andric // is also used to indicate the primary definition of a nested class. That is 240bdd1243dSDimitry Andric // to say, if you have: 241bdd1243dSDimitry Andric // struct A { 242bdd1243dSDimitry Andric // struct B {}; 243bdd1243dSDimitry Andric // using C = B; 244bdd1243dSDimitry Andric // }; 245bdd1243dSDimitry Andric // Then in the debug info, this will appear as: 246bdd1243dSDimitry Andric // LF_STRUCTURE `A::B` [type index = N] 247bdd1243dSDimitry Andric // LF_STRUCTURE `A` 248bdd1243dSDimitry Andric // LF_NESTTYPE [name = `B`, index = N] 249bdd1243dSDimitry Andric // LF_NESTTYPE [name = `C`, index = N] 250bdd1243dSDimitry Andric // In order to accurately reconstruct the decl context hierarchy, we need to 251bdd1243dSDimitry Andric // know which ones are actual definitions and which ones are just aliases. 252bdd1243dSDimitry Andric 253bdd1243dSDimitry Andric // If it's a simple type, then this is something like `using foo = int`. 254bdd1243dSDimitry Andric if (Record.Type.isSimple()) 255bdd1243dSDimitry Andric return std::nullopt; 256bdd1243dSDimitry Andric 257bdd1243dSDimitry Andric CVType cvt = tpi.getType(Record.Type); 258bdd1243dSDimitry Andric 259bdd1243dSDimitry Andric if (!IsTagRecord(cvt)) 260bdd1243dSDimitry Andric return std::nullopt; 261bdd1243dSDimitry Andric 262bdd1243dSDimitry Andric // If it's an inner definition, then treat whatever name we have here as a 263bdd1243dSDimitry Andric // single component of a mangled name. So we can inject it into the parent's 264bdd1243dSDimitry Andric // mangled name to see if it matches. 265bdd1243dSDimitry Andric CVTagRecord child = CVTagRecord::create(cvt); 266bdd1243dSDimitry Andric std::string qname = std::string(parent.asTag().getUniqueName()); 267bdd1243dSDimitry Andric if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4) 268bdd1243dSDimitry Andric return std::nullopt; 269bdd1243dSDimitry Andric 270bdd1243dSDimitry Andric // qname[3] is the tag type identifier (struct, class, union, etc). Since the 271bdd1243dSDimitry Andric // inner tag type is not necessarily the same as the outer tag type, re-write 272bdd1243dSDimitry Andric // it to match the inner tag type. 273bdd1243dSDimitry Andric qname[3] = child.asTag().getUniqueName()[3]; 274bdd1243dSDimitry Andric std::string piece; 275bdd1243dSDimitry Andric if (qname[3] == 'W') 276bdd1243dSDimitry Andric piece = "4"; 277bdd1243dSDimitry Andric piece += Record.Name; 278bdd1243dSDimitry Andric piece.push_back('@'); 279bdd1243dSDimitry Andric qname.insert(4, std::move(piece)); 280bdd1243dSDimitry Andric if (qname != child.asTag().UniqueName) 281bdd1243dSDimitry Andric return std::nullopt; 282bdd1243dSDimitry Andric 283bdd1243dSDimitry Andric return std::move(child); 284bdd1243dSDimitry Andric } 285bdd1243dSDimitry Andric 2860b57cec5SDimitry Andric void SymbolFileNativePDB::Initialize() { 2870b57cec5SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 2880b57cec5SDimitry Andric GetPluginDescriptionStatic(), CreateInstance, 2890b57cec5SDimitry Andric DebuggerInitialize); 2900b57cec5SDimitry Andric } 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric void SymbolFileNativePDB::Terminate() { 2930b57cec5SDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric void SymbolFileNativePDB::DebuggerInitialize(Debugger &debugger) {} 2970b57cec5SDimitry Andric 298349cc55cSDimitry Andric llvm::StringRef SymbolFileNativePDB::GetPluginDescriptionStatic() { 2990b57cec5SDimitry Andric return "Microsoft PDB debug symbol cross-platform file reader."; 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 3029dba64beSDimitry Andric SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) { 3039dba64beSDimitry Andric return new SymbolFileNativePDB(std::move(objfile_sp)); 3040b57cec5SDimitry Andric } 3050b57cec5SDimitry Andric 3069dba64beSDimitry Andric SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp) 30781ad6265SDimitry Andric : SymbolFileCommon(std::move(objfile_sp)) {} 3080b57cec5SDimitry Andric 309fe6060f1SDimitry Andric SymbolFileNativePDB::~SymbolFileNativePDB() = default; 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric uint32_t SymbolFileNativePDB::CalculateAbilities() { 3120b57cec5SDimitry Andric uint32_t abilities = 0; 3139dba64beSDimitry Andric if (!m_objfile_sp) 3140b57cec5SDimitry Andric return 0; 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric if (!m_index) { 3170b57cec5SDimitry Andric // Lazily load and match the PDB file, but only do this once. 318e8d8bef9SDimitry Andric PDBFile *pdb_file; 319e8d8bef9SDimitry Andric if (auto *pdb = llvm::dyn_cast<ObjectFilePDB>(m_objfile_sp.get())) { 320e8d8bef9SDimitry Andric pdb_file = &pdb->GetPDBFile(); 321e8d8bef9SDimitry Andric } else { 322e8d8bef9SDimitry Andric m_file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(), 323e8d8bef9SDimitry Andric m_allocator); 324e8d8bef9SDimitry Andric pdb_file = m_file_up.get(); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 327e8d8bef9SDimitry Andric if (!pdb_file) 3280b57cec5SDimitry Andric return 0; 3290b57cec5SDimitry Andric 330e8d8bef9SDimitry Andric auto expected_index = PdbIndex::create(pdb_file); 3310b57cec5SDimitry Andric if (!expected_index) { 3320b57cec5SDimitry Andric llvm::consumeError(expected_index.takeError()); 3330b57cec5SDimitry Andric return 0; 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric m_index = std::move(*expected_index); 3360b57cec5SDimitry Andric } 3370b57cec5SDimitry Andric if (!m_index) 3380b57cec5SDimitry Andric return 0; 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric // We don't especially have to be precise here. We only distinguish between 3410b57cec5SDimitry Andric // stripped and not stripped. 3420b57cec5SDimitry Andric abilities = kAllAbilities; 3430b57cec5SDimitry Andric 3440b57cec5SDimitry Andric if (m_index->dbi().isStripped()) 3450b57cec5SDimitry Andric abilities &= ~(Blocks | LocalVariables); 3460b57cec5SDimitry Andric return abilities; 3470b57cec5SDimitry Andric } 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric void SymbolFileNativePDB::InitializeObject() { 350e8d8bef9SDimitry Andric m_obj_load_address = m_objfile_sp->GetModule() 351e8d8bef9SDimitry Andric ->GetObjectFile() 352e8d8bef9SDimitry Andric ->GetBaseAddress() 353e8d8bef9SDimitry Andric .GetFileAddress(); 3540b57cec5SDimitry Andric m_index->SetLoadAddress(m_obj_load_address); 3550b57cec5SDimitry Andric m_index->ParseSectionContribs(); 3560b57cec5SDimitry Andric 3579dba64beSDimitry Andric auto ts_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage( 3580b57cec5SDimitry Andric lldb::eLanguageTypeC_plus_plus); 3599dba64beSDimitry Andric if (auto err = ts_or_err.takeError()) { 36081ad6265SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), 36106c3fb27SDimitry Andric "Failed to initialize: {0}"); 3629dba64beSDimitry Andric } else { 363bdd1243dSDimitry Andric if (auto ts = *ts_or_err) 364bdd1243dSDimitry Andric ts->SetSymbolFile(this); 365bdd1243dSDimitry Andric BuildParentMap(); 3669dba64beSDimitry Andric } 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric 3699dba64beSDimitry Andric uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() { 3700b57cec5SDimitry Andric const DbiModuleList &modules = m_index->dbi().modules(); 3710b57cec5SDimitry Andric uint32_t count = modules.getModuleCount(); 3720b57cec5SDimitry Andric if (count == 0) 3730b57cec5SDimitry Andric return count; 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric // The linker can inject an additional "dummy" compilation unit into the 3760b57cec5SDimitry Andric // PDB. Ignore this special compile unit for our purposes, if it is there. 3770b57cec5SDimitry Andric // It is always the last one. 3780b57cec5SDimitry Andric DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1); 3790b57cec5SDimitry Andric if (last.getModuleName() == "* Linker *") 3800b57cec5SDimitry Andric --count; 3810b57cec5SDimitry Andric return count; 3820b57cec5SDimitry Andric } 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { 3850b57cec5SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi); 3860b57cec5SDimitry Andric CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset); 3870b57cec5SDimitry Andric CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); 38804eeddc0SDimitry Andric lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id); 38904eeddc0SDimitry Andric BlockSP child_block = std::make_shared<Block>(opaque_block_uid); 390bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage()); 391bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 392bdd1243dSDimitry Andric return *child_block; 393bdd1243dSDimitry Andric auto ts = *ts_or_err; 394bdd1243dSDimitry Andric if (!ts) 395bdd1243dSDimitry Andric return *child_block; 396bdd1243dSDimitry Andric PdbAstBuilder* ast_builder = ts->GetNativePDBParser(); 39704eeddc0SDimitry Andric 39804eeddc0SDimitry Andric switch (sym.kind()) { 39904eeddc0SDimitry Andric case S_GPROC32: 40004eeddc0SDimitry Andric case S_LPROC32: { 40104eeddc0SDimitry Andric // This is a function. It must be global. Creating the Function entry 40204eeddc0SDimitry Andric // for it automatically creates a block for it. 40304eeddc0SDimitry Andric FunctionSP func = GetOrCreateFunction(block_id, *comp_unit); 404bdd1243dSDimitry Andric if (func) { 40504eeddc0SDimitry Andric Block &block = func->GetBlock(false); 40604eeddc0SDimitry Andric if (block.GetNumRanges() == 0) 40704eeddc0SDimitry Andric block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize())); 40804eeddc0SDimitry Andric return block; 4090b57cec5SDimitry Andric } 410bdd1243dSDimitry Andric break; 411bdd1243dSDimitry Andric } 41204eeddc0SDimitry Andric case S_BLOCK32: { 4130b57cec5SDimitry Andric // This is a block. Its parent is either a function or another block. In 41404eeddc0SDimitry Andric // either case, its parent can be viewed as a block (e.g. a function 41504eeddc0SDimitry Andric // contains 1 big block. So just get the parent block and add this block 41604eeddc0SDimitry Andric // to it. 4170b57cec5SDimitry Andric BlockSym block(static_cast<SymbolRecordKind>(sym.kind())); 4180b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block)); 4190b57cec5SDimitry Andric lldbassert(block.Parent != 0); 4200b57cec5SDimitry Andric PdbCompilandSymId parent_id(block_id.modi, block.Parent); 4210b57cec5SDimitry Andric Block &parent_block = GetOrCreateBlock(parent_id); 422bdd1243dSDimitry Andric Function *func = parent_block.CalculateSymbolContextFunction(); 423bdd1243dSDimitry Andric lldbassert(func); 424bdd1243dSDimitry Andric lldb::addr_t block_base = 425bdd1243dSDimitry Andric m_index->MakeVirtualAddress(block.Segment, block.CodeOffset); 426bdd1243dSDimitry Andric lldb::addr_t func_base = 427bdd1243dSDimitry Andric func->GetAddressRange().GetBaseAddress().GetFileAddress(); 428bdd1243dSDimitry Andric if (block_base >= func_base) 429bdd1243dSDimitry Andric child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize)); 430bdd1243dSDimitry Andric else { 431bdd1243dSDimitry Andric GetObjectFile()->GetModule()->ReportError( 432bdd1243dSDimitry Andric "S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range " 433bdd1243dSDimitry Andric "[{2:x16}-{3:x16}) which has a base that is less than the " 434bdd1243dSDimitry Andric "function's " 435bdd1243dSDimitry Andric "low PC 0x%" PRIx64 ". Please file a bug and attach the file at the " 436bdd1243dSDimitry Andric "start of this error message", 437bdd1243dSDimitry Andric block_id.modi, block_id.offset, block_base, 438bdd1243dSDimitry Andric block_base + block.CodeSize, func_base); 439bdd1243dSDimitry Andric } 44004eeddc0SDimitry Andric parent_block.AddChild(child_block); 441bdd1243dSDimitry Andric ast_builder->GetOrCreateBlockDecl(block_id); 44204eeddc0SDimitry Andric m_blocks.insert({opaque_block_uid, child_block}); 44304eeddc0SDimitry Andric break; 44404eeddc0SDimitry Andric } 44504eeddc0SDimitry Andric case S_INLINESITE: { 44604eeddc0SDimitry Andric // This ensures line table is parsed first so we have inline sites info. 44704eeddc0SDimitry Andric comp_unit->GetLineTable(); 44804eeddc0SDimitry Andric 44904eeddc0SDimitry Andric std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid]; 45004eeddc0SDimitry Andric Block &parent_block = GetOrCreateBlock(inline_site->parent_id); 4510b57cec5SDimitry Andric parent_block.AddChild(child_block); 452bdd1243dSDimitry Andric ast_builder->GetOrCreateInlinedFunctionDecl(block_id); 45304eeddc0SDimitry Andric // Copy ranges from InlineSite to Block. 45404eeddc0SDimitry Andric for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) { 45504eeddc0SDimitry Andric auto *entry = inline_site->ranges.GetEntryAtIndex(i); 45604eeddc0SDimitry Andric child_block->AddRange( 45704eeddc0SDimitry Andric Block::Range(entry->GetRangeBase(), entry->GetByteSize())); 45804eeddc0SDimitry Andric } 45904eeddc0SDimitry Andric child_block->FinalizeRanges(); 4600b57cec5SDimitry Andric 46104eeddc0SDimitry Andric // Get the inlined function callsite info. 46204eeddc0SDimitry Andric Declaration &decl = inline_site->inline_function_info->GetDeclaration(); 46304eeddc0SDimitry Andric Declaration &callsite = inline_site->inline_function_info->GetCallSite(); 46404eeddc0SDimitry Andric child_block->SetInlinedFunctionInfo( 46504eeddc0SDimitry Andric inline_site->inline_function_info->GetName().GetCString(), nullptr, 46604eeddc0SDimitry Andric &decl, &callsite); 4670b57cec5SDimitry Andric m_blocks.insert({opaque_block_uid, child_block}); 46804eeddc0SDimitry Andric break; 46904eeddc0SDimitry Andric } 47004eeddc0SDimitry Andric default: 47104eeddc0SDimitry Andric lldbassert(false && "Symbol is not a block!"); 47204eeddc0SDimitry Andric } 47304eeddc0SDimitry Andric 4740b57cec5SDimitry Andric return *child_block; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id, 4780b57cec5SDimitry Andric CompileUnit &comp_unit) { 4790b57cec5SDimitry Andric const CompilandIndexItem *cci = 4800b57cec5SDimitry Andric m_index->compilands().GetCompiland(func_id.modi); 4810b57cec5SDimitry Andric lldbassert(cci); 4820b57cec5SDimitry Andric CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset); 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric lldbassert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32); 4850b57cec5SDimitry Andric SegmentOffsetLength sol = GetSegmentOffsetAndLength(sym_record); 4860b57cec5SDimitry Andric 48781ad6265SDimitry Andric auto file_vm_addr = 48881ad6265SDimitry Andric m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset); 4890b57cec5SDimitry Andric if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0) 4900b57cec5SDimitry Andric return nullptr; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric AddressRange func_range(file_vm_addr, sol.length, 4930b57cec5SDimitry Andric comp_unit.GetModule()->GetSectionList()); 4940b57cec5SDimitry Andric if (!func_range.GetBaseAddress().IsValid()) 4950b57cec5SDimitry Andric return nullptr; 4960b57cec5SDimitry Andric 4970b57cec5SDimitry Andric ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind())); 4980b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc)); 4990b57cec5SDimitry Andric if (proc.FunctionType == TypeIndex::None()) 5000b57cec5SDimitry Andric return nullptr; 5010b57cec5SDimitry Andric TypeSP func_type = GetOrCreateType(proc.FunctionType); 5020b57cec5SDimitry Andric if (!func_type) 5030b57cec5SDimitry Andric return nullptr; 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric PdbTypeSymId sig_id(proc.FunctionType, false); 5060b57cec5SDimitry Andric Mangled mangled(proc.Name); 5070b57cec5SDimitry Andric FunctionSP func_sp = std::make_shared<Function>( 5080b57cec5SDimitry Andric &comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled, 5090b57cec5SDimitry Andric func_type.get(), func_range); 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andric comp_unit.AddFunction(func_sp); 5120b57cec5SDimitry Andric 513bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage()); 514bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 515bdd1243dSDimitry Andric return func_sp; 516bdd1243dSDimitry Andric auto ts = *ts_or_err; 517bdd1243dSDimitry Andric if (!ts) 518bdd1243dSDimitry Andric return func_sp; 519bdd1243dSDimitry Andric ts->GetNativePDBParser()->GetOrCreateFunctionDecl(func_id); 5200b57cec5SDimitry Andric 5210b57cec5SDimitry Andric return func_sp; 5220b57cec5SDimitry Andric } 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric CompUnitSP 5250b57cec5SDimitry Andric SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) { 5260b57cec5SDimitry Andric lldb::LanguageType lang = 5270b57cec5SDimitry Andric cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage()) 5280b57cec5SDimitry Andric : lldb::eLanguageTypeUnknown; 5290b57cec5SDimitry Andric 5300b57cec5SDimitry Andric LazyBool optimized = eLazyBoolNo; 5310b57cec5SDimitry Andric if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations()) 5320b57cec5SDimitry Andric optimized = eLazyBoolYes; 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric llvm::SmallString<64> source_file_name = 5350b57cec5SDimitry Andric m_index->compilands().GetMainSourceFile(cci); 53681ad6265SDimitry Andric FileSpec fs(llvm::sys::path::convert_to_slash( 53781ad6265SDimitry Andric source_file_name, llvm::sys::path::Style::windows_backslash)); 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric CompUnitSP cu_sp = 5409dba64beSDimitry Andric std::make_shared<CompileUnit>(m_objfile_sp->GetModule(), nullptr, fs, 5410b57cec5SDimitry Andric toOpaqueUid(cci.m_id), lang, optimized); 5420b57cec5SDimitry Andric 5439dba64beSDimitry Andric SetCompileUnitAtIndex(cci.m_id.modi, cu_sp); 5440b57cec5SDimitry Andric return cu_sp; 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric 5470b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id, 5480b57cec5SDimitry Andric const ModifierRecord &mr, 5490b57cec5SDimitry Andric CompilerType ct) { 5500b57cec5SDimitry Andric TpiStream &stream = m_index->tpi(); 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric std::string name; 5530b57cec5SDimitry Andric if (mr.ModifiedType.isSimple()) 5545ffd83dbSDimitry Andric name = std::string(GetSimpleTypeName(mr.ModifiedType.getSimpleKind())); 5550b57cec5SDimitry Andric else 5560b57cec5SDimitry Andric name = computeTypeName(stream.typeCollection(), mr.ModifiedType); 5570b57cec5SDimitry Andric Declaration decl; 5580b57cec5SDimitry Andric lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType); 5590b57cec5SDimitry Andric 560bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(name), 561e8d8bef9SDimitry Andric modified_type->GetByteSize(nullptr), nullptr, 562bdd1243dSDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, 563bdd1243dSDimitry Andric Type::ResolveState::Full); 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric lldb::TypeSP 5670b57cec5SDimitry Andric SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id, 5680b57cec5SDimitry Andric const llvm::codeview::PointerRecord &pr, 5690b57cec5SDimitry Andric CompilerType ct) { 5700b57cec5SDimitry Andric TypeSP pointee = GetOrCreateType(pr.ReferentType); 5710b57cec5SDimitry Andric if (!pointee) 5720b57cec5SDimitry Andric return nullptr; 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric if (pr.isPointerToMember()) { 5750b57cec5SDimitry Andric MemberPointerInfo mpi = pr.getMemberInfo(); 5760b57cec5SDimitry Andric GetOrCreateType(mpi.ContainingType); 5770b57cec5SDimitry Andric } 5780b57cec5SDimitry Andric 5790b57cec5SDimitry Andric Declaration decl; 580bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr, 581bdd1243dSDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, 582480093f4SDimitry Andric Type::ResolveState::Full); 5830b57cec5SDimitry Andric } 5840b57cec5SDimitry Andric 5850b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, 5860b57cec5SDimitry Andric CompilerType ct) { 5870b57cec5SDimitry Andric uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false)); 5880b57cec5SDimitry Andric if (ti == TypeIndex::NullptrT()) { 5890b57cec5SDimitry Andric Declaration decl; 590bdd1243dSDimitry Andric return MakeType(uid, ConstString("std::nullptr_t"), 0, nullptr, 591bdd1243dSDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, 592bdd1243dSDimitry Andric Type::ResolveState::Full); 5930b57cec5SDimitry Andric } 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric if (ti.getSimpleMode() != SimpleTypeMode::Direct) { 5960b57cec5SDimitry Andric TypeSP direct_sp = GetOrCreateType(ti.makeDirect()); 5970b57cec5SDimitry Andric uint32_t pointer_size = 0; 5980b57cec5SDimitry Andric switch (ti.getSimpleMode()) { 5990b57cec5SDimitry Andric case SimpleTypeMode::FarPointer32: 6000b57cec5SDimitry Andric case SimpleTypeMode::NearPointer32: 6010b57cec5SDimitry Andric pointer_size = 4; 6020b57cec5SDimitry Andric break; 6030b57cec5SDimitry Andric case SimpleTypeMode::NearPointer64: 6040b57cec5SDimitry Andric pointer_size = 8; 6050b57cec5SDimitry Andric break; 6060b57cec5SDimitry Andric default: 6070b57cec5SDimitry Andric // 128-bit and 16-bit pointers unsupported. 6080b57cec5SDimitry Andric return nullptr; 6090b57cec5SDimitry Andric } 6100b57cec5SDimitry Andric Declaration decl; 611bdd1243dSDimitry Andric return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID, 612480093f4SDimitry Andric Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); 6130b57cec5SDimitry Andric } 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated) 6160b57cec5SDimitry Andric return nullptr; 6170b57cec5SDimitry Andric 6180b57cec5SDimitry Andric size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind()); 6190b57cec5SDimitry Andric llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind()); 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric Declaration decl; 622bdd1243dSDimitry Andric return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID, 623bdd1243dSDimitry Andric Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); 6240b57cec5SDimitry Andric } 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric static std::string GetUnqualifiedTypeName(const TagRecord &record) { 6270b57cec5SDimitry Andric if (!record.hasUniqueName()) { 6280b57cec5SDimitry Andric MSVCUndecoratedNameParser parser(record.Name); 6290b57cec5SDimitry Andric llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers(); 6300b57cec5SDimitry Andric 6315ffd83dbSDimitry Andric return std::string(specs.back().GetBaseName()); 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric llvm::ms_demangle::Demangler demangler; 63506c3fb27SDimitry Andric std::string_view sv(record.UniqueName.begin(), record.UniqueName.size()); 6360b57cec5SDimitry Andric llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv); 6370b57cec5SDimitry Andric if (demangler.Error) 6385ffd83dbSDimitry Andric return std::string(record.Name); 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric llvm::ms_demangle::IdentifierNode *idn = 6410b57cec5SDimitry Andric ttn->QualifiedName->getUnqualifiedIdentifier(); 6420b57cec5SDimitry Andric return idn->toString(); 6430b57cec5SDimitry Andric } 6440b57cec5SDimitry Andric 6450b57cec5SDimitry Andric lldb::TypeSP 6460b57cec5SDimitry Andric SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id, 6470b57cec5SDimitry Andric const TagRecord &record, 6480b57cec5SDimitry Andric size_t size, CompilerType ct) { 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric std::string uname = GetUnqualifiedTypeName(record); 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric // FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE. 6530b57cec5SDimitry Andric Declaration decl; 654bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr, 655bdd1243dSDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, 656480093f4SDimitry Andric Type::ResolveState::Forward); 6570b57cec5SDimitry Andric } 6580b57cec5SDimitry Andric 6590b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id, 6600b57cec5SDimitry Andric const ClassRecord &cr, 6610b57cec5SDimitry Andric CompilerType ct) { 6620b57cec5SDimitry Andric return CreateClassStructUnion(type_id, cr, cr.getSize(), ct); 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id, 6660b57cec5SDimitry Andric const UnionRecord &ur, 6670b57cec5SDimitry Andric CompilerType ct) { 6680b57cec5SDimitry Andric return CreateClassStructUnion(type_id, ur, ur.getSize(), ct); 6690b57cec5SDimitry Andric } 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id, 6720b57cec5SDimitry Andric const EnumRecord &er, 6730b57cec5SDimitry Andric CompilerType ct) { 6740b57cec5SDimitry Andric std::string uname = GetUnqualifiedTypeName(er); 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric Declaration decl; 6770b57cec5SDimitry Andric TypeSP underlying_type = GetOrCreateType(er.UnderlyingType); 6780b57cec5SDimitry Andric 679bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(uname), 680bdd1243dSDimitry Andric underlying_type->GetByteSize(nullptr), nullptr, 681bdd1243dSDimitry Andric LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, 682bdd1243dSDimitry Andric ct, lldb_private::Type::ResolveState::Forward); 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id, 6860b57cec5SDimitry Andric const ArrayRecord &ar, 6870b57cec5SDimitry Andric CompilerType ct) { 6880b57cec5SDimitry Andric TypeSP element_type = GetOrCreateType(ar.ElementType); 6890b57cec5SDimitry Andric 6900b57cec5SDimitry Andric Declaration decl; 691bdd1243dSDimitry Andric TypeSP array_sp = 692bdd1243dSDimitry Andric MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr, 6930b57cec5SDimitry Andric LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct, 694480093f4SDimitry Andric lldb_private::Type::ResolveState::Full); 6950b57cec5SDimitry Andric array_sp->SetEncodingType(element_type.get()); 6960b57cec5SDimitry Andric return array_sp; 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id, 7000b57cec5SDimitry Andric const MemberFunctionRecord &mfr, 7010b57cec5SDimitry Andric CompilerType ct) { 7020b57cec5SDimitry Andric Declaration decl; 703bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr, 704bdd1243dSDimitry Andric LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, 705bdd1243dSDimitry Andric ct, lldb_private::Type::ResolveState::Full); 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id, 7090b57cec5SDimitry Andric const ProcedureRecord &pr, 7100b57cec5SDimitry Andric CompilerType ct) { 7110b57cec5SDimitry Andric Declaration decl; 712bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr, 713bdd1243dSDimitry Andric LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, 714bdd1243dSDimitry Andric ct, lldb_private::Type::ResolveState::Full); 7150b57cec5SDimitry Andric } 7160b57cec5SDimitry Andric 7170b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) { 7180b57cec5SDimitry Andric if (type_id.index.isSimple()) 7190b57cec5SDimitry Andric return CreateSimpleType(type_id.index, ct); 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi(); 7220b57cec5SDimitry Andric CVType cvt = stream.getType(type_id.index); 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric if (cvt.kind() == LF_MODIFIER) { 7250b57cec5SDimitry Andric ModifierRecord modifier; 7260b57cec5SDimitry Andric llvm::cantFail( 7270b57cec5SDimitry Andric TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier)); 7280b57cec5SDimitry Andric return CreateModifierType(type_id, modifier, ct); 7290b57cec5SDimitry Andric } 7300b57cec5SDimitry Andric 7310b57cec5SDimitry Andric if (cvt.kind() == LF_POINTER) { 7320b57cec5SDimitry Andric PointerRecord pointer; 7330b57cec5SDimitry Andric llvm::cantFail( 7340b57cec5SDimitry Andric TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer)); 7350b57cec5SDimitry Andric return CreatePointerType(type_id, pointer, ct); 7360b57cec5SDimitry Andric } 7370b57cec5SDimitry Andric 7380b57cec5SDimitry Andric if (IsClassRecord(cvt.kind())) { 7390b57cec5SDimitry Andric ClassRecord cr; 7400b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr)); 7410b57cec5SDimitry Andric return CreateTagType(type_id, cr, ct); 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric if (cvt.kind() == LF_ENUM) { 7450b57cec5SDimitry Andric EnumRecord er; 7460b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)); 7470b57cec5SDimitry Andric return CreateTagType(type_id, er, ct); 7480b57cec5SDimitry Andric } 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric if (cvt.kind() == LF_UNION) { 7510b57cec5SDimitry Andric UnionRecord ur; 7520b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur)); 7530b57cec5SDimitry Andric return CreateTagType(type_id, ur, ct); 7540b57cec5SDimitry Andric } 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric if (cvt.kind() == LF_ARRAY) { 7570b57cec5SDimitry Andric ArrayRecord ar; 7580b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar)); 7590b57cec5SDimitry Andric return CreateArrayType(type_id, ar, ct); 7600b57cec5SDimitry Andric } 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric if (cvt.kind() == LF_PROCEDURE) { 7630b57cec5SDimitry Andric ProcedureRecord pr; 7640b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr)); 7650b57cec5SDimitry Andric return CreateProcedureType(type_id, pr, ct); 7660b57cec5SDimitry Andric } 7670b57cec5SDimitry Andric if (cvt.kind() == LF_MFUNCTION) { 7680b57cec5SDimitry Andric MemberFunctionRecord mfr; 7690b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr)); 7700b57cec5SDimitry Andric return CreateFunctionType(type_id, mfr, ct); 7710b57cec5SDimitry Andric } 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric return nullptr; 7740b57cec5SDimitry Andric } 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) { 7770b57cec5SDimitry Andric // If they search for a UDT which is a forward ref, try and resolve the full 7780b57cec5SDimitry Andric // decl and just map the forward ref uid to the full decl record. 779bdd1243dSDimitry Andric std::optional<PdbTypeSymId> full_decl_uid; 7800b57cec5SDimitry Andric if (IsForwardRefUdt(type_id, m_index->tpi())) { 7810b57cec5SDimitry Andric auto expected_full_ti = 7820b57cec5SDimitry Andric m_index->tpi().findFullDeclForForwardRef(type_id.index); 7830b57cec5SDimitry Andric if (!expected_full_ti) 7840b57cec5SDimitry Andric llvm::consumeError(expected_full_ti.takeError()); 7850b57cec5SDimitry Andric else if (*expected_full_ti != type_id.index) { 7860b57cec5SDimitry Andric full_decl_uid = PdbTypeSymId(*expected_full_ti, false); 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric // It's possible that a lookup would occur for the full decl causing it 7890b57cec5SDimitry Andric // to be cached, then a second lookup would occur for the forward decl. 7900b57cec5SDimitry Andric // We don't want to create a second full decl, so make sure the full 7910b57cec5SDimitry Andric // decl hasn't already been cached. 7920b57cec5SDimitry Andric auto full_iter = m_types.find(toOpaqueUid(*full_decl_uid)); 7930b57cec5SDimitry Andric if (full_iter != m_types.end()) { 7940b57cec5SDimitry Andric TypeSP result = full_iter->second; 7950b57cec5SDimitry Andric // Map the forward decl to the TypeSP for the full decl so we can take 7960b57cec5SDimitry Andric // the fast path next time. 7970b57cec5SDimitry Andric m_types[toOpaqueUid(type_id)] = result; 7980b57cec5SDimitry Andric return result; 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric } 8010b57cec5SDimitry Andric } 8020b57cec5SDimitry Andric 8030b57cec5SDimitry Andric PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id; 804bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 805bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 806bdd1243dSDimitry Andric return nullptr; 807bdd1243dSDimitry Andric auto ts = *ts_or_err; 808bdd1243dSDimitry Andric if (!ts) 809bdd1243dSDimitry Andric return nullptr; 8100b57cec5SDimitry Andric 811bdd1243dSDimitry Andric PdbAstBuilder* ast_builder = ts->GetNativePDBParser(); 812bdd1243dSDimitry Andric clang::QualType qt = ast_builder->GetOrCreateType(best_decl_id); 81381ad6265SDimitry Andric if (qt.isNull()) 81481ad6265SDimitry Andric return nullptr; 8150b57cec5SDimitry Andric 816bdd1243dSDimitry Andric TypeSP result = CreateType(best_decl_id, ast_builder->ToCompilerType(qt)); 8170b57cec5SDimitry Andric if (!result) 8180b57cec5SDimitry Andric return nullptr; 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric uint64_t best_uid = toOpaqueUid(best_decl_id); 8210b57cec5SDimitry Andric m_types[best_uid] = result; 8220b57cec5SDimitry Andric // If we had both a forward decl and a full decl, make both point to the new 8230b57cec5SDimitry Andric // type. 8240b57cec5SDimitry Andric if (full_decl_uid) 8250b57cec5SDimitry Andric m_types[toOpaqueUid(type_id)] = result; 8260b57cec5SDimitry Andric 8270b57cec5SDimitry Andric return result; 8280b57cec5SDimitry Andric } 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) { 8310b57cec5SDimitry Andric // We can't use try_emplace / overwrite here because the process of creating 8320b57cec5SDimitry Andric // a type could create nested types, which could invalidate iterators. So 8330b57cec5SDimitry Andric // we have to do a 2-phase lookup / insert. 8340b57cec5SDimitry Andric auto iter = m_types.find(toOpaqueUid(type_id)); 8350b57cec5SDimitry Andric if (iter != m_types.end()) 8360b57cec5SDimitry Andric return iter->second; 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric TypeSP type = CreateAndCacheType(type_id); 8390b57cec5SDimitry Andric if (type) 8409dba64beSDimitry Andric GetTypeList().Insert(type); 8410b57cec5SDimitry Andric return type; 8420b57cec5SDimitry Andric } 8430b57cec5SDimitry Andric 8440b57cec5SDimitry Andric VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { 8450b57cec5SDimitry Andric CVSymbol sym = m_index->symrecords().readRecord(var_id.offset); 8460b57cec5SDimitry Andric if (sym.kind() == S_CONSTANT) 8470b57cec5SDimitry Andric return CreateConstantSymbol(var_id, sym); 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric lldb::ValueType scope = eValueTypeInvalid; 8500b57cec5SDimitry Andric TypeIndex ti; 8510b57cec5SDimitry Andric llvm::StringRef name; 8520b57cec5SDimitry Andric lldb::addr_t addr = 0; 8530b57cec5SDimitry Andric uint16_t section = 0; 8540b57cec5SDimitry Andric uint32_t offset = 0; 8550b57cec5SDimitry Andric bool is_external = false; 8560b57cec5SDimitry Andric switch (sym.kind()) { 8570b57cec5SDimitry Andric case S_GDATA32: 8580b57cec5SDimitry Andric is_external = true; 859bdd1243dSDimitry Andric [[fallthrough]]; 8600b57cec5SDimitry Andric case S_LDATA32: { 8610b57cec5SDimitry Andric DataSym ds(sym.kind()); 8620b57cec5SDimitry Andric llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds)); 8630b57cec5SDimitry Andric ti = ds.Type; 8640b57cec5SDimitry Andric scope = (sym.kind() == S_GDATA32) ? eValueTypeVariableGlobal 8650b57cec5SDimitry Andric : eValueTypeVariableStatic; 8660b57cec5SDimitry Andric name = ds.Name; 8670b57cec5SDimitry Andric section = ds.Segment; 8680b57cec5SDimitry Andric offset = ds.DataOffset; 8690b57cec5SDimitry Andric addr = m_index->MakeVirtualAddress(ds.Segment, ds.DataOffset); 8700b57cec5SDimitry Andric break; 8710b57cec5SDimitry Andric } 8720b57cec5SDimitry Andric case S_GTHREAD32: 8730b57cec5SDimitry Andric is_external = true; 874bdd1243dSDimitry Andric [[fallthrough]]; 8750b57cec5SDimitry Andric case S_LTHREAD32: { 8760b57cec5SDimitry Andric ThreadLocalDataSym tlds(sym.kind()); 8770b57cec5SDimitry Andric llvm::cantFail( 8780b57cec5SDimitry Andric SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, tlds)); 8790b57cec5SDimitry Andric ti = tlds.Type; 8800b57cec5SDimitry Andric name = tlds.Name; 8810b57cec5SDimitry Andric section = tlds.Segment; 8820b57cec5SDimitry Andric offset = tlds.DataOffset; 8830b57cec5SDimitry Andric addr = m_index->MakeVirtualAddress(tlds.Segment, tlds.DataOffset); 8840b57cec5SDimitry Andric scope = eValueTypeVariableThreadLocal; 8850b57cec5SDimitry Andric break; 8860b57cec5SDimitry Andric } 8870b57cec5SDimitry Andric default: 8880b57cec5SDimitry Andric llvm_unreachable("unreachable!"); 8890b57cec5SDimitry Andric } 8900b57cec5SDimitry Andric 8910b57cec5SDimitry Andric CompUnitSP comp_unit; 892bdd1243dSDimitry Andric std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr); 89381ad6265SDimitry Andric if (!modi) { 89481ad6265SDimitry Andric return nullptr; 89581ad6265SDimitry Andric } 89681ad6265SDimitry Andric 8970b57cec5SDimitry Andric CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(*modi); 8980b57cec5SDimitry Andric comp_unit = GetOrCreateCompileUnit(cci); 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric Declaration decl; 9010b57cec5SDimitry Andric PdbTypeSymId tid(ti, false); 9020b57cec5SDimitry Andric SymbolFileTypeSP type_sp = 9030b57cec5SDimitry Andric std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid)); 9040b57cec5SDimitry Andric Variable::RangeList ranges; 905bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage()); 906bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 907bdd1243dSDimitry Andric return nullptr; 908bdd1243dSDimitry Andric auto ts = *ts_or_err; 909bdd1243dSDimitry Andric if (!ts) 910bdd1243dSDimitry Andric return nullptr; 9110b57cec5SDimitry Andric 912bdd1243dSDimitry Andric ts->GetNativePDBParser()->GetOrCreateVariableDecl(var_id); 9130b57cec5SDimitry Andric 914753f127fSDimitry Andric ModuleSP module_sp = GetObjectFile()->GetModule(); 915753f127fSDimitry Andric DWARFExpressionList location( 916753f127fSDimitry Andric module_sp, MakeGlobalLocationExpression(section, offset, module_sp), 917753f127fSDimitry Andric nullptr); 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric std::string global_name("::"); 9200b57cec5SDimitry Andric global_name += name; 921e8d8bef9SDimitry Andric bool artificial = false; 922e8d8bef9SDimitry Andric bool location_is_constant_data = false; 923e8d8bef9SDimitry Andric bool static_member = false; 9240b57cec5SDimitry Andric VariableSP var_sp = std::make_shared<Variable>( 9250b57cec5SDimitry Andric toOpaqueUid(var_id), name.str().c_str(), global_name.c_str(), type_sp, 926e8d8bef9SDimitry Andric scope, comp_unit.get(), ranges, &decl, location, is_external, artificial, 927e8d8bef9SDimitry Andric location_is_constant_data, static_member); 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric return var_sp; 9300b57cec5SDimitry Andric } 9310b57cec5SDimitry Andric 9320b57cec5SDimitry Andric lldb::VariableSP 9330b57cec5SDimitry Andric SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id, 9340b57cec5SDimitry Andric const CVSymbol &cvs) { 9350b57cec5SDimitry Andric TpiStream &tpi = m_index->tpi(); 9360b57cec5SDimitry Andric ConstantSym constant(cvs.kind()); 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(cvs, constant)); 9390b57cec5SDimitry Andric std::string global_name("::"); 9400b57cec5SDimitry Andric global_name += constant.Name; 9410b57cec5SDimitry Andric PdbTypeSymId tid(constant.Type, false); 9420b57cec5SDimitry Andric SymbolFileTypeSP type_sp = 9430b57cec5SDimitry Andric std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid)); 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric Declaration decl; 9460b57cec5SDimitry Andric Variable::RangeList ranges; 9470b57cec5SDimitry Andric ModuleSP module = GetObjectFile()->GetModule(); 948753f127fSDimitry Andric DWARFExpressionList location(module, 949753f127fSDimitry Andric MakeConstantLocationExpression( 950753f127fSDimitry Andric constant.Type, tpi, constant.Value, module), 951753f127fSDimitry Andric nullptr); 9520b57cec5SDimitry Andric 953e8d8bef9SDimitry Andric bool external = false; 954e8d8bef9SDimitry Andric bool artificial = false; 955e8d8bef9SDimitry Andric bool location_is_constant_data = true; 956e8d8bef9SDimitry Andric bool static_member = false; 9570b57cec5SDimitry Andric VariableSP var_sp = std::make_shared<Variable>( 9580b57cec5SDimitry Andric toOpaqueUid(var_id), constant.Name.str().c_str(), global_name.c_str(), 9590b57cec5SDimitry Andric type_sp, eValueTypeVariableGlobal, module.get(), ranges, &decl, location, 960e8d8bef9SDimitry Andric external, artificial, location_is_constant_data, static_member); 9610b57cec5SDimitry Andric return var_sp; 9620b57cec5SDimitry Andric } 9630b57cec5SDimitry Andric 9640b57cec5SDimitry Andric VariableSP 9650b57cec5SDimitry Andric SymbolFileNativePDB::GetOrCreateGlobalVariable(PdbGlobalSymId var_id) { 9660b57cec5SDimitry Andric auto emplace_result = m_global_vars.try_emplace(toOpaqueUid(var_id), nullptr); 96781ad6265SDimitry Andric if (emplace_result.second) { 96881ad6265SDimitry Andric if (VariableSP var_sp = CreateGlobalVariable(var_id)) 96981ad6265SDimitry Andric emplace_result.first->second = var_sp; 97081ad6265SDimitry Andric else 97181ad6265SDimitry Andric return nullptr; 97281ad6265SDimitry Andric } 9730b57cec5SDimitry Andric 9740b57cec5SDimitry Andric return emplace_result.first->second; 9750b57cec5SDimitry Andric } 9760b57cec5SDimitry Andric 9770b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::GetOrCreateType(TypeIndex ti) { 9780b57cec5SDimitry Andric return GetOrCreateType(PdbTypeSymId(ti, false)); 9790b57cec5SDimitry Andric } 9800b57cec5SDimitry Andric 9810b57cec5SDimitry Andric FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbCompilandSymId func_id, 9820b57cec5SDimitry Andric CompileUnit &comp_unit) { 9830b57cec5SDimitry Andric auto emplace_result = m_functions.try_emplace(toOpaqueUid(func_id), nullptr); 9840b57cec5SDimitry Andric if (emplace_result.second) 9850b57cec5SDimitry Andric emplace_result.first->second = CreateFunction(func_id, comp_unit); 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric return emplace_result.first->second; 9880b57cec5SDimitry Andric } 9890b57cec5SDimitry Andric 9900b57cec5SDimitry Andric CompUnitSP 9910b57cec5SDimitry Andric SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) { 9920b57cec5SDimitry Andric 9930b57cec5SDimitry Andric auto emplace_result = 9940b57cec5SDimitry Andric m_compilands.try_emplace(toOpaqueUid(cci.m_id), nullptr); 9950b57cec5SDimitry Andric if (emplace_result.second) 9960b57cec5SDimitry Andric emplace_result.first->second = CreateCompileUnit(cci); 9970b57cec5SDimitry Andric 9980b57cec5SDimitry Andric lldbassert(emplace_result.first->second); 9990b57cec5SDimitry Andric return emplace_result.first->second; 10000b57cec5SDimitry Andric } 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric Block &SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) { 10030b57cec5SDimitry Andric auto iter = m_blocks.find(toOpaqueUid(block_id)); 10040b57cec5SDimitry Andric if (iter != m_blocks.end()) 10050b57cec5SDimitry Andric return *iter->second; 10060b57cec5SDimitry Andric 10070b57cec5SDimitry Andric return CreateBlock(block_id); 10080b57cec5SDimitry Andric } 10090b57cec5SDimitry Andric 10100b57cec5SDimitry Andric void SymbolFileNativePDB::ParseDeclsForContext( 10110b57cec5SDimitry Andric lldb_private::CompilerDeclContext decl_ctx) { 1012bdd1243dSDimitry Andric TypeSystem* ts_or_err = decl_ctx.GetTypeSystem(); 1013bdd1243dSDimitry Andric if (!ts_or_err) 1014bdd1243dSDimitry Andric return; 1015bdd1243dSDimitry Andric PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser(); 1016bdd1243dSDimitry Andric clang::DeclContext *context = ast_builder->FromCompilerDeclContext(decl_ctx); 10170b57cec5SDimitry Andric if (!context) 10180b57cec5SDimitry Andric return; 1019bdd1243dSDimitry Andric ast_builder->ParseDeclsForContext(*context); 10200b57cec5SDimitry Andric } 10210b57cec5SDimitry Andric 10220b57cec5SDimitry Andric lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) { 10230b57cec5SDimitry Andric if (index >= GetNumCompileUnits()) 10240b57cec5SDimitry Andric return CompUnitSP(); 10250b57cec5SDimitry Andric lldbassert(index < UINT16_MAX); 10260b57cec5SDimitry Andric if (index >= UINT16_MAX) 10270b57cec5SDimitry Andric return nullptr; 10280b57cec5SDimitry Andric 10290b57cec5SDimitry Andric CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index); 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andric return GetOrCreateCompileUnit(item); 10320b57cec5SDimitry Andric } 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andric lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) { 10359dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 10360b57cec5SDimitry Andric PdbSymUid uid(comp_unit.GetID()); 10370b57cec5SDimitry Andric lldbassert(uid.kind() == PdbSymUidKind::Compiland); 10380b57cec5SDimitry Andric 10390b57cec5SDimitry Andric CompilandIndexItem *item = 10400b57cec5SDimitry Andric m_index->compilands().GetCompiland(uid.asCompiland().modi); 10410b57cec5SDimitry Andric lldbassert(item); 10420b57cec5SDimitry Andric if (!item->m_compile_opts) 10430b57cec5SDimitry Andric return lldb::eLanguageTypeUnknown; 10440b57cec5SDimitry Andric 10450b57cec5SDimitry Andric return TranslateLanguage(item->m_compile_opts->getLanguage()); 10460b57cec5SDimitry Andric } 10470b57cec5SDimitry Andric 10480eae32dcSDimitry Andric void SymbolFileNativePDB::AddSymbols(Symtab &symtab) {} 10490b57cec5SDimitry Andric 10500b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) { 10519dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 10520b57cec5SDimitry Andric PdbSymUid uid{comp_unit.GetID()}; 10530b57cec5SDimitry Andric lldbassert(uid.kind() == PdbSymUidKind::Compiland); 10540b57cec5SDimitry Andric uint16_t modi = uid.asCompiland().modi; 10550b57cec5SDimitry Andric CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi); 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric size_t count = comp_unit.GetNumFunctions(); 10580b57cec5SDimitry Andric const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray(); 10590b57cec5SDimitry Andric for (auto iter = syms.begin(); iter != syms.end(); ++iter) { 10600b57cec5SDimitry Andric if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) 10610b57cec5SDimitry Andric continue; 10620b57cec5SDimitry Andric 10630b57cec5SDimitry Andric PdbCompilandSymId sym_id{modi, iter.offset()}; 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric FunctionSP func = GetOrCreateFunction(sym_id, comp_unit); 10660b57cec5SDimitry Andric } 10670b57cec5SDimitry Andric 10680b57cec5SDimitry Andric size_t new_count = comp_unit.GetNumFunctions(); 10690b57cec5SDimitry Andric lldbassert(new_count >= count); 10700b57cec5SDimitry Andric return new_count - count; 10710b57cec5SDimitry Andric } 10720b57cec5SDimitry Andric 10730b57cec5SDimitry Andric static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) { 10740b57cec5SDimitry Andric // If any of these flags are set, we need to resolve the compile unit. 10750b57cec5SDimitry Andric uint32_t flags = eSymbolContextCompUnit; 10760b57cec5SDimitry Andric flags |= eSymbolContextVariable; 10770b57cec5SDimitry Andric flags |= eSymbolContextFunction; 10780b57cec5SDimitry Andric flags |= eSymbolContextBlock; 10790b57cec5SDimitry Andric flags |= eSymbolContextLineEntry; 10800b57cec5SDimitry Andric return (resolve_scope & flags) != 0; 10810b57cec5SDimitry Andric } 10820b57cec5SDimitry Andric 10830b57cec5SDimitry Andric uint32_t SymbolFileNativePDB::ResolveSymbolContext( 10840b57cec5SDimitry Andric const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) { 10859dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 10860b57cec5SDimitry Andric uint32_t resolved_flags = 0; 10870b57cec5SDimitry Andric lldb::addr_t file_addr = addr.GetFileAddress(); 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric if (NeedsResolvedCompileUnit(resolve_scope)) { 1090bdd1243dSDimitry Andric std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr); 10910b57cec5SDimitry Andric if (!modi) 10920b57cec5SDimitry Andric return 0; 109381ad6265SDimitry Andric CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi); 1094349cc55cSDimitry Andric if (!cu_sp) 10950b57cec5SDimitry Andric return 0; 10960b57cec5SDimitry Andric 1097349cc55cSDimitry Andric sc.comp_unit = cu_sp.get(); 10980b57cec5SDimitry Andric resolved_flags |= eSymbolContextCompUnit; 10990b57cec5SDimitry Andric } 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric if (resolve_scope & eSymbolContextFunction || 11020b57cec5SDimitry Andric resolve_scope & eSymbolContextBlock) { 11030b57cec5SDimitry Andric lldbassert(sc.comp_unit); 11040b57cec5SDimitry Andric std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr); 11050b57cec5SDimitry Andric // Search the matches in reverse. This way if there are multiple matches 11060b57cec5SDimitry Andric // (for example we are 3 levels deep in a nested scope) it will find the 11070b57cec5SDimitry Andric // innermost one first. 11080b57cec5SDimitry Andric for (const auto &match : llvm::reverse(matches)) { 11090b57cec5SDimitry Andric if (match.uid.kind() != PdbSymUidKind::CompilandSym) 11100b57cec5SDimitry Andric continue; 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric PdbCompilandSymId csid = match.uid.asCompilandSym(); 11130b57cec5SDimitry Andric CVSymbol cvs = m_index->ReadSymbolRecord(csid); 11140b57cec5SDimitry Andric PDB_SymType type = CVSymToPDBSym(cvs.kind()); 11150b57cec5SDimitry Andric if (type != PDB_SymType::Function && type != PDB_SymType::Block) 11160b57cec5SDimitry Andric continue; 11170b57cec5SDimitry Andric if (type == PDB_SymType::Function) { 11180b57cec5SDimitry Andric sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get(); 1119bdd1243dSDimitry Andric if (sc.function) { 112004eeddc0SDimitry Andric Block &block = sc.function->GetBlock(true); 112104eeddc0SDimitry Andric addr_t func_base = 112204eeddc0SDimitry Andric sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 112304eeddc0SDimitry Andric addr_t offset = file_addr - func_base; 112404eeddc0SDimitry Andric sc.block = block.FindInnermostBlockByOffset(offset); 11250b57cec5SDimitry Andric } 1126bdd1243dSDimitry Andric } 11270b57cec5SDimitry Andric 11280b57cec5SDimitry Andric if (type == PDB_SymType::Block) { 1129bdd1243dSDimitry Andric Block &block = GetOrCreateBlock(csid); 1130bdd1243dSDimitry Andric sc.function = block.CalculateSymbolContextFunction(); 1131bdd1243dSDimitry Andric if (sc.function) { 1132bdd1243dSDimitry Andric sc.function->GetBlock(true); 1133bdd1243dSDimitry Andric addr_t func_base = 1134bdd1243dSDimitry Andric sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 1135bdd1243dSDimitry Andric addr_t offset = file_addr - func_base; 1136bdd1243dSDimitry Andric sc.block = block.FindInnermostBlockByOffset(offset); 1137bdd1243dSDimitry Andric } 11380b57cec5SDimitry Andric } 113904eeddc0SDimitry Andric if (sc.function) 11400b57cec5SDimitry Andric resolved_flags |= eSymbolContextFunction; 114104eeddc0SDimitry Andric if (sc.block) 11420b57cec5SDimitry Andric resolved_flags |= eSymbolContextBlock; 11430b57cec5SDimitry Andric break; 11440b57cec5SDimitry Andric } 11450b57cec5SDimitry Andric } 11460b57cec5SDimitry Andric 11470b57cec5SDimitry Andric if (resolve_scope & eSymbolContextLineEntry) { 11480b57cec5SDimitry Andric lldbassert(sc.comp_unit); 11490b57cec5SDimitry Andric if (auto *line_table = sc.comp_unit->GetLineTable()) { 11500b57cec5SDimitry Andric if (line_table->FindLineEntryByAddress(addr, sc.line_entry)) 11510b57cec5SDimitry Andric resolved_flags |= eSymbolContextLineEntry; 11520b57cec5SDimitry Andric } 11530b57cec5SDimitry Andric } 11540b57cec5SDimitry Andric 11550b57cec5SDimitry Andric return resolved_flags; 11560b57cec5SDimitry Andric } 11570b57cec5SDimitry Andric 11580b57cec5SDimitry Andric uint32_t SymbolFileNativePDB::ResolveSymbolContext( 1159fe6060f1SDimitry Andric const SourceLocationSpec &src_location_spec, 11600b57cec5SDimitry Andric lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { 116104eeddc0SDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 116204eeddc0SDimitry Andric const uint32_t prev_size = sc_list.GetSize(); 116304eeddc0SDimitry Andric if (resolve_scope & eSymbolContextCompUnit) { 116404eeddc0SDimitry Andric for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus; 116504eeddc0SDimitry Andric ++cu_idx) { 116604eeddc0SDimitry Andric CompileUnit *cu = ParseCompileUnitAtIndex(cu_idx).get(); 116704eeddc0SDimitry Andric if (!cu) 116804eeddc0SDimitry Andric continue; 116904eeddc0SDimitry Andric 117004eeddc0SDimitry Andric bool file_spec_matches_cu_file_spec = FileSpec::Match( 117104eeddc0SDimitry Andric src_location_spec.GetFileSpec(), cu->GetPrimaryFile()); 117204eeddc0SDimitry Andric if (file_spec_matches_cu_file_spec) { 117304eeddc0SDimitry Andric cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list); 117404eeddc0SDimitry Andric break; 11750b57cec5SDimitry Andric } 11760b57cec5SDimitry Andric } 117704eeddc0SDimitry Andric } 117804eeddc0SDimitry Andric return sc_list.GetSize() - prev_size; 11790b57cec5SDimitry Andric } 11800b57cec5SDimitry Andric 11810b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) { 11820b57cec5SDimitry Andric // Unfortunately LLDB is set up to parse the entire compile unit line table 11830b57cec5SDimitry Andric // all at once, even if all it really needs is line info for a specific 11840b57cec5SDimitry Andric // function. In the future it would be nice if it could set the sc.m_function 11850b57cec5SDimitry Andric // member, and we could only get the line info for the function in question. 11869dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 11870b57cec5SDimitry Andric PdbSymUid cu_id(comp_unit.GetID()); 11880b57cec5SDimitry Andric lldbassert(cu_id.kind() == PdbSymUidKind::Compiland); 118904eeddc0SDimitry Andric uint16_t modi = cu_id.asCompiland().modi; 119004eeddc0SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi); 119104eeddc0SDimitry Andric lldbassert(cii); 119204eeddc0SDimitry Andric 119304eeddc0SDimitry Andric // Parse DEBUG_S_LINES subsections first, then parse all S_INLINESITE records 119404eeddc0SDimitry Andric // in this CU. Add line entries into the set first so that if there are line 119504eeddc0SDimitry Andric // entries with same addres, the later is always more accurate than the 119604eeddc0SDimitry Andric // former. 119704eeddc0SDimitry Andric std::set<LineTable::Entry, LineTableEntryComparator> line_set; 11980b57cec5SDimitry Andric 11990b57cec5SDimitry Andric // This is basically a copy of the .debug$S subsections from all original COFF 12000b57cec5SDimitry Andric // object files merged together with address relocations applied. We are 12010b57cec5SDimitry Andric // looking for all DEBUG_S_LINES subsections. 12020b57cec5SDimitry Andric for (const DebugSubsectionRecord &dssr : 120304eeddc0SDimitry Andric cii->m_debug_stream.getSubsectionsArray()) { 12040b57cec5SDimitry Andric if (dssr.kind() != DebugSubsectionKind::Lines) 12050b57cec5SDimitry Andric continue; 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric DebugLinesSubsectionRef lines; 12080b57cec5SDimitry Andric llvm::BinaryStreamReader reader(dssr.getRecordData()); 12090b57cec5SDimitry Andric if (auto EC = lines.initialize(reader)) { 12100b57cec5SDimitry Andric llvm::consumeError(std::move(EC)); 12110b57cec5SDimitry Andric return false; 12120b57cec5SDimitry Andric } 12130b57cec5SDimitry Andric 12140b57cec5SDimitry Andric const LineFragmentHeader *lfh = lines.header(); 12150b57cec5SDimitry Andric uint64_t virtual_addr = 12160b57cec5SDimitry Andric m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset); 121781ad6265SDimitry Andric if (virtual_addr == LLDB_INVALID_ADDRESS) 121881ad6265SDimitry Andric continue; 12190b57cec5SDimitry Andric 12200b57cec5SDimitry Andric for (const LineColumnEntry &group : lines) { 122104eeddc0SDimitry Andric llvm::Expected<uint32_t> file_index_or_err = 122204eeddc0SDimitry Andric GetFileIndex(*cii, group.NameIndex); 122304eeddc0SDimitry Andric if (!file_index_or_err) 12240b57cec5SDimitry Andric continue; 122504eeddc0SDimitry Andric uint32_t file_index = file_index_or_err.get(); 12260b57cec5SDimitry Andric lldbassert(!group.LineNumbers.empty()); 122704eeddc0SDimitry Andric CompilandIndexItem::GlobalLineTable::Entry line_entry( 122804eeddc0SDimitry Andric LLDB_INVALID_ADDRESS, 0); 12290b57cec5SDimitry Andric for (const LineNumberEntry &entry : group.LineNumbers) { 123004eeddc0SDimitry Andric LineInfo cur_info(entry.Flags); 123104eeddc0SDimitry Andric 123204eeddc0SDimitry Andric if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto()) 123304eeddc0SDimitry Andric continue; 123404eeddc0SDimitry Andric 123504eeddc0SDimitry Andric uint64_t addr = virtual_addr + entry.Offset; 123604eeddc0SDimitry Andric 123704eeddc0SDimitry Andric bool is_statement = cur_info.isStatement(); 123804eeddc0SDimitry Andric bool is_prologue = IsFunctionPrologue(*cii, addr); 123904eeddc0SDimitry Andric bool is_epilogue = IsFunctionEpilogue(*cii, addr); 124004eeddc0SDimitry Andric 124104eeddc0SDimitry Andric uint32_t lno = cur_info.getStartLine(); 124204eeddc0SDimitry Andric 124381ad6265SDimitry Andric LineTable::Entry new_entry(addr, lno, 0, file_index, is_statement, false, 124404eeddc0SDimitry Andric is_prologue, is_epilogue, false); 124581ad6265SDimitry Andric // Terminal entry has lower precedence than new entry. 124681ad6265SDimitry Andric auto iter = line_set.find(new_entry); 124781ad6265SDimitry Andric if (iter != line_set.end() && iter->is_terminal_entry) 124881ad6265SDimitry Andric line_set.erase(iter); 124981ad6265SDimitry Andric line_set.insert(new_entry); 125004eeddc0SDimitry Andric 125104eeddc0SDimitry Andric if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) { 125204eeddc0SDimitry Andric line_entry.SetRangeEnd(addr); 125304eeddc0SDimitry Andric cii->m_global_line_table.Append(line_entry); 125404eeddc0SDimitry Andric } 125504eeddc0SDimitry Andric line_entry.SetRangeBase(addr); 125604eeddc0SDimitry Andric line_entry.data = {file_index, lno}; 12570b57cec5SDimitry Andric } 12580b57cec5SDimitry Andric LineInfo last_line(group.LineNumbers.back().Flags); 125904eeddc0SDimitry Andric line_set.emplace(virtual_addr + lfh->CodeSize, last_line.getEndLine(), 0, 126004eeddc0SDimitry Andric file_index, false, false, false, false, true); 126104eeddc0SDimitry Andric 126204eeddc0SDimitry Andric if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) { 126304eeddc0SDimitry Andric line_entry.SetRangeEnd(virtual_addr + lfh->CodeSize); 126404eeddc0SDimitry Andric cii->m_global_line_table.Append(line_entry); 12650b57cec5SDimitry Andric } 12660b57cec5SDimitry Andric } 126704eeddc0SDimitry Andric } 126804eeddc0SDimitry Andric 126904eeddc0SDimitry Andric cii->m_global_line_table.Sort(); 127004eeddc0SDimitry Andric 127104eeddc0SDimitry Andric // Parse all S_INLINESITE in this CU. 127204eeddc0SDimitry Andric const CVSymbolArray &syms = cii->m_debug_stream.getSymbolArray(); 127304eeddc0SDimitry Andric for (auto iter = syms.begin(); iter != syms.end();) { 127404eeddc0SDimitry Andric if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) { 127504eeddc0SDimitry Andric ++iter; 127604eeddc0SDimitry Andric continue; 127704eeddc0SDimitry Andric } 127804eeddc0SDimitry Andric 127904eeddc0SDimitry Andric uint32_t record_offset = iter.offset(); 128004eeddc0SDimitry Andric CVSymbol func_record = 128104eeddc0SDimitry Andric cii->m_debug_stream.readSymbolAtOffset(record_offset); 128204eeddc0SDimitry Andric SegmentOffsetLength sol = GetSegmentOffsetAndLength(func_record); 128381ad6265SDimitry Andric addr_t file_vm_addr = 128481ad6265SDimitry Andric m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset); 128581ad6265SDimitry Andric if (file_vm_addr == LLDB_INVALID_ADDRESS) 128681ad6265SDimitry Andric continue; 128781ad6265SDimitry Andric 128804eeddc0SDimitry Andric AddressRange func_range(file_vm_addr, sol.length, 128904eeddc0SDimitry Andric comp_unit.GetModule()->GetSectionList()); 129004eeddc0SDimitry Andric Address func_base = func_range.GetBaseAddress(); 129104eeddc0SDimitry Andric PdbCompilandSymId func_id{modi, record_offset}; 129204eeddc0SDimitry Andric 129304eeddc0SDimitry Andric // Iterate all S_INLINESITEs in the function. 129404eeddc0SDimitry Andric auto parse_inline_sites = [&](SymbolKind kind, PdbCompilandSymId id) { 129504eeddc0SDimitry Andric if (kind != S_INLINESITE) 129604eeddc0SDimitry Andric return false; 129704eeddc0SDimitry Andric 129804eeddc0SDimitry Andric ParseInlineSite(id, func_base); 129904eeddc0SDimitry Andric 130004eeddc0SDimitry Andric for (const auto &line_entry : 130104eeddc0SDimitry Andric m_inline_sites[toOpaqueUid(id)]->line_entries) { 130204eeddc0SDimitry Andric // If line_entry is not terminal entry, remove previous line entry at 130304eeddc0SDimitry Andric // the same address and insert new one. Terminal entry inside an inline 130404eeddc0SDimitry Andric // site might not be terminal entry for its parent. 130504eeddc0SDimitry Andric if (!line_entry.is_terminal_entry) 130604eeddc0SDimitry Andric line_set.erase(line_entry); 130704eeddc0SDimitry Andric line_set.insert(line_entry); 130804eeddc0SDimitry Andric } 130904eeddc0SDimitry Andric // No longer useful after adding to line_set. 131004eeddc0SDimitry Andric m_inline_sites[toOpaqueUid(id)]->line_entries.clear(); 131104eeddc0SDimitry Andric return true; 131204eeddc0SDimitry Andric }; 131304eeddc0SDimitry Andric ParseSymbolArrayInScope(func_id, parse_inline_sites); 131404eeddc0SDimitry Andric // Jump to the end of the function record. 131504eeddc0SDimitry Andric iter = syms.at(getScopeEndOffset(func_record)); 131604eeddc0SDimitry Andric } 131704eeddc0SDimitry Andric 131804eeddc0SDimitry Andric cii->m_global_line_table.Clear(); 131904eeddc0SDimitry Andric 132004eeddc0SDimitry Andric // Add line entries in line_set to line_table. 132104eeddc0SDimitry Andric auto line_table = std::make_unique<LineTable>(&comp_unit); 132204eeddc0SDimitry Andric std::unique_ptr<LineSequence> sequence( 132304eeddc0SDimitry Andric line_table->CreateLineSequenceContainer()); 132404eeddc0SDimitry Andric for (const auto &line_entry : line_set) { 132504eeddc0SDimitry Andric line_table->AppendLineEntryToSequence( 132604eeddc0SDimitry Andric sequence.get(), line_entry.file_addr, line_entry.line, 132704eeddc0SDimitry Andric line_entry.column, line_entry.file_idx, 132804eeddc0SDimitry Andric line_entry.is_start_of_statement, line_entry.is_start_of_basic_block, 132904eeddc0SDimitry Andric line_entry.is_prologue_end, line_entry.is_epilogue_begin, 133004eeddc0SDimitry Andric line_entry.is_terminal_entry); 133104eeddc0SDimitry Andric } 133204eeddc0SDimitry Andric line_table->InsertSequence(sequence.get()); 13330b57cec5SDimitry Andric 13340b57cec5SDimitry Andric if (line_table->GetSize() == 0) 13350b57cec5SDimitry Andric return false; 13360b57cec5SDimitry Andric 13370b57cec5SDimitry Andric comp_unit.SetLineTable(line_table.release()); 13380b57cec5SDimitry Andric return true; 13390b57cec5SDimitry Andric } 13400b57cec5SDimitry Andric 13410b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) { 13420b57cec5SDimitry Andric // PDB doesn't contain information about macros 13430b57cec5SDimitry Andric return false; 13440b57cec5SDimitry Andric } 13450b57cec5SDimitry Andric 134604eeddc0SDimitry Andric llvm::Expected<uint32_t> 134704eeddc0SDimitry Andric SymbolFileNativePDB::GetFileIndex(const CompilandIndexItem &cii, 134804eeddc0SDimitry Andric uint32_t file_id) { 134906c3fb27SDimitry Andric if (!cii.m_strings.hasChecksums() || !cii.m_strings.hasStrings()) 135006c3fb27SDimitry Andric return llvm::make_error<RawError>(raw_error_code::no_entry); 135106c3fb27SDimitry Andric 135204eeddc0SDimitry Andric const auto &checksums = cii.m_strings.checksums().getArray(); 135304eeddc0SDimitry Andric const auto &strings = cii.m_strings.strings(); 135404eeddc0SDimitry Andric // Indices in this structure are actually offsets of records in the 135504eeddc0SDimitry Andric // DEBUG_S_FILECHECKSUMS subsection. Those entries then have an index 135604eeddc0SDimitry Andric // into the global PDB string table. 135704eeddc0SDimitry Andric auto iter = checksums.at(file_id); 135804eeddc0SDimitry Andric if (iter == checksums.end()) 135904eeddc0SDimitry Andric return llvm::make_error<RawError>(raw_error_code::no_entry); 136004eeddc0SDimitry Andric 136104eeddc0SDimitry Andric llvm::Expected<llvm::StringRef> efn = strings.getString(iter->FileNameOffset); 136204eeddc0SDimitry Andric if (!efn) { 136304eeddc0SDimitry Andric return efn.takeError(); 136404eeddc0SDimitry Andric } 136504eeddc0SDimitry Andric 136604eeddc0SDimitry Andric // LLDB wants the index of the file in the list of support files. 136704eeddc0SDimitry Andric auto fn_iter = llvm::find(cii.m_file_list, *efn); 136881ad6265SDimitry Andric if (fn_iter != cii.m_file_list.end()) 136981ad6265SDimitry Andric return std::distance(cii.m_file_list.begin(), fn_iter); 137081ad6265SDimitry Andric return llvm::make_error<RawError>(raw_error_code::no_entry); 137104eeddc0SDimitry Andric } 137204eeddc0SDimitry Andric 13730b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit, 13740b57cec5SDimitry Andric FileSpecList &support_files) { 13759dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 13760b57cec5SDimitry Andric PdbSymUid cu_id(comp_unit.GetID()); 13770b57cec5SDimitry Andric lldbassert(cu_id.kind() == PdbSymUidKind::Compiland); 13780b57cec5SDimitry Andric CompilandIndexItem *cci = 13790b57cec5SDimitry Andric m_index->compilands().GetCompiland(cu_id.asCompiland().modi); 13800b57cec5SDimitry Andric lldbassert(cci); 13810b57cec5SDimitry Andric 13820b57cec5SDimitry Andric for (llvm::StringRef f : cci->m_file_list) { 13830b57cec5SDimitry Andric FileSpec::Style style = 13840b57cec5SDimitry Andric f.startswith("/") ? FileSpec::Style::posix : FileSpec::Style::windows; 13850b57cec5SDimitry Andric FileSpec spec(f, style); 13860b57cec5SDimitry Andric support_files.Append(spec); 13870b57cec5SDimitry Andric } 13880b57cec5SDimitry Andric return true; 13890b57cec5SDimitry Andric } 13900b57cec5SDimitry Andric 13910b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseImportedModules( 13920b57cec5SDimitry Andric const SymbolContext &sc, std::vector<SourceModule> &imported_modules) { 13930b57cec5SDimitry Andric // PDB does not yet support module debug info 13940b57cec5SDimitry Andric return false; 13950b57cec5SDimitry Andric } 13960b57cec5SDimitry Andric 139704eeddc0SDimitry Andric void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id, 139804eeddc0SDimitry Andric Address func_addr) { 139904eeddc0SDimitry Andric lldb::user_id_t opaque_uid = toOpaqueUid(id); 140006c3fb27SDimitry Andric if (m_inline_sites.contains(opaque_uid)) 140104eeddc0SDimitry Andric return; 140204eeddc0SDimitry Andric 140304eeddc0SDimitry Andric addr_t func_base = func_addr.GetFileAddress(); 140404eeddc0SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi); 140504eeddc0SDimitry Andric CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset); 140604eeddc0SDimitry Andric CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); 140704eeddc0SDimitry Andric 140804eeddc0SDimitry Andric InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind())); 140904eeddc0SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site)); 141004eeddc0SDimitry Andric PdbCompilandSymId parent_id(id.modi, inline_site.Parent); 141104eeddc0SDimitry Andric 141204eeddc0SDimitry Andric std::shared_ptr<InlineSite> inline_site_sp = 141304eeddc0SDimitry Andric std::make_shared<InlineSite>(parent_id); 141404eeddc0SDimitry Andric 141504eeddc0SDimitry Andric // Get the inlined function declaration info. 141604eeddc0SDimitry Andric auto iter = cii->m_inline_map.find(inline_site.Inlinee); 141704eeddc0SDimitry Andric if (iter == cii->m_inline_map.end()) 141804eeddc0SDimitry Andric return; 141904eeddc0SDimitry Andric InlineeSourceLine inlinee_line = iter->second; 142004eeddc0SDimitry Andric 142104eeddc0SDimitry Andric const FileSpecList &files = comp_unit->GetSupportFiles(); 142204eeddc0SDimitry Andric FileSpec decl_file; 142304eeddc0SDimitry Andric llvm::Expected<uint32_t> file_index_or_err = 142404eeddc0SDimitry Andric GetFileIndex(*cii, inlinee_line.Header->FileID); 142504eeddc0SDimitry Andric if (!file_index_or_err) 142604eeddc0SDimitry Andric return; 142781ad6265SDimitry Andric uint32_t file_offset = file_index_or_err.get(); 142881ad6265SDimitry Andric decl_file = files.GetFileSpecAtIndex(file_offset); 142904eeddc0SDimitry Andric uint32_t decl_line = inlinee_line.Header->SourceLineNum; 143004eeddc0SDimitry Andric std::unique_ptr<Declaration> decl_up = 143104eeddc0SDimitry Andric std::make_unique<Declaration>(decl_file, decl_line); 143204eeddc0SDimitry Andric 143304eeddc0SDimitry Andric // Parse range and line info. 143404eeddc0SDimitry Andric uint32_t code_offset = 0; 143504eeddc0SDimitry Andric int32_t line_offset = 0; 1436bdd1243dSDimitry Andric std::optional<uint32_t> code_offset_base; 1437bdd1243dSDimitry Andric std::optional<uint32_t> code_offset_end; 1438bdd1243dSDimitry Andric std::optional<int32_t> cur_line_offset; 1439bdd1243dSDimitry Andric std::optional<int32_t> next_line_offset; 1440bdd1243dSDimitry Andric std::optional<uint32_t> next_file_offset; 144104eeddc0SDimitry Andric 144281ad6265SDimitry Andric bool is_terminal_entry = false; 144381ad6265SDimitry Andric bool is_start_of_statement = true; 144404eeddc0SDimitry Andric // The first instruction is the prologue end. 144504eeddc0SDimitry Andric bool is_prologue_end = true; 144604eeddc0SDimitry Andric 144781ad6265SDimitry Andric auto update_code_offset = [&](uint32_t code_delta) { 144881ad6265SDimitry Andric if (!code_offset_base) 144981ad6265SDimitry Andric code_offset_base = code_offset; 145081ad6265SDimitry Andric else if (!code_offset_end) 145181ad6265SDimitry Andric code_offset_end = *code_offset_base + code_delta; 145204eeddc0SDimitry Andric }; 145381ad6265SDimitry Andric auto update_line_offset = [&](int32_t line_delta) { 145404eeddc0SDimitry Andric line_offset += line_delta; 145581ad6265SDimitry Andric if (!code_offset_base || !cur_line_offset) 145681ad6265SDimitry Andric cur_line_offset = line_offset; 145781ad6265SDimitry Andric else 145881ad6265SDimitry Andric next_line_offset = line_offset; 145981ad6265SDimitry Andric ; 146081ad6265SDimitry Andric }; 146181ad6265SDimitry Andric auto update_file_offset = [&](uint32_t offset) { 146281ad6265SDimitry Andric if (!code_offset_base) 146381ad6265SDimitry Andric file_offset = offset; 146481ad6265SDimitry Andric else 146581ad6265SDimitry Andric next_file_offset = offset; 146604eeddc0SDimitry Andric }; 146704eeddc0SDimitry Andric 146804eeddc0SDimitry Andric for (auto &annot : inline_site.annotations()) { 146904eeddc0SDimitry Andric switch (annot.OpCode) { 147004eeddc0SDimitry Andric case BinaryAnnotationsOpCode::CodeOffset: 147104eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeOffset: 147204eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: 147381ad6265SDimitry Andric code_offset += annot.U1; 147481ad6265SDimitry Andric update_code_offset(annot.U1); 147504eeddc0SDimitry Andric break; 147604eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeLineOffset: 147781ad6265SDimitry Andric update_line_offset(annot.S1); 147804eeddc0SDimitry Andric break; 147904eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeLength: 148081ad6265SDimitry Andric update_code_offset(annot.U1); 148104eeddc0SDimitry Andric code_offset += annot.U1; 148281ad6265SDimitry Andric is_terminal_entry = true; 148304eeddc0SDimitry Andric break; 148404eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: 148581ad6265SDimitry Andric code_offset += annot.U1; 148681ad6265SDimitry Andric update_code_offset(annot.U1); 148781ad6265SDimitry Andric update_line_offset(annot.S1); 148804eeddc0SDimitry Andric break; 148904eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: 149081ad6265SDimitry Andric code_offset += annot.U2; 149181ad6265SDimitry Andric update_code_offset(annot.U2); 149281ad6265SDimitry Andric update_code_offset(annot.U1); 149381ad6265SDimitry Andric code_offset += annot.U1; 149481ad6265SDimitry Andric is_terminal_entry = true; 149581ad6265SDimitry Andric break; 149681ad6265SDimitry Andric case BinaryAnnotationsOpCode::ChangeFile: 149781ad6265SDimitry Andric update_file_offset(annot.U1); 149804eeddc0SDimitry Andric break; 149904eeddc0SDimitry Andric default: 150004eeddc0SDimitry Andric break; 150104eeddc0SDimitry Andric } 150281ad6265SDimitry Andric 150381ad6265SDimitry Andric // Add range if current range is finished. 150481ad6265SDimitry Andric if (code_offset_base && code_offset_end && cur_line_offset) { 150581ad6265SDimitry Andric inline_site_sp->ranges.Append(RangeSourceLineVector::Entry( 150681ad6265SDimitry Andric *code_offset_base, *code_offset_end - *code_offset_base, 150781ad6265SDimitry Andric decl_line + *cur_line_offset)); 150881ad6265SDimitry Andric // Set base, end, file offset and line offset for next range. 150981ad6265SDimitry Andric if (next_file_offset) 151081ad6265SDimitry Andric file_offset = *next_file_offset; 151181ad6265SDimitry Andric if (next_line_offset) { 151281ad6265SDimitry Andric cur_line_offset = next_line_offset; 1513bdd1243dSDimitry Andric next_line_offset = std::nullopt; 151481ad6265SDimitry Andric } 1515bdd1243dSDimitry Andric code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end; 1516bdd1243dSDimitry Andric code_offset_end = next_file_offset = std::nullopt; 151781ad6265SDimitry Andric } 151881ad6265SDimitry Andric if (code_offset_base && cur_line_offset) { 151981ad6265SDimitry Andric if (is_terminal_entry) { 152081ad6265SDimitry Andric LineTable::Entry line_entry( 152181ad6265SDimitry Andric func_base + *code_offset_base, decl_line + *cur_line_offset, 0, 152281ad6265SDimitry Andric file_offset, false, false, false, false, true); 152381ad6265SDimitry Andric inline_site_sp->line_entries.push_back(line_entry); 152481ad6265SDimitry Andric } else { 152581ad6265SDimitry Andric LineTable::Entry line_entry(func_base + *code_offset_base, 152681ad6265SDimitry Andric decl_line + *cur_line_offset, 0, 152781ad6265SDimitry Andric file_offset, is_start_of_statement, false, 152881ad6265SDimitry Andric is_prologue_end, false, false); 152981ad6265SDimitry Andric inline_site_sp->line_entries.push_back(line_entry); 153081ad6265SDimitry Andric is_prologue_end = false; 153181ad6265SDimitry Andric is_start_of_statement = false; 153281ad6265SDimitry Andric } 153381ad6265SDimitry Andric } 153481ad6265SDimitry Andric if (is_terminal_entry) 153581ad6265SDimitry Andric is_start_of_statement = true; 153681ad6265SDimitry Andric is_terminal_entry = false; 153704eeddc0SDimitry Andric } 153804eeddc0SDimitry Andric 153904eeddc0SDimitry Andric inline_site_sp->ranges.Sort(); 154004eeddc0SDimitry Andric 154104eeddc0SDimitry Andric // Get the inlined function callsite info. 154204eeddc0SDimitry Andric std::unique_ptr<Declaration> callsite_up; 154304eeddc0SDimitry Andric if (!inline_site_sp->ranges.IsEmpty()) { 154404eeddc0SDimitry Andric auto *entry = inline_site_sp->ranges.GetEntryAtIndex(0); 154504eeddc0SDimitry Andric addr_t base_offset = entry->GetRangeBase(); 154604eeddc0SDimitry Andric if (cii->m_debug_stream.readSymbolAtOffset(parent_id.offset).kind() == 154704eeddc0SDimitry Andric S_INLINESITE) { 154804eeddc0SDimitry Andric // Its parent is another inline site, lookup parent site's range vector 154904eeddc0SDimitry Andric // for callsite line. 155004eeddc0SDimitry Andric ParseInlineSite(parent_id, func_base); 155104eeddc0SDimitry Andric std::shared_ptr<InlineSite> parent_site = 155204eeddc0SDimitry Andric m_inline_sites[toOpaqueUid(parent_id)]; 155304eeddc0SDimitry Andric FileSpec &parent_decl_file = 155404eeddc0SDimitry Andric parent_site->inline_function_info->GetDeclaration().GetFile(); 155504eeddc0SDimitry Andric if (auto *parent_entry = 155604eeddc0SDimitry Andric parent_site->ranges.FindEntryThatContains(base_offset)) { 155704eeddc0SDimitry Andric callsite_up = 155804eeddc0SDimitry Andric std::make_unique<Declaration>(parent_decl_file, parent_entry->data); 155904eeddc0SDimitry Andric } 156004eeddc0SDimitry Andric } else { 156104eeddc0SDimitry Andric // Its parent is a function, lookup global line table for callsite. 156204eeddc0SDimitry Andric if (auto *entry = cii->m_global_line_table.FindEntryThatContains( 156304eeddc0SDimitry Andric func_base + base_offset)) { 156404eeddc0SDimitry Andric const FileSpec &callsite_file = 156504eeddc0SDimitry Andric files.GetFileSpecAtIndex(entry->data.first); 156604eeddc0SDimitry Andric callsite_up = 156704eeddc0SDimitry Andric std::make_unique<Declaration>(callsite_file, entry->data.second); 156804eeddc0SDimitry Andric } 156904eeddc0SDimitry Andric } 157004eeddc0SDimitry Andric } 157104eeddc0SDimitry Andric 157204eeddc0SDimitry Andric // Get the inlined function name. 157304eeddc0SDimitry Andric CVType inlinee_cvt = m_index->ipi().getType(inline_site.Inlinee); 157404eeddc0SDimitry Andric std::string inlinee_name; 157504eeddc0SDimitry Andric if (inlinee_cvt.kind() == LF_MFUNC_ID) { 157604eeddc0SDimitry Andric MemberFuncIdRecord mfr; 157704eeddc0SDimitry Andric cantFail( 157804eeddc0SDimitry Andric TypeDeserializer::deserializeAs<MemberFuncIdRecord>(inlinee_cvt, mfr)); 157904eeddc0SDimitry Andric LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); 158004eeddc0SDimitry Andric inlinee_name.append(std::string(types.getTypeName(mfr.ClassType))); 158104eeddc0SDimitry Andric inlinee_name.append("::"); 158204eeddc0SDimitry Andric inlinee_name.append(mfr.getName().str()); 158304eeddc0SDimitry Andric } else if (inlinee_cvt.kind() == LF_FUNC_ID) { 158404eeddc0SDimitry Andric FuncIdRecord fir; 158504eeddc0SDimitry Andric cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(inlinee_cvt, fir)); 158604eeddc0SDimitry Andric TypeIndex parent_idx = fir.getParentScope(); 158704eeddc0SDimitry Andric if (!parent_idx.isNoneType()) { 158804eeddc0SDimitry Andric LazyRandomTypeCollection &ids = m_index->ipi().typeCollection(); 158904eeddc0SDimitry Andric inlinee_name.append(std::string(ids.getTypeName(parent_idx))); 159004eeddc0SDimitry Andric inlinee_name.append("::"); 159104eeddc0SDimitry Andric } 159204eeddc0SDimitry Andric inlinee_name.append(fir.getName().str()); 159304eeddc0SDimitry Andric } 159404eeddc0SDimitry Andric inline_site_sp->inline_function_info = std::make_shared<InlineFunctionInfo>( 159504eeddc0SDimitry Andric inlinee_name.c_str(), llvm::StringRef(), decl_up.get(), 159604eeddc0SDimitry Andric callsite_up.get()); 159704eeddc0SDimitry Andric 159804eeddc0SDimitry Andric m_inline_sites[opaque_uid] = inline_site_sp; 159904eeddc0SDimitry Andric } 160004eeddc0SDimitry Andric 16010b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) { 16029dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 160304eeddc0SDimitry Andric PdbCompilandSymId func_id = PdbSymUid(func.GetID()).asCompilandSym(); 160404eeddc0SDimitry Andric // After we iterate through inline sites inside the function, we already get 160504eeddc0SDimitry Andric // all the info needed, removing from the map to save memory. 160604eeddc0SDimitry Andric std::set<uint64_t> remove_uids; 160704eeddc0SDimitry Andric auto parse_blocks = [&](SymbolKind kind, PdbCompilandSymId id) { 160804eeddc0SDimitry Andric if (kind == S_GPROC32 || kind == S_LPROC32 || kind == S_BLOCK32 || 160904eeddc0SDimitry Andric kind == S_INLINESITE) { 161004eeddc0SDimitry Andric GetOrCreateBlock(id); 161104eeddc0SDimitry Andric if (kind == S_INLINESITE) 161204eeddc0SDimitry Andric remove_uids.insert(toOpaqueUid(id)); 161304eeddc0SDimitry Andric return true; 161404eeddc0SDimitry Andric } 161504eeddc0SDimitry Andric return false; 161604eeddc0SDimitry Andric }; 161704eeddc0SDimitry Andric size_t count = ParseSymbolArrayInScope(func_id, parse_blocks); 161804eeddc0SDimitry Andric for (uint64_t uid : remove_uids) { 161904eeddc0SDimitry Andric m_inline_sites.erase(uid); 162004eeddc0SDimitry Andric } 162104eeddc0SDimitry Andric return count; 162204eeddc0SDimitry Andric } 162304eeddc0SDimitry Andric 162404eeddc0SDimitry Andric size_t SymbolFileNativePDB::ParseSymbolArrayInScope( 162504eeddc0SDimitry Andric PdbCompilandSymId parent_id, 162604eeddc0SDimitry Andric llvm::function_ref<bool(SymbolKind, PdbCompilandSymId)> fn) { 162704eeddc0SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(parent_id.modi); 162804eeddc0SDimitry Andric CVSymbolArray syms = 162904eeddc0SDimitry Andric cii->m_debug_stream.getSymbolArrayForScope(parent_id.offset); 163004eeddc0SDimitry Andric 163104eeddc0SDimitry Andric size_t count = 1; 163204eeddc0SDimitry Andric for (auto iter = syms.begin(); iter != syms.end(); ++iter) { 163304eeddc0SDimitry Andric PdbCompilandSymId child_id(parent_id.modi, iter.offset()); 163404eeddc0SDimitry Andric if (fn(iter->kind(), child_id)) 163504eeddc0SDimitry Andric ++count; 163604eeddc0SDimitry Andric } 163704eeddc0SDimitry Andric 163804eeddc0SDimitry Andric return count; 16390b57cec5SDimitry Andric } 16400b57cec5SDimitry Andric 1641bdd1243dSDimitry Andric void SymbolFileNativePDB::DumpClangAST(Stream &s) { 1642bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); 1643bdd1243dSDimitry Andric if (!ts_or_err) 1644bdd1243dSDimitry Andric return; 1645bdd1243dSDimitry Andric auto ts = *ts_or_err; 1646bdd1243dSDimitry Andric TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); 1647bdd1243dSDimitry Andric if (!clang) 1648bdd1243dSDimitry Andric return; 1649bdd1243dSDimitry Andric clang->GetNativePDBParser()->Dump(s); 1650bdd1243dSDimitry Andric } 16510b57cec5SDimitry Andric 16529dba64beSDimitry Andric void SymbolFileNativePDB::FindGlobalVariables( 16535ffd83dbSDimitry Andric ConstString name, const CompilerDeclContext &parent_decl_ctx, 16540b57cec5SDimitry Andric uint32_t max_matches, VariableList &variables) { 16559dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 16560b57cec5SDimitry Andric using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; 16570b57cec5SDimitry Andric 16580b57cec5SDimitry Andric std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName( 16590b57cec5SDimitry Andric name.GetStringRef(), m_index->symrecords()); 16600b57cec5SDimitry Andric for (const SymbolAndOffset &result : results) { 16610b57cec5SDimitry Andric switch (result.second.kind()) { 16620b57cec5SDimitry Andric case SymbolKind::S_GDATA32: 16630b57cec5SDimitry Andric case SymbolKind::S_LDATA32: 16640b57cec5SDimitry Andric case SymbolKind::S_GTHREAD32: 16650b57cec5SDimitry Andric case SymbolKind::S_LTHREAD32: 16660b57cec5SDimitry Andric case SymbolKind::S_CONSTANT: { 16670b57cec5SDimitry Andric PdbGlobalSymId global(result.first, false); 166881ad6265SDimitry Andric if (VariableSP var = GetOrCreateGlobalVariable(global)) 16690b57cec5SDimitry Andric variables.AddVariable(var); 16700b57cec5SDimitry Andric break; 16710b57cec5SDimitry Andric } 16720b57cec5SDimitry Andric default: 16730b57cec5SDimitry Andric continue; 16740b57cec5SDimitry Andric } 16750b57cec5SDimitry Andric } 16760b57cec5SDimitry Andric } 16770b57cec5SDimitry Andric 16789dba64beSDimitry Andric void SymbolFileNativePDB::FindFunctions( 1679bdd1243dSDimitry Andric const Module::LookupInfo &lookup_info, 1680bdd1243dSDimitry Andric const CompilerDeclContext &parent_decl_ctx, bool include_inlines, 16810b57cec5SDimitry Andric SymbolContextList &sc_list) { 16829dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 1683bdd1243dSDimitry Andric ConstString name = lookup_info.GetLookupName(); 1684bdd1243dSDimitry Andric FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); 1685bdd1243dSDimitry Andric if (name_type_mask & eFunctionNameTypeFull) 1686bdd1243dSDimitry Andric name = lookup_info.GetName(); 1687bdd1243dSDimitry Andric 16884824e7fdSDimitry Andric // For now we only support lookup by method name or full name. 16894824e7fdSDimitry Andric if (!(name_type_mask & eFunctionNameTypeFull || 16904824e7fdSDimitry Andric name_type_mask & eFunctionNameTypeMethod)) 16919dba64beSDimitry Andric return; 16920b57cec5SDimitry Andric 16930b57cec5SDimitry Andric using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; 16940b57cec5SDimitry Andric 16950b57cec5SDimitry Andric std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName( 16960b57cec5SDimitry Andric name.GetStringRef(), m_index->symrecords()); 16970b57cec5SDimitry Andric for (const SymbolAndOffset &match : matches) { 16980b57cec5SDimitry Andric if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF) 16990b57cec5SDimitry Andric continue; 17000b57cec5SDimitry Andric ProcRefSym proc(match.second.kind()); 17010b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc)); 17020b57cec5SDimitry Andric 17030b57cec5SDimitry Andric if (!IsValidRecord(proc)) 17040b57cec5SDimitry Andric continue; 17050b57cec5SDimitry Andric 17060b57cec5SDimitry Andric CompilandIndexItem &cci = 17070b57cec5SDimitry Andric m_index->compilands().GetOrCreateCompiland(proc.modi()); 17080b57cec5SDimitry Andric SymbolContext sc; 17090b57cec5SDimitry Andric 17100b57cec5SDimitry Andric sc.comp_unit = GetOrCreateCompileUnit(cci).get(); 17110b57cec5SDimitry Andric PdbCompilandSymId func_id(proc.modi(), proc.SymOffset); 17120b57cec5SDimitry Andric sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get(); 17130b57cec5SDimitry Andric 17140b57cec5SDimitry Andric sc_list.Append(sc); 17150b57cec5SDimitry Andric } 17160b57cec5SDimitry Andric } 17170b57cec5SDimitry Andric 17189dba64beSDimitry Andric void SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex, 17199dba64beSDimitry Andric bool include_inlines, 17209dba64beSDimitry Andric SymbolContextList &sc_list) {} 17210b57cec5SDimitry Andric 17229dba64beSDimitry Andric void SymbolFileNativePDB::FindTypes( 17235ffd83dbSDimitry Andric ConstString name, const CompilerDeclContext &parent_decl_ctx, 17249dba64beSDimitry Andric uint32_t max_matches, llvm::DenseSet<SymbolFile *> &searched_symbol_files, 17259dba64beSDimitry Andric TypeMap &types) { 17269dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 17270b57cec5SDimitry Andric if (!name) 17289dba64beSDimitry Andric return; 17290b57cec5SDimitry Andric 17300b57cec5SDimitry Andric searched_symbol_files.clear(); 17310b57cec5SDimitry Andric searched_symbol_files.insert(this); 17320b57cec5SDimitry Andric 17330b57cec5SDimitry Andric // There is an assumption 'name' is not a regex 17349dba64beSDimitry Andric FindTypesByName(name.GetStringRef(), max_matches, types); 17350b57cec5SDimitry Andric } 17360b57cec5SDimitry Andric 1737480093f4SDimitry Andric void SymbolFileNativePDB::FindTypes( 1738480093f4SDimitry Andric llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, 1739480093f4SDimitry Andric llvm::DenseSet<SymbolFile *> &searched_symbol_files, TypeMap &types) {} 17400b57cec5SDimitry Andric 17419dba64beSDimitry Andric void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name, 17420b57cec5SDimitry Andric uint32_t max_matches, 17430b57cec5SDimitry Andric TypeMap &types) { 17440b57cec5SDimitry Andric 17450b57cec5SDimitry Andric std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name); 17460b57cec5SDimitry Andric if (max_matches > 0 && max_matches < matches.size()) 17470b57cec5SDimitry Andric matches.resize(max_matches); 17480b57cec5SDimitry Andric 17490b57cec5SDimitry Andric for (TypeIndex ti : matches) { 17500b57cec5SDimitry Andric TypeSP type = GetOrCreateType(ti); 17510b57cec5SDimitry Andric if (!type) 17520b57cec5SDimitry Andric continue; 17530b57cec5SDimitry Andric 17540b57cec5SDimitry Andric types.Insert(type); 17550b57cec5SDimitry Andric } 17560b57cec5SDimitry Andric } 17570b57cec5SDimitry Andric 17580b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) { 17599dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 17600b57cec5SDimitry Andric // Only do the full type scan the first time. 17610b57cec5SDimitry Andric if (m_done_full_type_scan) 17620b57cec5SDimitry Andric return 0; 17630b57cec5SDimitry Andric 17649dba64beSDimitry Andric const size_t old_count = GetTypeList().GetSize(); 17650b57cec5SDimitry Andric LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); 17660b57cec5SDimitry Andric 17670b57cec5SDimitry Andric // First process the entire TPI stream. 17680b57cec5SDimitry Andric for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) { 17690b57cec5SDimitry Andric TypeSP type = GetOrCreateType(*ti); 17700b57cec5SDimitry Andric if (type) 17710b57cec5SDimitry Andric (void)type->GetFullCompilerType(); 17720b57cec5SDimitry Andric } 17730b57cec5SDimitry Andric 17740b57cec5SDimitry Andric // Next look for S_UDT records in the globals stream. 17750b57cec5SDimitry Andric for (const uint32_t gid : m_index->globals().getGlobalsTable()) { 17760b57cec5SDimitry Andric PdbGlobalSymId global{gid, false}; 17770b57cec5SDimitry Andric CVSymbol sym = m_index->ReadSymbolRecord(global); 17780b57cec5SDimitry Andric if (sym.kind() != S_UDT) 17790b57cec5SDimitry Andric continue; 17800b57cec5SDimitry Andric 17810b57cec5SDimitry Andric UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym)); 17820b57cec5SDimitry Andric bool is_typedef = true; 17830b57cec5SDimitry Andric if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) { 17840b57cec5SDimitry Andric CVType cvt = m_index->tpi().getType(udt.Type); 17850b57cec5SDimitry Andric llvm::StringRef name = CVTagRecord::create(cvt).name(); 17860b57cec5SDimitry Andric if (name == udt.Name) 17870b57cec5SDimitry Andric is_typedef = false; 17880b57cec5SDimitry Andric } 17890b57cec5SDimitry Andric 17900b57cec5SDimitry Andric if (is_typedef) 17910b57cec5SDimitry Andric GetOrCreateTypedef(global); 17920b57cec5SDimitry Andric } 17930b57cec5SDimitry Andric 17949dba64beSDimitry Andric const size_t new_count = GetTypeList().GetSize(); 17950b57cec5SDimitry Andric 17960b57cec5SDimitry Andric m_done_full_type_scan = true; 17970b57cec5SDimitry Andric 17980b57cec5SDimitry Andric return new_count - old_count; 17990b57cec5SDimitry Andric } 18000b57cec5SDimitry Andric 18010b57cec5SDimitry Andric size_t 18020b57cec5SDimitry Andric SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit, 18030b57cec5SDimitry Andric VariableList &variables) { 18040b57cec5SDimitry Andric PdbSymUid sym_uid(comp_unit.GetID()); 18050b57cec5SDimitry Andric lldbassert(sym_uid.kind() == PdbSymUidKind::Compiland); 18060b57cec5SDimitry Andric return 0; 18070b57cec5SDimitry Andric } 18080b57cec5SDimitry Andric 18090b57cec5SDimitry Andric VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, 18100b57cec5SDimitry Andric PdbCompilandSymId var_id, 18110b57cec5SDimitry Andric bool is_param) { 18120b57cec5SDimitry Andric ModuleSP module = GetObjectFile()->GetModule(); 18130b57cec5SDimitry Andric Block &block = GetOrCreateBlock(scope_id); 1814753f127fSDimitry Andric // Get function block. 1815753f127fSDimitry Andric Block *func_block = █ 1816753f127fSDimitry Andric while (func_block->GetParent()) { 1817753f127fSDimitry Andric func_block = func_block->GetParent(); 1818753f127fSDimitry Andric } 1819753f127fSDimitry Andric Address addr; 1820753f127fSDimitry Andric func_block->GetStartAddress(addr); 18210b57cec5SDimitry Andric VariableInfo var_info = 1822753f127fSDimitry Andric GetVariableLocationInfo(*m_index, var_id, *func_block, module); 1823bdd1243dSDimitry Andric Function *func = func_block->CalculateSymbolContextFunction(); 1824bdd1243dSDimitry Andric if (!func) 18250b57cec5SDimitry Andric return nullptr; 1826bdd1243dSDimitry Andric // Use empty dwarf expr if optimized away so that it won't be filtered out 1827bdd1243dSDimitry Andric // when lookuping local variables in this scope. 1828bdd1243dSDimitry Andric if (!var_info.location.IsValid()) 1829bdd1243dSDimitry Andric var_info.location = DWARFExpressionList(module, DWARFExpression(), nullptr); 1830bdd1243dSDimitry Andric var_info.location.SetFuncFileAddress( 1831bdd1243dSDimitry Andric func->GetAddressRange().GetBaseAddress().GetFileAddress()); 18320b57cec5SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi); 18330b57cec5SDimitry Andric CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii); 18340b57cec5SDimitry Andric TypeSP type_sp = GetOrCreateType(var_info.type); 1835bdd1243dSDimitry Andric if (!type_sp) 1836bdd1243dSDimitry Andric return nullptr; 18370b57cec5SDimitry Andric std::string name = var_info.name.str(); 18380b57cec5SDimitry Andric Declaration decl; 18390b57cec5SDimitry Andric SymbolFileTypeSP sftype = 18400b57cec5SDimitry Andric std::make_shared<SymbolFileType>(*this, type_sp->GetID()); 18410b57cec5SDimitry Andric 184281ad6265SDimitry Andric is_param |= var_info.is_param; 18430b57cec5SDimitry Andric ValueType var_scope = 18440b57cec5SDimitry Andric is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal; 1845e8d8bef9SDimitry Andric bool external = false; 1846e8d8bef9SDimitry Andric bool artificial = false; 1847e8d8bef9SDimitry Andric bool location_is_constant_data = false; 1848e8d8bef9SDimitry Andric bool static_member = false; 1849bdd1243dSDimitry Andric Variable::RangeList scope_ranges; 18500b57cec5SDimitry Andric VariableSP var_sp = std::make_shared<Variable>( 18510b57cec5SDimitry Andric toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope, 1852bdd1243dSDimitry Andric &block, scope_ranges, &decl, var_info.location, external, artificial, 1853753f127fSDimitry Andric location_is_constant_data, static_member); 1854bdd1243dSDimitry Andric if (!is_param) { 1855bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage()); 1856bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 1857bdd1243dSDimitry Andric return nullptr; 1858bdd1243dSDimitry Andric auto ts = *ts_or_err; 1859bdd1243dSDimitry Andric if (!ts) 1860bdd1243dSDimitry Andric return nullptr; 18610b57cec5SDimitry Andric 1862bdd1243dSDimitry Andric ts->GetNativePDBParser()->GetOrCreateVariableDecl(scope_id, var_id); 1863bdd1243dSDimitry Andric } 18640b57cec5SDimitry Andric m_local_variables[toOpaqueUid(var_id)] = var_sp; 18650b57cec5SDimitry Andric return var_sp; 18660b57cec5SDimitry Andric } 18670b57cec5SDimitry Andric 18680b57cec5SDimitry Andric VariableSP SymbolFileNativePDB::GetOrCreateLocalVariable( 18690b57cec5SDimitry Andric PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) { 18700b57cec5SDimitry Andric auto iter = m_local_variables.find(toOpaqueUid(var_id)); 18710b57cec5SDimitry Andric if (iter != m_local_variables.end()) 18720b57cec5SDimitry Andric return iter->second; 18730b57cec5SDimitry Andric 18740b57cec5SDimitry Andric return CreateLocalVariable(scope_id, var_id, is_param); 18750b57cec5SDimitry Andric } 18760b57cec5SDimitry Andric 18770b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) { 18780b57cec5SDimitry Andric CVSymbol sym = m_index->ReadSymbolRecord(id); 18790b57cec5SDimitry Andric lldbassert(sym.kind() == SymbolKind::S_UDT); 18800b57cec5SDimitry Andric 18810b57cec5SDimitry Andric UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym)); 18820b57cec5SDimitry Andric 18830b57cec5SDimitry Andric TypeSP target_type = GetOrCreateType(udt.Type); 18840b57cec5SDimitry Andric 1885bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 1886bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 1887bdd1243dSDimitry Andric return nullptr; 1888bdd1243dSDimitry Andric auto ts = *ts_or_err; 1889bdd1243dSDimitry Andric if (!ts) 1890bdd1243dSDimitry Andric return nullptr; 1891bdd1243dSDimitry Andric 1892bdd1243dSDimitry Andric ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id); 18930b57cec5SDimitry Andric 18940b57cec5SDimitry Andric Declaration decl; 1895bdd1243dSDimitry Andric return MakeType( 1896bdd1243dSDimitry Andric toOpaqueUid(id), ConstString(udt.Name), target_type->GetByteSize(nullptr), 1897bdd1243dSDimitry Andric nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID, 1898bdd1243dSDimitry Andric decl, target_type->GetForwardCompilerType(), 1899480093f4SDimitry Andric lldb_private::Type::ResolveState::Forward); 19000b57cec5SDimitry Andric } 19010b57cec5SDimitry Andric 19020b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) { 19030b57cec5SDimitry Andric auto iter = m_types.find(toOpaqueUid(id)); 19040b57cec5SDimitry Andric if (iter != m_types.end()) 19050b57cec5SDimitry Andric return iter->second; 19060b57cec5SDimitry Andric 19070b57cec5SDimitry Andric return CreateTypedef(id); 19080b57cec5SDimitry Andric } 19090b57cec5SDimitry Andric 19100b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) { 19110b57cec5SDimitry Andric Block &block = GetOrCreateBlock(block_id); 19120b57cec5SDimitry Andric 19130b57cec5SDimitry Andric size_t count = 0; 19140b57cec5SDimitry Andric 19150b57cec5SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi); 19160b57cec5SDimitry Andric CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset); 19170b57cec5SDimitry Andric uint32_t params_remaining = 0; 19180b57cec5SDimitry Andric switch (sym.kind()) { 19190b57cec5SDimitry Andric case S_GPROC32: 19200b57cec5SDimitry Andric case S_LPROC32: { 19210b57cec5SDimitry Andric ProcSym proc(static_cast<SymbolRecordKind>(sym.kind())); 19220b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym, proc)); 19230b57cec5SDimitry Andric CVType signature = m_index->tpi().getType(proc.FunctionType); 1924bdd1243dSDimitry Andric if (signature.kind() == LF_PROCEDURE) { 19250b57cec5SDimitry Andric ProcedureRecord sig; 1926bdd1243dSDimitry Andric if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>( 1927bdd1243dSDimitry Andric signature, sig)) { 1928bdd1243dSDimitry Andric llvm::consumeError(std::move(e)); 1929bdd1243dSDimitry Andric return 0; 1930bdd1243dSDimitry Andric } 19310b57cec5SDimitry Andric params_remaining = sig.getParameterCount(); 1932bdd1243dSDimitry Andric } else if (signature.kind() == LF_MFUNCTION) { 1933bdd1243dSDimitry Andric MemberFunctionRecord sig; 1934bdd1243dSDimitry Andric if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>( 1935bdd1243dSDimitry Andric signature, sig)) { 1936bdd1243dSDimitry Andric llvm::consumeError(std::move(e)); 1937bdd1243dSDimitry Andric return 0; 1938bdd1243dSDimitry Andric } 1939bdd1243dSDimitry Andric params_remaining = sig.getParameterCount(); 1940bdd1243dSDimitry Andric } else 1941bdd1243dSDimitry Andric return 0; 19420b57cec5SDimitry Andric break; 19430b57cec5SDimitry Andric } 19440b57cec5SDimitry Andric case S_BLOCK32: 19450b57cec5SDimitry Andric break; 194604eeddc0SDimitry Andric case S_INLINESITE: 194781ad6265SDimitry Andric break; 19480b57cec5SDimitry Andric default: 19490b57cec5SDimitry Andric lldbassert(false && "Symbol is not a block!"); 19500b57cec5SDimitry Andric return 0; 19510b57cec5SDimitry Andric } 19520b57cec5SDimitry Andric 19530b57cec5SDimitry Andric VariableListSP variables = block.GetBlockVariableList(false); 19540b57cec5SDimitry Andric if (!variables) { 19550b57cec5SDimitry Andric variables = std::make_shared<VariableList>(); 19560b57cec5SDimitry Andric block.SetVariableList(variables); 19570b57cec5SDimitry Andric } 19580b57cec5SDimitry Andric 19590b57cec5SDimitry Andric CVSymbolArray syms = limitSymbolArrayToScope( 19600b57cec5SDimitry Andric cii->m_debug_stream.getSymbolArray(), block_id.offset); 19610b57cec5SDimitry Andric 19620b57cec5SDimitry Andric // Skip the first record since it's a PROC32 or BLOCK32, and there's 19630b57cec5SDimitry Andric // no point examining it since we know it's not a local variable. 19640b57cec5SDimitry Andric syms.drop_front(); 19650b57cec5SDimitry Andric auto iter = syms.begin(); 19660b57cec5SDimitry Andric auto end = syms.end(); 19670b57cec5SDimitry Andric 19680b57cec5SDimitry Andric while (iter != end) { 19690b57cec5SDimitry Andric uint32_t record_offset = iter.offset(); 19700b57cec5SDimitry Andric CVSymbol variable_cvs = *iter; 19710b57cec5SDimitry Andric PdbCompilandSymId child_sym_id(block_id.modi, record_offset); 19720b57cec5SDimitry Andric ++iter; 19730b57cec5SDimitry Andric 197481ad6265SDimitry Andric // If this is a block or inline site, recurse into its children and then 197581ad6265SDimitry Andric // skip it. 197681ad6265SDimitry Andric if (variable_cvs.kind() == S_BLOCK32 || 197781ad6265SDimitry Andric variable_cvs.kind() == S_INLINESITE) { 19780b57cec5SDimitry Andric uint32_t block_end = getScopeEndOffset(variable_cvs); 19790b57cec5SDimitry Andric count += ParseVariablesForBlock(child_sym_id); 19800b57cec5SDimitry Andric iter = syms.at(block_end); 19810b57cec5SDimitry Andric continue; 19820b57cec5SDimitry Andric } 19830b57cec5SDimitry Andric 19840b57cec5SDimitry Andric bool is_param = params_remaining > 0; 19850b57cec5SDimitry Andric VariableSP variable; 19860b57cec5SDimitry Andric switch (variable_cvs.kind()) { 19870b57cec5SDimitry Andric case S_REGREL32: 19880b57cec5SDimitry Andric case S_REGISTER: 19890b57cec5SDimitry Andric case S_LOCAL: 19900b57cec5SDimitry Andric variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param); 19910b57cec5SDimitry Andric if (is_param) 19920b57cec5SDimitry Andric --params_remaining; 19930b57cec5SDimitry Andric if (variable) 19940b57cec5SDimitry Andric variables->AddVariableIfUnique(variable); 19950b57cec5SDimitry Andric break; 19960b57cec5SDimitry Andric default: 19970b57cec5SDimitry Andric break; 19980b57cec5SDimitry Andric } 19990b57cec5SDimitry Andric } 20000b57cec5SDimitry Andric 20010b57cec5SDimitry Andric // Pass false for set_children, since we call this recursively so that the 20020b57cec5SDimitry Andric // children will call this for themselves. 20030b57cec5SDimitry Andric block.SetDidParseVariables(true, false); 20040b57cec5SDimitry Andric 20050b57cec5SDimitry Andric return count; 20060b57cec5SDimitry Andric } 20070b57cec5SDimitry Andric 20080b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) { 20099dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 20100b57cec5SDimitry Andric lldbassert(sc.function || sc.comp_unit); 20110b57cec5SDimitry Andric 20120b57cec5SDimitry Andric VariableListSP variables; 20130b57cec5SDimitry Andric if (sc.block) { 20140b57cec5SDimitry Andric PdbSymUid block_id(sc.block->GetID()); 20150b57cec5SDimitry Andric 20160b57cec5SDimitry Andric size_t count = ParseVariablesForBlock(block_id.asCompilandSym()); 20170b57cec5SDimitry Andric return count; 20180b57cec5SDimitry Andric } 20190b57cec5SDimitry Andric 20200b57cec5SDimitry Andric if (sc.function) { 20210b57cec5SDimitry Andric PdbSymUid block_id(sc.function->GetID()); 20220b57cec5SDimitry Andric 20230b57cec5SDimitry Andric size_t count = ParseVariablesForBlock(block_id.asCompilandSym()); 20240b57cec5SDimitry Andric return count; 20250b57cec5SDimitry Andric } 20260b57cec5SDimitry Andric 20270b57cec5SDimitry Andric if (sc.comp_unit) { 20280b57cec5SDimitry Andric variables = sc.comp_unit->GetVariableList(false); 20290b57cec5SDimitry Andric if (!variables) { 20300b57cec5SDimitry Andric variables = std::make_shared<VariableList>(); 20310b57cec5SDimitry Andric sc.comp_unit->SetVariableList(variables); 20320b57cec5SDimitry Andric } 20330b57cec5SDimitry Andric return ParseVariablesForCompileUnit(*sc.comp_unit, *variables); 20340b57cec5SDimitry Andric } 20350b57cec5SDimitry Andric 20360b57cec5SDimitry Andric llvm_unreachable("Unreachable!"); 20370b57cec5SDimitry Andric } 20380b57cec5SDimitry Andric 20390b57cec5SDimitry Andric CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) { 2040bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 2041bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 2042bdd1243dSDimitry Andric return CompilerDecl(); 2043bdd1243dSDimitry Andric auto ts = *ts_or_err; 2044bdd1243dSDimitry Andric if (!ts) 2045bdd1243dSDimitry Andric return {}; 2046bdd1243dSDimitry Andric 2047bdd1243dSDimitry Andric if (auto decl = ts->GetNativePDBParser()->GetOrCreateDeclForUid(uid)) 204881ad6265SDimitry Andric return *decl; 20499dba64beSDimitry Andric return CompilerDecl(); 20500b57cec5SDimitry Andric } 20510b57cec5SDimitry Andric 20520b57cec5SDimitry Andric CompilerDeclContext 20530b57cec5SDimitry Andric SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) { 2054bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 2055bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 2056bdd1243dSDimitry Andric return {}; 2057bdd1243dSDimitry Andric auto ts = *ts_or_err; 2058bdd1243dSDimitry Andric if (!ts) 2059bdd1243dSDimitry Andric return {}; 2060bdd1243dSDimitry Andric 2061bdd1243dSDimitry Andric PdbAstBuilder *ast_builder = ts->GetNativePDBParser(); 20620b57cec5SDimitry Andric clang::DeclContext *context = 2063bdd1243dSDimitry Andric ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid)); 20640b57cec5SDimitry Andric if (!context) 20650b57cec5SDimitry Andric return {}; 20660b57cec5SDimitry Andric 2067bdd1243dSDimitry Andric return ast_builder->ToCompilerDeclContext(*context); 20680b57cec5SDimitry Andric } 20690b57cec5SDimitry Andric 20700b57cec5SDimitry Andric CompilerDeclContext 20710b57cec5SDimitry Andric SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { 2072bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 2073bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 2074bdd1243dSDimitry Andric return CompilerDeclContext(); 2075bdd1243dSDimitry Andric auto ts = *ts_or_err; 2076bdd1243dSDimitry Andric if (!ts) 2077bdd1243dSDimitry Andric return {}; 2078bdd1243dSDimitry Andric 2079bdd1243dSDimitry Andric PdbAstBuilder *ast_builder = ts->GetNativePDBParser(); 2080bdd1243dSDimitry Andric clang::DeclContext *context = ast_builder->GetParentDeclContext(PdbSymUid(uid)); 2081bdd1243dSDimitry Andric if (!context) 2082bdd1243dSDimitry Andric return CompilerDeclContext(); 2083bdd1243dSDimitry Andric return ast_builder->ToCompilerDeclContext(*context); 20840b57cec5SDimitry Andric } 20850b57cec5SDimitry Andric 20860b57cec5SDimitry Andric Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) { 20879dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 20880b57cec5SDimitry Andric auto iter = m_types.find(type_uid); 20890b57cec5SDimitry Andric // lldb should not be passing us non-sensical type uids. the only way it 20900b57cec5SDimitry Andric // could have a type uid in the first place is if we handed it out, in which 20910b57cec5SDimitry Andric // case we should know about the type. However, that doesn't mean we've 20920b57cec5SDimitry Andric // instantiated it yet. We can vend out a UID for a future type. So if the 20930b57cec5SDimitry Andric // type doesn't exist, let's instantiate it now. 20940b57cec5SDimitry Andric if (iter != m_types.end()) 20950b57cec5SDimitry Andric return &*iter->second; 20960b57cec5SDimitry Andric 20970b57cec5SDimitry Andric PdbSymUid uid(type_uid); 20980b57cec5SDimitry Andric lldbassert(uid.kind() == PdbSymUidKind::Type); 20990b57cec5SDimitry Andric PdbTypeSymId type_id = uid.asTypeSym(); 21000b57cec5SDimitry Andric if (type_id.index.isNoneType()) 21010b57cec5SDimitry Andric return nullptr; 21020b57cec5SDimitry Andric 21030b57cec5SDimitry Andric TypeSP type_sp = CreateAndCacheType(type_id); 2104bdd1243dSDimitry Andric if (!type_sp) 2105bdd1243dSDimitry Andric return nullptr; 21060b57cec5SDimitry Andric return &*type_sp; 21070b57cec5SDimitry Andric } 21080b57cec5SDimitry Andric 2109bdd1243dSDimitry Andric std::optional<SymbolFile::ArrayInfo> 21100b57cec5SDimitry Andric SymbolFileNativePDB::GetDynamicArrayInfoForUID( 21110b57cec5SDimitry Andric lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { 2112bdd1243dSDimitry Andric return std::nullopt; 21130b57cec5SDimitry Andric } 21140b57cec5SDimitry Andric 21150b57cec5SDimitry Andric bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) { 2116bdd1243dSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 2117bdd1243dSDimitry Andric auto ts = compiler_type.GetTypeSystem(); 2118bdd1243dSDimitry Andric auto clang_type_system = ts.dyn_cast_or_null<TypeSystemClang>(); 2119bdd1243dSDimitry Andric if (!clang_type_system) 2120bdd1243dSDimitry Andric return false; 2121bdd1243dSDimitry Andric 2122bdd1243dSDimitry Andric PdbAstBuilder *ast_builder = 2123bdd1243dSDimitry Andric static_cast<PdbAstBuilder *>(clang_type_system->GetNativePDBParser()); 2124bdd1243dSDimitry Andric if (ast_builder && 2125bdd1243dSDimitry Andric ast_builder->GetClangASTImporter().CanImport(compiler_type)) 2126bdd1243dSDimitry Andric return ast_builder->GetClangASTImporter().CompleteType(compiler_type); 21270b57cec5SDimitry Andric clang::QualType qt = 21280b57cec5SDimitry Andric clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType()); 21290b57cec5SDimitry Andric 2130bdd1243dSDimitry Andric return ast_builder->CompleteType(qt); 21310b57cec5SDimitry Andric } 21320b57cec5SDimitry Andric 21339dba64beSDimitry Andric void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, 21340b57cec5SDimitry Andric TypeClass type_mask, 21359dba64beSDimitry Andric lldb_private::TypeList &type_list) {} 21360b57cec5SDimitry Andric 213706c3fb27SDimitry Andric CompilerDeclContext SymbolFileNativePDB::FindNamespace( 213806c3fb27SDimitry Andric ConstString name, const CompilerDeclContext &parent_decl_ctx, bool) { 21390b57cec5SDimitry Andric return {}; 21400b57cec5SDimitry Andric } 21410b57cec5SDimitry Andric 2142bdd1243dSDimitry Andric llvm::Expected<lldb::TypeSystemSP> 21430b57cec5SDimitry Andric SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { 21449dba64beSDimitry Andric auto type_system_or_err = 21459dba64beSDimitry Andric m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); 2146bdd1243dSDimitry Andric if (type_system_or_err) 2147bdd1243dSDimitry Andric if (auto ts = *type_system_or_err) 2148bdd1243dSDimitry Andric ts->SetSymbolFile(this); 21499dba64beSDimitry Andric return type_system_or_err; 21500b57cec5SDimitry Andric } 21510b57cec5SDimitry Andric 2152349cc55cSDimitry Andric uint64_t SymbolFileNativePDB::GetDebugInfoSize() { 2153349cc55cSDimitry Andric // PDB files are a separate file that contains all debug info. 2154349cc55cSDimitry Andric return m_index->pdb().getFileSize(); 21550b57cec5SDimitry Andric } 2156bdd1243dSDimitry Andric 2157bdd1243dSDimitry Andric void SymbolFileNativePDB::BuildParentMap() { 2158bdd1243dSDimitry Andric LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); 2159bdd1243dSDimitry Andric 2160bdd1243dSDimitry Andric llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full; 2161bdd1243dSDimitry Andric llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward; 2162bdd1243dSDimitry Andric 2163bdd1243dSDimitry Andric struct RecordIndices { 2164bdd1243dSDimitry Andric TypeIndex forward; 2165bdd1243dSDimitry Andric TypeIndex full; 2166bdd1243dSDimitry Andric }; 2167bdd1243dSDimitry Andric 2168bdd1243dSDimitry Andric llvm::StringMap<RecordIndices> record_indices; 2169bdd1243dSDimitry Andric 2170bdd1243dSDimitry Andric for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) { 2171bdd1243dSDimitry Andric CVType type = types.getType(*ti); 2172bdd1243dSDimitry Andric if (!IsTagRecord(type)) 2173bdd1243dSDimitry Andric continue; 2174bdd1243dSDimitry Andric 2175bdd1243dSDimitry Andric CVTagRecord tag = CVTagRecord::create(type); 2176bdd1243dSDimitry Andric 2177bdd1243dSDimitry Andric RecordIndices &indices = record_indices[tag.asTag().getUniqueName()]; 2178bdd1243dSDimitry Andric if (tag.asTag().isForwardRef()) 2179bdd1243dSDimitry Andric indices.forward = *ti; 2180bdd1243dSDimitry Andric else 2181bdd1243dSDimitry Andric indices.full = *ti; 2182bdd1243dSDimitry Andric 2183bdd1243dSDimitry Andric if (indices.full != TypeIndex::None() && 2184bdd1243dSDimitry Andric indices.forward != TypeIndex::None()) { 2185bdd1243dSDimitry Andric forward_to_full[indices.forward] = indices.full; 2186bdd1243dSDimitry Andric full_to_forward[indices.full] = indices.forward; 2187bdd1243dSDimitry Andric } 2188bdd1243dSDimitry Andric 2189bdd1243dSDimitry Andric // We're looking for LF_NESTTYPE records in the field list, so ignore 2190bdd1243dSDimitry Andric // forward references (no field list), and anything without a nested class 2191bdd1243dSDimitry Andric // (since there won't be any LF_NESTTYPE records). 2192bdd1243dSDimitry Andric if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass()) 2193bdd1243dSDimitry Andric continue; 2194bdd1243dSDimitry Andric 2195bdd1243dSDimitry Andric struct ProcessTpiStream : public TypeVisitorCallbacks { 2196bdd1243dSDimitry Andric ProcessTpiStream(PdbIndex &index, TypeIndex parent, 2197bdd1243dSDimitry Andric const CVTagRecord &parent_cvt, 2198bdd1243dSDimitry Andric llvm::DenseMap<TypeIndex, TypeIndex> &parents) 2199bdd1243dSDimitry Andric : index(index), parents(parents), parent(parent), 2200bdd1243dSDimitry Andric parent_cvt(parent_cvt) {} 2201bdd1243dSDimitry Andric 2202bdd1243dSDimitry Andric PdbIndex &index; 2203bdd1243dSDimitry Andric llvm::DenseMap<TypeIndex, TypeIndex> &parents; 2204bdd1243dSDimitry Andric 2205bdd1243dSDimitry Andric unsigned unnamed_type_index = 1; 2206bdd1243dSDimitry Andric TypeIndex parent; 2207bdd1243dSDimitry Andric const CVTagRecord &parent_cvt; 2208bdd1243dSDimitry Andric 2209bdd1243dSDimitry Andric llvm::Error visitKnownMember(CVMemberRecord &CVR, 2210bdd1243dSDimitry Andric NestedTypeRecord &Record) override { 2211bdd1243dSDimitry Andric std::string unnamed_type_name; 2212bdd1243dSDimitry Andric if (Record.Name.empty()) { 2213bdd1243dSDimitry Andric unnamed_type_name = 2214bdd1243dSDimitry Andric llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str(); 2215bdd1243dSDimitry Andric Record.Name = unnamed_type_name; 2216bdd1243dSDimitry Andric ++unnamed_type_index; 2217bdd1243dSDimitry Andric } 2218bdd1243dSDimitry Andric std::optional<CVTagRecord> tag = 2219bdd1243dSDimitry Andric GetNestedTagDefinition(Record, parent_cvt, index.tpi()); 2220bdd1243dSDimitry Andric if (!tag) 2221bdd1243dSDimitry Andric return llvm::ErrorSuccess(); 2222bdd1243dSDimitry Andric 2223bdd1243dSDimitry Andric parents[Record.Type] = parent; 2224bdd1243dSDimitry Andric return llvm::ErrorSuccess(); 2225bdd1243dSDimitry Andric } 2226bdd1243dSDimitry Andric }; 2227bdd1243dSDimitry Andric 2228bdd1243dSDimitry Andric CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList); 2229bdd1243dSDimitry Andric ProcessTpiStream process(*m_index, *ti, tag, m_parent_types); 2230bdd1243dSDimitry Andric FieldListRecord field_list; 2231bdd1243dSDimitry Andric if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>( 2232bdd1243dSDimitry Andric field_list_cvt, field_list)) 2233bdd1243dSDimitry Andric llvm::consumeError(std::move(error)); 2234bdd1243dSDimitry Andric if (llvm::Error error = visitMemberRecordStream(field_list.Data, process)) 2235bdd1243dSDimitry Andric llvm::consumeError(std::move(error)); 2236bdd1243dSDimitry Andric } 2237bdd1243dSDimitry Andric 2238bdd1243dSDimitry Andric // Now that we know the forward -> full mapping of all type indices, we can 2239bdd1243dSDimitry Andric // re-write all the indices. At the end of this process, we want a mapping 2240bdd1243dSDimitry Andric // consisting of fwd -> full and full -> full for all child -> parent indices. 2241bdd1243dSDimitry Andric // We can re-write the values in place, but for the keys, we must save them 2242bdd1243dSDimitry Andric // off so that we don't modify the map in place while also iterating it. 2243bdd1243dSDimitry Andric std::vector<TypeIndex> full_keys; 2244bdd1243dSDimitry Andric std::vector<TypeIndex> fwd_keys; 2245bdd1243dSDimitry Andric for (auto &entry : m_parent_types) { 2246bdd1243dSDimitry Andric TypeIndex key = entry.first; 2247bdd1243dSDimitry Andric TypeIndex value = entry.second; 2248bdd1243dSDimitry Andric 2249bdd1243dSDimitry Andric auto iter = forward_to_full.find(value); 2250bdd1243dSDimitry Andric if (iter != forward_to_full.end()) 2251bdd1243dSDimitry Andric entry.second = iter->second; 2252bdd1243dSDimitry Andric 2253bdd1243dSDimitry Andric iter = forward_to_full.find(key); 2254bdd1243dSDimitry Andric if (iter != forward_to_full.end()) 2255bdd1243dSDimitry Andric fwd_keys.push_back(key); 2256bdd1243dSDimitry Andric else 2257bdd1243dSDimitry Andric full_keys.push_back(key); 2258bdd1243dSDimitry Andric } 2259bdd1243dSDimitry Andric for (TypeIndex fwd : fwd_keys) { 2260bdd1243dSDimitry Andric TypeIndex full = forward_to_full[fwd]; 2261bdd1243dSDimitry Andric m_parent_types[full] = m_parent_types[fwd]; 2262bdd1243dSDimitry Andric } 2263bdd1243dSDimitry Andric for (TypeIndex full : full_keys) { 2264bdd1243dSDimitry Andric TypeIndex fwd = full_to_forward[full]; 2265bdd1243dSDimitry Andric m_parent_types[fwd] = m_parent_types[full]; 2266bdd1243dSDimitry Andric } 2267bdd1243dSDimitry Andric } 2268bdd1243dSDimitry Andric 2269bdd1243dSDimitry Andric std::optional<PdbCompilandSymId> 2270bdd1243dSDimitry Andric SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) { 2271bdd1243dSDimitry Andric CVSymbol sym = m_index->ReadSymbolRecord(id); 2272bdd1243dSDimitry Andric if (symbolOpensScope(sym.kind())) { 2273bdd1243dSDimitry Andric // If this exact symbol opens a scope, we can just directly access its 2274bdd1243dSDimitry Andric // parent. 2275bdd1243dSDimitry Andric id.offset = getScopeParentOffset(sym); 2276bdd1243dSDimitry Andric // Global symbols have parent offset of 0. Return std::nullopt to indicate 2277bdd1243dSDimitry Andric // this. 2278bdd1243dSDimitry Andric if (id.offset == 0) 2279bdd1243dSDimitry Andric return std::nullopt; 2280bdd1243dSDimitry Andric return id; 2281bdd1243dSDimitry Andric } 2282bdd1243dSDimitry Andric 2283bdd1243dSDimitry Andric // Otherwise we need to start at the beginning and iterate forward until we 2284bdd1243dSDimitry Andric // reach (or pass) this particular symbol 2285bdd1243dSDimitry Andric CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi); 2286bdd1243dSDimitry Andric const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray(); 2287bdd1243dSDimitry Andric 2288bdd1243dSDimitry Andric auto begin = syms.begin(); 2289bdd1243dSDimitry Andric auto end = syms.at(id.offset); 2290bdd1243dSDimitry Andric std::vector<PdbCompilandSymId> scope_stack; 2291bdd1243dSDimitry Andric 2292bdd1243dSDimitry Andric while (begin != end) { 2293bdd1243dSDimitry Andric if (begin.offset() > id.offset) { 2294bdd1243dSDimitry Andric // We passed it. We couldn't even find this symbol record. 2295bdd1243dSDimitry Andric lldbassert(false && "Invalid compiland symbol id!"); 2296bdd1243dSDimitry Andric return std::nullopt; 2297bdd1243dSDimitry Andric } 2298bdd1243dSDimitry Andric 2299bdd1243dSDimitry Andric // We haven't found the symbol yet. Check if we need to open or close the 2300bdd1243dSDimitry Andric // scope stack. 2301bdd1243dSDimitry Andric if (symbolOpensScope(begin->kind())) { 2302bdd1243dSDimitry Andric // We can use the end offset of the scope to determine whether or not 2303bdd1243dSDimitry Andric // we can just outright skip this entire scope. 2304bdd1243dSDimitry Andric uint32_t scope_end = getScopeEndOffset(*begin); 2305bdd1243dSDimitry Andric if (scope_end < id.offset) { 2306bdd1243dSDimitry Andric begin = syms.at(scope_end); 2307bdd1243dSDimitry Andric } else { 2308bdd1243dSDimitry Andric // The symbol we're looking for is somewhere in this scope. 2309bdd1243dSDimitry Andric scope_stack.emplace_back(id.modi, begin.offset()); 2310bdd1243dSDimitry Andric } 2311bdd1243dSDimitry Andric } else if (symbolEndsScope(begin->kind())) { 2312bdd1243dSDimitry Andric scope_stack.pop_back(); 2313bdd1243dSDimitry Andric } 2314bdd1243dSDimitry Andric ++begin; 2315bdd1243dSDimitry Andric } 2316bdd1243dSDimitry Andric if (scope_stack.empty()) 2317bdd1243dSDimitry Andric return std::nullopt; 2318bdd1243dSDimitry Andric // We have a match! Return the top of the stack 2319bdd1243dSDimitry Andric return scope_stack.back(); 2320bdd1243dSDimitry Andric } 2321bdd1243dSDimitry Andric 2322bdd1243dSDimitry Andric std::optional<llvm::codeview::TypeIndex> 2323bdd1243dSDimitry Andric SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) { 2324bdd1243dSDimitry Andric auto parent_iter = m_parent_types.find(ti); 2325bdd1243dSDimitry Andric if (parent_iter == m_parent_types.end()) 2326bdd1243dSDimitry Andric return std::nullopt; 2327bdd1243dSDimitry Andric return parent_iter->second; 2328bdd1243dSDimitry Andric } 2329