174e08ca0SZachary Turner //===-- SymbolFilePDB.cpp ---------------------------------------*- C++ -*-===// 274e08ca0SZachary Turner // 374e08ca0SZachary Turner // The LLVM Compiler Infrastructure 474e08ca0SZachary Turner // 574e08ca0SZachary Turner // This file is distributed under the University of Illinois Open Source 674e08ca0SZachary Turner // License. See LICENSE.TXT for details. 774e08ca0SZachary Turner // 874e08ca0SZachary Turner //===----------------------------------------------------------------------===// 974e08ca0SZachary Turner 1074e08ca0SZachary Turner #include "SymbolFilePDB.h" 1174e08ca0SZachary Turner 1242dff790SZachary Turner #include "clang/Lex/Lexer.h" 1342dff790SZachary Turner 1474e08ca0SZachary Turner #include "lldb/Core/Module.h" 1574e08ca0SZachary Turner #include "lldb/Core/PluginManager.h" 1642dff790SZachary Turner #include "lldb/Symbol/ClangASTContext.h" 1774e08ca0SZachary Turner #include "lldb/Symbol/CompileUnit.h" 1874e08ca0SZachary Turner #include "lldb/Symbol/LineTable.h" 1974e08ca0SZachary Turner #include "lldb/Symbol/ObjectFile.h" 2074e08ca0SZachary Turner #include "lldb/Symbol/SymbolContext.h" 2110a02577SAaron Smith #include "lldb/Symbol/SymbolVendor.h" 2242dff790SZachary Turner #include "lldb/Symbol/TypeMap.h" 23ec40f818SAaron Smith #include "lldb/Symbol/TypeList.h" 2486e9434dSAaron Smith #include "lldb/Utility/RegularExpression.h" 2574e08ca0SZachary Turner 26b8d8c62bSPavel Labath #include "llvm/DebugInfo/PDB/GenericError.h" 271f8552abSAaron Smith #include "llvm/DebugInfo/PDB/IPDBDataStream.h" 2874e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" 2974e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" 3074e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" 311f8552abSAaron Smith #include "llvm/DebugInfo/PDB/IPDBTable.h" 3274e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbol.h" 337ac1c780SAaron Smith #include "llvm/DebugInfo/PDB/PDBSymbolBlock.h" 3474e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" 3574e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h" 361f8552abSAaron Smith #include "llvm/DebugInfo/PDB/PDBSymbolData.h" 3774e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" 3874e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 3974e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" 4074e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" 417ac1c780SAaron Smith #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" 4242dff790SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" 4342dff790SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" 4442dff790SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" 4542dff790SZachary Turner 467ac1c780SAaron Smith #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" 4742dff790SZachary Turner #include "Plugins/SymbolFile/PDB/PDBASTParser.h" 4842dff790SZachary Turner 4942dff790SZachary Turner #include <regex> 5074e08ca0SZachary Turner 5110a02577SAaron Smith using namespace lldb; 5274e08ca0SZachary Turner using namespace lldb_private; 5354fd7ff6SZachary Turner using namespace llvm::pdb; 5474e08ca0SZachary Turner 55b9c1b51eSKate Stone namespace { 56b9c1b51eSKate Stone lldb::LanguageType TranslateLanguage(PDB_Lang lang) { 57b9c1b51eSKate Stone switch (lang) { 5854fd7ff6SZachary Turner case PDB_Lang::Cpp: 5974e08ca0SZachary Turner return lldb::LanguageType::eLanguageTypeC_plus_plus; 6054fd7ff6SZachary Turner case PDB_Lang::C: 6174e08ca0SZachary Turner return lldb::LanguageType::eLanguageTypeC; 6274e08ca0SZachary Turner default: 6374e08ca0SZachary Turner return lldb::LanguageType::eLanguageTypeUnknown; 6474e08ca0SZachary Turner } 6574e08ca0SZachary Turner } 667e8c7beaSZachary Turner 67b9c1b51eSKate Stone bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line, 68b9c1b51eSKate Stone uint32_t addr_length) { 69b9c1b51eSKate Stone return ((requested_line == 0 || actual_line == requested_line) && 70b9c1b51eSKate Stone addr_length > 0); 717e8c7beaSZachary Turner } 7274e08ca0SZachary Turner } 7374e08ca0SZachary Turner 74b9c1b51eSKate Stone void SymbolFilePDB::Initialize() { 75b9c1b51eSKate Stone PluginManager::RegisterPlugin(GetPluginNameStatic(), 76b9c1b51eSKate Stone GetPluginDescriptionStatic(), CreateInstance, 7774e08ca0SZachary Turner DebuggerInitialize); 7874e08ca0SZachary Turner } 7974e08ca0SZachary Turner 80b9c1b51eSKate Stone void SymbolFilePDB::Terminate() { 8174e08ca0SZachary Turner PluginManager::UnregisterPlugin(CreateInstance); 8274e08ca0SZachary Turner } 8374e08ca0SZachary Turner 84b9c1b51eSKate Stone void SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {} 8574e08ca0SZachary Turner 86b9c1b51eSKate Stone lldb_private::ConstString SymbolFilePDB::GetPluginNameStatic() { 8774e08ca0SZachary Turner static ConstString g_name("pdb"); 8874e08ca0SZachary Turner return g_name; 8974e08ca0SZachary Turner } 9074e08ca0SZachary Turner 91b9c1b51eSKate Stone const char *SymbolFilePDB::GetPluginDescriptionStatic() { 9274e08ca0SZachary Turner return "Microsoft PDB debug symbol file reader."; 9374e08ca0SZachary Turner } 9474e08ca0SZachary Turner 9574e08ca0SZachary Turner lldb_private::SymbolFile * 96b9c1b51eSKate Stone SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) { 9774e08ca0SZachary Turner return new SymbolFilePDB(obj_file); 9874e08ca0SZachary Turner } 9974e08ca0SZachary Turner 10074e08ca0SZachary Turner SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file) 10110a02577SAaron Smith : SymbolFile(object_file), m_session_up(), m_global_scope_up(), 10210a02577SAaron Smith m_cached_compile_unit_count(0), m_tu_decl_ctx_up() {} 10374e08ca0SZachary Turner 104b9c1b51eSKate Stone SymbolFilePDB::~SymbolFilePDB() {} 10574e08ca0SZachary Turner 106b9c1b51eSKate Stone uint32_t SymbolFilePDB::CalculateAbilities() { 1071f8552abSAaron Smith uint32_t abilities = 0; 1081f8552abSAaron Smith if (!m_obj_file) 1091f8552abSAaron Smith return 0; 1101f8552abSAaron Smith 111b9c1b51eSKate Stone if (!m_session_up) { 11274e08ca0SZachary Turner // Lazily load and match the PDB file, but only do this once. 11374e08ca0SZachary Turner std::string exePath = m_obj_file->GetFileSpec().GetPath(); 114b9c1b51eSKate Stone auto error = loadDataForEXE(PDB_ReaderType::DIA, llvm::StringRef(exePath), 115b9c1b51eSKate Stone m_session_up); 116b9c1b51eSKate Stone if (error) { 1174fd6a960SZachary Turner llvm::consumeError(std::move(error)); 1181f8552abSAaron Smith auto module_sp = m_obj_file->GetModule(); 1191f8552abSAaron Smith if (!module_sp) 1201f8552abSAaron Smith return 0; 1211f8552abSAaron Smith // See if any symbol file is specified through `--symfile` option. 1221f8552abSAaron Smith FileSpec symfile = module_sp->GetSymbolFileFileSpec(); 1231f8552abSAaron Smith if (!symfile) 1241f8552abSAaron Smith return 0; 1251f8552abSAaron Smith error = loadDataForPDB(PDB_ReaderType::DIA, 1261f8552abSAaron Smith llvm::StringRef(symfile.GetPath()), 1271f8552abSAaron Smith m_session_up); 1281f8552abSAaron Smith if (error) { 1291f8552abSAaron Smith llvm::consumeError(std::move(error)); 13074e08ca0SZachary Turner return 0; 13174e08ca0SZachary Turner } 132b8d8c62bSPavel Labath } 1331f8552abSAaron Smith } 1341f8552abSAaron Smith if (!m_session_up.get()) 1351f8552abSAaron Smith return 0; 1361f8552abSAaron Smith 1371f8552abSAaron Smith auto enum_tables_up = m_session_up->getEnumTables(); 1381f8552abSAaron Smith if (!enum_tables_up) 1391f8552abSAaron Smith return 0; 1401f8552abSAaron Smith while (auto table_up = enum_tables_up->getNext()) { 1411f8552abSAaron Smith if (table_up->getItemCount() == 0) 1421f8552abSAaron Smith continue; 1431f8552abSAaron Smith auto type = table_up->getTableType(); 1441f8552abSAaron Smith switch (type) { 1451f8552abSAaron Smith case PDB_TableType::Symbols: 1461f8552abSAaron Smith // This table represents a store of symbols with types listed in 1471f8552abSAaron Smith // PDBSym_Type 1481f8552abSAaron Smith abilities |= (CompileUnits | Functions | Blocks | 1491f8552abSAaron Smith GlobalVariables | LocalVariables | VariableTypes); 1501f8552abSAaron Smith break; 1511f8552abSAaron Smith case PDB_TableType::LineNumbers: 1521f8552abSAaron Smith abilities |= LineTables; 1531f8552abSAaron Smith break; 1541f8552abSAaron Smith default: break; 1551f8552abSAaron Smith } 1561f8552abSAaron Smith } 1571f8552abSAaron Smith return abilities; 15874e08ca0SZachary Turner } 15974e08ca0SZachary Turner 160b9c1b51eSKate Stone void SymbolFilePDB::InitializeObject() { 16174e08ca0SZachary Turner lldb::addr_t obj_load_address = m_obj_file->GetFileOffset(); 16210a02577SAaron Smith lldbassert(obj_load_address && 16310a02577SAaron Smith obj_load_address != LLDB_INVALID_ADDRESS); 16474e08ca0SZachary Turner m_session_up->setLoadAddress(obj_load_address); 16510a02577SAaron Smith if (!m_global_scope_up) 16610a02577SAaron Smith m_global_scope_up = m_session_up->getGlobalScope(); 16710a02577SAaron Smith lldbassert(m_global_scope_up.get()); 16842dff790SZachary Turner 169b9c1b51eSKate Stone TypeSystem *type_system = 170b9c1b51eSKate Stone GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 171b9c1b51eSKate Stone ClangASTContext *clang_type_system = 172b9c1b51eSKate Stone llvm::dyn_cast_or_null<ClangASTContext>(type_system); 17310a02577SAaron Smith lldbassert(clang_type_system); 174b9c1b51eSKate Stone m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>( 175b9c1b51eSKate Stone type_system, clang_type_system->GetTranslationUnitDecl()); 17674e08ca0SZachary Turner } 17774e08ca0SZachary Turner 178b9c1b51eSKate Stone uint32_t SymbolFilePDB::GetNumCompileUnits() { 179b9c1b51eSKate Stone if (m_cached_compile_unit_count == 0) { 18010a02577SAaron Smith auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); 18110a02577SAaron Smith if (!compilands) 18210a02577SAaron Smith return 0; 18310a02577SAaron Smith 18410a02577SAaron Smith // The linker could link *.dll (compiland language = LINK), or import 18510a02577SAaron Smith // *.dll. For example, a compiland with name `Import:KERNEL32.dll` 18610a02577SAaron Smith // could be found as a child of the global scope (PDB executable). 18710a02577SAaron Smith // Usually, such compilands contain `thunk` symbols in which we are not 18810a02577SAaron Smith // interested for now. However we still count them in the compiland list. 18910a02577SAaron Smith // If we perform any compiland related activity, like finding symbols 19010a02577SAaron Smith // through llvm::pdb::IPDBSession methods, such compilands will all be 19110a02577SAaron Smith // searched automatically no matter whether we include them or not. 19274e08ca0SZachary Turner m_cached_compile_unit_count = compilands->getChildCount(); 19374e08ca0SZachary Turner 194b9c1b51eSKate Stone // The linker can inject an additional "dummy" compilation unit into the 1959d0eb996SAdrian McCarthy // PDB. Ignore this special compile unit for our purposes, if it is there. 1969d0eb996SAdrian McCarthy // It is always the last one. 19710a02577SAaron Smith auto last_compiland_up = 19810a02577SAaron Smith compilands->getChildAtIndex(m_cached_compile_unit_count - 1); 19910a02577SAaron Smith lldbassert(last_compiland_up.get()); 20010a02577SAaron Smith std::string name = last_compiland_up->getName(); 20174e08ca0SZachary Turner if (name == "* Linker *") 20274e08ca0SZachary Turner --m_cached_compile_unit_count; 20374e08ca0SZachary Turner } 20474e08ca0SZachary Turner return m_cached_compile_unit_count; 20574e08ca0SZachary Turner } 20674e08ca0SZachary Turner 20710a02577SAaron Smith void SymbolFilePDB::GetCompileUnitIndex( 20810a02577SAaron Smith const llvm::pdb::PDBSymbolCompiland *pdb_compiland, 20910a02577SAaron Smith uint32_t &index) { 21010a02577SAaron Smith if (!pdb_compiland) 21110a02577SAaron Smith return; 21210a02577SAaron Smith 21310a02577SAaron Smith auto results_up = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); 21410a02577SAaron Smith if (!results_up) 21510a02577SAaron Smith return; 21610a02577SAaron Smith auto uid = pdb_compiland->getSymIndexId(); 217fbdf0b93SRaphael Isemann for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) { 21810a02577SAaron Smith auto compiland_up = results_up->getChildAtIndex(cu_idx); 21910a02577SAaron Smith if (!compiland_up) 22010a02577SAaron Smith continue; 22110a02577SAaron Smith if (compiland_up->getSymIndexId() == uid) { 22210a02577SAaron Smith index = cu_idx; 22310a02577SAaron Smith return; 22410a02577SAaron Smith } 22510a02577SAaron Smith } 22610a02577SAaron Smith index = UINT32_MAX; 22710a02577SAaron Smith return; 22810a02577SAaron Smith } 22910a02577SAaron Smith 23010a02577SAaron Smith std::unique_ptr<llvm::pdb::PDBSymbolCompiland> 23110a02577SAaron Smith SymbolFilePDB::GetPDBCompilandByUID(uint32_t uid) { 23210a02577SAaron Smith return m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(uid); 23310a02577SAaron Smith } 23410a02577SAaron Smith 235b9c1b51eSKate Stone lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) { 23610a02577SAaron Smith if (index >= GetNumCompileUnits()) 23710a02577SAaron Smith return CompUnitSP(); 23874e08ca0SZachary Turner 23910a02577SAaron Smith // Assuming we always retrieve same compilands listed in same order through 24010a02577SAaron Smith // `PDBSymbolExe::findAllChildren` method, otherwise using `index` to get a 24110a02577SAaron Smith // compile unit makes no sense. 24210a02577SAaron Smith auto results = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); 24310a02577SAaron Smith if (!results) 24410a02577SAaron Smith return CompUnitSP(); 24510a02577SAaron Smith auto compiland_up = results->getChildAtIndex(index); 24610a02577SAaron Smith if (!compiland_up) 24710a02577SAaron Smith return CompUnitSP(); 24810a02577SAaron Smith return ParseCompileUnitForUID(compiland_up->getSymIndexId(), index); 24974e08ca0SZachary Turner } 25074e08ca0SZachary Turner 25174e08ca0SZachary Turner lldb::LanguageType 252b9c1b51eSKate Stone SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) { 25374e08ca0SZachary Turner // What fields should I expect to be filled out on the SymbolContext? Is it 25474e08ca0SZachary Turner // safe to assume that `sc.comp_unit` is valid? 25574e08ca0SZachary Turner if (!sc.comp_unit) 25674e08ca0SZachary Turner return lldb::eLanguageTypeUnknown; 25774e08ca0SZachary Turner 25810a02577SAaron Smith auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); 25910a02577SAaron Smith if (!compiland_up) 26074e08ca0SZachary Turner return lldb::eLanguageTypeUnknown; 26110a02577SAaron Smith auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>(); 26274e08ca0SZachary Turner if (!details) 26374e08ca0SZachary Turner return lldb::eLanguageTypeUnknown; 26474e08ca0SZachary Turner return TranslateLanguage(details->getLanguage()); 26574e08ca0SZachary Turner } 26674e08ca0SZachary Turner 2677ac1c780SAaron Smith lldb_private::Function * 2687ac1c780SAaron Smith SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc( 2697ac1c780SAaron Smith const PDBSymbolFunc *pdb_func, 2707ac1c780SAaron Smith const lldb_private::SymbolContext &sc) { 2717ac1c780SAaron Smith assert(pdb_func != nullptr); 2727ac1c780SAaron Smith lldbassert(sc.comp_unit && sc.module_sp.get()); 2737ac1c780SAaron Smith 2747ac1c780SAaron Smith auto file_vm_addr = pdb_func->getVirtualAddress(); 2757ac1c780SAaron Smith if (file_vm_addr == LLDB_INVALID_ADDRESS) 2767ac1c780SAaron Smith return nullptr; 2777ac1c780SAaron Smith 2787ac1c780SAaron Smith auto func_length = pdb_func->getLength(); 2797ac1c780SAaron Smith AddressRange func_range = AddressRange(file_vm_addr, 2807ac1c780SAaron Smith func_length, 2817ac1c780SAaron Smith sc.module_sp->GetSectionList()); 2827ac1c780SAaron Smith if (!func_range.GetBaseAddress().IsValid()) 2837ac1c780SAaron Smith return nullptr; 2847ac1c780SAaron Smith 2857ac1c780SAaron Smith lldb_private::Type* func_type = ResolveTypeUID(pdb_func->getSymIndexId()); 2867ac1c780SAaron Smith if (!func_type) 2877ac1c780SAaron Smith return nullptr; 2887ac1c780SAaron Smith 289*f76fe682SAaron Smith user_id_t func_type_uid = pdb_func->getSignatureId(); 290*f76fe682SAaron Smith 2917ac1c780SAaron Smith Mangled mangled = GetMangledForPDBFunc(pdb_func); 2927ac1c780SAaron Smith 2937ac1c780SAaron Smith FunctionSP func_sp = std::make_shared<Function>(sc.comp_unit, 2947ac1c780SAaron Smith pdb_func->getSymIndexId(), 2957ac1c780SAaron Smith func_type_uid, 2967ac1c780SAaron Smith mangled, 2977ac1c780SAaron Smith func_type, 2987ac1c780SAaron Smith func_range); 2997ac1c780SAaron Smith 3007ac1c780SAaron Smith sc.comp_unit->AddFunction(func_sp); 3017ac1c780SAaron Smith return func_sp.get(); 3027ac1c780SAaron Smith } 3037ac1c780SAaron Smith 304b9c1b51eSKate Stone size_t SymbolFilePDB::ParseCompileUnitFunctions( 305b9c1b51eSKate Stone const lldb_private::SymbolContext &sc) { 3067ac1c780SAaron Smith lldbassert(sc.comp_unit); 3077ac1c780SAaron Smith size_t func_added = 0; 3087ac1c780SAaron Smith auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); 3097ac1c780SAaron Smith if (!compiland_up) 3107ac1c780SAaron Smith return 0; 3117ac1c780SAaron Smith auto results_up = compiland_up->findAllChildren<PDBSymbolFunc>(); 3127ac1c780SAaron Smith if (!results_up) 3137ac1c780SAaron Smith return 0; 3147ac1c780SAaron Smith while (auto pdb_func_up = results_up->getNext()) { 3157ac1c780SAaron Smith auto func_sp = 3167ac1c780SAaron Smith sc.comp_unit->FindFunctionByUID(pdb_func_up->getSymIndexId()); 3177ac1c780SAaron Smith if (!func_sp) { 3187ac1c780SAaron Smith if (ParseCompileUnitFunctionForPDBFunc(pdb_func_up.get(), sc)) 3197ac1c780SAaron Smith ++func_added; 3207ac1c780SAaron Smith } 3217ac1c780SAaron Smith } 3227ac1c780SAaron Smith return func_added; 32374e08ca0SZachary Turner } 32474e08ca0SZachary Turner 325b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitLineTable( 326b9c1b51eSKate Stone const lldb_private::SymbolContext &sc) { 32710a02577SAaron Smith lldbassert(sc.comp_unit); 32810a02577SAaron Smith if (sc.comp_unit->GetLineTable()) 32910a02577SAaron Smith return true; 33074e08ca0SZachary Turner return ParseCompileUnitLineTable(sc, 0); 33174e08ca0SZachary Turner } 33274e08ca0SZachary Turner 333b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitDebugMacros( 334b9c1b51eSKate Stone const lldb_private::SymbolContext &sc) { 33574e08ca0SZachary Turner // PDB doesn't contain information about macros 33674e08ca0SZachary Turner return false; 33774e08ca0SZachary Turner } 33874e08ca0SZachary Turner 339b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitSupportFiles( 340b9c1b51eSKate Stone const lldb_private::SymbolContext &sc, 341b9c1b51eSKate Stone lldb_private::FileSpecList &support_files) { 34210a02577SAaron Smith lldbassert(sc.comp_unit); 34374e08ca0SZachary Turner 344b9c1b51eSKate Stone // In theory this is unnecessary work for us, because all of this information 3459d0eb996SAdrian McCarthy // is easily (and quickly) accessible from DebugInfoPDB, so caching it a 3469d0eb996SAdrian McCarthy // second time seems like a waste. Unfortunately, there's no good way around 3479d0eb996SAdrian McCarthy // this short of a moderate refactor since SymbolVendor depends on being able 3489d0eb996SAdrian McCarthy // to cache this list. 34910a02577SAaron Smith auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); 35010a02577SAaron Smith if (!compiland_up) 35174e08ca0SZachary Turner return false; 35210a02577SAaron Smith auto files = m_session_up->getSourceFilesForCompiland(*compiland_up); 35374e08ca0SZachary Turner if (!files || files->getChildCount() == 0) 35474e08ca0SZachary Turner return false; 35574e08ca0SZachary Turner 356b9c1b51eSKate Stone while (auto file = files->getNext()) { 35710a02577SAaron Smith FileSpec spec(file->getFileName(), false, FileSpec::ePathSyntaxWindows); 35810a02577SAaron Smith support_files.AppendIfUnique(spec); 35974e08ca0SZachary Turner } 36074e08ca0SZachary Turner return true; 36174e08ca0SZachary Turner } 36274e08ca0SZachary Turner 363b9c1b51eSKate Stone bool SymbolFilePDB::ParseImportedModules( 364b9c1b51eSKate Stone const lldb_private::SymbolContext &sc, 365b9c1b51eSKate Stone std::vector<lldb_private::ConstString> &imported_modules) { 36674e08ca0SZachary Turner // PDB does not yet support module debug info 36774e08ca0SZachary Turner return false; 36874e08ca0SZachary Turner } 36974e08ca0SZachary Turner 3707ac1c780SAaron Smith static size_t 3717ac1c780SAaron Smith ParseFunctionBlocksForPDBSymbol(const lldb_private::SymbolContext &sc, 3727ac1c780SAaron Smith uint64_t func_file_vm_addr, 3737ac1c780SAaron Smith const llvm::pdb::PDBSymbol *pdb_symbol, 3747ac1c780SAaron Smith lldb_private::Block *parent_block, 3757ac1c780SAaron Smith bool is_top_parent) { 3767ac1c780SAaron Smith assert(pdb_symbol && parent_block); 3777ac1c780SAaron Smith 3787ac1c780SAaron Smith size_t num_added = 0; 3797ac1c780SAaron Smith switch (pdb_symbol->getSymTag()) { 3807ac1c780SAaron Smith case PDB_SymType::Block: 3817ac1c780SAaron Smith case PDB_SymType::Function: { 3827ac1c780SAaron Smith Block *block = nullptr; 3837ac1c780SAaron Smith auto &raw_sym = pdb_symbol->getRawSymbol(); 3847ac1c780SAaron Smith if (auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(pdb_symbol)) { 3857ac1c780SAaron Smith if (pdb_func->hasNoInlineAttribute()) 3867ac1c780SAaron Smith break; 3877ac1c780SAaron Smith if (is_top_parent) 3887ac1c780SAaron Smith block = parent_block; 3897ac1c780SAaron Smith else 3907ac1c780SAaron Smith break; 3917ac1c780SAaron Smith } else if (llvm::dyn_cast<PDBSymbolBlock>(pdb_symbol)) { 3927ac1c780SAaron Smith auto uid = pdb_symbol->getSymIndexId(); 3937ac1c780SAaron Smith if (parent_block->FindBlockByID(uid)) 3947ac1c780SAaron Smith break; 3957ac1c780SAaron Smith if (raw_sym.getVirtualAddress() < func_file_vm_addr) 3967ac1c780SAaron Smith break; 3977ac1c780SAaron Smith 3987ac1c780SAaron Smith auto block_sp = std::make_shared<Block>(pdb_symbol->getSymIndexId()); 3997ac1c780SAaron Smith parent_block->AddChild(block_sp); 4007ac1c780SAaron Smith block = block_sp.get(); 4017ac1c780SAaron Smith } else 4027ac1c780SAaron Smith llvm_unreachable("Unexpected PDB symbol!"); 4037ac1c780SAaron Smith 4047ac1c780SAaron Smith block->AddRange( 4057ac1c780SAaron Smith Block::Range(raw_sym.getVirtualAddress() - func_file_vm_addr, 4067ac1c780SAaron Smith raw_sym.getLength())); 4077ac1c780SAaron Smith block->FinalizeRanges(); 4087ac1c780SAaron Smith ++num_added; 4097ac1c780SAaron Smith 4107ac1c780SAaron Smith auto results_up = pdb_symbol->findAllChildren(); 4117ac1c780SAaron Smith if (!results_up) 4127ac1c780SAaron Smith break; 4137ac1c780SAaron Smith while (auto symbol_up = results_up->getNext()) { 4147ac1c780SAaron Smith num_added += ParseFunctionBlocksForPDBSymbol(sc, func_file_vm_addr, 4157ac1c780SAaron Smith symbol_up.get(), 4167ac1c780SAaron Smith block, false); 4177ac1c780SAaron Smith } 4187ac1c780SAaron Smith } break; 4197ac1c780SAaron Smith default: break; 4207ac1c780SAaron Smith } 4217ac1c780SAaron Smith return num_added; 4227ac1c780SAaron Smith } 4237ac1c780SAaron Smith 42474e08ca0SZachary Turner size_t 425b9c1b51eSKate Stone SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc) { 4267ac1c780SAaron Smith lldbassert(sc.comp_unit && sc.function); 4277ac1c780SAaron Smith size_t num_added = 0; 4287ac1c780SAaron Smith auto uid = sc.function->GetID(); 4297ac1c780SAaron Smith auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid); 4307ac1c780SAaron Smith if (!pdb_func_up) 4317ac1c780SAaron Smith return 0; 4327ac1c780SAaron Smith Block &parent_block = sc.function->GetBlock(false); 4337ac1c780SAaron Smith num_added = 4347ac1c780SAaron Smith ParseFunctionBlocksForPDBSymbol(sc, pdb_func_up->getVirtualAddress(), 4357ac1c780SAaron Smith pdb_func_up.get(), &parent_block, true); 4367ac1c780SAaron Smith return num_added; 437b9c1b51eSKate Stone } 438b9c1b51eSKate Stone 439b9c1b51eSKate Stone size_t SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) { 440ec40f818SAaron Smith lldbassert(sc.module_sp.get()); 441ec40f818SAaron Smith size_t num_added = 0; 442ec40f818SAaron Smith auto results_up = m_session_up->getGlobalScope()->findAllChildren(); 443ec40f818SAaron Smith if (!results_up) 444ec40f818SAaron Smith return 0; 445ec40f818SAaron Smith while (auto symbol_up = results_up->getNext()) { 446ec40f818SAaron Smith switch (symbol_up->getSymTag()) { 447ec40f818SAaron Smith case PDB_SymType::Enum: 448ec40f818SAaron Smith case PDB_SymType::UDT: 449ec40f818SAaron Smith case PDB_SymType::Typedef: 450ec40f818SAaron Smith break; 451ec40f818SAaron Smith default: 452ec40f818SAaron Smith continue; 453ec40f818SAaron Smith } 454ec40f818SAaron Smith 455ec40f818SAaron Smith auto type_uid = symbol_up->getSymIndexId(); 456ec40f818SAaron Smith if (m_types.find(type_uid) != m_types.end()) 457ec40f818SAaron Smith continue; 458ec40f818SAaron Smith 459ec40f818SAaron Smith // This should cause the type to get cached and stored in the `m_types` 460ec40f818SAaron Smith // lookup. 461ec40f818SAaron Smith if (!ResolveTypeUID(symbol_up->getSymIndexId())) 462ec40f818SAaron Smith continue; 463ec40f818SAaron Smith 464ec40f818SAaron Smith ++num_added; 465ec40f818SAaron Smith } 466ec40f818SAaron Smith return num_added; 46774e08ca0SZachary Turner } 46874e08ca0SZachary Turner 46974e08ca0SZachary Turner size_t 470b9c1b51eSKate Stone SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) { 47174e08ca0SZachary Turner // TODO: Implement this 47274e08ca0SZachary Turner return size_t(); 47374e08ca0SZachary Turner } 47474e08ca0SZachary Turner 475b9c1b51eSKate Stone lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) { 47642dff790SZachary Turner auto find_result = m_types.find(type_uid); 47742dff790SZachary Turner if (find_result != m_types.end()) 47842dff790SZachary Turner return find_result->second.get(); 47942dff790SZachary Turner 480b9c1b51eSKate Stone TypeSystem *type_system = 481b9c1b51eSKate Stone GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 482b9c1b51eSKate Stone ClangASTContext *clang_type_system = 483b9c1b51eSKate Stone llvm::dyn_cast_or_null<ClangASTContext>(type_system); 48442dff790SZachary Turner if (!clang_type_system) 48574e08ca0SZachary Turner return nullptr; 486b9c1b51eSKate Stone PDBASTParser *pdb = 487b9c1b51eSKate Stone llvm::dyn_cast<PDBASTParser>(clang_type_system->GetPDBParser()); 48842dff790SZachary Turner if (!pdb) 48942dff790SZachary Turner return nullptr; 49042dff790SZachary Turner 49142dff790SZachary Turner auto pdb_type = m_session_up->getSymbolById(type_uid); 49242dff790SZachary Turner if (pdb_type == nullptr) 49342dff790SZachary Turner return nullptr; 49442dff790SZachary Turner 49542dff790SZachary Turner lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type); 496ec40f818SAaron Smith if (result.get()) { 49742dff790SZachary Turner m_types.insert(std::make_pair(type_uid, result)); 498ec40f818SAaron Smith auto type_list = GetTypeList(); 499*f76fe682SAaron Smith if (type_list) 500ec40f818SAaron Smith type_list->Insert(result); 501ec40f818SAaron Smith } 50242dff790SZachary Turner return result.get(); 50374e08ca0SZachary Turner } 50474e08ca0SZachary Turner 505b9c1b51eSKate Stone bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) { 50674e08ca0SZachary Turner // TODO: Implement this 50774e08ca0SZachary Turner return false; 50874e08ca0SZachary Turner } 50974e08ca0SZachary Turner 510b9c1b51eSKate Stone lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) { 51174e08ca0SZachary Turner return lldb_private::CompilerDecl(); 51274e08ca0SZachary Turner } 51374e08ca0SZachary Turner 51474e08ca0SZachary Turner lldb_private::CompilerDeclContext 515b9c1b51eSKate Stone SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) { 516b9c1b51eSKate Stone // PDB always uses the translation unit decl context for everything. We can 5179d0eb996SAdrian McCarthy // improve this later but it's not easy because PDB doesn't provide a high 5189d0eb996SAdrian McCarthy // enough level of type fidelity in this area. 51942dff790SZachary Turner return *m_tu_decl_ctx_up; 52074e08ca0SZachary Turner } 52174e08ca0SZachary Turner 52274e08ca0SZachary Turner lldb_private::CompilerDeclContext 523b9c1b51eSKate Stone SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { 52442dff790SZachary Turner return *m_tu_decl_ctx_up; 52574e08ca0SZachary Turner } 52674e08ca0SZachary Turner 527b9c1b51eSKate Stone void SymbolFilePDB::ParseDeclsForContext( 528b9c1b51eSKate Stone lldb_private::CompilerDeclContext decl_ctx) {} 52974e08ca0SZachary Turner 53074e08ca0SZachary Turner uint32_t 531b9c1b51eSKate Stone SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, 532b9c1b51eSKate Stone uint32_t resolve_scope, 533b9c1b51eSKate Stone lldb_private::SymbolContext &sc) { 5347ac1c780SAaron Smith uint32_t resolved_flags = 0; 5354d4d63eeSPavel Labath if (resolve_scope & eSymbolContextCompUnit || 5364d4d63eeSPavel Labath resolve_scope & eSymbolContextVariable || 5374d4d63eeSPavel Labath resolve_scope & eSymbolContextFunction || 5384d4d63eeSPavel Labath resolve_scope & eSymbolContextBlock || 5397ac1c780SAaron Smith resolve_scope & eSymbolContextLineEntry) { 5407ac1c780SAaron Smith addr_t file_vm_addr = so_addr.GetFileAddress(); 5417ac1c780SAaron Smith auto symbol_up = 5427ac1c780SAaron Smith m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::None); 5437ac1c780SAaron Smith if (!symbol_up) 5447ac1c780SAaron Smith return 0; 5457ac1c780SAaron Smith 5467ac1c780SAaron Smith auto cu_sp = GetCompileUnitContainsAddress(so_addr); 5477ac1c780SAaron Smith if (!cu_sp) { 5487ac1c780SAaron Smith if (resolved_flags | eSymbolContextVariable) { 5497ac1c780SAaron Smith // TODO: Resolve variables 5507ac1c780SAaron Smith } 5517ac1c780SAaron Smith return 0; 5527ac1c780SAaron Smith } 5537ac1c780SAaron Smith sc.comp_unit = cu_sp.get(); 5547ac1c780SAaron Smith resolved_flags |= eSymbolContextCompUnit; 5557ac1c780SAaron Smith lldbassert(sc.module_sp == cu_sp->GetModule()); 5567ac1c780SAaron Smith 5577ac1c780SAaron Smith switch (symbol_up->getSymTag()) { 5587ac1c780SAaron Smith case PDB_SymType::Function: 5597ac1c780SAaron Smith if (resolve_scope & eSymbolContextFunction) { 5607ac1c780SAaron Smith auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get()); 5617ac1c780SAaron Smith assert(pdb_func); 5627ac1c780SAaron Smith auto func_uid = pdb_func->getSymIndexId(); 5637ac1c780SAaron Smith sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get(); 5647ac1c780SAaron Smith if (sc.function == nullptr) 5657ac1c780SAaron Smith sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, sc); 5667ac1c780SAaron Smith if (sc.function) { 5677ac1c780SAaron Smith resolved_flags |= eSymbolContextFunction; 5687ac1c780SAaron Smith if (resolve_scope & eSymbolContextBlock) { 5697ac1c780SAaron Smith Block &block = sc.function->GetBlock(true); 5707ac1c780SAaron Smith sc.block = block.FindBlockByID(sc.function->GetID()); 5717ac1c780SAaron Smith if (sc.block) 5727ac1c780SAaron Smith resolved_flags |= eSymbolContextBlock; 5737ac1c780SAaron Smith } 5747ac1c780SAaron Smith } 5757ac1c780SAaron Smith } 5767ac1c780SAaron Smith break; 5777ac1c780SAaron Smith default: 5787ac1c780SAaron Smith break; 5797ac1c780SAaron Smith } 5807ac1c780SAaron Smith 5817ac1c780SAaron Smith if (resolve_scope & eSymbolContextLineEntry) { 5827ac1c780SAaron Smith if (auto *line_table = sc.comp_unit->GetLineTable()) { 5837ac1c780SAaron Smith Address addr(so_addr); 5847ac1c780SAaron Smith if (line_table->FindLineEntryByAddress(addr, sc.line_entry)) 5857ac1c780SAaron Smith resolved_flags |= eSymbolContextLineEntry; 5867ac1c780SAaron Smith } 5877ac1c780SAaron Smith } 5887ac1c780SAaron Smith } 5897ac1c780SAaron Smith return resolved_flags; 59074e08ca0SZachary Turner } 59174e08ca0SZachary Turner 59210a02577SAaron Smith std::string SymbolFilePDB::GetSourceFileNameForPDBCompiland( 59310a02577SAaron Smith const PDBSymbolCompiland *pdb_compiland) { 59410a02577SAaron Smith if (!pdb_compiland) 59510a02577SAaron Smith return std::string(); 59610a02577SAaron Smith 59710a02577SAaron Smith std::string source_file_name; 59810a02577SAaron Smith // `getSourceFileName` returns the basename of the original source file 59910a02577SAaron Smith // used to generate this compiland. It does not return the full path. 60010a02577SAaron Smith // Currently the only way to get that is to do a basename lookup to get the 60110a02577SAaron Smith // IPDBSourceFile, but this is ambiguous in the case of two source files 60210a02577SAaron Smith // with the same name contributing to the same compiland. This is an edge 60310a02577SAaron Smith // case that we ignore for now, although we need to a long-term solution. 60410a02577SAaron Smith std::string file_name = pdb_compiland->getSourceFileName(); 60510a02577SAaron Smith if (!file_name.empty()) { 60610a02577SAaron Smith auto one_src_file_up = 60710a02577SAaron Smith m_session_up->findOneSourceFile(pdb_compiland, file_name, 60810a02577SAaron Smith PDB_NameSearchFlags::NS_CaseInsensitive); 60910a02577SAaron Smith if (one_src_file_up) 61010a02577SAaron Smith source_file_name = one_src_file_up->getFileName(); 61110a02577SAaron Smith } 61210a02577SAaron Smith // For some reason, source file name could be empty, so we will walk through 61310a02577SAaron Smith // all source files of this compiland, and determine the right source file 61410a02577SAaron Smith // if any that is used to generate this compiland based on language 61510a02577SAaron Smith // indicated in compilanddetails language field. 61610a02577SAaron Smith if (!source_file_name.empty()) 61710a02577SAaron Smith return source_file_name; 61810a02577SAaron Smith 61910a02577SAaron Smith auto details_up = pdb_compiland->findOneChild<PDBSymbolCompilandDetails>(); 62010a02577SAaron Smith PDB_Lang pdb_lang = details_up ? details_up->getLanguage() : PDB_Lang::Cpp; 62110a02577SAaron Smith auto src_files_up = 62210a02577SAaron Smith m_session_up->getSourceFilesForCompiland(*pdb_compiland); 62310a02577SAaron Smith if (src_files_up) { 62410a02577SAaron Smith while (auto file_up = src_files_up->getNext()) { 62510a02577SAaron Smith FileSpec file_spec(file_up->getFileName(), false, 62610a02577SAaron Smith FileSpec::ePathSyntaxWindows); 62710a02577SAaron Smith auto file_extension = file_spec.GetFileNameExtension(); 62810a02577SAaron Smith if (pdb_lang == PDB_Lang::Cpp || pdb_lang == PDB_Lang::C) { 62910a02577SAaron Smith static const char* exts[] = { "cpp", "c", "cc", "cxx" }; 63010a02577SAaron Smith if (llvm::is_contained(exts, file_extension.GetStringRef().lower())) 63110a02577SAaron Smith source_file_name = file_up->getFileName(); 63210a02577SAaron Smith break; 63310a02577SAaron Smith } else if (pdb_lang == PDB_Lang::Masm && 63410a02577SAaron Smith ConstString::Compare(file_extension, ConstString("ASM"), 63510a02577SAaron Smith false) == 0) { 63610a02577SAaron Smith source_file_name = file_up->getFileName(); 63710a02577SAaron Smith break; 63810a02577SAaron Smith } 63910a02577SAaron Smith } 64010a02577SAaron Smith } 64110a02577SAaron Smith return source_file_name; 64210a02577SAaron Smith } 64310a02577SAaron Smith 644b9c1b51eSKate Stone uint32_t SymbolFilePDB::ResolveSymbolContext( 645b9c1b51eSKate Stone const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines, 646b9c1b51eSKate Stone uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) { 64710a02577SAaron Smith const size_t old_size = sc_list.GetSize(); 648b9c1b51eSKate Stone if (resolve_scope & lldb::eSymbolContextCompUnit) { 649b9c1b51eSKate Stone // Locate all compilation units with line numbers referencing the specified 6509d0eb996SAdrian McCarthy // file. For example, if `file_spec` is <vector>, then this should return 6519d0eb996SAdrian McCarthy // all source files and header files that reference <vector>, either 6529d0eb996SAdrian McCarthy // directly or indirectly. 653b9c1b51eSKate Stone auto compilands = m_session_up->findCompilandsForSourceFile( 654b9c1b51eSKate Stone file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive); 65574e08ca0SZachary Turner 65610a02577SAaron Smith if (!compilands) 65710a02577SAaron Smith return 0; 65810a02577SAaron Smith 6599d0eb996SAdrian McCarthy // For each one, either find its previously parsed data or parse it afresh 6609d0eb996SAdrian McCarthy // and add it to the symbol context list. 661b9c1b51eSKate Stone while (auto compiland = compilands->getNext()) { 662b9c1b51eSKate Stone // If we're not checking inlines, then don't add line information for this 6639d0eb996SAdrian McCarthy // file unless the FileSpec matches. 6647ac1c780SAaron Smith // For inline functions, we don't have to match the FileSpec since they 6657ac1c780SAaron Smith // could be defined in headers other than file specified in FileSpec. 666b9c1b51eSKate Stone if (!check_inlines) { 667b9c1b51eSKate Stone // `getSourceFileName` returns the basename of the original source file 6689d0eb996SAdrian McCarthy // used to generate this compiland. It does not return the full path. 6699d0eb996SAdrian McCarthy // Currently the only way to get that is to do a basename lookup to get 6709d0eb996SAdrian McCarthy // the IPDBSourceFile, but this is ambiguous in the case of two source 6719d0eb996SAdrian McCarthy // files with the same name contributing to the same compiland. This is 6729d0eb996SAdrian McCarthy // a moderately extreme edge case, so we consider this OK for now, 6739d0eb996SAdrian McCarthy // although we need to find a long-term solution. 67410a02577SAaron Smith std::string source_file = 67510a02577SAaron Smith GetSourceFileNameForPDBCompiland(compiland.get()); 67610a02577SAaron Smith if (source_file.empty()) 67710a02577SAaron Smith continue; 67874e08ca0SZachary Turner FileSpec this_spec(source_file, false, FileSpec::ePathSyntaxWindows); 67910a02577SAaron Smith bool need_full_match = !file_spec.GetDirectory().IsEmpty(); 68010a02577SAaron Smith if (FileSpec::Compare(file_spec, this_spec, need_full_match) != 0) 68174e08ca0SZachary Turner continue; 68274e08ca0SZachary Turner } 68374e08ca0SZachary Turner 68474e08ca0SZachary Turner SymbolContext sc; 68510a02577SAaron Smith auto cu = ParseCompileUnitForUID(compiland->getSymIndexId()); 68610a02577SAaron Smith if (!cu.get()) 68710a02577SAaron Smith continue; 68874e08ca0SZachary Turner sc.comp_unit = cu.get(); 68974e08ca0SZachary Turner sc.module_sp = cu->GetModule(); 69074e08ca0SZachary Turner 691b9c1b51eSKate Stone // If we were asked to resolve line entries, add all entries to the line 6929d0eb996SAdrian McCarthy // table that match the requested line (or all lines if `line` == 0). 6937ac1c780SAaron Smith if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock | 6947ac1c780SAaron Smith eSymbolContextLineEntry)) { 6957ac1c780SAaron Smith bool has_line_table = ParseCompileUnitLineTable(sc, line); 6967ac1c780SAaron Smith 6977ac1c780SAaron Smith if ((resolve_scope & eSymbolContextLineEntry) && !has_line_table) { 6987ac1c780SAaron Smith // The query asks for line entries, but we can't get them for the 6997ac1c780SAaron Smith // compile unit. This is not normal for `line` = 0. So just assert it. 700*f76fe682SAaron Smith assert(line && "Couldn't get all line entries!\n"); 7017ac1c780SAaron Smith 7027ac1c780SAaron Smith // Current compiland does not have the requested line. Search next. 7037ac1c780SAaron Smith continue; 7047ac1c780SAaron Smith } 7057ac1c780SAaron Smith 7067ac1c780SAaron Smith if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock)) { 7077ac1c780SAaron Smith if (!has_line_table) 7087ac1c780SAaron Smith continue; 7097ac1c780SAaron Smith 7107ac1c780SAaron Smith auto *line_table = sc.comp_unit->GetLineTable(); 7117ac1c780SAaron Smith lldbassert(line_table); 7127ac1c780SAaron Smith 7137ac1c780SAaron Smith uint32_t num_line_entries = line_table->GetSize(); 7147ac1c780SAaron Smith // Skip the terminal line entry. 7157ac1c780SAaron Smith --num_line_entries; 7167ac1c780SAaron Smith 7177ac1c780SAaron Smith // If `line `!= 0, see if we can resolve function for each line 7187ac1c780SAaron Smith // entry in the line table. 7197ac1c780SAaron Smith for (uint32_t line_idx = 0; line && line_idx < num_line_entries; 7207ac1c780SAaron Smith ++line_idx) { 7217ac1c780SAaron Smith if (!line_table->GetLineEntryAtIndex(line_idx, sc.line_entry)) 7227ac1c780SAaron Smith continue; 7237ac1c780SAaron Smith 7247ac1c780SAaron Smith auto file_vm_addr = 7257ac1c780SAaron Smith sc.line_entry.range.GetBaseAddress().GetFileAddress(); 7267ac1c780SAaron Smith if (file_vm_addr == LLDB_INVALID_ADDRESS) 7277ac1c780SAaron Smith continue; 7287ac1c780SAaron Smith 7297ac1c780SAaron Smith auto symbol_up = 7307ac1c780SAaron Smith m_session_up->findSymbolByAddress(file_vm_addr, 7317ac1c780SAaron Smith PDB_SymType::Function); 7327ac1c780SAaron Smith if (symbol_up) { 7337ac1c780SAaron Smith auto func_uid = symbol_up->getSymIndexId(); 7347ac1c780SAaron Smith sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get(); 7357ac1c780SAaron Smith if (sc.function == nullptr) { 7367ac1c780SAaron Smith auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get()); 7377ac1c780SAaron Smith assert(pdb_func); 7387ac1c780SAaron Smith sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, sc); 7397ac1c780SAaron Smith } 7407ac1c780SAaron Smith if (sc.function && (resolve_scope & eSymbolContextBlock)) { 7417ac1c780SAaron Smith Block &block = sc.function->GetBlock(true); 7427ac1c780SAaron Smith sc.block = block.FindBlockByID(sc.function->GetID()); 7437ac1c780SAaron Smith } 7447ac1c780SAaron Smith } 7457ac1c780SAaron Smith sc_list.Append(sc); 7467ac1c780SAaron Smith } 7477ac1c780SAaron Smith } else if (has_line_table) { 7487ac1c780SAaron Smith // We can parse line table for the compile unit. But no query to 7497ac1c780SAaron Smith // resolve function or block. We append `sc` to the list anyway. 7507ac1c780SAaron Smith sc_list.Append(sc); 7517ac1c780SAaron Smith } 7527ac1c780SAaron Smith } else { 7537ac1c780SAaron Smith // No query for line entry, function or block. But we have a valid 7547ac1c780SAaron Smith // compile unit, append `sc` to the list. 7557ac1c780SAaron Smith sc_list.Append(sc); 7567ac1c780SAaron Smith } 75774e08ca0SZachary Turner } 75874e08ca0SZachary Turner } 75910a02577SAaron Smith return sc_list.GetSize() - old_size; 76074e08ca0SZachary Turner } 76174e08ca0SZachary Turner 762b9c1b51eSKate Stone uint32_t SymbolFilePDB::FindGlobalVariables( 763b9c1b51eSKate Stone const lldb_private::ConstString &name, 76474e08ca0SZachary Turner const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, 765b9c1b51eSKate Stone uint32_t max_matches, lldb_private::VariableList &variables) { 76674e08ca0SZachary Turner return uint32_t(); 76774e08ca0SZachary Turner } 76874e08ca0SZachary Turner 76974e08ca0SZachary Turner uint32_t 770b9c1b51eSKate Stone SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression ®ex, 771b9c1b51eSKate Stone bool append, uint32_t max_matches, 772b9c1b51eSKate Stone lldb_private::VariableList &variables) { 773b9c1b51eSKate Stone return uint32_t(); 774b9c1b51eSKate Stone } 775b9c1b51eSKate Stone 7767ac1c780SAaron Smith bool SymbolFilePDB::ResolveFunction(llvm::pdb::PDBSymbolFunc *pdb_func, 7777ac1c780SAaron Smith bool include_inlines, 7787ac1c780SAaron Smith lldb_private::SymbolContextList &sc_list) { 7797ac1c780SAaron Smith if (!pdb_func) 7807ac1c780SAaron Smith return false; 7817ac1c780SAaron Smith lldb_private::SymbolContext sc; 7827ac1c780SAaron Smith auto file_vm_addr = pdb_func->getVirtualAddress(); 7837ac1c780SAaron Smith if (file_vm_addr == LLDB_INVALID_ADDRESS) 7847ac1c780SAaron Smith return false; 7857ac1c780SAaron Smith 7867ac1c780SAaron Smith Address so_addr(file_vm_addr); 7877ac1c780SAaron Smith sc.comp_unit = GetCompileUnitContainsAddress(so_addr).get(); 7887ac1c780SAaron Smith if (!sc.comp_unit) 7897ac1c780SAaron Smith return false; 7907ac1c780SAaron Smith sc.module_sp = sc.comp_unit->GetModule(); 7917ac1c780SAaron Smith auto symbol_up = 7927ac1c780SAaron Smith m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::Function); 7937ac1c780SAaron Smith if (!symbol_up) 7947ac1c780SAaron Smith return false; 7957ac1c780SAaron Smith 7967ac1c780SAaron Smith auto *func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get()); 7977ac1c780SAaron Smith assert(func); 7987ac1c780SAaron Smith sc.function = ParseCompileUnitFunctionForPDBFunc(func, sc); 7997ac1c780SAaron Smith if (!sc.function) 8007ac1c780SAaron Smith return false; 8017ac1c780SAaron Smith 8027ac1c780SAaron Smith sc_list.Append(sc); 8037ac1c780SAaron Smith return true; 8047ac1c780SAaron Smith } 8057ac1c780SAaron Smith 8067ac1c780SAaron Smith bool SymbolFilePDB::ResolveFunction(uint32_t uid, bool include_inlines, 8077ac1c780SAaron Smith lldb_private::SymbolContextList &sc_list) { 8087ac1c780SAaron Smith auto pdb_func_up = 8097ac1c780SAaron Smith m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid); 8107ac1c780SAaron Smith if (!pdb_func_up && !(include_inlines && pdb_func_up->hasInlineAttribute())) 8117ac1c780SAaron Smith return false; 8127ac1c780SAaron Smith return ResolveFunction(pdb_func_up.get(), include_inlines, sc_list); 8137ac1c780SAaron Smith } 8147ac1c780SAaron Smith 8157ac1c780SAaron Smith void SymbolFilePDB::CacheFunctionNames() { 8167ac1c780SAaron Smith if (!m_func_full_names.IsEmpty()) 8177ac1c780SAaron Smith return; 8187ac1c780SAaron Smith 8197ac1c780SAaron Smith std::map<uint64_t, uint32_t> addr_ids; 8207ac1c780SAaron Smith 8217ac1c780SAaron Smith if (auto results_up = m_global_scope_up->findAllChildren<PDBSymbolFunc>()) { 8227ac1c780SAaron Smith while (auto pdb_func_up = results_up->getNext()) { 823*f76fe682SAaron Smith if (pdb_func_up->isCompilerGenerated()) 824*f76fe682SAaron Smith continue; 825*f76fe682SAaron Smith 8267ac1c780SAaron Smith auto name = pdb_func_up->getName(); 8277ac1c780SAaron Smith auto demangled_name = pdb_func_up->getUndecoratedName(); 8287ac1c780SAaron Smith if (name.empty() && demangled_name.empty()) 8297ac1c780SAaron Smith continue; 8307ac1c780SAaron Smith 831*f76fe682SAaron Smith auto uid = pdb_func_up->getSymIndexId(); 8327ac1c780SAaron Smith if (!demangled_name.empty() && pdb_func_up->getVirtualAddress()) 8337ac1c780SAaron Smith addr_ids.insert(std::make_pair(pdb_func_up->getVirtualAddress(), uid)); 8347ac1c780SAaron Smith 8357ac1c780SAaron Smith if (auto parent = pdb_func_up->getClassParent()) { 8367ac1c780SAaron Smith 8377ac1c780SAaron Smith // PDB have symbols for class/struct methods or static methods in Enum 8387ac1c780SAaron Smith // Class. We won't bother to check if the parent is UDT or Enum here. 8397ac1c780SAaron Smith m_func_method_names.Append(ConstString(name), uid); 8407ac1c780SAaron Smith 8417ac1c780SAaron Smith ConstString cstr_name(name); 8427ac1c780SAaron Smith 8437ac1c780SAaron Smith // To search a method name, like NS::Class:MemberFunc, LLDB searches its 8447ac1c780SAaron Smith // base name, i.e. MemberFunc by default. Since PDBSymbolFunc does not 8457ac1c780SAaron Smith // have inforamtion of this, we extract base names and cache them by our 8467ac1c780SAaron Smith // own effort. 8477ac1c780SAaron Smith llvm::StringRef basename; 8487ac1c780SAaron Smith CPlusPlusLanguage::MethodName cpp_method(cstr_name); 8497ac1c780SAaron Smith if (cpp_method.IsValid()) { 8507ac1c780SAaron Smith llvm::StringRef context; 8517ac1c780SAaron Smith basename = cpp_method.GetBasename(); 8527ac1c780SAaron Smith if (basename.empty()) 8537ac1c780SAaron Smith CPlusPlusLanguage::ExtractContextAndIdentifier(name.c_str(), 8547ac1c780SAaron Smith context, basename); 8557ac1c780SAaron Smith } 8567ac1c780SAaron Smith 8577ac1c780SAaron Smith if (!basename.empty()) 8587ac1c780SAaron Smith m_func_base_names.Append(ConstString(basename), uid); 8597ac1c780SAaron Smith else { 8607ac1c780SAaron Smith m_func_base_names.Append(ConstString(name), uid); 8617ac1c780SAaron Smith } 8627ac1c780SAaron Smith 8637ac1c780SAaron Smith if (!demangled_name.empty()) 8647ac1c780SAaron Smith m_func_full_names.Append(ConstString(demangled_name), uid); 8657ac1c780SAaron Smith 8667ac1c780SAaron Smith } else { 8677ac1c780SAaron Smith // Handle not-method symbols. 8687ac1c780SAaron Smith 8697ac1c780SAaron Smith // The function name might contain namespace, or its lexical scope. It 8707ac1c780SAaron Smith // is not safe to get its base name by applying same scheme as we deal 8717ac1c780SAaron Smith // with the method names. 8727ac1c780SAaron Smith // FIXME: Remove namespace if function is static in a scope. 8737ac1c780SAaron Smith m_func_base_names.Append(ConstString(name), uid); 8747ac1c780SAaron Smith 8757ac1c780SAaron Smith if (name == "main") { 8767ac1c780SAaron Smith m_func_full_names.Append(ConstString(name), uid); 8777ac1c780SAaron Smith 8787ac1c780SAaron Smith if (!demangled_name.empty() && name != demangled_name) { 8797ac1c780SAaron Smith m_func_full_names.Append(ConstString(demangled_name), uid); 8807ac1c780SAaron Smith m_func_base_names.Append(ConstString(demangled_name), uid); 8817ac1c780SAaron Smith } 8827ac1c780SAaron Smith } else if (!demangled_name.empty()) { 8837ac1c780SAaron Smith m_func_full_names.Append(ConstString(demangled_name), uid); 8847ac1c780SAaron Smith } else { 8857ac1c780SAaron Smith m_func_full_names.Append(ConstString(name), uid); 8867ac1c780SAaron Smith } 8877ac1c780SAaron Smith } 8887ac1c780SAaron Smith } 8897ac1c780SAaron Smith } 8907ac1c780SAaron Smith 8917ac1c780SAaron Smith if (auto results_up = 8927ac1c780SAaron Smith m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>()) { 8937ac1c780SAaron Smith while (auto pub_sym_up = results_up->getNext()) { 8947ac1c780SAaron Smith if (!pub_sym_up->isFunction()) 8957ac1c780SAaron Smith continue; 8967ac1c780SAaron Smith auto name = pub_sym_up->getName(); 8977ac1c780SAaron Smith if (name.empty()) 8987ac1c780SAaron Smith continue; 8997ac1c780SAaron Smith 9007ac1c780SAaron Smith if (CPlusPlusLanguage::IsCPPMangledName(name.c_str())) { 9017ac1c780SAaron Smith auto vm_addr = pub_sym_up->getVirtualAddress(); 9027ac1c780SAaron Smith 9037ac1c780SAaron Smith // PDB public symbol has mangled name for its associated function. 9047ac1c780SAaron Smith if (vm_addr && addr_ids.find(vm_addr) != addr_ids.end()) { 9057ac1c780SAaron Smith // Cache mangled name. 9067ac1c780SAaron Smith m_func_full_names.Append(ConstString(name), addr_ids[vm_addr]); 9077ac1c780SAaron Smith } 9087ac1c780SAaron Smith } 9097ac1c780SAaron Smith } 9107ac1c780SAaron Smith } 9117ac1c780SAaron Smith // Sort them before value searching is working properly 9127ac1c780SAaron Smith m_func_full_names.Sort(); 9137ac1c780SAaron Smith m_func_full_names.SizeToFit(); 9147ac1c780SAaron Smith m_func_method_names.Sort(); 9157ac1c780SAaron Smith m_func_method_names.SizeToFit(); 9167ac1c780SAaron Smith m_func_base_names.Sort(); 9177ac1c780SAaron Smith m_func_base_names.SizeToFit(); 9187ac1c780SAaron Smith } 9197ac1c780SAaron Smith 920b9c1b51eSKate Stone uint32_t SymbolFilePDB::FindFunctions( 921b9c1b51eSKate Stone const lldb_private::ConstString &name, 922b9c1b51eSKate Stone const lldb_private::CompilerDeclContext *parent_decl_ctx, 923b9c1b51eSKate Stone uint32_t name_type_mask, bool include_inlines, bool append, 924b9c1b51eSKate Stone lldb_private::SymbolContextList &sc_list) { 9257ac1c780SAaron Smith if (!append) 9267ac1c780SAaron Smith sc_list.Clear(); 9277ac1c780SAaron Smith lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0); 9287ac1c780SAaron Smith 9297ac1c780SAaron Smith if (name_type_mask == eFunctionNameTypeNone) 9307ac1c780SAaron Smith return 0; 9317ac1c780SAaron Smith if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) 9327ac1c780SAaron Smith return 0; 9337ac1c780SAaron Smith if (name.IsEmpty()) 9347ac1c780SAaron Smith return 0; 9357ac1c780SAaron Smith 9367ac1c780SAaron Smith auto old_size = sc_list.GetSize(); 9374d4d63eeSPavel Labath if (name_type_mask & eFunctionNameTypeFull || 9384d4d63eeSPavel Labath name_type_mask & eFunctionNameTypeBase || 9397ac1c780SAaron Smith name_type_mask & eFunctionNameTypeMethod) { 9407ac1c780SAaron Smith CacheFunctionNames(); 9417ac1c780SAaron Smith 9427ac1c780SAaron Smith std::set<uint32_t> resolved_ids; 9437ac1c780SAaron Smith auto ResolveFn = [include_inlines, &name, &sc_list, &resolved_ids, this] ( 9447ac1c780SAaron Smith UniqueCStringMap<uint32_t> &Names) 9457ac1c780SAaron Smith { 9467ac1c780SAaron Smith std::vector<uint32_t> ids; 9477ac1c780SAaron Smith if (Names.GetValues(name, ids)) { 9487ac1c780SAaron Smith for (auto id : ids) { 9497ac1c780SAaron Smith if (resolved_ids.find(id) == resolved_ids.end()) { 9507ac1c780SAaron Smith if (ResolveFunction(id, include_inlines, sc_list)) 9517ac1c780SAaron Smith resolved_ids.insert(id); 9527ac1c780SAaron Smith } 9537ac1c780SAaron Smith } 9547ac1c780SAaron Smith } 9557ac1c780SAaron Smith }; 9567ac1c780SAaron Smith if (name_type_mask & eFunctionNameTypeFull) { 9577ac1c780SAaron Smith ResolveFn(m_func_full_names); 9587ac1c780SAaron Smith } 9597ac1c780SAaron Smith if (name_type_mask & eFunctionNameTypeBase) { 9607ac1c780SAaron Smith ResolveFn(m_func_base_names); 9617ac1c780SAaron Smith } 9627ac1c780SAaron Smith if (name_type_mask & eFunctionNameTypeMethod) { 9637ac1c780SAaron Smith ResolveFn(m_func_method_names); 9647ac1c780SAaron Smith } 9657ac1c780SAaron Smith } 9667ac1c780SAaron Smith return sc_list.GetSize() - old_size; 96774e08ca0SZachary Turner } 96874e08ca0SZachary Turner 96974e08ca0SZachary Turner uint32_t 970b9c1b51eSKate Stone SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression ®ex, 971b9c1b51eSKate Stone bool include_inlines, bool append, 972b9c1b51eSKate Stone lldb_private::SymbolContextList &sc_list) { 9737ac1c780SAaron Smith if (!append) 9747ac1c780SAaron Smith sc_list.Clear(); 9757ac1c780SAaron Smith if (!regex.IsValid()) 9767ac1c780SAaron Smith return 0; 9777ac1c780SAaron Smith 9787ac1c780SAaron Smith auto old_size = sc_list.GetSize(); 9797ac1c780SAaron Smith CacheFunctionNames(); 9807ac1c780SAaron Smith 9817ac1c780SAaron Smith std::set<uint32_t> resolved_ids; 9827ac1c780SAaron Smith auto ResolveFn = [®ex, include_inlines, &sc_list, &resolved_ids, this] ( 9837ac1c780SAaron Smith UniqueCStringMap<uint32_t> &Names) 9847ac1c780SAaron Smith { 9857ac1c780SAaron Smith std::vector<uint32_t> ids; 9867ac1c780SAaron Smith if (Names.GetValues(regex, ids)) { 9877ac1c780SAaron Smith for (auto id : ids) { 9887ac1c780SAaron Smith if (resolved_ids.find(id) == resolved_ids.end()) 9897ac1c780SAaron Smith if (ResolveFunction(id, include_inlines, sc_list)) 9907ac1c780SAaron Smith resolved_ids.insert(id); 9917ac1c780SAaron Smith } 9927ac1c780SAaron Smith } 9937ac1c780SAaron Smith }; 9947ac1c780SAaron Smith ResolveFn(m_func_full_names); 9957ac1c780SAaron Smith ResolveFn(m_func_base_names); 9967ac1c780SAaron Smith 9977ac1c780SAaron Smith return sc_list.GetSize() - old_size; 99874e08ca0SZachary Turner } 99974e08ca0SZachary Turner 1000b9c1b51eSKate Stone void SymbolFilePDB::GetMangledNamesForFunction( 1001b9c1b51eSKate Stone const std::string &scope_qualified_name, 1002b9c1b51eSKate Stone std::vector<lldb_private::ConstString> &mangled_names) {} 100374e08ca0SZachary Turner 1004b9c1b51eSKate Stone uint32_t SymbolFilePDB::FindTypes( 1005b9c1b51eSKate Stone const lldb_private::SymbolContext &sc, 1006b9c1b51eSKate Stone const lldb_private::ConstString &name, 1007b9c1b51eSKate Stone const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, 1008b9c1b51eSKate Stone uint32_t max_matches, 100974e08ca0SZachary Turner llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, 1010b9c1b51eSKate Stone lldb_private::TypeMap &types) { 101142dff790SZachary Turner if (!append) 101242dff790SZachary Turner types.Clear(); 101342dff790SZachary Turner if (!name) 101442dff790SZachary Turner return 0; 10157ac1c780SAaron Smith if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) 10167ac1c780SAaron Smith return 0; 101742dff790SZachary Turner 101842dff790SZachary Turner searched_symbol_files.clear(); 101942dff790SZachary Turner searched_symbol_files.insert(this); 102042dff790SZachary Turner 102142dff790SZachary Turner std::string name_str = name.AsCString(); 102242dff790SZachary Turner 102386e9434dSAaron Smith // There is an assumption 'name' is not a regex 102442dff790SZachary Turner FindTypesByName(name_str, max_matches, types); 102586e9434dSAaron Smith 102642dff790SZachary Turner return types.GetSize(); 102742dff790SZachary Turner } 102842dff790SZachary Turner 102986e9434dSAaron Smith void 103086e9434dSAaron Smith SymbolFilePDB::FindTypesByRegex(const lldb_private::RegularExpression ®ex, 1031b9c1b51eSKate Stone uint32_t max_matches, 1032b9c1b51eSKate Stone lldb_private::TypeMap &types) { 1033b9c1b51eSKate Stone // When searching by regex, we need to go out of our way to limit the search 10349d0eb996SAdrian McCarthy // space as much as possible since this searches EVERYTHING in the PDB, 10359d0eb996SAdrian McCarthy // manually doing regex comparisons. PDB library isn't optimized for regex 10369d0eb996SAdrian McCarthy // searches or searches across multiple symbol types at the same time, so the 1037b9c1b51eSKate Stone // best we can do is to search enums, then typedefs, then classes one by one, 10389d0eb996SAdrian McCarthy // and do a regex comparison against each of them. 1039b9c1b51eSKate Stone PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef, 1040b9c1b51eSKate Stone PDB_SymType::UDT}; 104154fd7ff6SZachary Turner std::unique_ptr<IPDBEnumSymbols> results; 104242dff790SZachary Turner 104342dff790SZachary Turner uint32_t matches = 0; 104442dff790SZachary Turner 1045b9c1b51eSKate Stone for (auto tag : tags_to_search) { 104610a02577SAaron Smith results = m_global_scope_up->findAllChildren(tag); 104710a02577SAaron Smith if (!results) 104810a02577SAaron Smith continue; 104910a02577SAaron Smith 1050b9c1b51eSKate Stone while (auto result = results->getNext()) { 105142dff790SZachary Turner if (max_matches > 0 && matches >= max_matches) 105242dff790SZachary Turner break; 105342dff790SZachary Turner 105442dff790SZachary Turner std::string type_name; 105554fd7ff6SZachary Turner if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(result.get())) 105642dff790SZachary Turner type_name = enum_type->getName(); 1057b9c1b51eSKate Stone else if (auto typedef_type = 1058b9c1b51eSKate Stone llvm::dyn_cast<PDBSymbolTypeTypedef>(result.get())) 105942dff790SZachary Turner type_name = typedef_type->getName(); 106054fd7ff6SZachary Turner else if (auto class_type = llvm::dyn_cast<PDBSymbolTypeUDT>(result.get())) 106142dff790SZachary Turner type_name = class_type->getName(); 1062b9c1b51eSKate Stone else { 10639d0eb996SAdrian McCarthy // We're looking only for types that have names. Skip symbols, as well 10649d0eb996SAdrian McCarthy // as unnamed types such as arrays, pointers, etc. 106542dff790SZachary Turner continue; 106642dff790SZachary Turner } 106742dff790SZachary Turner 106886e9434dSAaron Smith if (!regex.Execute(type_name)) 106942dff790SZachary Turner continue; 107042dff790SZachary Turner 1071b9c1b51eSKate Stone // This should cause the type to get cached and stored in the `m_types` 1072b9c1b51eSKate Stone // lookup. 107342dff790SZachary Turner if (!ResolveTypeUID(result->getSymIndexId())) 107442dff790SZachary Turner continue; 107542dff790SZachary Turner 107642dff790SZachary Turner auto iter = m_types.find(result->getSymIndexId()); 107742dff790SZachary Turner if (iter == m_types.end()) 107842dff790SZachary Turner continue; 107942dff790SZachary Turner types.Insert(iter->second); 108042dff790SZachary Turner ++matches; 108142dff790SZachary Turner } 108242dff790SZachary Turner } 108342dff790SZachary Turner } 108442dff790SZachary Turner 1085b9c1b51eSKate Stone void SymbolFilePDB::FindTypesByName(const std::string &name, 1086b9c1b51eSKate Stone uint32_t max_matches, 1087b9c1b51eSKate Stone lldb_private::TypeMap &types) { 108854fd7ff6SZachary Turner std::unique_ptr<IPDBEnumSymbols> results; 1089*f76fe682SAaron Smith if (name.empty()) 1090*f76fe682SAaron Smith return; 109110a02577SAaron Smith results = m_global_scope_up->findChildren(PDB_SymType::None, name, 1092b9c1b51eSKate Stone PDB_NameSearchFlags::NS_Default); 109310a02577SAaron Smith if (!results) 109410a02577SAaron Smith return; 109542dff790SZachary Turner 109642dff790SZachary Turner uint32_t matches = 0; 109742dff790SZachary Turner 1098b9c1b51eSKate Stone while (auto result = results->getNext()) { 109942dff790SZachary Turner if (max_matches > 0 && matches >= max_matches) 110042dff790SZachary Turner break; 1101b9c1b51eSKate Stone switch (result->getSymTag()) { 110254fd7ff6SZachary Turner case PDB_SymType::Enum: 110354fd7ff6SZachary Turner case PDB_SymType::UDT: 110454fd7ff6SZachary Turner case PDB_SymType::Typedef: 110542dff790SZachary Turner break; 110642dff790SZachary Turner default: 11079d0eb996SAdrian McCarthy // We're looking only for types that have names. Skip symbols, as well as 110842dff790SZachary Turner // unnamed types such as arrays, pointers, etc. 110942dff790SZachary Turner continue; 111042dff790SZachary Turner } 111142dff790SZachary Turner 1112b9c1b51eSKate Stone // This should cause the type to get cached and stored in the `m_types` 1113b9c1b51eSKate Stone // lookup. 111442dff790SZachary Turner if (!ResolveTypeUID(result->getSymIndexId())) 111542dff790SZachary Turner continue; 111642dff790SZachary Turner 111742dff790SZachary Turner auto iter = m_types.find(result->getSymIndexId()); 111842dff790SZachary Turner if (iter == m_types.end()) 111942dff790SZachary Turner continue; 112042dff790SZachary Turner types.Insert(iter->second); 112142dff790SZachary Turner ++matches; 112242dff790SZachary Turner } 112374e08ca0SZachary Turner } 112474e08ca0SZachary Turner 1125b9c1b51eSKate Stone size_t SymbolFilePDB::FindTypes( 1126b9c1b51eSKate Stone const std::vector<lldb_private::CompilerContext> &contexts, bool append, 1127b9c1b51eSKate Stone lldb_private::TypeMap &types) { 112842dff790SZachary Turner return 0; 112974e08ca0SZachary Turner } 113074e08ca0SZachary Turner 1131ec40f818SAaron Smith lldb_private::TypeList *SymbolFilePDB::GetTypeList() { 1132ec40f818SAaron Smith return m_obj_file->GetModule()->GetTypeList(); 1133ec40f818SAaron Smith } 113474e08ca0SZachary Turner 11357ac1c780SAaron Smith void 11367ac1c780SAaron Smith SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol *pdb_symbol, 11377ac1c780SAaron Smith uint32_t type_mask, 11387ac1c780SAaron Smith TypeCollection &type_collection) { 11397ac1c780SAaron Smith if (!pdb_symbol) 11407ac1c780SAaron Smith return; 11417ac1c780SAaron Smith 11427ac1c780SAaron Smith bool can_parse = false; 11437ac1c780SAaron Smith switch (pdb_symbol->getSymTag()) { 11447ac1c780SAaron Smith case PDB_SymType::ArrayType: 11457ac1c780SAaron Smith can_parse = ((type_mask & eTypeClassArray) != 0); 11467ac1c780SAaron Smith break; 11477ac1c780SAaron Smith case PDB_SymType::BuiltinType: 11487ac1c780SAaron Smith can_parse = ((type_mask & eTypeClassBuiltin) != 0); 11497ac1c780SAaron Smith break; 11507ac1c780SAaron Smith case PDB_SymType::Enum: 11517ac1c780SAaron Smith can_parse = ((type_mask & eTypeClassEnumeration) != 0); 11527ac1c780SAaron Smith break; 11537ac1c780SAaron Smith case PDB_SymType::Function: 11547ac1c780SAaron Smith case PDB_SymType::FunctionSig: 11557ac1c780SAaron Smith can_parse = ((type_mask & eTypeClassFunction) != 0); 11567ac1c780SAaron Smith break; 11577ac1c780SAaron Smith case PDB_SymType::PointerType: 11587ac1c780SAaron Smith can_parse = ((type_mask & (eTypeClassPointer | eTypeClassBlockPointer | 11597ac1c780SAaron Smith eTypeClassMemberPointer)) != 0); 11607ac1c780SAaron Smith break; 11617ac1c780SAaron Smith case PDB_SymType::Typedef: 11627ac1c780SAaron Smith can_parse = ((type_mask & eTypeClassTypedef) != 0); 11637ac1c780SAaron Smith break; 11647ac1c780SAaron Smith case PDB_SymType::UDT: { 11657ac1c780SAaron Smith auto *udt = llvm::dyn_cast<PDBSymbolTypeUDT>(pdb_symbol); 11667ac1c780SAaron Smith assert(udt); 11677ac1c780SAaron Smith can_parse = (udt->getUdtKind() != PDB_UdtType::Interface && 11687ac1c780SAaron Smith ((type_mask & (eTypeClassClass | eTypeClassStruct | 11697ac1c780SAaron Smith eTypeClassUnion)) != 0)); 11707ac1c780SAaron Smith } break; 11717ac1c780SAaron Smith default:break; 11727ac1c780SAaron Smith } 11737ac1c780SAaron Smith 11747ac1c780SAaron Smith if (can_parse) { 11757ac1c780SAaron Smith if (auto *type = ResolveTypeUID(pdb_symbol->getSymIndexId())) { 11767ac1c780SAaron Smith auto result = 11777ac1c780SAaron Smith std::find(type_collection.begin(), type_collection.end(), type); 11787ac1c780SAaron Smith if (result == type_collection.end()) 11797ac1c780SAaron Smith type_collection.push_back(type); 11807ac1c780SAaron Smith } 11817ac1c780SAaron Smith } 11827ac1c780SAaron Smith 11837ac1c780SAaron Smith auto results_up = pdb_symbol->findAllChildren(); 11847ac1c780SAaron Smith while (auto symbol_up = results_up->getNext()) 11857ac1c780SAaron Smith GetTypesForPDBSymbol(symbol_up.get(), type_mask, type_collection); 11867ac1c780SAaron Smith } 11877ac1c780SAaron Smith 1188b9c1b51eSKate Stone size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, 1189b9c1b51eSKate Stone uint32_t type_mask, 1190b9c1b51eSKate Stone lldb_private::TypeList &type_list) { 11917ac1c780SAaron Smith TypeCollection type_collection; 11927ac1c780SAaron Smith uint32_t old_size = type_list.GetSize(); 11937ac1c780SAaron Smith CompileUnit *cu = sc_scope ? 11947ac1c780SAaron Smith sc_scope->CalculateSymbolContextCompileUnit() : nullptr; 11957ac1c780SAaron Smith if (cu) { 11967ac1c780SAaron Smith auto compiland_up = GetPDBCompilandByUID(cu->GetID()); 11977ac1c780SAaron Smith GetTypesForPDBSymbol(compiland_up.get(), type_mask, type_collection); 11987ac1c780SAaron Smith } else { 11997ac1c780SAaron Smith for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) { 12007ac1c780SAaron Smith auto cu_sp = ParseCompileUnitAtIndex(cu_idx); 12017ac1c780SAaron Smith if (cu_sp.get()) { 12027ac1c780SAaron Smith auto compiland_up = GetPDBCompilandByUID(cu_sp->GetID()); 12037ac1c780SAaron Smith GetTypesForPDBSymbol(compiland_up.get(), type_mask, type_collection); 12047ac1c780SAaron Smith } 12057ac1c780SAaron Smith } 12067ac1c780SAaron Smith } 12077ac1c780SAaron Smith 12087ac1c780SAaron Smith for (auto type : type_collection) { 12097ac1c780SAaron Smith type->GetForwardCompilerType(); 12107ac1c780SAaron Smith type_list.Insert(type->shared_from_this()); 12117ac1c780SAaron Smith } 12127ac1c780SAaron Smith return type_list.GetSize() - old_size; 121374e08ca0SZachary Turner } 121474e08ca0SZachary Turner 121574e08ca0SZachary Turner lldb_private::TypeSystem * 1216b9c1b51eSKate Stone SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { 1217b9c1b51eSKate Stone auto type_system = 1218b9c1b51eSKate Stone m_obj_file->GetModule()->GetTypeSystemForLanguage(language); 121974e08ca0SZachary Turner if (type_system) 122074e08ca0SZachary Turner type_system->SetSymbolFile(this); 122174e08ca0SZachary Turner return type_system; 122274e08ca0SZachary Turner } 122374e08ca0SZachary Turner 1224b9c1b51eSKate Stone lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace( 1225b9c1b51eSKate Stone const lldb_private::SymbolContext &sc, 1226b9c1b51eSKate Stone const lldb_private::ConstString &name, 1227b9c1b51eSKate Stone const lldb_private::CompilerDeclContext *parent_decl_ctx) { 122874e08ca0SZachary Turner return lldb_private::CompilerDeclContext(); 122974e08ca0SZachary Turner } 123074e08ca0SZachary Turner 1231b9c1b51eSKate Stone lldb_private::ConstString SymbolFilePDB::GetPluginName() { 123274e08ca0SZachary Turner static ConstString g_name("pdb"); 123374e08ca0SZachary Turner return g_name; 123474e08ca0SZachary Turner } 123574e08ca0SZachary Turner 1236b9c1b51eSKate Stone uint32_t SymbolFilePDB::GetPluginVersion() { return 1; } 123774e08ca0SZachary Turner 1238b9c1b51eSKate Stone IPDBSession &SymbolFilePDB::GetPDBSession() { return *m_session_up; } 1239b9c1b51eSKate Stone 1240b9c1b51eSKate Stone const IPDBSession &SymbolFilePDB::GetPDBSession() const { 124142dff790SZachary Turner return *m_session_up; 124242dff790SZachary Turner } 124342dff790SZachary Turner 124410a02577SAaron Smith lldb::CompUnitSP 124510a02577SAaron Smith SymbolFilePDB::ParseCompileUnitForUID(uint32_t id, uint32_t index) { 124674e08ca0SZachary Turner auto found_cu = m_comp_units.find(id); 124774e08ca0SZachary Turner if (found_cu != m_comp_units.end()) 124874e08ca0SZachary Turner return found_cu->second; 124974e08ca0SZachary Turner 125010a02577SAaron Smith auto compiland_up = GetPDBCompilandByUID(id); 125110a02577SAaron Smith if (!compiland_up) 125210a02577SAaron Smith return CompUnitSP(); 125374e08ca0SZachary Turner 125474e08ca0SZachary Turner lldb::LanguageType lang; 125510a02577SAaron Smith auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>(); 125674e08ca0SZachary Turner if (!details) 125774e08ca0SZachary Turner lang = lldb::eLanguageTypeC_plus_plus; 125874e08ca0SZachary Turner else 125974e08ca0SZachary Turner lang = TranslateLanguage(details->getLanguage()); 126074e08ca0SZachary Turner 1261*f76fe682SAaron Smith if (lang == lldb::LanguageType::eLanguageTypeUnknown) 1262*f76fe682SAaron Smith return CompUnitSP(); 1263*f76fe682SAaron Smith 1264*f76fe682SAaron Smith std::string path = GetSourceFileNameForPDBCompiland(compiland_up.get()); 1265*f76fe682SAaron Smith if (path.empty()) 1266*f76fe682SAaron Smith return CompUnitSP(); 1267*f76fe682SAaron Smith 1268b9c1b51eSKate Stone // Don't support optimized code for now, DebugInfoPDB does not return this 1269b9c1b51eSKate Stone // information. 1270ad2b63cbSGreg Clayton LazyBool optimized = eLazyBoolNo; 127110a02577SAaron Smith auto cu_sp = std::make_shared<CompileUnit>( 1272b9c1b51eSKate Stone m_obj_file->GetModule(), nullptr, path.c_str(), id, lang, optimized); 127310a02577SAaron Smith 127410a02577SAaron Smith if (!cu_sp) 127510a02577SAaron Smith return CompUnitSP(); 127610a02577SAaron Smith 127710a02577SAaron Smith m_comp_units.insert(std::make_pair(id, cu_sp)); 127810a02577SAaron Smith if (index == UINT32_MAX) 127910a02577SAaron Smith GetCompileUnitIndex(compiland_up.get(), index); 128010a02577SAaron Smith lldbassert(index != UINT32_MAX); 128110a02577SAaron Smith m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex( 128210a02577SAaron Smith index, cu_sp); 128310a02577SAaron Smith return cu_sp; 128474e08ca0SZachary Turner } 128574e08ca0SZachary Turner 1286b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitLineTable( 1287b9c1b51eSKate Stone const lldb_private::SymbolContext &sc, uint32_t match_line) { 128810a02577SAaron Smith lldbassert(sc.comp_unit); 128910a02577SAaron Smith 129010a02577SAaron Smith auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); 129110a02577SAaron Smith if (!compiland_up) 129210a02577SAaron Smith return false; 129374e08ca0SZachary Turner 1294b9c1b51eSKate Stone // LineEntry needs the *index* of the file into the list of support files 12959d0eb996SAdrian McCarthy // returned by ParseCompileUnitSupportFiles. But the underlying SDK gives us 12969d0eb996SAdrian McCarthy // a globally unique idenfitifier in the namespace of the PDB. So, we have to 12979d0eb996SAdrian McCarthy // do a mapping so that we can hand out indices. 129842dff790SZachary Turner llvm::DenseMap<uint32_t, uint32_t> index_map; 129910a02577SAaron Smith BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map); 130074e08ca0SZachary Turner auto line_table = llvm::make_unique<LineTable>(sc.comp_unit); 130174e08ca0SZachary Turner 130210a02577SAaron Smith // Find contributions to `compiland` from all source and header files. 130374e08ca0SZachary Turner std::string path = sc.comp_unit->GetPath(); 130410a02577SAaron Smith auto files = m_session_up->getSourceFilesForCompiland(*compiland_up); 130510a02577SAaron Smith if (!files) 130610a02577SAaron Smith return false; 130774e08ca0SZachary Turner 1308b9c1b51eSKate Stone // For each source and header file, create a LineSequence for contributions to 130910a02577SAaron Smith // the compiland from that file, and add the sequence. 1310b9c1b51eSKate Stone while (auto file = files->getNext()) { 1311b9c1b51eSKate Stone std::unique_ptr<LineSequence> sequence( 1312b9c1b51eSKate Stone line_table->CreateLineSequenceContainer()); 131310a02577SAaron Smith auto lines = m_session_up->findLineNumbers(*compiland_up, *file); 131410a02577SAaron Smith if (!lines) 131510a02577SAaron Smith continue; 131674e08ca0SZachary Turner int entry_count = lines->getChildCount(); 131774e08ca0SZachary Turner 13187e8c7beaSZachary Turner uint64_t prev_addr; 13197e8c7beaSZachary Turner uint32_t prev_length; 13207e8c7beaSZachary Turner uint32_t prev_line; 13217e8c7beaSZachary Turner uint32_t prev_source_idx; 13227e8c7beaSZachary Turner 1323b9c1b51eSKate Stone for (int i = 0; i < entry_count; ++i) { 132474e08ca0SZachary Turner auto line = lines->getChildAtIndex(i); 132574e08ca0SZachary Turner 13267e8c7beaSZachary Turner uint64_t lno = line->getLineNumber(); 13277e8c7beaSZachary Turner uint64_t addr = line->getVirtualAddress(); 13287e8c7beaSZachary Turner uint32_t length = line->getLength(); 132974e08ca0SZachary Turner uint32_t source_id = line->getSourceFileId(); 13307e8c7beaSZachary Turner uint32_t col = line->getColumnNumber(); 133174e08ca0SZachary Turner uint32_t source_idx = index_map[source_id]; 133274e08ca0SZachary Turner 1333b9c1b51eSKate Stone // There was a gap between the current entry and the previous entry if the 13349d0eb996SAdrian McCarthy // addresses don't perfectly line up. 13357e8c7beaSZachary Turner bool is_gap = (i > 0) && (prev_addr + prev_length < addr); 13367e8c7beaSZachary Turner 1337b9c1b51eSKate Stone // Before inserting the current entry, insert a terminal entry at the end 13389d0eb996SAdrian McCarthy // of the previous entry's address range if the current entry resulted in 13399d0eb996SAdrian McCarthy // a gap from the previous entry. 1340b9c1b51eSKate Stone if (is_gap && ShouldAddLine(match_line, prev_line, prev_length)) { 1341b9c1b51eSKate Stone line_table->AppendLineEntryToSequence( 1342b9c1b51eSKate Stone sequence.get(), prev_addr + prev_length, prev_line, 0, 13437e8c7beaSZachary Turner prev_source_idx, false, false, false, false, true); 13447e8c7beaSZachary Turner } 13457e8c7beaSZachary Turner 1346b9c1b51eSKate Stone if (ShouldAddLine(match_line, lno, length)) { 13477e8c7beaSZachary Turner bool is_statement = line->isStatement(); 134874e08ca0SZachary Turner bool is_prologue = false; 134974e08ca0SZachary Turner bool is_epilogue = false; 1350b9c1b51eSKate Stone auto func = 1351b9c1b51eSKate Stone m_session_up->findSymbolByAddress(addr, PDB_SymType::Function); 1352b9c1b51eSKate Stone if (func) { 135354fd7ff6SZachary Turner auto prologue = func->findOneChild<PDBSymbolFuncDebugStart>(); 135410a02577SAaron Smith if (prologue) 13557e8c7beaSZachary Turner is_prologue = (addr == prologue->getVirtualAddress()); 135674e08ca0SZachary Turner 135754fd7ff6SZachary Turner auto epilogue = func->findOneChild<PDBSymbolFuncDebugEnd>(); 135810a02577SAaron Smith if (epilogue) 13597e8c7beaSZachary Turner is_epilogue = (addr == epilogue->getVirtualAddress()); 13607e8c7beaSZachary Turner } 136174e08ca0SZachary Turner 1362b9c1b51eSKate Stone line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col, 1363b9c1b51eSKate Stone source_idx, is_statement, false, 13647e8c7beaSZachary Turner is_prologue, is_epilogue, false); 13657e8c7beaSZachary Turner } 13667e8c7beaSZachary Turner 13677e8c7beaSZachary Turner prev_addr = addr; 13687e8c7beaSZachary Turner prev_length = length; 13697e8c7beaSZachary Turner prev_line = lno; 13707e8c7beaSZachary Turner prev_source_idx = source_idx; 13717e8c7beaSZachary Turner } 13727e8c7beaSZachary Turner 1373b9c1b51eSKate Stone if (entry_count > 0 && ShouldAddLine(match_line, prev_line, prev_length)) { 13747e8c7beaSZachary Turner // The end is always a terminal entry, so insert it regardless. 1375b9c1b51eSKate Stone line_table->AppendLineEntryToSequence( 1376b9c1b51eSKate Stone sequence.get(), prev_addr + prev_length, prev_line, 0, 13777e8c7beaSZachary Turner prev_source_idx, false, false, false, false, true); 137874e08ca0SZachary Turner } 137974e08ca0SZachary Turner 13807e8c7beaSZachary Turner line_table->InsertSequence(sequence.release()); 138174e08ca0SZachary Turner } 138274e08ca0SZachary Turner 138310a02577SAaron Smith if (line_table->GetSize()) { 138474e08ca0SZachary Turner sc.comp_unit->SetLineTable(line_table.release()); 138574e08ca0SZachary Turner return true; 138674e08ca0SZachary Turner } 138710a02577SAaron Smith return false; 138810a02577SAaron Smith } 138974e08ca0SZachary Turner 1390b9c1b51eSKate Stone void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap( 139110a02577SAaron Smith const PDBSymbolCompiland &compiland, 1392b9c1b51eSKate Stone llvm::DenseMap<uint32_t, uint32_t> &index_map) const { 1393b9c1b51eSKate Stone // This is a hack, but we need to convert the source id into an index into the 13949d0eb996SAdrian McCarthy // support files array. We don't want to do path comparisons to avoid 13959d0eb996SAdrian McCarthy // basename / full path issues that may or may not even be a problem, so we 13969d0eb996SAdrian McCarthy // use the globally unique source file identifiers. Ideally we could use the 13979d0eb996SAdrian McCarthy // global identifiers everywhere, but LineEntry currently assumes indices. 139810a02577SAaron Smith auto source_files = m_session_up->getSourceFilesForCompiland(compiland); 139910a02577SAaron Smith if (!source_files) 140010a02577SAaron Smith return; 140174e08ca0SZachary Turner int index = 0; 140274e08ca0SZachary Turner 1403b9c1b51eSKate Stone while (auto file = source_files->getNext()) { 140474e08ca0SZachary Turner uint32_t source_id = file->getUniqueId(); 140574e08ca0SZachary Turner index_map[source_id] = index++; 140674e08ca0SZachary Turner } 140774e08ca0SZachary Turner } 14087ac1c780SAaron Smith 14097ac1c780SAaron Smith lldb::CompUnitSP SymbolFilePDB::GetCompileUnitContainsAddress( 14107ac1c780SAaron Smith const lldb_private::Address &so_addr) { 14117ac1c780SAaron Smith lldb::addr_t file_vm_addr = so_addr.GetFileAddress(); 14127ac1c780SAaron Smith if (file_vm_addr == LLDB_INVALID_ADDRESS) 14137ac1c780SAaron Smith return nullptr; 14147ac1c780SAaron Smith 14157ac1c780SAaron Smith auto lines_up = 14167ac1c780SAaron Smith m_session_up->findLineNumbersByAddress(file_vm_addr, /*Length=*/200); 14177ac1c780SAaron Smith if (!lines_up) 14187ac1c780SAaron Smith return nullptr; 14197ac1c780SAaron Smith 14207ac1c780SAaron Smith auto first_line_up = lines_up->getNext(); 14217ac1c780SAaron Smith if (!first_line_up) 14227ac1c780SAaron Smith return nullptr; 14237ac1c780SAaron Smith auto compiland_up = GetPDBCompilandByUID(first_line_up->getCompilandId()); 14247ac1c780SAaron Smith if (compiland_up) { 14257ac1c780SAaron Smith return ParseCompileUnitForUID(compiland_up->getSymIndexId()); 14267ac1c780SAaron Smith } 14277ac1c780SAaron Smith 14287ac1c780SAaron Smith return nullptr; 14297ac1c780SAaron Smith } 14307ac1c780SAaron Smith 14317ac1c780SAaron Smith Mangled 14327ac1c780SAaron Smith SymbolFilePDB::GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc *pdb_func) { 14337ac1c780SAaron Smith Mangled mangled; 14347ac1c780SAaron Smith if (!pdb_func) 14357ac1c780SAaron Smith return mangled; 14367ac1c780SAaron Smith 14377ac1c780SAaron Smith auto func_name = pdb_func->getName(); 14387ac1c780SAaron Smith auto func_undecorated_name = pdb_func->getUndecoratedName(); 14397ac1c780SAaron Smith std::string func_decorated_name; 14407ac1c780SAaron Smith 14417ac1c780SAaron Smith // Seek from public symbols for non-static function's decorated name if any. 14427ac1c780SAaron Smith // For static functions, they don't have undecorated names and aren't exposed 14437ac1c780SAaron Smith // in Public Symbols either. 14447ac1c780SAaron Smith if (!func_undecorated_name.empty()) { 14457ac1c780SAaron Smith auto result_up = 14467ac1c780SAaron Smith m_global_scope_up->findChildren(PDB_SymType::PublicSymbol, 14477ac1c780SAaron Smith func_undecorated_name, 14487ac1c780SAaron Smith PDB_NameSearchFlags::NS_UndecoratedName); 14497ac1c780SAaron Smith if (result_up) { 14507ac1c780SAaron Smith while (auto symbol_up = result_up->getNext()) { 14517ac1c780SAaron Smith // For a public symbol, it is unique. 14527ac1c780SAaron Smith lldbassert(result_up->getChildCount() == 1); 14537ac1c780SAaron Smith if (auto *pdb_public_sym = 1454*f76fe682SAaron Smith llvm::dyn_cast_or_null<PDBSymbolPublicSymbol>(symbol_up.get())) { 14557ac1c780SAaron Smith if (pdb_public_sym->isFunction()) { 14567ac1c780SAaron Smith func_decorated_name = pdb_public_sym->getName(); 1457*f76fe682SAaron Smith break; 14587ac1c780SAaron Smith } 14597ac1c780SAaron Smith } 14607ac1c780SAaron Smith } 14617ac1c780SAaron Smith } 14627ac1c780SAaron Smith } 14637ac1c780SAaron Smith if (!func_decorated_name.empty()) { 14647ac1c780SAaron Smith mangled.SetMangledName(ConstString(func_decorated_name)); 14657ac1c780SAaron Smith 14667ac1c780SAaron Smith // For MSVC, format of C funciton's decorated name depends on calling 14677ac1c780SAaron Smith // conventon. Unfortunately none of the format is recognized by current 14687ac1c780SAaron Smith // LLDB. For example, `_purecall` is a __cdecl C function. From PDB, 14697ac1c780SAaron Smith // `__purecall` is retrieved as both its decorated and 14707ac1c780SAaron Smith // undecorated name (using PDBSymbolFunc::getUndecoratedName method). 14717ac1c780SAaron Smith // However `__purecall` string is not treated as mangled in LLDB 14727ac1c780SAaron Smith // (neither `?` nor `_Z` prefix). Mangled::GetDemangledName method 14737ac1c780SAaron Smith // will fail internally and caches an empty string as its undecorated 14747ac1c780SAaron Smith // name. So we will face a contradition here for the same symbol: 14757ac1c780SAaron Smith // non-empty undecorated name from PDB 14767ac1c780SAaron Smith // empty undecorated name from LLDB 14777ac1c780SAaron Smith if (!func_undecorated_name.empty() && 14787ac1c780SAaron Smith mangled.GetDemangledName(mangled.GuessLanguage()).IsEmpty()) 14797ac1c780SAaron Smith mangled.SetDemangledName(ConstString(func_undecorated_name)); 14807ac1c780SAaron Smith 14817ac1c780SAaron Smith // LLDB uses several flags to control how a C++ decorated name is 14827ac1c780SAaron Smith // undecorated for MSVC. See `safeUndecorateName` in Class Mangled. 14837ac1c780SAaron Smith // So the yielded name could be different from what we retrieve from 14847ac1c780SAaron Smith // PDB source unless we also apply same flags in getting undecorated 14857ac1c780SAaron Smith // name through PDBSymbolFunc::getUndecoratedNameEx method. 14867ac1c780SAaron Smith if (!func_undecorated_name.empty() && 14877ac1c780SAaron Smith mangled.GetDemangledName(mangled.GuessLanguage()) != 14887ac1c780SAaron Smith ConstString(func_undecorated_name)) 14897ac1c780SAaron Smith mangled.SetDemangledName(ConstString(func_undecorated_name)); 14907ac1c780SAaron Smith } else if (!func_undecorated_name.empty()) { 14917ac1c780SAaron Smith mangled.SetDemangledName(ConstString(func_undecorated_name)); 14927ac1c780SAaron Smith } else if (!func_name.empty()) 14937ac1c780SAaron Smith mangled.SetValue(ConstString(func_name), false); 14947ac1c780SAaron Smith 14957ac1c780SAaron Smith return mangled; 14967ac1c780SAaron Smith } 14977ac1c780SAaron Smith 14987ac1c780SAaron Smith bool SymbolFilePDB::DeclContextMatchesThisSymbolFile( 14997ac1c780SAaron Smith const lldb_private::CompilerDeclContext *decl_ctx) { 15007ac1c780SAaron Smith if (decl_ctx == nullptr || !decl_ctx->IsValid()) 15017ac1c780SAaron Smith return true; 15027ac1c780SAaron Smith 15037ac1c780SAaron Smith TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem(); 15047ac1c780SAaron Smith if (!decl_ctx_type_system) 15057ac1c780SAaron Smith return false; 15067ac1c780SAaron Smith TypeSystem *type_system = GetTypeSystemForLanguage( 15077ac1c780SAaron Smith decl_ctx_type_system->GetMinimumLanguage(nullptr)); 15087ac1c780SAaron Smith if (decl_ctx_type_system == type_system) 15097ac1c780SAaron Smith return true; // The type systems match, return true 15107ac1c780SAaron Smith 15117ac1c780SAaron Smith return false; 15127ac1c780SAaron Smith } 1513