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/Symbol/CompileUnit.h" 180b57cec5SDimitry Andric #include "lldb/Symbol/LineTable.h" 190b57cec5SDimitry Andric #include "lldb/Symbol/ObjectFile.h" 200b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h" 210b57cec5SDimitry Andric #include "lldb/Symbol/SymbolVendor.h" 220b57cec5SDimitry Andric #include "lldb/Symbol/Variable.h" 230b57cec5SDimitry Andric #include "lldb/Symbol/VariableList.h" 2481ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h" 259dba64beSDimitry Andric #include "lldb/Utility/Log.h" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CVRecord.h" 280b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/CVTypeVisitor.h" 290b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h" 300b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" 310b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/RecordName.h" 320b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" 330b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" 340b57cec5SDimitry Andric #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" 350b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/DbiStream.h" 360b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/GlobalsStream.h" 370b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/InfoStream.h" 380b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h" 39e8d8bef9SDimitry Andric #include "llvm/DebugInfo/PDB/Native/NativeSession.h" 400b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/PDBFile.h" 410b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/SymbolStream.h" 420b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/Native/TpiStream.h" 43e8d8bef9SDimitry Andric #include "llvm/DebugInfo/PDB/PDB.h" 440b57cec5SDimitry Andric #include "llvm/DebugInfo/PDB/PDBTypes.h" 450b57cec5SDimitry Andric #include "llvm/Demangle/MicrosoftDemangle.h" 460b57cec5SDimitry Andric #include "llvm/Object/COFF.h" 470b57cec5SDimitry Andric #include "llvm/Support/Allocator.h" 480b57cec5SDimitry Andric #include "llvm/Support/BinaryStreamReader.h" 490b57cec5SDimitry Andric #include "llvm/Support/Error.h" 500b57cec5SDimitry Andric #include "llvm/Support/ErrorOr.h" 510b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric #include "DWARFLocationExpression.h" 540b57cec5SDimitry Andric #include "PdbSymUid.h" 550b57cec5SDimitry Andric #include "PdbUtil.h" 560b57cec5SDimitry Andric #include "UdtRecordCompleter.h" 57bdd1243dSDimitry Andric #include <optional> 5806c3fb27SDimitry Andric #include <string_view> 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric using namespace lldb; 610b57cec5SDimitry Andric using namespace lldb_private; 620b57cec5SDimitry Andric using namespace npdb; 630b57cec5SDimitry Andric using namespace llvm::codeview; 640b57cec5SDimitry Andric using namespace llvm::pdb; 650b57cec5SDimitry Andric 66480093f4SDimitry Andric char SymbolFileNativePDB::ID; 67480093f4SDimitry Andric 680b57cec5SDimitry Andric static lldb::LanguageType TranslateLanguage(PDB_Lang lang) { 690b57cec5SDimitry Andric switch (lang) { 700b57cec5SDimitry Andric case PDB_Lang::Cpp: 710b57cec5SDimitry Andric return lldb::LanguageType::eLanguageTypeC_plus_plus; 720b57cec5SDimitry Andric case PDB_Lang::C: 730b57cec5SDimitry Andric return lldb::LanguageType::eLanguageTypeC; 740b57cec5SDimitry Andric case PDB_Lang::Swift: 750b57cec5SDimitry Andric return lldb::LanguageType::eLanguageTypeSwift; 7681ad6265SDimitry Andric case PDB_Lang::Rust: 7781ad6265SDimitry Andric return lldb::LanguageType::eLanguageTypeRust; 7806c3fb27SDimitry Andric case PDB_Lang::ObjC: 7906c3fb27SDimitry Andric return lldb::LanguageType::eLanguageTypeObjC; 8006c3fb27SDimitry Andric case PDB_Lang::ObjCpp: 8106c3fb27SDimitry Andric return lldb::LanguageType::eLanguageTypeObjC_plus_plus; 820b57cec5SDimitry Andric default: 830b57cec5SDimitry Andric return lldb::LanguageType::eLanguageTypeUnknown; 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric static std::unique_ptr<PDBFile> 880b57cec5SDimitry Andric loadMatchingPDBFile(std::string exe_path, llvm::BumpPtrAllocator &allocator) { 890b57cec5SDimitry Andric // Try to find a matching PDB for an EXE. 900b57cec5SDimitry Andric using namespace llvm::object; 910b57cec5SDimitry Andric auto expected_binary = createBinary(exe_path); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric // If the file isn't a PE/COFF executable, fail. 940b57cec5SDimitry Andric if (!expected_binary) { 950b57cec5SDimitry Andric llvm::consumeError(expected_binary.takeError()); 960b57cec5SDimitry Andric return nullptr; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric OwningBinary<Binary> binary = std::move(*expected_binary); 990b57cec5SDimitry Andric 1009dba64beSDimitry Andric // TODO: Avoid opening the PE/COFF binary twice by reading this information 1019dba64beSDimitry Andric // directly from the lldb_private::ObjectFile. 1020b57cec5SDimitry Andric auto *obj = llvm::dyn_cast<llvm::object::COFFObjectFile>(binary.getBinary()); 1030b57cec5SDimitry Andric if (!obj) 1040b57cec5SDimitry Andric return nullptr; 1050b57cec5SDimitry Andric const llvm::codeview::DebugInfo *pdb_info = nullptr; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric // If it doesn't have a debug directory, fail. 1080b57cec5SDimitry Andric llvm::StringRef pdb_file; 1095ffd83dbSDimitry Andric if (llvm::Error e = obj->getDebugPDBInfo(pdb_info, pdb_file)) { 1105ffd83dbSDimitry Andric consumeError(std::move(e)); 1110b57cec5SDimitry Andric return nullptr; 1125ffd83dbSDimitry Andric } 1130b57cec5SDimitry Andric 114e8d8bef9SDimitry Andric // If the file doesn't exist, perhaps the path specified at build time 115e8d8bef9SDimitry Andric // doesn't match the PDB's current location, so check the location of the 116e8d8bef9SDimitry Andric // executable. 117e8d8bef9SDimitry Andric if (!FileSystem::Instance().Exists(pdb_file)) { 118e8d8bef9SDimitry Andric const auto exe_dir = FileSpec(exe_path).CopyByRemovingLastPathComponent(); 119e8d8bef9SDimitry Andric const auto pdb_name = FileSpec(pdb_file).GetFilename().GetCString(); 120bdd1243dSDimitry Andric pdb_file = exe_dir.CopyByAppendingPathComponent(pdb_name).GetPathAsConstString().GetStringRef(); 121e8d8bef9SDimitry Andric } 122e8d8bef9SDimitry Andric 123e8d8bef9SDimitry Andric // If the file is not a PDB or if it doesn't have a matching GUID, fail. 124e8d8bef9SDimitry Andric auto pdb = ObjectFilePDB::loadPDBFile(std::string(pdb_file), allocator); 1250b57cec5SDimitry Andric if (!pdb) 1260b57cec5SDimitry Andric return nullptr; 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric auto expected_info = pdb->getPDBInfoStream(); 1290b57cec5SDimitry Andric if (!expected_info) { 1300b57cec5SDimitry Andric llvm::consumeError(expected_info.takeError()); 1310b57cec5SDimitry Andric return nullptr; 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric llvm::codeview::GUID guid; 1340b57cec5SDimitry Andric memcpy(&guid, pdb_info->PDB70.Signature, 16); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric if (expected_info->getGuid() != guid) 1370b57cec5SDimitry Andric return nullptr; 1380b57cec5SDimitry Andric return pdb; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric static bool IsFunctionPrologue(const CompilandIndexItem &cci, 1420b57cec5SDimitry Andric lldb::addr_t addr) { 1430b57cec5SDimitry Andric // FIXME: Implement this. 1440b57cec5SDimitry Andric return false; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric static bool IsFunctionEpilogue(const CompilandIndexItem &cci, 1480b57cec5SDimitry Andric lldb::addr_t addr) { 1490b57cec5SDimitry Andric // FIXME: Implement this. 1500b57cec5SDimitry Andric return false; 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric static llvm::StringRef GetSimpleTypeName(SimpleTypeKind kind) { 1540b57cec5SDimitry Andric switch (kind) { 1550b57cec5SDimitry Andric case SimpleTypeKind::Boolean128: 1560b57cec5SDimitry Andric case SimpleTypeKind::Boolean16: 1570b57cec5SDimitry Andric case SimpleTypeKind::Boolean32: 1580b57cec5SDimitry Andric case SimpleTypeKind::Boolean64: 1590b57cec5SDimitry Andric case SimpleTypeKind::Boolean8: 1600b57cec5SDimitry Andric return "bool"; 1610b57cec5SDimitry Andric case SimpleTypeKind::Byte: 1620b57cec5SDimitry Andric case SimpleTypeKind::UnsignedCharacter: 1630b57cec5SDimitry Andric return "unsigned char"; 1640b57cec5SDimitry Andric case SimpleTypeKind::NarrowCharacter: 1650b57cec5SDimitry Andric return "char"; 1660b57cec5SDimitry Andric case SimpleTypeKind::SignedCharacter: 1670b57cec5SDimitry Andric case SimpleTypeKind::SByte: 1680b57cec5SDimitry Andric return "signed char"; 1690b57cec5SDimitry Andric case SimpleTypeKind::Character16: 1700b57cec5SDimitry Andric return "char16_t"; 1710b57cec5SDimitry Andric case SimpleTypeKind::Character32: 1720b57cec5SDimitry Andric return "char32_t"; 17381ad6265SDimitry Andric case SimpleTypeKind::Character8: 17481ad6265SDimitry Andric return "char8_t"; 1750b57cec5SDimitry Andric case SimpleTypeKind::Complex80: 1760b57cec5SDimitry Andric case SimpleTypeKind::Complex64: 1770b57cec5SDimitry Andric case SimpleTypeKind::Complex32: 1780b57cec5SDimitry Andric return "complex"; 1790b57cec5SDimitry Andric case SimpleTypeKind::Float128: 1800b57cec5SDimitry Andric case SimpleTypeKind::Float80: 1810b57cec5SDimitry Andric return "long double"; 1820b57cec5SDimitry Andric case SimpleTypeKind::Float64: 1830b57cec5SDimitry Andric return "double"; 1840b57cec5SDimitry Andric case SimpleTypeKind::Float32: 1850b57cec5SDimitry Andric return "float"; 1860b57cec5SDimitry Andric case SimpleTypeKind::Float16: 1870b57cec5SDimitry Andric return "single"; 1880b57cec5SDimitry Andric case SimpleTypeKind::Int128: 1890b57cec5SDimitry Andric return "__int128"; 1900b57cec5SDimitry Andric case SimpleTypeKind::Int64: 1910b57cec5SDimitry Andric case SimpleTypeKind::Int64Quad: 1920b57cec5SDimitry Andric return "int64_t"; 1930b57cec5SDimitry Andric case SimpleTypeKind::Int32: 1940b57cec5SDimitry Andric return "int"; 1950b57cec5SDimitry Andric case SimpleTypeKind::Int16: 1960b57cec5SDimitry Andric return "short"; 1970b57cec5SDimitry Andric case SimpleTypeKind::UInt128: 1980b57cec5SDimitry Andric return "unsigned __int128"; 1990b57cec5SDimitry Andric case SimpleTypeKind::UInt64: 2000b57cec5SDimitry Andric case SimpleTypeKind::UInt64Quad: 2010b57cec5SDimitry Andric return "uint64_t"; 2020b57cec5SDimitry Andric case SimpleTypeKind::HResult: 2030b57cec5SDimitry Andric return "HRESULT"; 2040b57cec5SDimitry Andric case SimpleTypeKind::UInt32: 2050b57cec5SDimitry Andric return "unsigned"; 2060b57cec5SDimitry Andric case SimpleTypeKind::UInt16: 2070b57cec5SDimitry Andric case SimpleTypeKind::UInt16Short: 2080b57cec5SDimitry Andric return "unsigned short"; 2090b57cec5SDimitry Andric case SimpleTypeKind::Int32Long: 2100b57cec5SDimitry Andric return "long"; 2110b57cec5SDimitry Andric case SimpleTypeKind::UInt32Long: 2120b57cec5SDimitry Andric return "unsigned long"; 2130b57cec5SDimitry Andric case SimpleTypeKind::Void: 2140b57cec5SDimitry Andric return "void"; 2150b57cec5SDimitry Andric case SimpleTypeKind::WideCharacter: 2160b57cec5SDimitry Andric return "wchar_t"; 2170b57cec5SDimitry Andric default: 2180b57cec5SDimitry Andric return ""; 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric static bool IsClassRecord(TypeLeafKind kind) { 2230b57cec5SDimitry Andric switch (kind) { 2240b57cec5SDimitry Andric case LF_STRUCTURE: 2250b57cec5SDimitry Andric case LF_CLASS: 2260b57cec5SDimitry Andric case LF_INTERFACE: 2270b57cec5SDimitry Andric return true; 2280b57cec5SDimitry Andric default: 2290b57cec5SDimitry Andric return false; 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric } 2320b57cec5SDimitry Andric 233bdd1243dSDimitry Andric static std::optional<CVTagRecord> 234bdd1243dSDimitry Andric GetNestedTagDefinition(const NestedTypeRecord &Record, 235bdd1243dSDimitry Andric const CVTagRecord &parent, TpiStream &tpi) { 236bdd1243dSDimitry Andric // An LF_NESTTYPE is essentially a nested typedef / using declaration, but it 237bdd1243dSDimitry Andric // is also used to indicate the primary definition of a nested class. That is 238bdd1243dSDimitry Andric // to say, if you have: 239bdd1243dSDimitry Andric // struct A { 240bdd1243dSDimitry Andric // struct B {}; 241bdd1243dSDimitry Andric // using C = B; 242bdd1243dSDimitry Andric // }; 243bdd1243dSDimitry Andric // Then in the debug info, this will appear as: 244bdd1243dSDimitry Andric // LF_STRUCTURE `A::B` [type index = N] 245bdd1243dSDimitry Andric // LF_STRUCTURE `A` 246bdd1243dSDimitry Andric // LF_NESTTYPE [name = `B`, index = N] 247bdd1243dSDimitry Andric // LF_NESTTYPE [name = `C`, index = N] 248bdd1243dSDimitry Andric // In order to accurately reconstruct the decl context hierarchy, we need to 249bdd1243dSDimitry Andric // know which ones are actual definitions and which ones are just aliases. 250bdd1243dSDimitry Andric 251bdd1243dSDimitry Andric // If it's a simple type, then this is something like `using foo = int`. 252bdd1243dSDimitry Andric if (Record.Type.isSimple()) 253bdd1243dSDimitry Andric return std::nullopt; 254bdd1243dSDimitry Andric 255bdd1243dSDimitry Andric CVType cvt = tpi.getType(Record.Type); 256bdd1243dSDimitry Andric 257bdd1243dSDimitry Andric if (!IsTagRecord(cvt)) 258bdd1243dSDimitry Andric return std::nullopt; 259bdd1243dSDimitry Andric 260bdd1243dSDimitry Andric // If it's an inner definition, then treat whatever name we have here as a 261bdd1243dSDimitry Andric // single component of a mangled name. So we can inject it into the parent's 262bdd1243dSDimitry Andric // mangled name to see if it matches. 263bdd1243dSDimitry Andric CVTagRecord child = CVTagRecord::create(cvt); 264bdd1243dSDimitry Andric std::string qname = std::string(parent.asTag().getUniqueName()); 265bdd1243dSDimitry Andric if (qname.size() < 4 || child.asTag().getUniqueName().size() < 4) 266bdd1243dSDimitry Andric return std::nullopt; 267bdd1243dSDimitry Andric 268bdd1243dSDimitry Andric // qname[3] is the tag type identifier (struct, class, union, etc). Since the 269bdd1243dSDimitry Andric // inner tag type is not necessarily the same as the outer tag type, re-write 270bdd1243dSDimitry Andric // it to match the inner tag type. 271bdd1243dSDimitry Andric qname[3] = child.asTag().getUniqueName()[3]; 272bdd1243dSDimitry Andric std::string piece; 273bdd1243dSDimitry Andric if (qname[3] == 'W') 274bdd1243dSDimitry Andric piece = "4"; 275bdd1243dSDimitry Andric piece += Record.Name; 276bdd1243dSDimitry Andric piece.push_back('@'); 277bdd1243dSDimitry Andric qname.insert(4, std::move(piece)); 278bdd1243dSDimitry Andric if (qname != child.asTag().UniqueName) 279bdd1243dSDimitry Andric return std::nullopt; 280bdd1243dSDimitry Andric 281bdd1243dSDimitry Andric return std::move(child); 282bdd1243dSDimitry Andric } 283bdd1243dSDimitry Andric 2840b57cec5SDimitry Andric void SymbolFileNativePDB::Initialize() { 2850b57cec5SDimitry Andric PluginManager::RegisterPlugin(GetPluginNameStatic(), 2860b57cec5SDimitry Andric GetPluginDescriptionStatic(), CreateInstance, 2870b57cec5SDimitry Andric DebuggerInitialize); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric void SymbolFileNativePDB::Terminate() { 2910b57cec5SDimitry Andric PluginManager::UnregisterPlugin(CreateInstance); 2920b57cec5SDimitry Andric } 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric void SymbolFileNativePDB::DebuggerInitialize(Debugger &debugger) {} 2950b57cec5SDimitry Andric 296349cc55cSDimitry Andric llvm::StringRef SymbolFileNativePDB::GetPluginDescriptionStatic() { 2970b57cec5SDimitry Andric return "Microsoft PDB debug symbol cross-platform file reader."; 2980b57cec5SDimitry Andric } 2990b57cec5SDimitry Andric 3009dba64beSDimitry Andric SymbolFile *SymbolFileNativePDB::CreateInstance(ObjectFileSP objfile_sp) { 3019dba64beSDimitry Andric return new SymbolFileNativePDB(std::move(objfile_sp)); 3020b57cec5SDimitry Andric } 3030b57cec5SDimitry Andric 3049dba64beSDimitry Andric SymbolFileNativePDB::SymbolFileNativePDB(ObjectFileSP objfile_sp) 30581ad6265SDimitry Andric : SymbolFileCommon(std::move(objfile_sp)) {} 3060b57cec5SDimitry Andric 307fe6060f1SDimitry Andric SymbolFileNativePDB::~SymbolFileNativePDB() = default; 3080b57cec5SDimitry Andric 3090b57cec5SDimitry Andric uint32_t SymbolFileNativePDB::CalculateAbilities() { 3100b57cec5SDimitry Andric uint32_t abilities = 0; 3119dba64beSDimitry Andric if (!m_objfile_sp) 3120b57cec5SDimitry Andric return 0; 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric if (!m_index) { 3150b57cec5SDimitry Andric // Lazily load and match the PDB file, but only do this once. 316e8d8bef9SDimitry Andric PDBFile *pdb_file; 317e8d8bef9SDimitry Andric if (auto *pdb = llvm::dyn_cast<ObjectFilePDB>(m_objfile_sp.get())) { 318e8d8bef9SDimitry Andric pdb_file = &pdb->GetPDBFile(); 319e8d8bef9SDimitry Andric } else { 320e8d8bef9SDimitry Andric m_file_up = loadMatchingPDBFile(m_objfile_sp->GetFileSpec().GetPath(), 321e8d8bef9SDimitry Andric m_allocator); 322e8d8bef9SDimitry Andric pdb_file = m_file_up.get(); 3230b57cec5SDimitry Andric } 3240b57cec5SDimitry Andric 325e8d8bef9SDimitry Andric if (!pdb_file) 3260b57cec5SDimitry Andric return 0; 3270b57cec5SDimitry Andric 328e8d8bef9SDimitry Andric auto expected_index = PdbIndex::create(pdb_file); 3290b57cec5SDimitry Andric if (!expected_index) { 3300b57cec5SDimitry Andric llvm::consumeError(expected_index.takeError()); 3310b57cec5SDimitry Andric return 0; 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric m_index = std::move(*expected_index); 3340b57cec5SDimitry Andric } 3350b57cec5SDimitry Andric if (!m_index) 3360b57cec5SDimitry Andric return 0; 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric // We don't especially have to be precise here. We only distinguish between 3390b57cec5SDimitry Andric // stripped and not stripped. 3400b57cec5SDimitry Andric abilities = kAllAbilities; 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric if (m_index->dbi().isStripped()) 3430b57cec5SDimitry Andric abilities &= ~(Blocks | LocalVariables); 3440b57cec5SDimitry Andric return abilities; 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric void SymbolFileNativePDB::InitializeObject() { 348e8d8bef9SDimitry Andric m_obj_load_address = m_objfile_sp->GetModule() 349e8d8bef9SDimitry Andric ->GetObjectFile() 350e8d8bef9SDimitry Andric ->GetBaseAddress() 351e8d8bef9SDimitry Andric .GetFileAddress(); 3520b57cec5SDimitry Andric m_index->SetLoadAddress(m_obj_load_address); 3530b57cec5SDimitry Andric m_index->ParseSectionContribs(); 3540b57cec5SDimitry Andric 3559dba64beSDimitry Andric auto ts_or_err = m_objfile_sp->GetModule()->GetTypeSystemForLanguage( 3560b57cec5SDimitry Andric lldb::eLanguageTypeC_plus_plus); 3579dba64beSDimitry Andric if (auto err = ts_or_err.takeError()) { 35881ad6265SDimitry Andric LLDB_LOG_ERROR(GetLog(LLDBLog::Symbols), std::move(err), 35906c3fb27SDimitry Andric "Failed to initialize: {0}"); 3609dba64beSDimitry Andric } else { 361bdd1243dSDimitry Andric if (auto ts = *ts_or_err) 362bdd1243dSDimitry Andric ts->SetSymbolFile(this); 363bdd1243dSDimitry Andric BuildParentMap(); 3649dba64beSDimitry Andric } 3650b57cec5SDimitry Andric } 3660b57cec5SDimitry Andric 3679dba64beSDimitry Andric uint32_t SymbolFileNativePDB::CalculateNumCompileUnits() { 3680b57cec5SDimitry Andric const DbiModuleList &modules = m_index->dbi().modules(); 3690b57cec5SDimitry Andric uint32_t count = modules.getModuleCount(); 3700b57cec5SDimitry Andric if (count == 0) 3710b57cec5SDimitry Andric return count; 3720b57cec5SDimitry Andric 3730b57cec5SDimitry Andric // The linker can inject an additional "dummy" compilation unit into the 3740b57cec5SDimitry Andric // PDB. Ignore this special compile unit for our purposes, if it is there. 3750b57cec5SDimitry Andric // It is always the last one. 3760b57cec5SDimitry Andric DbiModuleDescriptor last = modules.getModuleDescriptor(count - 1); 3770b57cec5SDimitry Andric if (last.getModuleName() == "* Linker *") 3780b57cec5SDimitry Andric --count; 3790b57cec5SDimitry Andric return count; 3800b57cec5SDimitry Andric } 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric Block &SymbolFileNativePDB::CreateBlock(PdbCompilandSymId block_id) { 3830b57cec5SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi); 3840b57cec5SDimitry Andric CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset); 3850b57cec5SDimitry Andric CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); 38604eeddc0SDimitry Andric lldb::user_id_t opaque_block_uid = toOpaqueUid(block_id); 38704eeddc0SDimitry Andric BlockSP child_block = std::make_shared<Block>(opaque_block_uid); 388bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage()); 389bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 390bdd1243dSDimitry Andric return *child_block; 391bdd1243dSDimitry Andric auto ts = *ts_or_err; 392bdd1243dSDimitry Andric if (!ts) 393bdd1243dSDimitry Andric return *child_block; 394bdd1243dSDimitry Andric PdbAstBuilder* ast_builder = ts->GetNativePDBParser(); 39504eeddc0SDimitry Andric 39604eeddc0SDimitry Andric switch (sym.kind()) { 39704eeddc0SDimitry Andric case S_GPROC32: 39804eeddc0SDimitry Andric case S_LPROC32: { 39904eeddc0SDimitry Andric // This is a function. It must be global. Creating the Function entry 40004eeddc0SDimitry Andric // for it automatically creates a block for it. 40104eeddc0SDimitry Andric FunctionSP func = GetOrCreateFunction(block_id, *comp_unit); 402bdd1243dSDimitry Andric if (func) { 40304eeddc0SDimitry Andric Block &block = func->GetBlock(false); 40404eeddc0SDimitry Andric if (block.GetNumRanges() == 0) 40504eeddc0SDimitry Andric block.AddRange(Block::Range(0, func->GetAddressRange().GetByteSize())); 40604eeddc0SDimitry Andric return block; 4070b57cec5SDimitry Andric } 408bdd1243dSDimitry Andric break; 409bdd1243dSDimitry Andric } 41004eeddc0SDimitry Andric case S_BLOCK32: { 4110b57cec5SDimitry Andric // This is a block. Its parent is either a function or another block. In 41204eeddc0SDimitry Andric // either case, its parent can be viewed as a block (e.g. a function 41304eeddc0SDimitry Andric // contains 1 big block. So just get the parent block and add this block 41404eeddc0SDimitry Andric // to it. 4150b57cec5SDimitry Andric BlockSym block(static_cast<SymbolRecordKind>(sym.kind())); 4160b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<BlockSym>(sym, block)); 4170b57cec5SDimitry Andric lldbassert(block.Parent != 0); 4180b57cec5SDimitry Andric PdbCompilandSymId parent_id(block_id.modi, block.Parent); 4190b57cec5SDimitry Andric Block &parent_block = GetOrCreateBlock(parent_id); 420bdd1243dSDimitry Andric Function *func = parent_block.CalculateSymbolContextFunction(); 421bdd1243dSDimitry Andric lldbassert(func); 422bdd1243dSDimitry Andric lldb::addr_t block_base = 423bdd1243dSDimitry Andric m_index->MakeVirtualAddress(block.Segment, block.CodeOffset); 424bdd1243dSDimitry Andric lldb::addr_t func_base = 425bdd1243dSDimitry Andric func->GetAddressRange().GetBaseAddress().GetFileAddress(); 426bdd1243dSDimitry Andric if (block_base >= func_base) 427bdd1243dSDimitry Andric child_block->AddRange(Block::Range(block_base - func_base, block.CodeSize)); 428bdd1243dSDimitry Andric else { 429bdd1243dSDimitry Andric GetObjectFile()->GetModule()->ReportError( 430bdd1243dSDimitry Andric "S_BLOCK32 at modi: {0:d} offset: {1:d}: adding range " 431bdd1243dSDimitry Andric "[{2:x16}-{3:x16}) which has a base that is less than the " 432bdd1243dSDimitry Andric "function's " 433bdd1243dSDimitry Andric "low PC 0x%" PRIx64 ". Please file a bug and attach the file at the " 434bdd1243dSDimitry Andric "start of this error message", 435bdd1243dSDimitry Andric block_id.modi, block_id.offset, block_base, 436bdd1243dSDimitry Andric block_base + block.CodeSize, func_base); 437bdd1243dSDimitry Andric } 43804eeddc0SDimitry Andric parent_block.AddChild(child_block); 439bdd1243dSDimitry Andric ast_builder->GetOrCreateBlockDecl(block_id); 44004eeddc0SDimitry Andric m_blocks.insert({opaque_block_uid, child_block}); 44104eeddc0SDimitry Andric break; 44204eeddc0SDimitry Andric } 44304eeddc0SDimitry Andric case S_INLINESITE: { 44404eeddc0SDimitry Andric // This ensures line table is parsed first so we have inline sites info. 44504eeddc0SDimitry Andric comp_unit->GetLineTable(); 44604eeddc0SDimitry Andric 44704eeddc0SDimitry Andric std::shared_ptr<InlineSite> inline_site = m_inline_sites[opaque_block_uid]; 44804eeddc0SDimitry Andric Block &parent_block = GetOrCreateBlock(inline_site->parent_id); 4490b57cec5SDimitry Andric parent_block.AddChild(child_block); 450bdd1243dSDimitry Andric ast_builder->GetOrCreateInlinedFunctionDecl(block_id); 45104eeddc0SDimitry Andric // Copy ranges from InlineSite to Block. 45204eeddc0SDimitry Andric for (size_t i = 0; i < inline_site->ranges.GetSize(); ++i) { 45304eeddc0SDimitry Andric auto *entry = inline_site->ranges.GetEntryAtIndex(i); 45404eeddc0SDimitry Andric child_block->AddRange( 45504eeddc0SDimitry Andric Block::Range(entry->GetRangeBase(), entry->GetByteSize())); 45604eeddc0SDimitry Andric } 45704eeddc0SDimitry Andric child_block->FinalizeRanges(); 4580b57cec5SDimitry Andric 45904eeddc0SDimitry Andric // Get the inlined function callsite info. 46004eeddc0SDimitry Andric Declaration &decl = inline_site->inline_function_info->GetDeclaration(); 46104eeddc0SDimitry Andric Declaration &callsite = inline_site->inline_function_info->GetCallSite(); 46204eeddc0SDimitry Andric child_block->SetInlinedFunctionInfo( 46304eeddc0SDimitry Andric inline_site->inline_function_info->GetName().GetCString(), nullptr, 46404eeddc0SDimitry Andric &decl, &callsite); 4650b57cec5SDimitry Andric m_blocks.insert({opaque_block_uid, child_block}); 46604eeddc0SDimitry Andric break; 46704eeddc0SDimitry Andric } 46804eeddc0SDimitry Andric default: 46904eeddc0SDimitry Andric lldbassert(false && "Symbol is not a block!"); 47004eeddc0SDimitry Andric } 47104eeddc0SDimitry Andric 4720b57cec5SDimitry Andric return *child_block; 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id, 4760b57cec5SDimitry Andric CompileUnit &comp_unit) { 4770b57cec5SDimitry Andric const CompilandIndexItem *cci = 4780b57cec5SDimitry Andric m_index->compilands().GetCompiland(func_id.modi); 4790b57cec5SDimitry Andric lldbassert(cci); 4800b57cec5SDimitry Andric CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset); 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric lldbassert(sym_record.kind() == S_LPROC32 || sym_record.kind() == S_GPROC32); 4830b57cec5SDimitry Andric SegmentOffsetLength sol = GetSegmentOffsetAndLength(sym_record); 4840b57cec5SDimitry Andric 48581ad6265SDimitry Andric auto file_vm_addr = 48681ad6265SDimitry Andric m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset); 4870b57cec5SDimitry Andric if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0) 4880b57cec5SDimitry Andric return nullptr; 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric AddressRange func_range(file_vm_addr, sol.length, 4910b57cec5SDimitry Andric comp_unit.GetModule()->GetSectionList()); 4920b57cec5SDimitry Andric if (!func_range.GetBaseAddress().IsValid()) 4930b57cec5SDimitry Andric return nullptr; 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind())); 4960b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc)); 4970b57cec5SDimitry Andric if (proc.FunctionType == TypeIndex::None()) 4980b57cec5SDimitry Andric return nullptr; 4990b57cec5SDimitry Andric TypeSP func_type = GetOrCreateType(proc.FunctionType); 5000b57cec5SDimitry Andric if (!func_type) 5010b57cec5SDimitry Andric return nullptr; 5020b57cec5SDimitry Andric 5030b57cec5SDimitry Andric PdbTypeSymId sig_id(proc.FunctionType, false); 5040b57cec5SDimitry Andric Mangled mangled(proc.Name); 5050b57cec5SDimitry Andric FunctionSP func_sp = std::make_shared<Function>( 5060b57cec5SDimitry Andric &comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled, 5070b57cec5SDimitry Andric func_type.get(), func_range); 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric comp_unit.AddFunction(func_sp); 5100b57cec5SDimitry Andric 511bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(comp_unit.GetLanguage()); 512bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 513bdd1243dSDimitry Andric return func_sp; 514bdd1243dSDimitry Andric auto ts = *ts_or_err; 515bdd1243dSDimitry Andric if (!ts) 516bdd1243dSDimitry Andric return func_sp; 517bdd1243dSDimitry Andric ts->GetNativePDBParser()->GetOrCreateFunctionDecl(func_id); 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric return func_sp; 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric 5220b57cec5SDimitry Andric CompUnitSP 5230b57cec5SDimitry Andric SymbolFileNativePDB::CreateCompileUnit(const CompilandIndexItem &cci) { 5240b57cec5SDimitry Andric lldb::LanguageType lang = 5250b57cec5SDimitry Andric cci.m_compile_opts ? TranslateLanguage(cci.m_compile_opts->getLanguage()) 5260b57cec5SDimitry Andric : lldb::eLanguageTypeUnknown; 5270b57cec5SDimitry Andric 5280b57cec5SDimitry Andric LazyBool optimized = eLazyBoolNo; 5290b57cec5SDimitry Andric if (cci.m_compile_opts && cci.m_compile_opts->hasOptimizations()) 5300b57cec5SDimitry Andric optimized = eLazyBoolYes; 5310b57cec5SDimitry Andric 5320b57cec5SDimitry Andric llvm::SmallString<64> source_file_name = 5330b57cec5SDimitry Andric m_index->compilands().GetMainSourceFile(cci); 53481ad6265SDimitry Andric FileSpec fs(llvm::sys::path::convert_to_slash( 53581ad6265SDimitry Andric source_file_name, llvm::sys::path::Style::windows_backslash)); 5360b57cec5SDimitry Andric 5377a6dacacSDimitry Andric CompUnitSP cu_sp = std::make_shared<CompileUnit>( 5387a6dacacSDimitry Andric m_objfile_sp->GetModule(), nullptr, std::make_shared<SupportFile>(fs), 5390b57cec5SDimitry Andric toOpaqueUid(cci.m_id), lang, optimized); 5400b57cec5SDimitry Andric 5419dba64beSDimitry Andric SetCompileUnitAtIndex(cci.m_id.modi, cu_sp); 5420b57cec5SDimitry Andric return cu_sp; 5430b57cec5SDimitry Andric } 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateModifierType(PdbTypeSymId type_id, 5460b57cec5SDimitry Andric const ModifierRecord &mr, 5470b57cec5SDimitry Andric CompilerType ct) { 5480b57cec5SDimitry Andric TpiStream &stream = m_index->tpi(); 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric std::string name; 5510b57cec5SDimitry Andric if (mr.ModifiedType.isSimple()) 5525ffd83dbSDimitry Andric name = std::string(GetSimpleTypeName(mr.ModifiedType.getSimpleKind())); 5530b57cec5SDimitry Andric else 5540b57cec5SDimitry Andric name = computeTypeName(stream.typeCollection(), mr.ModifiedType); 5550b57cec5SDimitry Andric Declaration decl; 5560b57cec5SDimitry Andric lldb::TypeSP modified_type = GetOrCreateType(mr.ModifiedType); 5570b57cec5SDimitry Andric 558bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(name), 559e8d8bef9SDimitry Andric modified_type->GetByteSize(nullptr), nullptr, 560bdd1243dSDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, 561bdd1243dSDimitry Andric Type::ResolveState::Full); 5620b57cec5SDimitry Andric } 5630b57cec5SDimitry Andric 5640b57cec5SDimitry Andric lldb::TypeSP 5650b57cec5SDimitry Andric SymbolFileNativePDB::CreatePointerType(PdbTypeSymId type_id, 5660b57cec5SDimitry Andric const llvm::codeview::PointerRecord &pr, 5670b57cec5SDimitry Andric CompilerType ct) { 5680b57cec5SDimitry Andric TypeSP pointee = GetOrCreateType(pr.ReferentType); 5690b57cec5SDimitry Andric if (!pointee) 5700b57cec5SDimitry Andric return nullptr; 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric if (pr.isPointerToMember()) { 5730b57cec5SDimitry Andric MemberPointerInfo mpi = pr.getMemberInfo(); 5740b57cec5SDimitry Andric GetOrCreateType(mpi.ContainingType); 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric Declaration decl; 578bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(), pr.getSize(), nullptr, 579bdd1243dSDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, 580480093f4SDimitry Andric Type::ResolveState::Full); 5810b57cec5SDimitry Andric } 5820b57cec5SDimitry Andric 5830b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateSimpleType(TypeIndex ti, 5840b57cec5SDimitry Andric CompilerType ct) { 5850b57cec5SDimitry Andric uint64_t uid = toOpaqueUid(PdbTypeSymId(ti, false)); 5860b57cec5SDimitry Andric if (ti == TypeIndex::NullptrT()) { 5870b57cec5SDimitry Andric Declaration decl; 588bdd1243dSDimitry Andric return MakeType(uid, ConstString("std::nullptr_t"), 0, nullptr, 589bdd1243dSDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, 590bdd1243dSDimitry Andric Type::ResolveState::Full); 5910b57cec5SDimitry Andric } 5920b57cec5SDimitry Andric 5930b57cec5SDimitry Andric if (ti.getSimpleMode() != SimpleTypeMode::Direct) { 5940b57cec5SDimitry Andric TypeSP direct_sp = GetOrCreateType(ti.makeDirect()); 5950b57cec5SDimitry Andric uint32_t pointer_size = 0; 5960b57cec5SDimitry Andric switch (ti.getSimpleMode()) { 5970b57cec5SDimitry Andric case SimpleTypeMode::FarPointer32: 5980b57cec5SDimitry Andric case SimpleTypeMode::NearPointer32: 5990b57cec5SDimitry Andric pointer_size = 4; 6000b57cec5SDimitry Andric break; 6010b57cec5SDimitry Andric case SimpleTypeMode::NearPointer64: 6020b57cec5SDimitry Andric pointer_size = 8; 6030b57cec5SDimitry Andric break; 6040b57cec5SDimitry Andric default: 6050b57cec5SDimitry Andric // 128-bit and 16-bit pointers unsupported. 6060b57cec5SDimitry Andric return nullptr; 6070b57cec5SDimitry Andric } 6080b57cec5SDimitry Andric Declaration decl; 609bdd1243dSDimitry Andric return MakeType(uid, ConstString(), pointer_size, nullptr, LLDB_INVALID_UID, 610480093f4SDimitry Andric Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); 6110b57cec5SDimitry Andric } 6120b57cec5SDimitry Andric 6130b57cec5SDimitry Andric if (ti.getSimpleKind() == SimpleTypeKind::NotTranslated) 6140b57cec5SDimitry Andric return nullptr; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric size_t size = GetTypeSizeForSimpleKind(ti.getSimpleKind()); 6170b57cec5SDimitry Andric llvm::StringRef type_name = GetSimpleTypeName(ti.getSimpleKind()); 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric Declaration decl; 620bdd1243dSDimitry Andric return MakeType(uid, ConstString(type_name), size, nullptr, LLDB_INVALID_UID, 621bdd1243dSDimitry Andric Type::eEncodingIsUID, decl, ct, Type::ResolveState::Full); 6220b57cec5SDimitry Andric } 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric static std::string GetUnqualifiedTypeName(const TagRecord &record) { 6250b57cec5SDimitry Andric if (!record.hasUniqueName()) { 6260b57cec5SDimitry Andric MSVCUndecoratedNameParser parser(record.Name); 6270b57cec5SDimitry Andric llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers(); 6280b57cec5SDimitry Andric 6295ffd83dbSDimitry Andric return std::string(specs.back().GetBaseName()); 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric 6320b57cec5SDimitry Andric llvm::ms_demangle::Demangler demangler; 63306c3fb27SDimitry Andric std::string_view sv(record.UniqueName.begin(), record.UniqueName.size()); 6340b57cec5SDimitry Andric llvm::ms_demangle::TagTypeNode *ttn = demangler.parseTagUniqueName(sv); 6350b57cec5SDimitry Andric if (demangler.Error) 6365ffd83dbSDimitry Andric return std::string(record.Name); 6370b57cec5SDimitry Andric 6380b57cec5SDimitry Andric llvm::ms_demangle::IdentifierNode *idn = 6390b57cec5SDimitry Andric ttn->QualifiedName->getUnqualifiedIdentifier(); 6400b57cec5SDimitry Andric return idn->toString(); 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 6430b57cec5SDimitry Andric lldb::TypeSP 6440b57cec5SDimitry Andric SymbolFileNativePDB::CreateClassStructUnion(PdbTypeSymId type_id, 6450b57cec5SDimitry Andric const TagRecord &record, 6460b57cec5SDimitry Andric size_t size, CompilerType ct) { 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric std::string uname = GetUnqualifiedTypeName(record); 6490b57cec5SDimitry Andric 6500b57cec5SDimitry Andric // FIXME: Search IPI stream for LF_UDT_MOD_SRC_LINE. 6510b57cec5SDimitry Andric Declaration decl; 652bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(uname), size, nullptr, 653bdd1243dSDimitry Andric LLDB_INVALID_UID, Type::eEncodingIsUID, decl, ct, 654480093f4SDimitry Andric Type::ResolveState::Forward); 6550b57cec5SDimitry Andric } 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id, 6580b57cec5SDimitry Andric const ClassRecord &cr, 6590b57cec5SDimitry Andric CompilerType ct) { 6600b57cec5SDimitry Andric return CreateClassStructUnion(type_id, cr, cr.getSize(), ct); 6610b57cec5SDimitry Andric } 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id, 6640b57cec5SDimitry Andric const UnionRecord &ur, 6650b57cec5SDimitry Andric CompilerType ct) { 6660b57cec5SDimitry Andric return CreateClassStructUnion(type_id, ur, ur.getSize(), ct); 6670b57cec5SDimitry Andric } 6680b57cec5SDimitry Andric 6690b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::CreateTagType(PdbTypeSymId type_id, 6700b57cec5SDimitry Andric const EnumRecord &er, 6710b57cec5SDimitry Andric CompilerType ct) { 6720b57cec5SDimitry Andric std::string uname = GetUnqualifiedTypeName(er); 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric Declaration decl; 6750b57cec5SDimitry Andric TypeSP underlying_type = GetOrCreateType(er.UnderlyingType); 6760b57cec5SDimitry Andric 677bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(uname), 678bdd1243dSDimitry Andric underlying_type->GetByteSize(nullptr), nullptr, 679bdd1243dSDimitry Andric LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, 680bdd1243dSDimitry Andric ct, lldb_private::Type::ResolveState::Forward); 6810b57cec5SDimitry Andric } 6820b57cec5SDimitry Andric 6830b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateArrayType(PdbTypeSymId type_id, 6840b57cec5SDimitry Andric const ArrayRecord &ar, 6850b57cec5SDimitry Andric CompilerType ct) { 6860b57cec5SDimitry Andric TypeSP element_type = GetOrCreateType(ar.ElementType); 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric Declaration decl; 689bdd1243dSDimitry Andric TypeSP array_sp = 690bdd1243dSDimitry Andric MakeType(toOpaqueUid(type_id), ConstString(), ar.Size, nullptr, 6910b57cec5SDimitry Andric LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, ct, 692480093f4SDimitry Andric lldb_private::Type::ResolveState::Full); 6930b57cec5SDimitry Andric array_sp->SetEncodingType(element_type.get()); 6940b57cec5SDimitry Andric return array_sp; 6950b57cec5SDimitry Andric } 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateFunctionType(PdbTypeSymId type_id, 6980b57cec5SDimitry Andric const MemberFunctionRecord &mfr, 6990b57cec5SDimitry Andric CompilerType ct) { 7000b57cec5SDimitry Andric Declaration decl; 701bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr, 702bdd1243dSDimitry Andric LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, 703bdd1243dSDimitry Andric ct, lldb_private::Type::ResolveState::Full); 7040b57cec5SDimitry Andric } 7050b57cec5SDimitry Andric 7060b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateProcedureType(PdbTypeSymId type_id, 7070b57cec5SDimitry Andric const ProcedureRecord &pr, 7080b57cec5SDimitry Andric CompilerType ct) { 7090b57cec5SDimitry Andric Declaration decl; 710bdd1243dSDimitry Andric return MakeType(toOpaqueUid(type_id), ConstString(), 0, nullptr, 711bdd1243dSDimitry Andric LLDB_INVALID_UID, lldb_private::Type::eEncodingIsUID, decl, 712bdd1243dSDimitry Andric ct, lldb_private::Type::ResolveState::Full); 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateType(PdbTypeSymId type_id, CompilerType ct) { 7160b57cec5SDimitry Andric if (type_id.index.isSimple()) 7170b57cec5SDimitry Andric return CreateSimpleType(type_id.index, ct); 7180b57cec5SDimitry Andric 7190b57cec5SDimitry Andric TpiStream &stream = type_id.is_ipi ? m_index->ipi() : m_index->tpi(); 7200b57cec5SDimitry Andric CVType cvt = stream.getType(type_id.index); 7210b57cec5SDimitry Andric 7220b57cec5SDimitry Andric if (cvt.kind() == LF_MODIFIER) { 7230b57cec5SDimitry Andric ModifierRecord modifier; 7240b57cec5SDimitry Andric llvm::cantFail( 7250b57cec5SDimitry Andric TypeDeserializer::deserializeAs<ModifierRecord>(cvt, modifier)); 7260b57cec5SDimitry Andric return CreateModifierType(type_id, modifier, ct); 7270b57cec5SDimitry Andric } 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric if (cvt.kind() == LF_POINTER) { 7300b57cec5SDimitry Andric PointerRecord pointer; 7310b57cec5SDimitry Andric llvm::cantFail( 7320b57cec5SDimitry Andric TypeDeserializer::deserializeAs<PointerRecord>(cvt, pointer)); 7330b57cec5SDimitry Andric return CreatePointerType(type_id, pointer, ct); 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric if (IsClassRecord(cvt.kind())) { 7370b57cec5SDimitry Andric ClassRecord cr; 7380b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<ClassRecord>(cvt, cr)); 7390b57cec5SDimitry Andric return CreateTagType(type_id, cr, ct); 7400b57cec5SDimitry Andric } 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric if (cvt.kind() == LF_ENUM) { 7430b57cec5SDimitry Andric EnumRecord er; 7440b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<EnumRecord>(cvt, er)); 7450b57cec5SDimitry Andric return CreateTagType(type_id, er, ct); 7460b57cec5SDimitry Andric } 7470b57cec5SDimitry Andric 7480b57cec5SDimitry Andric if (cvt.kind() == LF_UNION) { 7490b57cec5SDimitry Andric UnionRecord ur; 7500b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<UnionRecord>(cvt, ur)); 7510b57cec5SDimitry Andric return CreateTagType(type_id, ur, ct); 7520b57cec5SDimitry Andric } 7530b57cec5SDimitry Andric 7540b57cec5SDimitry Andric if (cvt.kind() == LF_ARRAY) { 7550b57cec5SDimitry Andric ArrayRecord ar; 7560b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<ArrayRecord>(cvt, ar)); 7570b57cec5SDimitry Andric return CreateArrayType(type_id, ar, ct); 7580b57cec5SDimitry Andric } 7590b57cec5SDimitry Andric 7600b57cec5SDimitry Andric if (cvt.kind() == LF_PROCEDURE) { 7610b57cec5SDimitry Andric ProcedureRecord pr; 7620b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, pr)); 7630b57cec5SDimitry Andric return CreateProcedureType(type_id, pr, ct); 7640b57cec5SDimitry Andric } 7650b57cec5SDimitry Andric if (cvt.kind() == LF_MFUNCTION) { 7660b57cec5SDimitry Andric MemberFunctionRecord mfr; 7670b57cec5SDimitry Andric llvm::cantFail(TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfr)); 7680b57cec5SDimitry Andric return CreateFunctionType(type_id, mfr, ct); 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric return nullptr; 7720b57cec5SDimitry Andric } 7730b57cec5SDimitry Andric 7740b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateAndCacheType(PdbTypeSymId type_id) { 7750b57cec5SDimitry Andric // If they search for a UDT which is a forward ref, try and resolve the full 7760b57cec5SDimitry Andric // decl and just map the forward ref uid to the full decl record. 777bdd1243dSDimitry Andric std::optional<PdbTypeSymId> full_decl_uid; 7780b57cec5SDimitry Andric if (IsForwardRefUdt(type_id, m_index->tpi())) { 7790b57cec5SDimitry Andric auto expected_full_ti = 7800b57cec5SDimitry Andric m_index->tpi().findFullDeclForForwardRef(type_id.index); 7810b57cec5SDimitry Andric if (!expected_full_ti) 7820b57cec5SDimitry Andric llvm::consumeError(expected_full_ti.takeError()); 7830b57cec5SDimitry Andric else if (*expected_full_ti != type_id.index) { 7840b57cec5SDimitry Andric full_decl_uid = PdbTypeSymId(*expected_full_ti, false); 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric // It's possible that a lookup would occur for the full decl causing it 7870b57cec5SDimitry Andric // to be cached, then a second lookup would occur for the forward decl. 7880b57cec5SDimitry Andric // We don't want to create a second full decl, so make sure the full 7890b57cec5SDimitry Andric // decl hasn't already been cached. 7900b57cec5SDimitry Andric auto full_iter = m_types.find(toOpaqueUid(*full_decl_uid)); 7910b57cec5SDimitry Andric if (full_iter != m_types.end()) { 7920b57cec5SDimitry Andric TypeSP result = full_iter->second; 7930b57cec5SDimitry Andric // Map the forward decl to the TypeSP for the full decl so we can take 7940b57cec5SDimitry Andric // the fast path next time. 7950b57cec5SDimitry Andric m_types[toOpaqueUid(type_id)] = result; 7960b57cec5SDimitry Andric return result; 7970b57cec5SDimitry Andric } 7980b57cec5SDimitry Andric } 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric 8010b57cec5SDimitry Andric PdbTypeSymId best_decl_id = full_decl_uid ? *full_decl_uid : type_id; 802bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 803bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 804bdd1243dSDimitry Andric return nullptr; 805bdd1243dSDimitry Andric auto ts = *ts_or_err; 806bdd1243dSDimitry Andric if (!ts) 807bdd1243dSDimitry Andric return nullptr; 8080b57cec5SDimitry Andric 809bdd1243dSDimitry Andric PdbAstBuilder* ast_builder = ts->GetNativePDBParser(); 810bdd1243dSDimitry Andric clang::QualType qt = ast_builder->GetOrCreateType(best_decl_id); 81181ad6265SDimitry Andric if (qt.isNull()) 81281ad6265SDimitry Andric return nullptr; 8130b57cec5SDimitry Andric 814bdd1243dSDimitry Andric TypeSP result = CreateType(best_decl_id, ast_builder->ToCompilerType(qt)); 8150b57cec5SDimitry Andric if (!result) 8160b57cec5SDimitry Andric return nullptr; 8170b57cec5SDimitry Andric 8180b57cec5SDimitry Andric uint64_t best_uid = toOpaqueUid(best_decl_id); 8190b57cec5SDimitry Andric m_types[best_uid] = result; 8200b57cec5SDimitry Andric // If we had both a forward decl and a full decl, make both point to the new 8210b57cec5SDimitry Andric // type. 8220b57cec5SDimitry Andric if (full_decl_uid) 8230b57cec5SDimitry Andric m_types[toOpaqueUid(type_id)] = result; 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric return result; 8260b57cec5SDimitry Andric } 8270b57cec5SDimitry Andric 8280b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::GetOrCreateType(PdbTypeSymId type_id) { 8290b57cec5SDimitry Andric // We can't use try_emplace / overwrite here because the process of creating 8300b57cec5SDimitry Andric // a type could create nested types, which could invalidate iterators. So 8310b57cec5SDimitry Andric // we have to do a 2-phase lookup / insert. 8320b57cec5SDimitry Andric auto iter = m_types.find(toOpaqueUid(type_id)); 8330b57cec5SDimitry Andric if (iter != m_types.end()) 8340b57cec5SDimitry Andric return iter->second; 8350b57cec5SDimitry Andric 8360b57cec5SDimitry Andric TypeSP type = CreateAndCacheType(type_id); 8370b57cec5SDimitry Andric if (type) 8389dba64beSDimitry Andric GetTypeList().Insert(type); 8390b57cec5SDimitry Andric return type; 8400b57cec5SDimitry Andric } 8410b57cec5SDimitry Andric 8420b57cec5SDimitry Andric VariableSP SymbolFileNativePDB::CreateGlobalVariable(PdbGlobalSymId var_id) { 8430b57cec5SDimitry Andric CVSymbol sym = m_index->symrecords().readRecord(var_id.offset); 8440b57cec5SDimitry Andric if (sym.kind() == S_CONSTANT) 8450b57cec5SDimitry Andric return CreateConstantSymbol(var_id, sym); 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric lldb::ValueType scope = eValueTypeInvalid; 8480b57cec5SDimitry Andric TypeIndex ti; 8490b57cec5SDimitry Andric llvm::StringRef name; 8500b57cec5SDimitry Andric lldb::addr_t addr = 0; 8510b57cec5SDimitry Andric uint16_t section = 0; 8520b57cec5SDimitry Andric uint32_t offset = 0; 8530b57cec5SDimitry Andric bool is_external = false; 8540b57cec5SDimitry Andric switch (sym.kind()) { 8550b57cec5SDimitry Andric case S_GDATA32: 8560b57cec5SDimitry Andric is_external = true; 857bdd1243dSDimitry Andric [[fallthrough]]; 8580b57cec5SDimitry Andric case S_LDATA32: { 8590b57cec5SDimitry Andric DataSym ds(sym.kind()); 8600b57cec5SDimitry Andric llvm::cantFail(SymbolDeserializer::deserializeAs<DataSym>(sym, ds)); 8610b57cec5SDimitry Andric ti = ds.Type; 8620b57cec5SDimitry Andric scope = (sym.kind() == S_GDATA32) ? eValueTypeVariableGlobal 8630b57cec5SDimitry Andric : eValueTypeVariableStatic; 8640b57cec5SDimitry Andric name = ds.Name; 8650b57cec5SDimitry Andric section = ds.Segment; 8660b57cec5SDimitry Andric offset = ds.DataOffset; 8670b57cec5SDimitry Andric addr = m_index->MakeVirtualAddress(ds.Segment, ds.DataOffset); 8680b57cec5SDimitry Andric break; 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric case S_GTHREAD32: 8710b57cec5SDimitry Andric is_external = true; 872bdd1243dSDimitry Andric [[fallthrough]]; 8730b57cec5SDimitry Andric case S_LTHREAD32: { 8740b57cec5SDimitry Andric ThreadLocalDataSym tlds(sym.kind()); 8750b57cec5SDimitry Andric llvm::cantFail( 8760b57cec5SDimitry Andric SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym, tlds)); 8770b57cec5SDimitry Andric ti = tlds.Type; 8780b57cec5SDimitry Andric name = tlds.Name; 8790b57cec5SDimitry Andric section = tlds.Segment; 8800b57cec5SDimitry Andric offset = tlds.DataOffset; 8810b57cec5SDimitry Andric addr = m_index->MakeVirtualAddress(tlds.Segment, tlds.DataOffset); 8820b57cec5SDimitry Andric scope = eValueTypeVariableThreadLocal; 8830b57cec5SDimitry Andric break; 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric default: 8860b57cec5SDimitry Andric llvm_unreachable("unreachable!"); 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric CompUnitSP comp_unit; 890bdd1243dSDimitry Andric std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(addr); 89181ad6265SDimitry Andric if (!modi) { 89281ad6265SDimitry Andric return nullptr; 89381ad6265SDimitry Andric } 89481ad6265SDimitry Andric 8950b57cec5SDimitry Andric CompilandIndexItem &cci = m_index->compilands().GetOrCreateCompiland(*modi); 8960b57cec5SDimitry Andric comp_unit = GetOrCreateCompileUnit(cci); 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric Declaration decl; 8990b57cec5SDimitry Andric PdbTypeSymId tid(ti, false); 9000b57cec5SDimitry Andric SymbolFileTypeSP type_sp = 9010b57cec5SDimitry Andric std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid)); 9020b57cec5SDimitry Andric Variable::RangeList ranges; 903bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(comp_unit->GetLanguage()); 904bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 905bdd1243dSDimitry Andric return nullptr; 906bdd1243dSDimitry Andric auto ts = *ts_or_err; 907bdd1243dSDimitry Andric if (!ts) 908bdd1243dSDimitry Andric return nullptr; 9090b57cec5SDimitry Andric 910bdd1243dSDimitry Andric ts->GetNativePDBParser()->GetOrCreateVariableDecl(var_id); 9110b57cec5SDimitry Andric 912753f127fSDimitry Andric ModuleSP module_sp = GetObjectFile()->GetModule(); 913753f127fSDimitry Andric DWARFExpressionList location( 914753f127fSDimitry Andric module_sp, MakeGlobalLocationExpression(section, offset, module_sp), 915753f127fSDimitry Andric nullptr); 9160b57cec5SDimitry Andric 9170b57cec5SDimitry Andric std::string global_name("::"); 9180b57cec5SDimitry Andric global_name += name; 919e8d8bef9SDimitry Andric bool artificial = false; 920e8d8bef9SDimitry Andric bool location_is_constant_data = false; 921e8d8bef9SDimitry Andric bool static_member = false; 9220b57cec5SDimitry Andric VariableSP var_sp = std::make_shared<Variable>( 9230b57cec5SDimitry Andric toOpaqueUid(var_id), name.str().c_str(), global_name.c_str(), type_sp, 924e8d8bef9SDimitry Andric scope, comp_unit.get(), ranges, &decl, location, is_external, artificial, 925e8d8bef9SDimitry Andric location_is_constant_data, static_member); 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric return var_sp; 9280b57cec5SDimitry Andric } 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric lldb::VariableSP 9310b57cec5SDimitry Andric SymbolFileNativePDB::CreateConstantSymbol(PdbGlobalSymId var_id, 9320b57cec5SDimitry Andric const CVSymbol &cvs) { 9330b57cec5SDimitry Andric TpiStream &tpi = m_index->tpi(); 9340b57cec5SDimitry Andric ConstantSym constant(cvs.kind()); 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(cvs, constant)); 9370b57cec5SDimitry Andric std::string global_name("::"); 9380b57cec5SDimitry Andric global_name += constant.Name; 9390b57cec5SDimitry Andric PdbTypeSymId tid(constant.Type, false); 9400b57cec5SDimitry Andric SymbolFileTypeSP type_sp = 9410b57cec5SDimitry Andric std::make_shared<SymbolFileType>(*this, toOpaqueUid(tid)); 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric Declaration decl; 9440b57cec5SDimitry Andric Variable::RangeList ranges; 9450b57cec5SDimitry Andric ModuleSP module = GetObjectFile()->GetModule(); 946753f127fSDimitry Andric DWARFExpressionList location(module, 947753f127fSDimitry Andric MakeConstantLocationExpression( 948753f127fSDimitry Andric constant.Type, tpi, constant.Value, module), 949753f127fSDimitry Andric nullptr); 9500b57cec5SDimitry Andric 951e8d8bef9SDimitry Andric bool external = false; 952e8d8bef9SDimitry Andric bool artificial = false; 953e8d8bef9SDimitry Andric bool location_is_constant_data = true; 954e8d8bef9SDimitry Andric bool static_member = false; 9550b57cec5SDimitry Andric VariableSP var_sp = std::make_shared<Variable>( 9560b57cec5SDimitry Andric toOpaqueUid(var_id), constant.Name.str().c_str(), global_name.c_str(), 9570b57cec5SDimitry Andric type_sp, eValueTypeVariableGlobal, module.get(), ranges, &decl, location, 958e8d8bef9SDimitry Andric external, artificial, location_is_constant_data, static_member); 9590b57cec5SDimitry Andric return var_sp; 9600b57cec5SDimitry Andric } 9610b57cec5SDimitry Andric 9620b57cec5SDimitry Andric VariableSP 9630b57cec5SDimitry Andric SymbolFileNativePDB::GetOrCreateGlobalVariable(PdbGlobalSymId var_id) { 9640b57cec5SDimitry Andric auto emplace_result = m_global_vars.try_emplace(toOpaqueUid(var_id), nullptr); 96581ad6265SDimitry Andric if (emplace_result.second) { 96681ad6265SDimitry Andric if (VariableSP var_sp = CreateGlobalVariable(var_id)) 96781ad6265SDimitry Andric emplace_result.first->second = var_sp; 96881ad6265SDimitry Andric else 96981ad6265SDimitry Andric return nullptr; 97081ad6265SDimitry Andric } 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric return emplace_result.first->second; 9730b57cec5SDimitry Andric } 9740b57cec5SDimitry Andric 9750b57cec5SDimitry Andric lldb::TypeSP SymbolFileNativePDB::GetOrCreateType(TypeIndex ti) { 9760b57cec5SDimitry Andric return GetOrCreateType(PdbTypeSymId(ti, false)); 9770b57cec5SDimitry Andric } 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric FunctionSP SymbolFileNativePDB::GetOrCreateFunction(PdbCompilandSymId func_id, 9800b57cec5SDimitry Andric CompileUnit &comp_unit) { 9810b57cec5SDimitry Andric auto emplace_result = m_functions.try_emplace(toOpaqueUid(func_id), nullptr); 9820b57cec5SDimitry Andric if (emplace_result.second) 9830b57cec5SDimitry Andric emplace_result.first->second = CreateFunction(func_id, comp_unit); 9840b57cec5SDimitry Andric 9850b57cec5SDimitry Andric return emplace_result.first->second; 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric CompUnitSP 9890b57cec5SDimitry Andric SymbolFileNativePDB::GetOrCreateCompileUnit(const CompilandIndexItem &cci) { 9900b57cec5SDimitry Andric 9910b57cec5SDimitry Andric auto emplace_result = 9920b57cec5SDimitry Andric m_compilands.try_emplace(toOpaqueUid(cci.m_id), nullptr); 9930b57cec5SDimitry Andric if (emplace_result.second) 9940b57cec5SDimitry Andric emplace_result.first->second = CreateCompileUnit(cci); 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric lldbassert(emplace_result.first->second); 9970b57cec5SDimitry Andric return emplace_result.first->second; 9980b57cec5SDimitry Andric } 9990b57cec5SDimitry Andric 10000b57cec5SDimitry Andric Block &SymbolFileNativePDB::GetOrCreateBlock(PdbCompilandSymId block_id) { 10010b57cec5SDimitry Andric auto iter = m_blocks.find(toOpaqueUid(block_id)); 10020b57cec5SDimitry Andric if (iter != m_blocks.end()) 10030b57cec5SDimitry Andric return *iter->second; 10040b57cec5SDimitry Andric 10050b57cec5SDimitry Andric return CreateBlock(block_id); 10060b57cec5SDimitry Andric } 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric void SymbolFileNativePDB::ParseDeclsForContext( 10090b57cec5SDimitry Andric lldb_private::CompilerDeclContext decl_ctx) { 1010bdd1243dSDimitry Andric TypeSystem* ts_or_err = decl_ctx.GetTypeSystem(); 1011bdd1243dSDimitry Andric if (!ts_or_err) 1012bdd1243dSDimitry Andric return; 1013bdd1243dSDimitry Andric PdbAstBuilder* ast_builder = ts_or_err->GetNativePDBParser(); 1014bdd1243dSDimitry Andric clang::DeclContext *context = ast_builder->FromCompilerDeclContext(decl_ctx); 10150b57cec5SDimitry Andric if (!context) 10160b57cec5SDimitry Andric return; 1017bdd1243dSDimitry Andric ast_builder->ParseDeclsForContext(*context); 10180b57cec5SDimitry Andric } 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric lldb::CompUnitSP SymbolFileNativePDB::ParseCompileUnitAtIndex(uint32_t index) { 10210b57cec5SDimitry Andric if (index >= GetNumCompileUnits()) 10220b57cec5SDimitry Andric return CompUnitSP(); 10230b57cec5SDimitry Andric lldbassert(index < UINT16_MAX); 10240b57cec5SDimitry Andric if (index >= UINT16_MAX) 10250b57cec5SDimitry Andric return nullptr; 10260b57cec5SDimitry Andric 10270b57cec5SDimitry Andric CompilandIndexItem &item = m_index->compilands().GetOrCreateCompiland(index); 10280b57cec5SDimitry Andric 10290b57cec5SDimitry Andric return GetOrCreateCompileUnit(item); 10300b57cec5SDimitry Andric } 10310b57cec5SDimitry Andric 10320b57cec5SDimitry Andric lldb::LanguageType SymbolFileNativePDB::ParseLanguage(CompileUnit &comp_unit) { 10339dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 10340b57cec5SDimitry Andric PdbSymUid uid(comp_unit.GetID()); 10350b57cec5SDimitry Andric lldbassert(uid.kind() == PdbSymUidKind::Compiland); 10360b57cec5SDimitry Andric 10370b57cec5SDimitry Andric CompilandIndexItem *item = 10380b57cec5SDimitry Andric m_index->compilands().GetCompiland(uid.asCompiland().modi); 10390b57cec5SDimitry Andric lldbassert(item); 10400b57cec5SDimitry Andric if (!item->m_compile_opts) 10410b57cec5SDimitry Andric return lldb::eLanguageTypeUnknown; 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andric return TranslateLanguage(item->m_compile_opts->getLanguage()); 10440b57cec5SDimitry Andric } 10450b57cec5SDimitry Andric 10460eae32dcSDimitry Andric void SymbolFileNativePDB::AddSymbols(Symtab &symtab) {} 10470b57cec5SDimitry Andric 10480b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseFunctions(CompileUnit &comp_unit) { 10499dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 10500b57cec5SDimitry Andric PdbSymUid uid{comp_unit.GetID()}; 10510b57cec5SDimitry Andric lldbassert(uid.kind() == PdbSymUidKind::Compiland); 10520b57cec5SDimitry Andric uint16_t modi = uid.asCompiland().modi; 10530b57cec5SDimitry Andric CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(modi); 10540b57cec5SDimitry Andric 10550b57cec5SDimitry Andric size_t count = comp_unit.GetNumFunctions(); 10560b57cec5SDimitry Andric const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray(); 10570b57cec5SDimitry Andric for (auto iter = syms.begin(); iter != syms.end(); ++iter) { 10580b57cec5SDimitry Andric if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) 10590b57cec5SDimitry Andric continue; 10600b57cec5SDimitry Andric 10610b57cec5SDimitry Andric PdbCompilandSymId sym_id{modi, iter.offset()}; 10620b57cec5SDimitry Andric 10630b57cec5SDimitry Andric FunctionSP func = GetOrCreateFunction(sym_id, comp_unit); 10640b57cec5SDimitry Andric } 10650b57cec5SDimitry Andric 10660b57cec5SDimitry Andric size_t new_count = comp_unit.GetNumFunctions(); 10670b57cec5SDimitry Andric lldbassert(new_count >= count); 10680b57cec5SDimitry Andric return new_count - count; 10690b57cec5SDimitry Andric } 10700b57cec5SDimitry Andric 10710b57cec5SDimitry Andric static bool NeedsResolvedCompileUnit(uint32_t resolve_scope) { 10720b57cec5SDimitry Andric // If any of these flags are set, we need to resolve the compile unit. 10730b57cec5SDimitry Andric uint32_t flags = eSymbolContextCompUnit; 10740b57cec5SDimitry Andric flags |= eSymbolContextVariable; 10750b57cec5SDimitry Andric flags |= eSymbolContextFunction; 10760b57cec5SDimitry Andric flags |= eSymbolContextBlock; 10770b57cec5SDimitry Andric flags |= eSymbolContextLineEntry; 10780b57cec5SDimitry Andric return (resolve_scope & flags) != 0; 10790b57cec5SDimitry Andric } 10800b57cec5SDimitry Andric 10810b57cec5SDimitry Andric uint32_t SymbolFileNativePDB::ResolveSymbolContext( 10820b57cec5SDimitry Andric const Address &addr, SymbolContextItem resolve_scope, SymbolContext &sc) { 10839dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 10840b57cec5SDimitry Andric uint32_t resolved_flags = 0; 10850b57cec5SDimitry Andric lldb::addr_t file_addr = addr.GetFileAddress(); 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andric if (NeedsResolvedCompileUnit(resolve_scope)) { 1088bdd1243dSDimitry Andric std::optional<uint16_t> modi = m_index->GetModuleIndexForVa(file_addr); 10890b57cec5SDimitry Andric if (!modi) 10900b57cec5SDimitry Andric return 0; 109181ad6265SDimitry Andric CompUnitSP cu_sp = GetCompileUnitAtIndex(*modi); 1092349cc55cSDimitry Andric if (!cu_sp) 10930b57cec5SDimitry Andric return 0; 10940b57cec5SDimitry Andric 1095349cc55cSDimitry Andric sc.comp_unit = cu_sp.get(); 10960b57cec5SDimitry Andric resolved_flags |= eSymbolContextCompUnit; 10970b57cec5SDimitry Andric } 10980b57cec5SDimitry Andric 10990b57cec5SDimitry Andric if (resolve_scope & eSymbolContextFunction || 11000b57cec5SDimitry Andric resolve_scope & eSymbolContextBlock) { 11010b57cec5SDimitry Andric lldbassert(sc.comp_unit); 11020b57cec5SDimitry Andric std::vector<SymbolAndUid> matches = m_index->FindSymbolsByVa(file_addr); 11030b57cec5SDimitry Andric // Search the matches in reverse. This way if there are multiple matches 11040b57cec5SDimitry Andric // (for example we are 3 levels deep in a nested scope) it will find the 11050b57cec5SDimitry Andric // innermost one first. 11060b57cec5SDimitry Andric for (const auto &match : llvm::reverse(matches)) { 11070b57cec5SDimitry Andric if (match.uid.kind() != PdbSymUidKind::CompilandSym) 11080b57cec5SDimitry Andric continue; 11090b57cec5SDimitry Andric 11100b57cec5SDimitry Andric PdbCompilandSymId csid = match.uid.asCompilandSym(); 11110b57cec5SDimitry Andric CVSymbol cvs = m_index->ReadSymbolRecord(csid); 11120b57cec5SDimitry Andric PDB_SymType type = CVSymToPDBSym(cvs.kind()); 11130b57cec5SDimitry Andric if (type != PDB_SymType::Function && type != PDB_SymType::Block) 11140b57cec5SDimitry Andric continue; 11150b57cec5SDimitry Andric if (type == PDB_SymType::Function) { 11160b57cec5SDimitry Andric sc.function = GetOrCreateFunction(csid, *sc.comp_unit).get(); 1117bdd1243dSDimitry Andric if (sc.function) { 111804eeddc0SDimitry Andric Block &block = sc.function->GetBlock(true); 111904eeddc0SDimitry Andric addr_t func_base = 112004eeddc0SDimitry Andric sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 112104eeddc0SDimitry Andric addr_t offset = file_addr - func_base; 112204eeddc0SDimitry Andric sc.block = block.FindInnermostBlockByOffset(offset); 11230b57cec5SDimitry Andric } 1124bdd1243dSDimitry Andric } 11250b57cec5SDimitry Andric 11260b57cec5SDimitry Andric if (type == PDB_SymType::Block) { 1127bdd1243dSDimitry Andric Block &block = GetOrCreateBlock(csid); 1128bdd1243dSDimitry Andric sc.function = block.CalculateSymbolContextFunction(); 1129bdd1243dSDimitry Andric if (sc.function) { 1130bdd1243dSDimitry Andric sc.function->GetBlock(true); 1131bdd1243dSDimitry Andric addr_t func_base = 1132bdd1243dSDimitry Andric sc.function->GetAddressRange().GetBaseAddress().GetFileAddress(); 1133bdd1243dSDimitry Andric addr_t offset = file_addr - func_base; 1134bdd1243dSDimitry Andric sc.block = block.FindInnermostBlockByOffset(offset); 1135bdd1243dSDimitry Andric } 11360b57cec5SDimitry Andric } 113704eeddc0SDimitry Andric if (sc.function) 11380b57cec5SDimitry Andric resolved_flags |= eSymbolContextFunction; 113904eeddc0SDimitry Andric if (sc.block) 11400b57cec5SDimitry Andric resolved_flags |= eSymbolContextBlock; 11410b57cec5SDimitry Andric break; 11420b57cec5SDimitry Andric } 11430b57cec5SDimitry Andric } 11440b57cec5SDimitry Andric 11450b57cec5SDimitry Andric if (resolve_scope & eSymbolContextLineEntry) { 11460b57cec5SDimitry Andric lldbassert(sc.comp_unit); 11470b57cec5SDimitry Andric if (auto *line_table = sc.comp_unit->GetLineTable()) { 11480b57cec5SDimitry Andric if (line_table->FindLineEntryByAddress(addr, sc.line_entry)) 11490b57cec5SDimitry Andric resolved_flags |= eSymbolContextLineEntry; 11500b57cec5SDimitry Andric } 11510b57cec5SDimitry Andric } 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric return resolved_flags; 11540b57cec5SDimitry Andric } 11550b57cec5SDimitry Andric 11560b57cec5SDimitry Andric uint32_t SymbolFileNativePDB::ResolveSymbolContext( 1157fe6060f1SDimitry Andric const SourceLocationSpec &src_location_spec, 11580b57cec5SDimitry Andric lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) { 115904eeddc0SDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 116004eeddc0SDimitry Andric const uint32_t prev_size = sc_list.GetSize(); 116104eeddc0SDimitry Andric if (resolve_scope & eSymbolContextCompUnit) { 116204eeddc0SDimitry Andric for (uint32_t cu_idx = 0, num_cus = GetNumCompileUnits(); cu_idx < num_cus; 116304eeddc0SDimitry Andric ++cu_idx) { 116404eeddc0SDimitry Andric CompileUnit *cu = ParseCompileUnitAtIndex(cu_idx).get(); 116504eeddc0SDimitry Andric if (!cu) 116604eeddc0SDimitry Andric continue; 116704eeddc0SDimitry Andric 116804eeddc0SDimitry Andric bool file_spec_matches_cu_file_spec = FileSpec::Match( 116904eeddc0SDimitry Andric src_location_spec.GetFileSpec(), cu->GetPrimaryFile()); 117004eeddc0SDimitry Andric if (file_spec_matches_cu_file_spec) { 117104eeddc0SDimitry Andric cu->ResolveSymbolContext(src_location_spec, resolve_scope, sc_list); 117204eeddc0SDimitry Andric break; 11730b57cec5SDimitry Andric } 11740b57cec5SDimitry Andric } 117504eeddc0SDimitry Andric } 117604eeddc0SDimitry Andric return sc_list.GetSize() - prev_size; 11770b57cec5SDimitry Andric } 11780b57cec5SDimitry Andric 11790b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseLineTable(CompileUnit &comp_unit) { 11800b57cec5SDimitry Andric // Unfortunately LLDB is set up to parse the entire compile unit line table 11810b57cec5SDimitry Andric // all at once, even if all it really needs is line info for a specific 11820b57cec5SDimitry Andric // function. In the future it would be nice if it could set the sc.m_function 11830b57cec5SDimitry Andric // member, and we could only get the line info for the function in question. 11849dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 11850b57cec5SDimitry Andric PdbSymUid cu_id(comp_unit.GetID()); 11860b57cec5SDimitry Andric lldbassert(cu_id.kind() == PdbSymUidKind::Compiland); 118704eeddc0SDimitry Andric uint16_t modi = cu_id.asCompiland().modi; 118804eeddc0SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(modi); 118904eeddc0SDimitry Andric lldbassert(cii); 119004eeddc0SDimitry Andric 119104eeddc0SDimitry Andric // Parse DEBUG_S_LINES subsections first, then parse all S_INLINESITE records 119204eeddc0SDimitry Andric // in this CU. Add line entries into the set first so that if there are line 119304eeddc0SDimitry Andric // entries with same addres, the later is always more accurate than the 119404eeddc0SDimitry Andric // former. 119504eeddc0SDimitry Andric std::set<LineTable::Entry, LineTableEntryComparator> line_set; 11960b57cec5SDimitry Andric 11970b57cec5SDimitry Andric // This is basically a copy of the .debug$S subsections from all original COFF 11980b57cec5SDimitry Andric // object files merged together with address relocations applied. We are 11990b57cec5SDimitry Andric // looking for all DEBUG_S_LINES subsections. 12000b57cec5SDimitry Andric for (const DebugSubsectionRecord &dssr : 120104eeddc0SDimitry Andric cii->m_debug_stream.getSubsectionsArray()) { 12020b57cec5SDimitry Andric if (dssr.kind() != DebugSubsectionKind::Lines) 12030b57cec5SDimitry Andric continue; 12040b57cec5SDimitry Andric 12050b57cec5SDimitry Andric DebugLinesSubsectionRef lines; 12060b57cec5SDimitry Andric llvm::BinaryStreamReader reader(dssr.getRecordData()); 12070b57cec5SDimitry Andric if (auto EC = lines.initialize(reader)) { 12080b57cec5SDimitry Andric llvm::consumeError(std::move(EC)); 12090b57cec5SDimitry Andric return false; 12100b57cec5SDimitry Andric } 12110b57cec5SDimitry Andric 12120b57cec5SDimitry Andric const LineFragmentHeader *lfh = lines.header(); 12130b57cec5SDimitry Andric uint64_t virtual_addr = 12140b57cec5SDimitry Andric m_index->MakeVirtualAddress(lfh->RelocSegment, lfh->RelocOffset); 121581ad6265SDimitry Andric if (virtual_addr == LLDB_INVALID_ADDRESS) 121681ad6265SDimitry Andric continue; 12170b57cec5SDimitry Andric 12180b57cec5SDimitry Andric for (const LineColumnEntry &group : lines) { 121904eeddc0SDimitry Andric llvm::Expected<uint32_t> file_index_or_err = 122004eeddc0SDimitry Andric GetFileIndex(*cii, group.NameIndex); 122104eeddc0SDimitry Andric if (!file_index_or_err) 12220b57cec5SDimitry Andric continue; 122304eeddc0SDimitry Andric uint32_t file_index = file_index_or_err.get(); 12240b57cec5SDimitry Andric lldbassert(!group.LineNumbers.empty()); 122504eeddc0SDimitry Andric CompilandIndexItem::GlobalLineTable::Entry line_entry( 122604eeddc0SDimitry Andric LLDB_INVALID_ADDRESS, 0); 12270b57cec5SDimitry Andric for (const LineNumberEntry &entry : group.LineNumbers) { 122804eeddc0SDimitry Andric LineInfo cur_info(entry.Flags); 122904eeddc0SDimitry Andric 123004eeddc0SDimitry Andric if (cur_info.isAlwaysStepInto() || cur_info.isNeverStepInto()) 123104eeddc0SDimitry Andric continue; 123204eeddc0SDimitry Andric 123304eeddc0SDimitry Andric uint64_t addr = virtual_addr + entry.Offset; 123404eeddc0SDimitry Andric 123504eeddc0SDimitry Andric bool is_statement = cur_info.isStatement(); 123604eeddc0SDimitry Andric bool is_prologue = IsFunctionPrologue(*cii, addr); 123704eeddc0SDimitry Andric bool is_epilogue = IsFunctionEpilogue(*cii, addr); 123804eeddc0SDimitry Andric 123904eeddc0SDimitry Andric uint32_t lno = cur_info.getStartLine(); 124004eeddc0SDimitry Andric 124181ad6265SDimitry Andric LineTable::Entry new_entry(addr, lno, 0, file_index, is_statement, false, 124204eeddc0SDimitry Andric is_prologue, is_epilogue, false); 124381ad6265SDimitry Andric // Terminal entry has lower precedence than new entry. 124481ad6265SDimitry Andric auto iter = line_set.find(new_entry); 124581ad6265SDimitry Andric if (iter != line_set.end() && iter->is_terminal_entry) 124681ad6265SDimitry Andric line_set.erase(iter); 124781ad6265SDimitry Andric line_set.insert(new_entry); 124804eeddc0SDimitry Andric 124904eeddc0SDimitry Andric if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) { 125004eeddc0SDimitry Andric line_entry.SetRangeEnd(addr); 125104eeddc0SDimitry Andric cii->m_global_line_table.Append(line_entry); 125204eeddc0SDimitry Andric } 125304eeddc0SDimitry Andric line_entry.SetRangeBase(addr); 125404eeddc0SDimitry Andric line_entry.data = {file_index, lno}; 12550b57cec5SDimitry Andric } 12560b57cec5SDimitry Andric LineInfo last_line(group.LineNumbers.back().Flags); 125704eeddc0SDimitry Andric line_set.emplace(virtual_addr + lfh->CodeSize, last_line.getEndLine(), 0, 125804eeddc0SDimitry Andric file_index, false, false, false, false, true); 125904eeddc0SDimitry Andric 126004eeddc0SDimitry Andric if (line_entry.GetRangeBase() != LLDB_INVALID_ADDRESS) { 126104eeddc0SDimitry Andric line_entry.SetRangeEnd(virtual_addr + lfh->CodeSize); 126204eeddc0SDimitry Andric cii->m_global_line_table.Append(line_entry); 12630b57cec5SDimitry Andric } 12640b57cec5SDimitry Andric } 126504eeddc0SDimitry Andric } 126604eeddc0SDimitry Andric 126704eeddc0SDimitry Andric cii->m_global_line_table.Sort(); 126804eeddc0SDimitry Andric 126904eeddc0SDimitry Andric // Parse all S_INLINESITE in this CU. 127004eeddc0SDimitry Andric const CVSymbolArray &syms = cii->m_debug_stream.getSymbolArray(); 127104eeddc0SDimitry Andric for (auto iter = syms.begin(); iter != syms.end();) { 127204eeddc0SDimitry Andric if (iter->kind() != S_LPROC32 && iter->kind() != S_GPROC32) { 127304eeddc0SDimitry Andric ++iter; 127404eeddc0SDimitry Andric continue; 127504eeddc0SDimitry Andric } 127604eeddc0SDimitry Andric 127704eeddc0SDimitry Andric uint32_t record_offset = iter.offset(); 127804eeddc0SDimitry Andric CVSymbol func_record = 127904eeddc0SDimitry Andric cii->m_debug_stream.readSymbolAtOffset(record_offset); 128004eeddc0SDimitry Andric SegmentOffsetLength sol = GetSegmentOffsetAndLength(func_record); 128181ad6265SDimitry Andric addr_t file_vm_addr = 128281ad6265SDimitry Andric m_index->MakeVirtualAddress(sol.so.segment, sol.so.offset); 128381ad6265SDimitry Andric if (file_vm_addr == LLDB_INVALID_ADDRESS) 128481ad6265SDimitry Andric continue; 128581ad6265SDimitry Andric 128604eeddc0SDimitry Andric AddressRange func_range(file_vm_addr, sol.length, 128704eeddc0SDimitry Andric comp_unit.GetModule()->GetSectionList()); 128804eeddc0SDimitry Andric Address func_base = func_range.GetBaseAddress(); 128904eeddc0SDimitry Andric PdbCompilandSymId func_id{modi, record_offset}; 129004eeddc0SDimitry Andric 129104eeddc0SDimitry Andric // Iterate all S_INLINESITEs in the function. 129204eeddc0SDimitry Andric auto parse_inline_sites = [&](SymbolKind kind, PdbCompilandSymId id) { 129304eeddc0SDimitry Andric if (kind != S_INLINESITE) 129404eeddc0SDimitry Andric return false; 129504eeddc0SDimitry Andric 129604eeddc0SDimitry Andric ParseInlineSite(id, func_base); 129704eeddc0SDimitry Andric 129804eeddc0SDimitry Andric for (const auto &line_entry : 129904eeddc0SDimitry Andric m_inline_sites[toOpaqueUid(id)]->line_entries) { 130004eeddc0SDimitry Andric // If line_entry is not terminal entry, remove previous line entry at 130104eeddc0SDimitry Andric // the same address and insert new one. Terminal entry inside an inline 130204eeddc0SDimitry Andric // site might not be terminal entry for its parent. 130304eeddc0SDimitry Andric if (!line_entry.is_terminal_entry) 130404eeddc0SDimitry Andric line_set.erase(line_entry); 130504eeddc0SDimitry Andric line_set.insert(line_entry); 130604eeddc0SDimitry Andric } 130704eeddc0SDimitry Andric // No longer useful after adding to line_set. 130804eeddc0SDimitry Andric m_inline_sites[toOpaqueUid(id)]->line_entries.clear(); 130904eeddc0SDimitry Andric return true; 131004eeddc0SDimitry Andric }; 131104eeddc0SDimitry Andric ParseSymbolArrayInScope(func_id, parse_inline_sites); 131204eeddc0SDimitry Andric // Jump to the end of the function record. 131304eeddc0SDimitry Andric iter = syms.at(getScopeEndOffset(func_record)); 131404eeddc0SDimitry Andric } 131504eeddc0SDimitry Andric 131604eeddc0SDimitry Andric cii->m_global_line_table.Clear(); 131704eeddc0SDimitry Andric 131804eeddc0SDimitry Andric // Add line entries in line_set to line_table. 131904eeddc0SDimitry Andric auto line_table = std::make_unique<LineTable>(&comp_unit); 132004eeddc0SDimitry Andric std::unique_ptr<LineSequence> sequence( 132104eeddc0SDimitry Andric line_table->CreateLineSequenceContainer()); 132204eeddc0SDimitry Andric for (const auto &line_entry : line_set) { 132304eeddc0SDimitry Andric line_table->AppendLineEntryToSequence( 132404eeddc0SDimitry Andric sequence.get(), line_entry.file_addr, line_entry.line, 132504eeddc0SDimitry Andric line_entry.column, line_entry.file_idx, 132604eeddc0SDimitry Andric line_entry.is_start_of_statement, line_entry.is_start_of_basic_block, 132704eeddc0SDimitry Andric line_entry.is_prologue_end, line_entry.is_epilogue_begin, 132804eeddc0SDimitry Andric line_entry.is_terminal_entry); 132904eeddc0SDimitry Andric } 133004eeddc0SDimitry Andric line_table->InsertSequence(sequence.get()); 13310b57cec5SDimitry Andric 13320b57cec5SDimitry Andric if (line_table->GetSize() == 0) 13330b57cec5SDimitry Andric return false; 13340b57cec5SDimitry Andric 13350b57cec5SDimitry Andric comp_unit.SetLineTable(line_table.release()); 13360b57cec5SDimitry Andric return true; 13370b57cec5SDimitry Andric } 13380b57cec5SDimitry Andric 13390b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseDebugMacros(CompileUnit &comp_unit) { 13400b57cec5SDimitry Andric // PDB doesn't contain information about macros 13410b57cec5SDimitry Andric return false; 13420b57cec5SDimitry Andric } 13430b57cec5SDimitry Andric 134404eeddc0SDimitry Andric llvm::Expected<uint32_t> 134504eeddc0SDimitry Andric SymbolFileNativePDB::GetFileIndex(const CompilandIndexItem &cii, 134604eeddc0SDimitry Andric uint32_t file_id) { 134706c3fb27SDimitry Andric if (!cii.m_strings.hasChecksums() || !cii.m_strings.hasStrings()) 134806c3fb27SDimitry Andric return llvm::make_error<RawError>(raw_error_code::no_entry); 134906c3fb27SDimitry Andric 135004eeddc0SDimitry Andric const auto &checksums = cii.m_strings.checksums().getArray(); 135104eeddc0SDimitry Andric const auto &strings = cii.m_strings.strings(); 135204eeddc0SDimitry Andric // Indices in this structure are actually offsets of records in the 135304eeddc0SDimitry Andric // DEBUG_S_FILECHECKSUMS subsection. Those entries then have an index 135404eeddc0SDimitry Andric // into the global PDB string table. 135504eeddc0SDimitry Andric auto iter = checksums.at(file_id); 135604eeddc0SDimitry Andric if (iter == checksums.end()) 135704eeddc0SDimitry Andric return llvm::make_error<RawError>(raw_error_code::no_entry); 135804eeddc0SDimitry Andric 135904eeddc0SDimitry Andric llvm::Expected<llvm::StringRef> efn = strings.getString(iter->FileNameOffset); 136004eeddc0SDimitry Andric if (!efn) { 136104eeddc0SDimitry Andric return efn.takeError(); 136204eeddc0SDimitry Andric } 136304eeddc0SDimitry Andric 136404eeddc0SDimitry Andric // LLDB wants the index of the file in the list of support files. 136504eeddc0SDimitry Andric auto fn_iter = llvm::find(cii.m_file_list, *efn); 136681ad6265SDimitry Andric if (fn_iter != cii.m_file_list.end()) 136781ad6265SDimitry Andric return std::distance(cii.m_file_list.begin(), fn_iter); 136881ad6265SDimitry Andric return llvm::make_error<RawError>(raw_error_code::no_entry); 136904eeddc0SDimitry Andric } 137004eeddc0SDimitry Andric 13710b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseSupportFiles(CompileUnit &comp_unit, 13721db9f3b2SDimitry Andric SupportFileList &support_files) { 13739dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 13740b57cec5SDimitry Andric PdbSymUid cu_id(comp_unit.GetID()); 13750b57cec5SDimitry Andric lldbassert(cu_id.kind() == PdbSymUidKind::Compiland); 13760b57cec5SDimitry Andric CompilandIndexItem *cci = 13770b57cec5SDimitry Andric m_index->compilands().GetCompiland(cu_id.asCompiland().modi); 13780b57cec5SDimitry Andric lldbassert(cci); 13790b57cec5SDimitry Andric 13800b57cec5SDimitry Andric for (llvm::StringRef f : cci->m_file_list) { 13810b57cec5SDimitry Andric FileSpec::Style style = 13825f757f3fSDimitry Andric f.starts_with("/") ? FileSpec::Style::posix : FileSpec::Style::windows; 13830b57cec5SDimitry Andric FileSpec spec(f, style); 13840b57cec5SDimitry Andric support_files.Append(spec); 13850b57cec5SDimitry Andric } 13860b57cec5SDimitry Andric return true; 13870b57cec5SDimitry Andric } 13880b57cec5SDimitry Andric 13890b57cec5SDimitry Andric bool SymbolFileNativePDB::ParseImportedModules( 13900b57cec5SDimitry Andric const SymbolContext &sc, std::vector<SourceModule> &imported_modules) { 13910b57cec5SDimitry Andric // PDB does not yet support module debug info 13920b57cec5SDimitry Andric return false; 13930b57cec5SDimitry Andric } 13940b57cec5SDimitry Andric 139504eeddc0SDimitry Andric void SymbolFileNativePDB::ParseInlineSite(PdbCompilandSymId id, 139604eeddc0SDimitry Andric Address func_addr) { 139704eeddc0SDimitry Andric lldb::user_id_t opaque_uid = toOpaqueUid(id); 139806c3fb27SDimitry Andric if (m_inline_sites.contains(opaque_uid)) 139904eeddc0SDimitry Andric return; 140004eeddc0SDimitry Andric 140104eeddc0SDimitry Andric addr_t func_base = func_addr.GetFileAddress(); 140204eeddc0SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(id.modi); 140304eeddc0SDimitry Andric CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(id.offset); 140404eeddc0SDimitry Andric CompUnitSP comp_unit = GetOrCreateCompileUnit(*cii); 140504eeddc0SDimitry Andric 140604eeddc0SDimitry Andric InlineSiteSym inline_site(static_cast<SymbolRecordKind>(sym.kind())); 140704eeddc0SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<InlineSiteSym>(sym, inline_site)); 140804eeddc0SDimitry Andric PdbCompilandSymId parent_id(id.modi, inline_site.Parent); 140904eeddc0SDimitry Andric 141004eeddc0SDimitry Andric std::shared_ptr<InlineSite> inline_site_sp = 141104eeddc0SDimitry Andric std::make_shared<InlineSite>(parent_id); 141204eeddc0SDimitry Andric 141304eeddc0SDimitry Andric // Get the inlined function declaration info. 141404eeddc0SDimitry Andric auto iter = cii->m_inline_map.find(inline_site.Inlinee); 141504eeddc0SDimitry Andric if (iter == cii->m_inline_map.end()) 141604eeddc0SDimitry Andric return; 141704eeddc0SDimitry Andric InlineeSourceLine inlinee_line = iter->second; 141804eeddc0SDimitry Andric 14191db9f3b2SDimitry Andric const SupportFileList &files = comp_unit->GetSupportFiles(); 142004eeddc0SDimitry Andric FileSpec decl_file; 142104eeddc0SDimitry Andric llvm::Expected<uint32_t> file_index_or_err = 142204eeddc0SDimitry Andric GetFileIndex(*cii, inlinee_line.Header->FileID); 142304eeddc0SDimitry Andric if (!file_index_or_err) 142404eeddc0SDimitry Andric return; 142581ad6265SDimitry Andric uint32_t file_offset = file_index_or_err.get(); 142681ad6265SDimitry Andric decl_file = files.GetFileSpecAtIndex(file_offset); 142704eeddc0SDimitry Andric uint32_t decl_line = inlinee_line.Header->SourceLineNum; 142804eeddc0SDimitry Andric std::unique_ptr<Declaration> decl_up = 142904eeddc0SDimitry Andric std::make_unique<Declaration>(decl_file, decl_line); 143004eeddc0SDimitry Andric 143104eeddc0SDimitry Andric // Parse range and line info. 143204eeddc0SDimitry Andric uint32_t code_offset = 0; 143304eeddc0SDimitry Andric int32_t line_offset = 0; 1434bdd1243dSDimitry Andric std::optional<uint32_t> code_offset_base; 1435bdd1243dSDimitry Andric std::optional<uint32_t> code_offset_end; 1436bdd1243dSDimitry Andric std::optional<int32_t> cur_line_offset; 1437bdd1243dSDimitry Andric std::optional<int32_t> next_line_offset; 1438bdd1243dSDimitry Andric std::optional<uint32_t> next_file_offset; 143904eeddc0SDimitry Andric 144081ad6265SDimitry Andric bool is_terminal_entry = false; 144181ad6265SDimitry Andric bool is_start_of_statement = true; 144204eeddc0SDimitry Andric // The first instruction is the prologue end. 144304eeddc0SDimitry Andric bool is_prologue_end = true; 144404eeddc0SDimitry Andric 144581ad6265SDimitry Andric auto update_code_offset = [&](uint32_t code_delta) { 144681ad6265SDimitry Andric if (!code_offset_base) 144781ad6265SDimitry Andric code_offset_base = code_offset; 144881ad6265SDimitry Andric else if (!code_offset_end) 144981ad6265SDimitry Andric code_offset_end = *code_offset_base + code_delta; 145004eeddc0SDimitry Andric }; 145181ad6265SDimitry Andric auto update_line_offset = [&](int32_t line_delta) { 145204eeddc0SDimitry Andric line_offset += line_delta; 145381ad6265SDimitry Andric if (!code_offset_base || !cur_line_offset) 145481ad6265SDimitry Andric cur_line_offset = line_offset; 145581ad6265SDimitry Andric else 145681ad6265SDimitry Andric next_line_offset = line_offset; 145781ad6265SDimitry Andric ; 145881ad6265SDimitry Andric }; 145981ad6265SDimitry Andric auto update_file_offset = [&](uint32_t offset) { 146081ad6265SDimitry Andric if (!code_offset_base) 146181ad6265SDimitry Andric file_offset = offset; 146281ad6265SDimitry Andric else 146381ad6265SDimitry Andric next_file_offset = offset; 146404eeddc0SDimitry Andric }; 146504eeddc0SDimitry Andric 146604eeddc0SDimitry Andric for (auto &annot : inline_site.annotations()) { 146704eeddc0SDimitry Andric switch (annot.OpCode) { 146804eeddc0SDimitry Andric case BinaryAnnotationsOpCode::CodeOffset: 146904eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeOffset: 147004eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeOffsetBase: 147181ad6265SDimitry Andric code_offset += annot.U1; 147281ad6265SDimitry Andric update_code_offset(annot.U1); 147304eeddc0SDimitry Andric break; 147404eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeLineOffset: 147581ad6265SDimitry Andric update_line_offset(annot.S1); 147604eeddc0SDimitry Andric break; 147704eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeLength: 147881ad6265SDimitry Andric update_code_offset(annot.U1); 147904eeddc0SDimitry Andric code_offset += annot.U1; 148081ad6265SDimitry Andric is_terminal_entry = true; 148104eeddc0SDimitry Andric break; 148204eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeOffsetAndLineOffset: 148381ad6265SDimitry Andric code_offset += annot.U1; 148481ad6265SDimitry Andric update_code_offset(annot.U1); 148581ad6265SDimitry Andric update_line_offset(annot.S1); 148604eeddc0SDimitry Andric break; 148704eeddc0SDimitry Andric case BinaryAnnotationsOpCode::ChangeCodeLengthAndCodeOffset: 148881ad6265SDimitry Andric code_offset += annot.U2; 148981ad6265SDimitry Andric update_code_offset(annot.U2); 149081ad6265SDimitry Andric update_code_offset(annot.U1); 149181ad6265SDimitry Andric code_offset += annot.U1; 149281ad6265SDimitry Andric is_terminal_entry = true; 149381ad6265SDimitry Andric break; 149481ad6265SDimitry Andric case BinaryAnnotationsOpCode::ChangeFile: 149581ad6265SDimitry Andric update_file_offset(annot.U1); 149604eeddc0SDimitry Andric break; 149704eeddc0SDimitry Andric default: 149804eeddc0SDimitry Andric break; 149904eeddc0SDimitry Andric } 150081ad6265SDimitry Andric 150181ad6265SDimitry Andric // Add range if current range is finished. 150281ad6265SDimitry Andric if (code_offset_base && code_offset_end && cur_line_offset) { 150381ad6265SDimitry Andric inline_site_sp->ranges.Append(RangeSourceLineVector::Entry( 150481ad6265SDimitry Andric *code_offset_base, *code_offset_end - *code_offset_base, 150581ad6265SDimitry Andric decl_line + *cur_line_offset)); 150681ad6265SDimitry Andric // Set base, end, file offset and line offset for next range. 150781ad6265SDimitry Andric if (next_file_offset) 150881ad6265SDimitry Andric file_offset = *next_file_offset; 150981ad6265SDimitry Andric if (next_line_offset) { 151081ad6265SDimitry Andric cur_line_offset = next_line_offset; 1511bdd1243dSDimitry Andric next_line_offset = std::nullopt; 151281ad6265SDimitry Andric } 1513bdd1243dSDimitry Andric code_offset_base = is_terminal_entry ? std::nullopt : code_offset_end; 1514bdd1243dSDimitry Andric code_offset_end = next_file_offset = std::nullopt; 151581ad6265SDimitry Andric } 151681ad6265SDimitry Andric if (code_offset_base && cur_line_offset) { 151781ad6265SDimitry Andric if (is_terminal_entry) { 151881ad6265SDimitry Andric LineTable::Entry line_entry( 151981ad6265SDimitry Andric func_base + *code_offset_base, decl_line + *cur_line_offset, 0, 152081ad6265SDimitry Andric file_offset, false, false, false, false, true); 152181ad6265SDimitry Andric inline_site_sp->line_entries.push_back(line_entry); 152281ad6265SDimitry Andric } else { 152381ad6265SDimitry Andric LineTable::Entry line_entry(func_base + *code_offset_base, 152481ad6265SDimitry Andric decl_line + *cur_line_offset, 0, 152581ad6265SDimitry Andric file_offset, is_start_of_statement, false, 152681ad6265SDimitry Andric is_prologue_end, false, false); 152781ad6265SDimitry Andric inline_site_sp->line_entries.push_back(line_entry); 152881ad6265SDimitry Andric is_prologue_end = false; 152981ad6265SDimitry Andric is_start_of_statement = false; 153081ad6265SDimitry Andric } 153181ad6265SDimitry Andric } 153281ad6265SDimitry Andric if (is_terminal_entry) 153381ad6265SDimitry Andric is_start_of_statement = true; 153481ad6265SDimitry Andric is_terminal_entry = false; 153504eeddc0SDimitry Andric } 153604eeddc0SDimitry Andric 153704eeddc0SDimitry Andric inline_site_sp->ranges.Sort(); 153804eeddc0SDimitry Andric 153904eeddc0SDimitry Andric // Get the inlined function callsite info. 154004eeddc0SDimitry Andric std::unique_ptr<Declaration> callsite_up; 154104eeddc0SDimitry Andric if (!inline_site_sp->ranges.IsEmpty()) { 154204eeddc0SDimitry Andric auto *entry = inline_site_sp->ranges.GetEntryAtIndex(0); 154304eeddc0SDimitry Andric addr_t base_offset = entry->GetRangeBase(); 154404eeddc0SDimitry Andric if (cii->m_debug_stream.readSymbolAtOffset(parent_id.offset).kind() == 154504eeddc0SDimitry Andric S_INLINESITE) { 154604eeddc0SDimitry Andric // Its parent is another inline site, lookup parent site's range vector 154704eeddc0SDimitry Andric // for callsite line. 154804eeddc0SDimitry Andric ParseInlineSite(parent_id, func_base); 154904eeddc0SDimitry Andric std::shared_ptr<InlineSite> parent_site = 155004eeddc0SDimitry Andric m_inline_sites[toOpaqueUid(parent_id)]; 155104eeddc0SDimitry Andric FileSpec &parent_decl_file = 155204eeddc0SDimitry Andric parent_site->inline_function_info->GetDeclaration().GetFile(); 155304eeddc0SDimitry Andric if (auto *parent_entry = 155404eeddc0SDimitry Andric parent_site->ranges.FindEntryThatContains(base_offset)) { 155504eeddc0SDimitry Andric callsite_up = 155604eeddc0SDimitry Andric std::make_unique<Declaration>(parent_decl_file, parent_entry->data); 155704eeddc0SDimitry Andric } 155804eeddc0SDimitry Andric } else { 155904eeddc0SDimitry Andric // Its parent is a function, lookup global line table for callsite. 156004eeddc0SDimitry Andric if (auto *entry = cii->m_global_line_table.FindEntryThatContains( 156104eeddc0SDimitry Andric func_base + base_offset)) { 156204eeddc0SDimitry Andric const FileSpec &callsite_file = 156304eeddc0SDimitry Andric files.GetFileSpecAtIndex(entry->data.first); 156404eeddc0SDimitry Andric callsite_up = 156504eeddc0SDimitry Andric std::make_unique<Declaration>(callsite_file, entry->data.second); 156604eeddc0SDimitry Andric } 156704eeddc0SDimitry Andric } 156804eeddc0SDimitry Andric } 156904eeddc0SDimitry Andric 157004eeddc0SDimitry Andric // Get the inlined function name. 157104eeddc0SDimitry Andric CVType inlinee_cvt = m_index->ipi().getType(inline_site.Inlinee); 157204eeddc0SDimitry Andric std::string inlinee_name; 157304eeddc0SDimitry Andric if (inlinee_cvt.kind() == LF_MFUNC_ID) { 157404eeddc0SDimitry Andric MemberFuncIdRecord mfr; 157504eeddc0SDimitry Andric cantFail( 157604eeddc0SDimitry Andric TypeDeserializer::deserializeAs<MemberFuncIdRecord>(inlinee_cvt, mfr)); 157704eeddc0SDimitry Andric LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); 157804eeddc0SDimitry Andric inlinee_name.append(std::string(types.getTypeName(mfr.ClassType))); 157904eeddc0SDimitry Andric inlinee_name.append("::"); 158004eeddc0SDimitry Andric inlinee_name.append(mfr.getName().str()); 158104eeddc0SDimitry Andric } else if (inlinee_cvt.kind() == LF_FUNC_ID) { 158204eeddc0SDimitry Andric FuncIdRecord fir; 158304eeddc0SDimitry Andric cantFail(TypeDeserializer::deserializeAs<FuncIdRecord>(inlinee_cvt, fir)); 158404eeddc0SDimitry Andric TypeIndex parent_idx = fir.getParentScope(); 158504eeddc0SDimitry Andric if (!parent_idx.isNoneType()) { 158604eeddc0SDimitry Andric LazyRandomTypeCollection &ids = m_index->ipi().typeCollection(); 158704eeddc0SDimitry Andric inlinee_name.append(std::string(ids.getTypeName(parent_idx))); 158804eeddc0SDimitry Andric inlinee_name.append("::"); 158904eeddc0SDimitry Andric } 159004eeddc0SDimitry Andric inlinee_name.append(fir.getName().str()); 159104eeddc0SDimitry Andric } 159204eeddc0SDimitry Andric inline_site_sp->inline_function_info = std::make_shared<InlineFunctionInfo>( 159304eeddc0SDimitry Andric inlinee_name.c_str(), llvm::StringRef(), decl_up.get(), 159404eeddc0SDimitry Andric callsite_up.get()); 159504eeddc0SDimitry Andric 159604eeddc0SDimitry Andric m_inline_sites[opaque_uid] = inline_site_sp; 159704eeddc0SDimitry Andric } 159804eeddc0SDimitry Andric 15990b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) { 16009dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 160104eeddc0SDimitry Andric PdbCompilandSymId func_id = PdbSymUid(func.GetID()).asCompilandSym(); 160204eeddc0SDimitry Andric // After we iterate through inline sites inside the function, we already get 160304eeddc0SDimitry Andric // all the info needed, removing from the map to save memory. 160404eeddc0SDimitry Andric std::set<uint64_t> remove_uids; 160504eeddc0SDimitry Andric auto parse_blocks = [&](SymbolKind kind, PdbCompilandSymId id) { 160604eeddc0SDimitry Andric if (kind == S_GPROC32 || kind == S_LPROC32 || kind == S_BLOCK32 || 160704eeddc0SDimitry Andric kind == S_INLINESITE) { 160804eeddc0SDimitry Andric GetOrCreateBlock(id); 160904eeddc0SDimitry Andric if (kind == S_INLINESITE) 161004eeddc0SDimitry Andric remove_uids.insert(toOpaqueUid(id)); 161104eeddc0SDimitry Andric return true; 161204eeddc0SDimitry Andric } 161304eeddc0SDimitry Andric return false; 161404eeddc0SDimitry Andric }; 161504eeddc0SDimitry Andric size_t count = ParseSymbolArrayInScope(func_id, parse_blocks); 161604eeddc0SDimitry Andric for (uint64_t uid : remove_uids) { 161704eeddc0SDimitry Andric m_inline_sites.erase(uid); 161804eeddc0SDimitry Andric } 161904eeddc0SDimitry Andric return count; 162004eeddc0SDimitry Andric } 162104eeddc0SDimitry Andric 162204eeddc0SDimitry Andric size_t SymbolFileNativePDB::ParseSymbolArrayInScope( 162304eeddc0SDimitry Andric PdbCompilandSymId parent_id, 162404eeddc0SDimitry Andric llvm::function_ref<bool(SymbolKind, PdbCompilandSymId)> fn) { 162504eeddc0SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(parent_id.modi); 162604eeddc0SDimitry Andric CVSymbolArray syms = 162704eeddc0SDimitry Andric cii->m_debug_stream.getSymbolArrayForScope(parent_id.offset); 162804eeddc0SDimitry Andric 162904eeddc0SDimitry Andric size_t count = 1; 163004eeddc0SDimitry Andric for (auto iter = syms.begin(); iter != syms.end(); ++iter) { 163104eeddc0SDimitry Andric PdbCompilandSymId child_id(parent_id.modi, iter.offset()); 163204eeddc0SDimitry Andric if (fn(iter->kind(), child_id)) 163304eeddc0SDimitry Andric ++count; 163404eeddc0SDimitry Andric } 163504eeddc0SDimitry Andric 163604eeddc0SDimitry Andric return count; 16370b57cec5SDimitry Andric } 16380b57cec5SDimitry Andric 1639bdd1243dSDimitry Andric void SymbolFileNativePDB::DumpClangAST(Stream &s) { 1640bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(eLanguageTypeC_plus_plus); 1641bdd1243dSDimitry Andric if (!ts_or_err) 1642bdd1243dSDimitry Andric return; 1643bdd1243dSDimitry Andric auto ts = *ts_or_err; 1644bdd1243dSDimitry Andric TypeSystemClang *clang = llvm::dyn_cast_or_null<TypeSystemClang>(ts.get()); 1645bdd1243dSDimitry Andric if (!clang) 1646bdd1243dSDimitry Andric return; 1647bdd1243dSDimitry Andric clang->GetNativePDBParser()->Dump(s); 1648bdd1243dSDimitry Andric } 16490b57cec5SDimitry Andric 16509dba64beSDimitry Andric void SymbolFileNativePDB::FindGlobalVariables( 16515ffd83dbSDimitry Andric ConstString name, const CompilerDeclContext &parent_decl_ctx, 16520b57cec5SDimitry Andric uint32_t max_matches, VariableList &variables) { 16539dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 16540b57cec5SDimitry Andric using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; 16550b57cec5SDimitry Andric 16560b57cec5SDimitry Andric std::vector<SymbolAndOffset> results = m_index->globals().findRecordsByName( 16570b57cec5SDimitry Andric name.GetStringRef(), m_index->symrecords()); 16580b57cec5SDimitry Andric for (const SymbolAndOffset &result : results) { 16590b57cec5SDimitry Andric switch (result.second.kind()) { 16600b57cec5SDimitry Andric case SymbolKind::S_GDATA32: 16610b57cec5SDimitry Andric case SymbolKind::S_LDATA32: 16620b57cec5SDimitry Andric case SymbolKind::S_GTHREAD32: 16630b57cec5SDimitry Andric case SymbolKind::S_LTHREAD32: 16640b57cec5SDimitry Andric case SymbolKind::S_CONSTANT: { 16650b57cec5SDimitry Andric PdbGlobalSymId global(result.first, false); 166681ad6265SDimitry Andric if (VariableSP var = GetOrCreateGlobalVariable(global)) 16670b57cec5SDimitry Andric variables.AddVariable(var); 16680b57cec5SDimitry Andric break; 16690b57cec5SDimitry Andric } 16700b57cec5SDimitry Andric default: 16710b57cec5SDimitry Andric continue; 16720b57cec5SDimitry Andric } 16730b57cec5SDimitry Andric } 16740b57cec5SDimitry Andric } 16750b57cec5SDimitry Andric 16769dba64beSDimitry Andric void SymbolFileNativePDB::FindFunctions( 1677bdd1243dSDimitry Andric const Module::LookupInfo &lookup_info, 1678bdd1243dSDimitry Andric const CompilerDeclContext &parent_decl_ctx, bool include_inlines, 16790b57cec5SDimitry Andric SymbolContextList &sc_list) { 16809dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 1681bdd1243dSDimitry Andric ConstString name = lookup_info.GetLookupName(); 1682bdd1243dSDimitry Andric FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); 1683bdd1243dSDimitry Andric if (name_type_mask & eFunctionNameTypeFull) 1684bdd1243dSDimitry Andric name = lookup_info.GetName(); 1685bdd1243dSDimitry Andric 16864824e7fdSDimitry Andric // For now we only support lookup by method name or full name. 16874824e7fdSDimitry Andric if (!(name_type_mask & eFunctionNameTypeFull || 16884824e7fdSDimitry Andric name_type_mask & eFunctionNameTypeMethod)) 16899dba64beSDimitry Andric return; 16900b57cec5SDimitry Andric 16910b57cec5SDimitry Andric using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; 16920b57cec5SDimitry Andric 16930b57cec5SDimitry Andric std::vector<SymbolAndOffset> matches = m_index->globals().findRecordsByName( 16940b57cec5SDimitry Andric name.GetStringRef(), m_index->symrecords()); 16950b57cec5SDimitry Andric for (const SymbolAndOffset &match : matches) { 16960b57cec5SDimitry Andric if (match.second.kind() != S_PROCREF && match.second.kind() != S_LPROCREF) 16970b57cec5SDimitry Andric continue; 16980b57cec5SDimitry Andric ProcRefSym proc(match.second.kind()); 16990b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(match.second, proc)); 17000b57cec5SDimitry Andric 17010b57cec5SDimitry Andric if (!IsValidRecord(proc)) 17020b57cec5SDimitry Andric continue; 17030b57cec5SDimitry Andric 17040b57cec5SDimitry Andric CompilandIndexItem &cci = 17050b57cec5SDimitry Andric m_index->compilands().GetOrCreateCompiland(proc.modi()); 17060b57cec5SDimitry Andric SymbolContext sc; 17070b57cec5SDimitry Andric 17080b57cec5SDimitry Andric sc.comp_unit = GetOrCreateCompileUnit(cci).get(); 17090b57cec5SDimitry Andric PdbCompilandSymId func_id(proc.modi(), proc.SymOffset); 17100b57cec5SDimitry Andric sc.function = GetOrCreateFunction(func_id, *sc.comp_unit).get(); 17110b57cec5SDimitry Andric 17120b57cec5SDimitry Andric sc_list.Append(sc); 17130b57cec5SDimitry Andric } 17140b57cec5SDimitry Andric } 17150b57cec5SDimitry Andric 17169dba64beSDimitry Andric void SymbolFileNativePDB::FindFunctions(const RegularExpression ®ex, 17179dba64beSDimitry Andric bool include_inlines, 17189dba64beSDimitry Andric SymbolContextList &sc_list) {} 17190b57cec5SDimitry Andric 17205f757f3fSDimitry Andric void SymbolFileNativePDB::FindTypes(const lldb_private::TypeQuery &query, 17215f757f3fSDimitry Andric lldb_private::TypeResults &results) { 17225f757f3fSDimitry Andric 17235f757f3fSDimitry Andric // Make sure we haven't already searched this SymbolFile before. 17245f757f3fSDimitry Andric if (results.AlreadySearched(this)) 17259dba64beSDimitry Andric return; 17260b57cec5SDimitry Andric 17275f757f3fSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 17280b57cec5SDimitry Andric 17295f757f3fSDimitry Andric std::vector<TypeIndex> matches = 17305f757f3fSDimitry Andric m_index->tpi().findRecordsByName(query.GetTypeBasename().GetStringRef()); 17315f757f3fSDimitry Andric 17325f757f3fSDimitry Andric for (TypeIndex type_idx : matches) { 17335f757f3fSDimitry Andric TypeSP type_sp = GetOrCreateType(type_idx); 17345f757f3fSDimitry Andric if (!type_sp) 17355f757f3fSDimitry Andric continue; 17365f757f3fSDimitry Andric 17375f757f3fSDimitry Andric // We resolved a type. Get the fully qualified name to ensure it matches. 17385f757f3fSDimitry Andric ConstString name = type_sp->GetQualifiedName(); 17395f757f3fSDimitry Andric TypeQuery type_match(name.GetStringRef(), TypeQueryOptions::e_exact_match); 17405f757f3fSDimitry Andric if (query.ContextMatches(type_match.GetContextRef())) { 17415f757f3fSDimitry Andric results.InsertUnique(type_sp); 17425f757f3fSDimitry Andric if (results.Done(query)) 17435f757f3fSDimitry Andric return; 17440b57cec5SDimitry Andric } 17455f757f3fSDimitry Andric } 17465f757f3fSDimitry Andric } 17470b57cec5SDimitry Andric 17489dba64beSDimitry Andric void SymbolFileNativePDB::FindTypesByName(llvm::StringRef name, 17490b57cec5SDimitry Andric uint32_t max_matches, 17500b57cec5SDimitry Andric TypeMap &types) { 17510b57cec5SDimitry Andric 17520b57cec5SDimitry Andric std::vector<TypeIndex> matches = m_index->tpi().findRecordsByName(name); 17530b57cec5SDimitry Andric if (max_matches > 0 && max_matches < matches.size()) 17540b57cec5SDimitry Andric matches.resize(max_matches); 17550b57cec5SDimitry Andric 17560b57cec5SDimitry Andric for (TypeIndex ti : matches) { 17570b57cec5SDimitry Andric TypeSP type = GetOrCreateType(ti); 17580b57cec5SDimitry Andric if (!type) 17590b57cec5SDimitry Andric continue; 17600b57cec5SDimitry Andric 17610b57cec5SDimitry Andric types.Insert(type); 17620b57cec5SDimitry Andric } 17630b57cec5SDimitry Andric } 17640b57cec5SDimitry Andric 17650b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseTypes(CompileUnit &comp_unit) { 17669dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 17670b57cec5SDimitry Andric // Only do the full type scan the first time. 17680b57cec5SDimitry Andric if (m_done_full_type_scan) 17690b57cec5SDimitry Andric return 0; 17700b57cec5SDimitry Andric 17719dba64beSDimitry Andric const size_t old_count = GetTypeList().GetSize(); 17720b57cec5SDimitry Andric LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); 17730b57cec5SDimitry Andric 17740b57cec5SDimitry Andric // First process the entire TPI stream. 17750b57cec5SDimitry Andric for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) { 17760b57cec5SDimitry Andric TypeSP type = GetOrCreateType(*ti); 17770b57cec5SDimitry Andric if (type) 17780b57cec5SDimitry Andric (void)type->GetFullCompilerType(); 17790b57cec5SDimitry Andric } 17800b57cec5SDimitry Andric 17810b57cec5SDimitry Andric // Next look for S_UDT records in the globals stream. 17820b57cec5SDimitry Andric for (const uint32_t gid : m_index->globals().getGlobalsTable()) { 17830b57cec5SDimitry Andric PdbGlobalSymId global{gid, false}; 17840b57cec5SDimitry Andric CVSymbol sym = m_index->ReadSymbolRecord(global); 17850b57cec5SDimitry Andric if (sym.kind() != S_UDT) 17860b57cec5SDimitry Andric continue; 17870b57cec5SDimitry Andric 17880b57cec5SDimitry Andric UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym)); 17890b57cec5SDimitry Andric bool is_typedef = true; 17900b57cec5SDimitry Andric if (IsTagRecord(PdbTypeSymId{udt.Type, false}, m_index->tpi())) { 17910b57cec5SDimitry Andric CVType cvt = m_index->tpi().getType(udt.Type); 17920b57cec5SDimitry Andric llvm::StringRef name = CVTagRecord::create(cvt).name(); 17930b57cec5SDimitry Andric if (name == udt.Name) 17940b57cec5SDimitry Andric is_typedef = false; 17950b57cec5SDimitry Andric } 17960b57cec5SDimitry Andric 17970b57cec5SDimitry Andric if (is_typedef) 17980b57cec5SDimitry Andric GetOrCreateTypedef(global); 17990b57cec5SDimitry Andric } 18000b57cec5SDimitry Andric 18019dba64beSDimitry Andric const size_t new_count = GetTypeList().GetSize(); 18020b57cec5SDimitry Andric 18030b57cec5SDimitry Andric m_done_full_type_scan = true; 18040b57cec5SDimitry Andric 18050b57cec5SDimitry Andric return new_count - old_count; 18060b57cec5SDimitry Andric } 18070b57cec5SDimitry Andric 18080b57cec5SDimitry Andric size_t 18090b57cec5SDimitry Andric SymbolFileNativePDB::ParseVariablesForCompileUnit(CompileUnit &comp_unit, 18100b57cec5SDimitry Andric VariableList &variables) { 18110b57cec5SDimitry Andric PdbSymUid sym_uid(comp_unit.GetID()); 18120b57cec5SDimitry Andric lldbassert(sym_uid.kind() == PdbSymUidKind::Compiland); 18130b57cec5SDimitry Andric return 0; 18140b57cec5SDimitry Andric } 18150b57cec5SDimitry Andric 18160b57cec5SDimitry Andric VariableSP SymbolFileNativePDB::CreateLocalVariable(PdbCompilandSymId scope_id, 18170b57cec5SDimitry Andric PdbCompilandSymId var_id, 18180b57cec5SDimitry Andric bool is_param) { 18190b57cec5SDimitry Andric ModuleSP module = GetObjectFile()->GetModule(); 18200b57cec5SDimitry Andric Block &block = GetOrCreateBlock(scope_id); 1821753f127fSDimitry Andric // Get function block. 1822753f127fSDimitry Andric Block *func_block = █ 1823753f127fSDimitry Andric while (func_block->GetParent()) { 1824753f127fSDimitry Andric func_block = func_block->GetParent(); 1825753f127fSDimitry Andric } 1826753f127fSDimitry Andric Address addr; 1827753f127fSDimitry Andric func_block->GetStartAddress(addr); 18280b57cec5SDimitry Andric VariableInfo var_info = 1829753f127fSDimitry Andric GetVariableLocationInfo(*m_index, var_id, *func_block, module); 1830bdd1243dSDimitry Andric Function *func = func_block->CalculateSymbolContextFunction(); 1831bdd1243dSDimitry Andric if (!func) 18320b57cec5SDimitry Andric return nullptr; 1833bdd1243dSDimitry Andric // Use empty dwarf expr if optimized away so that it won't be filtered out 1834bdd1243dSDimitry Andric // when lookuping local variables in this scope. 1835bdd1243dSDimitry Andric if (!var_info.location.IsValid()) 1836bdd1243dSDimitry Andric var_info.location = DWARFExpressionList(module, DWARFExpression(), nullptr); 1837bdd1243dSDimitry Andric var_info.location.SetFuncFileAddress( 1838bdd1243dSDimitry Andric func->GetAddressRange().GetBaseAddress().GetFileAddress()); 18390b57cec5SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(var_id.modi); 18400b57cec5SDimitry Andric CompUnitSP comp_unit_sp = GetOrCreateCompileUnit(*cii); 18410b57cec5SDimitry Andric TypeSP type_sp = GetOrCreateType(var_info.type); 1842bdd1243dSDimitry Andric if (!type_sp) 1843bdd1243dSDimitry Andric return nullptr; 18440b57cec5SDimitry Andric std::string name = var_info.name.str(); 18450b57cec5SDimitry Andric Declaration decl; 18460b57cec5SDimitry Andric SymbolFileTypeSP sftype = 18470b57cec5SDimitry Andric std::make_shared<SymbolFileType>(*this, type_sp->GetID()); 18480b57cec5SDimitry Andric 184981ad6265SDimitry Andric is_param |= var_info.is_param; 18500b57cec5SDimitry Andric ValueType var_scope = 18510b57cec5SDimitry Andric is_param ? eValueTypeVariableArgument : eValueTypeVariableLocal; 1852e8d8bef9SDimitry Andric bool external = false; 1853e8d8bef9SDimitry Andric bool artificial = false; 1854e8d8bef9SDimitry Andric bool location_is_constant_data = false; 1855e8d8bef9SDimitry Andric bool static_member = false; 1856bdd1243dSDimitry Andric Variable::RangeList scope_ranges; 18570b57cec5SDimitry Andric VariableSP var_sp = std::make_shared<Variable>( 18580b57cec5SDimitry Andric toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope, 1859bdd1243dSDimitry Andric &block, scope_ranges, &decl, var_info.location, external, artificial, 1860753f127fSDimitry Andric location_is_constant_data, static_member); 1861bdd1243dSDimitry Andric if (!is_param) { 1862bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(comp_unit_sp->GetLanguage()); 1863bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 1864bdd1243dSDimitry Andric return nullptr; 1865bdd1243dSDimitry Andric auto ts = *ts_or_err; 1866bdd1243dSDimitry Andric if (!ts) 1867bdd1243dSDimitry Andric return nullptr; 18680b57cec5SDimitry Andric 1869bdd1243dSDimitry Andric ts->GetNativePDBParser()->GetOrCreateVariableDecl(scope_id, var_id); 1870bdd1243dSDimitry Andric } 18710b57cec5SDimitry Andric m_local_variables[toOpaqueUid(var_id)] = var_sp; 18720b57cec5SDimitry Andric return var_sp; 18730b57cec5SDimitry Andric } 18740b57cec5SDimitry Andric 18750b57cec5SDimitry Andric VariableSP SymbolFileNativePDB::GetOrCreateLocalVariable( 18760b57cec5SDimitry Andric PdbCompilandSymId scope_id, PdbCompilandSymId var_id, bool is_param) { 18770b57cec5SDimitry Andric auto iter = m_local_variables.find(toOpaqueUid(var_id)); 18780b57cec5SDimitry Andric if (iter != m_local_variables.end()) 18790b57cec5SDimitry Andric return iter->second; 18800b57cec5SDimitry Andric 18810b57cec5SDimitry Andric return CreateLocalVariable(scope_id, var_id, is_param); 18820b57cec5SDimitry Andric } 18830b57cec5SDimitry Andric 18840b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::CreateTypedef(PdbGlobalSymId id) { 18850b57cec5SDimitry Andric CVSymbol sym = m_index->ReadSymbolRecord(id); 18860b57cec5SDimitry Andric lldbassert(sym.kind() == SymbolKind::S_UDT); 18870b57cec5SDimitry Andric 18880b57cec5SDimitry Andric UDTSym udt = llvm::cantFail(SymbolDeserializer::deserializeAs<UDTSym>(sym)); 18890b57cec5SDimitry Andric 18900b57cec5SDimitry Andric TypeSP target_type = GetOrCreateType(udt.Type); 18910b57cec5SDimitry Andric 1892bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 1893bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 1894bdd1243dSDimitry Andric return nullptr; 1895bdd1243dSDimitry Andric auto ts = *ts_or_err; 1896bdd1243dSDimitry Andric if (!ts) 1897bdd1243dSDimitry Andric return nullptr; 1898bdd1243dSDimitry Andric 1899bdd1243dSDimitry Andric ts->GetNativePDBParser()->GetOrCreateTypedefDecl(id); 19000b57cec5SDimitry Andric 19010b57cec5SDimitry Andric Declaration decl; 1902bdd1243dSDimitry Andric return MakeType( 1903bdd1243dSDimitry Andric toOpaqueUid(id), ConstString(udt.Name), target_type->GetByteSize(nullptr), 1904bdd1243dSDimitry Andric nullptr, target_type->GetID(), lldb_private::Type::eEncodingIsTypedefUID, 1905bdd1243dSDimitry Andric decl, target_type->GetForwardCompilerType(), 1906480093f4SDimitry Andric lldb_private::Type::ResolveState::Forward); 19070b57cec5SDimitry Andric } 19080b57cec5SDimitry Andric 19090b57cec5SDimitry Andric TypeSP SymbolFileNativePDB::GetOrCreateTypedef(PdbGlobalSymId id) { 19100b57cec5SDimitry Andric auto iter = m_types.find(toOpaqueUid(id)); 19110b57cec5SDimitry Andric if (iter != m_types.end()) 19120b57cec5SDimitry Andric return iter->second; 19130b57cec5SDimitry Andric 19140b57cec5SDimitry Andric return CreateTypedef(id); 19150b57cec5SDimitry Andric } 19160b57cec5SDimitry Andric 19170b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseVariablesForBlock(PdbCompilandSymId block_id) { 19180b57cec5SDimitry Andric Block &block = GetOrCreateBlock(block_id); 19190b57cec5SDimitry Andric 19200b57cec5SDimitry Andric size_t count = 0; 19210b57cec5SDimitry Andric 19220b57cec5SDimitry Andric CompilandIndexItem *cii = m_index->compilands().GetCompiland(block_id.modi); 19230b57cec5SDimitry Andric CVSymbol sym = cii->m_debug_stream.readSymbolAtOffset(block_id.offset); 19240b57cec5SDimitry Andric uint32_t params_remaining = 0; 19250b57cec5SDimitry Andric switch (sym.kind()) { 19260b57cec5SDimitry Andric case S_GPROC32: 19270b57cec5SDimitry Andric case S_LPROC32: { 19280b57cec5SDimitry Andric ProcSym proc(static_cast<SymbolRecordKind>(sym.kind())); 19290b57cec5SDimitry Andric cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym, proc)); 19300b57cec5SDimitry Andric CVType signature = m_index->tpi().getType(proc.FunctionType); 1931bdd1243dSDimitry Andric if (signature.kind() == LF_PROCEDURE) { 19320b57cec5SDimitry Andric ProcedureRecord sig; 1933bdd1243dSDimitry Andric if (llvm::Error e = TypeDeserializer::deserializeAs<ProcedureRecord>( 1934bdd1243dSDimitry Andric signature, sig)) { 1935bdd1243dSDimitry Andric llvm::consumeError(std::move(e)); 1936bdd1243dSDimitry Andric return 0; 1937bdd1243dSDimitry Andric } 19380b57cec5SDimitry Andric params_remaining = sig.getParameterCount(); 1939bdd1243dSDimitry Andric } else if (signature.kind() == LF_MFUNCTION) { 1940bdd1243dSDimitry Andric MemberFunctionRecord sig; 1941bdd1243dSDimitry Andric if (llvm::Error e = TypeDeserializer::deserializeAs<MemberFunctionRecord>( 1942bdd1243dSDimitry Andric signature, sig)) { 1943bdd1243dSDimitry Andric llvm::consumeError(std::move(e)); 1944bdd1243dSDimitry Andric return 0; 1945bdd1243dSDimitry Andric } 1946bdd1243dSDimitry Andric params_remaining = sig.getParameterCount(); 1947bdd1243dSDimitry Andric } else 1948bdd1243dSDimitry Andric return 0; 19490b57cec5SDimitry Andric break; 19500b57cec5SDimitry Andric } 19510b57cec5SDimitry Andric case S_BLOCK32: 19520b57cec5SDimitry Andric break; 195304eeddc0SDimitry Andric case S_INLINESITE: 195481ad6265SDimitry Andric break; 19550b57cec5SDimitry Andric default: 19560b57cec5SDimitry Andric lldbassert(false && "Symbol is not a block!"); 19570b57cec5SDimitry Andric return 0; 19580b57cec5SDimitry Andric } 19590b57cec5SDimitry Andric 19600b57cec5SDimitry Andric VariableListSP variables = block.GetBlockVariableList(false); 19610b57cec5SDimitry Andric if (!variables) { 19620b57cec5SDimitry Andric variables = std::make_shared<VariableList>(); 19630b57cec5SDimitry Andric block.SetVariableList(variables); 19640b57cec5SDimitry Andric } 19650b57cec5SDimitry Andric 19660b57cec5SDimitry Andric CVSymbolArray syms = limitSymbolArrayToScope( 19670b57cec5SDimitry Andric cii->m_debug_stream.getSymbolArray(), block_id.offset); 19680b57cec5SDimitry Andric 19690b57cec5SDimitry Andric // Skip the first record since it's a PROC32 or BLOCK32, and there's 19700b57cec5SDimitry Andric // no point examining it since we know it's not a local variable. 19710b57cec5SDimitry Andric syms.drop_front(); 19720b57cec5SDimitry Andric auto iter = syms.begin(); 19730b57cec5SDimitry Andric auto end = syms.end(); 19740b57cec5SDimitry Andric 19750b57cec5SDimitry Andric while (iter != end) { 19760b57cec5SDimitry Andric uint32_t record_offset = iter.offset(); 19770b57cec5SDimitry Andric CVSymbol variable_cvs = *iter; 19780b57cec5SDimitry Andric PdbCompilandSymId child_sym_id(block_id.modi, record_offset); 19790b57cec5SDimitry Andric ++iter; 19800b57cec5SDimitry Andric 198181ad6265SDimitry Andric // If this is a block or inline site, recurse into its children and then 198281ad6265SDimitry Andric // skip it. 198381ad6265SDimitry Andric if (variable_cvs.kind() == S_BLOCK32 || 198481ad6265SDimitry Andric variable_cvs.kind() == S_INLINESITE) { 19850b57cec5SDimitry Andric uint32_t block_end = getScopeEndOffset(variable_cvs); 19860b57cec5SDimitry Andric count += ParseVariablesForBlock(child_sym_id); 19870b57cec5SDimitry Andric iter = syms.at(block_end); 19880b57cec5SDimitry Andric continue; 19890b57cec5SDimitry Andric } 19900b57cec5SDimitry Andric 19910b57cec5SDimitry Andric bool is_param = params_remaining > 0; 19920b57cec5SDimitry Andric VariableSP variable; 19930b57cec5SDimitry Andric switch (variable_cvs.kind()) { 19940b57cec5SDimitry Andric case S_REGREL32: 19950b57cec5SDimitry Andric case S_REGISTER: 19960b57cec5SDimitry Andric case S_LOCAL: 19970b57cec5SDimitry Andric variable = GetOrCreateLocalVariable(block_id, child_sym_id, is_param); 19980b57cec5SDimitry Andric if (is_param) 19990b57cec5SDimitry Andric --params_remaining; 20000b57cec5SDimitry Andric if (variable) 20010b57cec5SDimitry Andric variables->AddVariableIfUnique(variable); 20020b57cec5SDimitry Andric break; 20030b57cec5SDimitry Andric default: 20040b57cec5SDimitry Andric break; 20050b57cec5SDimitry Andric } 20060b57cec5SDimitry Andric } 20070b57cec5SDimitry Andric 20080b57cec5SDimitry Andric // Pass false for set_children, since we call this recursively so that the 20090b57cec5SDimitry Andric // children will call this for themselves. 20100b57cec5SDimitry Andric block.SetDidParseVariables(true, false); 20110b57cec5SDimitry Andric 20120b57cec5SDimitry Andric return count; 20130b57cec5SDimitry Andric } 20140b57cec5SDimitry Andric 20150b57cec5SDimitry Andric size_t SymbolFileNativePDB::ParseVariablesForContext(const SymbolContext &sc) { 20169dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 20170b57cec5SDimitry Andric lldbassert(sc.function || sc.comp_unit); 20180b57cec5SDimitry Andric 20190b57cec5SDimitry Andric VariableListSP variables; 20200b57cec5SDimitry Andric if (sc.block) { 20210b57cec5SDimitry Andric PdbSymUid block_id(sc.block->GetID()); 20220b57cec5SDimitry Andric 20230b57cec5SDimitry Andric size_t count = ParseVariablesForBlock(block_id.asCompilandSym()); 20240b57cec5SDimitry Andric return count; 20250b57cec5SDimitry Andric } 20260b57cec5SDimitry Andric 20270b57cec5SDimitry Andric if (sc.function) { 20280b57cec5SDimitry Andric PdbSymUid block_id(sc.function->GetID()); 20290b57cec5SDimitry Andric 20300b57cec5SDimitry Andric size_t count = ParseVariablesForBlock(block_id.asCompilandSym()); 20310b57cec5SDimitry Andric return count; 20320b57cec5SDimitry Andric } 20330b57cec5SDimitry Andric 20340b57cec5SDimitry Andric if (sc.comp_unit) { 20350b57cec5SDimitry Andric variables = sc.comp_unit->GetVariableList(false); 20360b57cec5SDimitry Andric if (!variables) { 20370b57cec5SDimitry Andric variables = std::make_shared<VariableList>(); 20380b57cec5SDimitry Andric sc.comp_unit->SetVariableList(variables); 20390b57cec5SDimitry Andric } 20400b57cec5SDimitry Andric return ParseVariablesForCompileUnit(*sc.comp_unit, *variables); 20410b57cec5SDimitry Andric } 20420b57cec5SDimitry Andric 20430b57cec5SDimitry Andric llvm_unreachable("Unreachable!"); 20440b57cec5SDimitry Andric } 20450b57cec5SDimitry Andric 20460b57cec5SDimitry Andric CompilerDecl SymbolFileNativePDB::GetDeclForUID(lldb::user_id_t uid) { 2047bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 2048bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 2049bdd1243dSDimitry Andric return CompilerDecl(); 2050bdd1243dSDimitry Andric auto ts = *ts_or_err; 2051bdd1243dSDimitry Andric if (!ts) 2052bdd1243dSDimitry Andric return {}; 2053bdd1243dSDimitry Andric 2054bdd1243dSDimitry Andric if (auto decl = ts->GetNativePDBParser()->GetOrCreateDeclForUid(uid)) 205581ad6265SDimitry Andric return *decl; 20569dba64beSDimitry Andric return CompilerDecl(); 20570b57cec5SDimitry Andric } 20580b57cec5SDimitry Andric 20590b57cec5SDimitry Andric CompilerDeclContext 20600b57cec5SDimitry Andric SymbolFileNativePDB::GetDeclContextForUID(lldb::user_id_t uid) { 2061bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 2062bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 2063bdd1243dSDimitry Andric return {}; 2064bdd1243dSDimitry Andric auto ts = *ts_or_err; 2065bdd1243dSDimitry Andric if (!ts) 2066bdd1243dSDimitry Andric return {}; 2067bdd1243dSDimitry Andric 2068bdd1243dSDimitry Andric PdbAstBuilder *ast_builder = ts->GetNativePDBParser(); 20690b57cec5SDimitry Andric clang::DeclContext *context = 2070bdd1243dSDimitry Andric ast_builder->GetOrCreateDeclContextForUid(PdbSymUid(uid)); 20710b57cec5SDimitry Andric if (!context) 20720b57cec5SDimitry Andric return {}; 20730b57cec5SDimitry Andric 2074bdd1243dSDimitry Andric return ast_builder->ToCompilerDeclContext(*context); 20750b57cec5SDimitry Andric } 20760b57cec5SDimitry Andric 20770b57cec5SDimitry Andric CompilerDeclContext 20780b57cec5SDimitry Andric SymbolFileNativePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { 2079bdd1243dSDimitry Andric auto ts_or_err = GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 2080bdd1243dSDimitry Andric if (auto err = ts_or_err.takeError()) 2081bdd1243dSDimitry Andric return CompilerDeclContext(); 2082bdd1243dSDimitry Andric auto ts = *ts_or_err; 2083bdd1243dSDimitry Andric if (!ts) 2084bdd1243dSDimitry Andric return {}; 2085bdd1243dSDimitry Andric 2086bdd1243dSDimitry Andric PdbAstBuilder *ast_builder = ts->GetNativePDBParser(); 2087bdd1243dSDimitry Andric clang::DeclContext *context = ast_builder->GetParentDeclContext(PdbSymUid(uid)); 2088bdd1243dSDimitry Andric if (!context) 2089bdd1243dSDimitry Andric return CompilerDeclContext(); 2090bdd1243dSDimitry Andric return ast_builder->ToCompilerDeclContext(*context); 20910b57cec5SDimitry Andric } 20920b57cec5SDimitry Andric 20930b57cec5SDimitry Andric Type *SymbolFileNativePDB::ResolveTypeUID(lldb::user_id_t type_uid) { 20949dba64beSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 20950b57cec5SDimitry Andric auto iter = m_types.find(type_uid); 20960b57cec5SDimitry Andric // lldb should not be passing us non-sensical type uids. the only way it 20970b57cec5SDimitry Andric // could have a type uid in the first place is if we handed it out, in which 20980b57cec5SDimitry Andric // case we should know about the type. However, that doesn't mean we've 20990b57cec5SDimitry Andric // instantiated it yet. We can vend out a UID for a future type. So if the 21000b57cec5SDimitry Andric // type doesn't exist, let's instantiate it now. 21010b57cec5SDimitry Andric if (iter != m_types.end()) 21020b57cec5SDimitry Andric return &*iter->second; 21030b57cec5SDimitry Andric 21040b57cec5SDimitry Andric PdbSymUid uid(type_uid); 21050b57cec5SDimitry Andric lldbassert(uid.kind() == PdbSymUidKind::Type); 21060b57cec5SDimitry Andric PdbTypeSymId type_id = uid.asTypeSym(); 21070b57cec5SDimitry Andric if (type_id.index.isNoneType()) 21080b57cec5SDimitry Andric return nullptr; 21090b57cec5SDimitry Andric 21100b57cec5SDimitry Andric TypeSP type_sp = CreateAndCacheType(type_id); 2111bdd1243dSDimitry Andric if (!type_sp) 2112bdd1243dSDimitry Andric return nullptr; 21130b57cec5SDimitry Andric return &*type_sp; 21140b57cec5SDimitry Andric } 21150b57cec5SDimitry Andric 2116bdd1243dSDimitry Andric std::optional<SymbolFile::ArrayInfo> 21170b57cec5SDimitry Andric SymbolFileNativePDB::GetDynamicArrayInfoForUID( 21180b57cec5SDimitry Andric lldb::user_id_t type_uid, const lldb_private::ExecutionContext *exe_ctx) { 2119bdd1243dSDimitry Andric return std::nullopt; 21200b57cec5SDimitry Andric } 21210b57cec5SDimitry Andric 21220b57cec5SDimitry Andric bool SymbolFileNativePDB::CompleteType(CompilerType &compiler_type) { 2123bdd1243dSDimitry Andric std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); 2124bdd1243dSDimitry Andric auto ts = compiler_type.GetTypeSystem(); 2125bdd1243dSDimitry Andric auto clang_type_system = ts.dyn_cast_or_null<TypeSystemClang>(); 2126bdd1243dSDimitry Andric if (!clang_type_system) 2127bdd1243dSDimitry Andric return false; 2128bdd1243dSDimitry Andric 2129bdd1243dSDimitry Andric PdbAstBuilder *ast_builder = 2130bdd1243dSDimitry Andric static_cast<PdbAstBuilder *>(clang_type_system->GetNativePDBParser()); 2131bdd1243dSDimitry Andric if (ast_builder && 2132bdd1243dSDimitry Andric ast_builder->GetClangASTImporter().CanImport(compiler_type)) 2133bdd1243dSDimitry Andric return ast_builder->GetClangASTImporter().CompleteType(compiler_type); 21340b57cec5SDimitry Andric clang::QualType qt = 21350b57cec5SDimitry Andric clang::QualType::getFromOpaquePtr(compiler_type.GetOpaqueQualType()); 21360b57cec5SDimitry Andric 2137bdd1243dSDimitry Andric return ast_builder->CompleteType(qt); 21380b57cec5SDimitry Andric } 21390b57cec5SDimitry Andric 21409dba64beSDimitry Andric void SymbolFileNativePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, 21410b57cec5SDimitry Andric TypeClass type_mask, 21429dba64beSDimitry Andric lldb_private::TypeList &type_list) {} 21430b57cec5SDimitry Andric 214406c3fb27SDimitry Andric CompilerDeclContext SymbolFileNativePDB::FindNamespace( 214506c3fb27SDimitry Andric ConstString name, const CompilerDeclContext &parent_decl_ctx, bool) { 21460b57cec5SDimitry Andric return {}; 21470b57cec5SDimitry Andric } 21480b57cec5SDimitry Andric 2149bdd1243dSDimitry Andric llvm::Expected<lldb::TypeSystemSP> 21500b57cec5SDimitry Andric SymbolFileNativePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { 21519dba64beSDimitry Andric auto type_system_or_err = 21529dba64beSDimitry Andric m_objfile_sp->GetModule()->GetTypeSystemForLanguage(language); 2153bdd1243dSDimitry Andric if (type_system_or_err) 2154bdd1243dSDimitry Andric if (auto ts = *type_system_or_err) 2155bdd1243dSDimitry Andric ts->SetSymbolFile(this); 21569dba64beSDimitry Andric return type_system_or_err; 21570b57cec5SDimitry Andric } 21580b57cec5SDimitry Andric 2159*0fca6ea1SDimitry Andric uint64_t SymbolFileNativePDB::GetDebugInfoSize(bool load_all_debug_info) { 2160349cc55cSDimitry Andric // PDB files are a separate file that contains all debug info. 2161349cc55cSDimitry Andric return m_index->pdb().getFileSize(); 21620b57cec5SDimitry Andric } 2163bdd1243dSDimitry Andric 2164bdd1243dSDimitry Andric void SymbolFileNativePDB::BuildParentMap() { 2165bdd1243dSDimitry Andric LazyRandomTypeCollection &types = m_index->tpi().typeCollection(); 2166bdd1243dSDimitry Andric 2167bdd1243dSDimitry Andric llvm::DenseMap<TypeIndex, TypeIndex> forward_to_full; 2168bdd1243dSDimitry Andric llvm::DenseMap<TypeIndex, TypeIndex> full_to_forward; 2169bdd1243dSDimitry Andric 2170bdd1243dSDimitry Andric struct RecordIndices { 2171bdd1243dSDimitry Andric TypeIndex forward; 2172bdd1243dSDimitry Andric TypeIndex full; 2173bdd1243dSDimitry Andric }; 2174bdd1243dSDimitry Andric 2175bdd1243dSDimitry Andric llvm::StringMap<RecordIndices> record_indices; 2176bdd1243dSDimitry Andric 2177bdd1243dSDimitry Andric for (auto ti = types.getFirst(); ti; ti = types.getNext(*ti)) { 2178bdd1243dSDimitry Andric CVType type = types.getType(*ti); 2179bdd1243dSDimitry Andric if (!IsTagRecord(type)) 2180bdd1243dSDimitry Andric continue; 2181bdd1243dSDimitry Andric 2182bdd1243dSDimitry Andric CVTagRecord tag = CVTagRecord::create(type); 2183bdd1243dSDimitry Andric 2184bdd1243dSDimitry Andric RecordIndices &indices = record_indices[tag.asTag().getUniqueName()]; 2185bdd1243dSDimitry Andric if (tag.asTag().isForwardRef()) 2186bdd1243dSDimitry Andric indices.forward = *ti; 2187bdd1243dSDimitry Andric else 2188bdd1243dSDimitry Andric indices.full = *ti; 2189bdd1243dSDimitry Andric 2190bdd1243dSDimitry Andric if (indices.full != TypeIndex::None() && 2191bdd1243dSDimitry Andric indices.forward != TypeIndex::None()) { 2192bdd1243dSDimitry Andric forward_to_full[indices.forward] = indices.full; 2193bdd1243dSDimitry Andric full_to_forward[indices.full] = indices.forward; 2194bdd1243dSDimitry Andric } 2195bdd1243dSDimitry Andric 2196bdd1243dSDimitry Andric // We're looking for LF_NESTTYPE records in the field list, so ignore 2197bdd1243dSDimitry Andric // forward references (no field list), and anything without a nested class 2198bdd1243dSDimitry Andric // (since there won't be any LF_NESTTYPE records). 2199bdd1243dSDimitry Andric if (tag.asTag().isForwardRef() || !tag.asTag().containsNestedClass()) 2200bdd1243dSDimitry Andric continue; 2201bdd1243dSDimitry Andric 2202bdd1243dSDimitry Andric struct ProcessTpiStream : public TypeVisitorCallbacks { 2203bdd1243dSDimitry Andric ProcessTpiStream(PdbIndex &index, TypeIndex parent, 2204bdd1243dSDimitry Andric const CVTagRecord &parent_cvt, 2205bdd1243dSDimitry Andric llvm::DenseMap<TypeIndex, TypeIndex> &parents) 2206bdd1243dSDimitry Andric : index(index), parents(parents), parent(parent), 2207bdd1243dSDimitry Andric parent_cvt(parent_cvt) {} 2208bdd1243dSDimitry Andric 2209bdd1243dSDimitry Andric PdbIndex &index; 2210bdd1243dSDimitry Andric llvm::DenseMap<TypeIndex, TypeIndex> &parents; 2211bdd1243dSDimitry Andric 2212bdd1243dSDimitry Andric unsigned unnamed_type_index = 1; 2213bdd1243dSDimitry Andric TypeIndex parent; 2214bdd1243dSDimitry Andric const CVTagRecord &parent_cvt; 2215bdd1243dSDimitry Andric 2216bdd1243dSDimitry Andric llvm::Error visitKnownMember(CVMemberRecord &CVR, 2217bdd1243dSDimitry Andric NestedTypeRecord &Record) override { 2218bdd1243dSDimitry Andric std::string unnamed_type_name; 2219bdd1243dSDimitry Andric if (Record.Name.empty()) { 2220bdd1243dSDimitry Andric unnamed_type_name = 2221bdd1243dSDimitry Andric llvm::formatv("<unnamed-type-$S{0}>", unnamed_type_index).str(); 2222bdd1243dSDimitry Andric Record.Name = unnamed_type_name; 2223bdd1243dSDimitry Andric ++unnamed_type_index; 2224bdd1243dSDimitry Andric } 2225bdd1243dSDimitry Andric std::optional<CVTagRecord> tag = 2226bdd1243dSDimitry Andric GetNestedTagDefinition(Record, parent_cvt, index.tpi()); 2227bdd1243dSDimitry Andric if (!tag) 2228bdd1243dSDimitry Andric return llvm::ErrorSuccess(); 2229bdd1243dSDimitry Andric 2230bdd1243dSDimitry Andric parents[Record.Type] = parent; 2231bdd1243dSDimitry Andric return llvm::ErrorSuccess(); 2232bdd1243dSDimitry Andric } 2233bdd1243dSDimitry Andric }; 2234bdd1243dSDimitry Andric 2235bdd1243dSDimitry Andric CVType field_list_cvt = m_index->tpi().getType(tag.asTag().FieldList); 2236bdd1243dSDimitry Andric ProcessTpiStream process(*m_index, *ti, tag, m_parent_types); 2237bdd1243dSDimitry Andric FieldListRecord field_list; 2238bdd1243dSDimitry Andric if (llvm::Error error = TypeDeserializer::deserializeAs<FieldListRecord>( 2239bdd1243dSDimitry Andric field_list_cvt, field_list)) 2240bdd1243dSDimitry Andric llvm::consumeError(std::move(error)); 2241bdd1243dSDimitry Andric if (llvm::Error error = visitMemberRecordStream(field_list.Data, process)) 2242bdd1243dSDimitry Andric llvm::consumeError(std::move(error)); 2243bdd1243dSDimitry Andric } 2244bdd1243dSDimitry Andric 2245bdd1243dSDimitry Andric // Now that we know the forward -> full mapping of all type indices, we can 2246bdd1243dSDimitry Andric // re-write all the indices. At the end of this process, we want a mapping 2247bdd1243dSDimitry Andric // consisting of fwd -> full and full -> full for all child -> parent indices. 2248bdd1243dSDimitry Andric // We can re-write the values in place, but for the keys, we must save them 2249bdd1243dSDimitry Andric // off so that we don't modify the map in place while also iterating it. 2250bdd1243dSDimitry Andric std::vector<TypeIndex> full_keys; 2251bdd1243dSDimitry Andric std::vector<TypeIndex> fwd_keys; 2252bdd1243dSDimitry Andric for (auto &entry : m_parent_types) { 2253bdd1243dSDimitry Andric TypeIndex key = entry.first; 2254bdd1243dSDimitry Andric TypeIndex value = entry.second; 2255bdd1243dSDimitry Andric 2256bdd1243dSDimitry Andric auto iter = forward_to_full.find(value); 2257bdd1243dSDimitry Andric if (iter != forward_to_full.end()) 2258bdd1243dSDimitry Andric entry.second = iter->second; 2259bdd1243dSDimitry Andric 2260bdd1243dSDimitry Andric iter = forward_to_full.find(key); 2261bdd1243dSDimitry Andric if (iter != forward_to_full.end()) 2262bdd1243dSDimitry Andric fwd_keys.push_back(key); 2263bdd1243dSDimitry Andric else 2264bdd1243dSDimitry Andric full_keys.push_back(key); 2265bdd1243dSDimitry Andric } 2266bdd1243dSDimitry Andric for (TypeIndex fwd : fwd_keys) { 2267bdd1243dSDimitry Andric TypeIndex full = forward_to_full[fwd]; 22681db9f3b2SDimitry Andric TypeIndex parent_idx = m_parent_types[fwd]; 22691db9f3b2SDimitry Andric m_parent_types[full] = parent_idx; 2270bdd1243dSDimitry Andric } 2271bdd1243dSDimitry Andric for (TypeIndex full : full_keys) { 2272bdd1243dSDimitry Andric TypeIndex fwd = full_to_forward[full]; 2273bdd1243dSDimitry Andric m_parent_types[fwd] = m_parent_types[full]; 2274bdd1243dSDimitry Andric } 2275bdd1243dSDimitry Andric } 2276bdd1243dSDimitry Andric 2277bdd1243dSDimitry Andric std::optional<PdbCompilandSymId> 2278bdd1243dSDimitry Andric SymbolFileNativePDB::FindSymbolScope(PdbCompilandSymId id) { 2279bdd1243dSDimitry Andric CVSymbol sym = m_index->ReadSymbolRecord(id); 2280bdd1243dSDimitry Andric if (symbolOpensScope(sym.kind())) { 2281bdd1243dSDimitry Andric // If this exact symbol opens a scope, we can just directly access its 2282bdd1243dSDimitry Andric // parent. 2283bdd1243dSDimitry Andric id.offset = getScopeParentOffset(sym); 2284bdd1243dSDimitry Andric // Global symbols have parent offset of 0. Return std::nullopt to indicate 2285bdd1243dSDimitry Andric // this. 2286bdd1243dSDimitry Andric if (id.offset == 0) 2287bdd1243dSDimitry Andric return std::nullopt; 2288bdd1243dSDimitry Andric return id; 2289bdd1243dSDimitry Andric } 2290bdd1243dSDimitry Andric 2291bdd1243dSDimitry Andric // Otherwise we need to start at the beginning and iterate forward until we 2292bdd1243dSDimitry Andric // reach (or pass) this particular symbol 2293bdd1243dSDimitry Andric CompilandIndexItem &cii = m_index->compilands().GetOrCreateCompiland(id.modi); 2294bdd1243dSDimitry Andric const CVSymbolArray &syms = cii.m_debug_stream.getSymbolArray(); 2295bdd1243dSDimitry Andric 2296bdd1243dSDimitry Andric auto begin = syms.begin(); 2297bdd1243dSDimitry Andric auto end = syms.at(id.offset); 2298bdd1243dSDimitry Andric std::vector<PdbCompilandSymId> scope_stack; 2299bdd1243dSDimitry Andric 2300bdd1243dSDimitry Andric while (begin != end) { 2301bdd1243dSDimitry Andric if (begin.offset() > id.offset) { 2302bdd1243dSDimitry Andric // We passed it. We couldn't even find this symbol record. 2303bdd1243dSDimitry Andric lldbassert(false && "Invalid compiland symbol id!"); 2304bdd1243dSDimitry Andric return std::nullopt; 2305bdd1243dSDimitry Andric } 2306bdd1243dSDimitry Andric 2307bdd1243dSDimitry Andric // We haven't found the symbol yet. Check if we need to open or close the 2308bdd1243dSDimitry Andric // scope stack. 2309bdd1243dSDimitry Andric if (symbolOpensScope(begin->kind())) { 2310bdd1243dSDimitry Andric // We can use the end offset of the scope to determine whether or not 2311bdd1243dSDimitry Andric // we can just outright skip this entire scope. 2312bdd1243dSDimitry Andric uint32_t scope_end = getScopeEndOffset(*begin); 2313bdd1243dSDimitry Andric if (scope_end < id.offset) { 2314bdd1243dSDimitry Andric begin = syms.at(scope_end); 2315bdd1243dSDimitry Andric } else { 2316bdd1243dSDimitry Andric // The symbol we're looking for is somewhere in this scope. 2317bdd1243dSDimitry Andric scope_stack.emplace_back(id.modi, begin.offset()); 2318bdd1243dSDimitry Andric } 2319bdd1243dSDimitry Andric } else if (symbolEndsScope(begin->kind())) { 2320bdd1243dSDimitry Andric scope_stack.pop_back(); 2321bdd1243dSDimitry Andric } 2322bdd1243dSDimitry Andric ++begin; 2323bdd1243dSDimitry Andric } 2324bdd1243dSDimitry Andric if (scope_stack.empty()) 2325bdd1243dSDimitry Andric return std::nullopt; 2326bdd1243dSDimitry Andric // We have a match! Return the top of the stack 2327bdd1243dSDimitry Andric return scope_stack.back(); 2328bdd1243dSDimitry Andric } 2329bdd1243dSDimitry Andric 2330bdd1243dSDimitry Andric std::optional<llvm::codeview::TypeIndex> 2331bdd1243dSDimitry Andric SymbolFileNativePDB::GetParentType(llvm::codeview::TypeIndex ti) { 2332bdd1243dSDimitry Andric auto parent_iter = m_parent_types.find(ti); 2333bdd1243dSDimitry Andric if (parent_iter == m_parent_types.end()) 2334bdd1243dSDimitry Andric return std::nullopt; 2335bdd1243dSDimitry Andric return parent_iter->second; 2336bdd1243dSDimitry Andric } 2337