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" 22ec40f818SAaron Smith #include "lldb/Symbol/TypeList.h" 23308e39caSAaron Smith #include "lldb/Symbol/TypeMap.h" 24cab0d23fSAaron Smith #include "lldb/Symbol/Variable.h" 2586e9434dSAaron Smith #include "lldb/Utility/RegularExpression.h" 2674e08ca0SZachary Turner 27b8d8c62bSPavel Labath #include "llvm/DebugInfo/PDB/GenericError.h" 281f8552abSAaron Smith #include "llvm/DebugInfo/PDB/IPDBDataStream.h" 2974e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" 3074e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBLineNumber.h" 31308e39caSAaron Smith #include "llvm/DebugInfo/PDB/IPDBSectionContrib.h" 3274e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" 331f8552abSAaron Smith #include "llvm/DebugInfo/PDB/IPDBTable.h" 3474e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbol.h" 357ac1c780SAaron Smith #include "llvm/DebugInfo/PDB/PDBSymbolBlock.h" 3674e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h" 3774e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h" 381f8552abSAaron Smith #include "llvm/DebugInfo/PDB/PDBSymbolData.h" 3974e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolExe.h" 4074e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h" 4174e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h" 4274e08ca0SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h" 437ac1c780SAaron Smith #include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h" 4442dff790SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h" 4542dff790SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h" 4642dff790SZachary Turner #include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h" 4742dff790SZachary Turner 487ac1c780SAaron Smith #include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" 4942dff790SZachary Turner #include "Plugins/SymbolFile/PDB/PDBASTParser.h" 5042dff790SZachary Turner 5142dff790SZachary Turner #include <regex> 5274e08ca0SZachary Turner 5310a02577SAaron Smith using namespace lldb; 5474e08ca0SZachary Turner using namespace lldb_private; 5554fd7ff6SZachary Turner using namespace llvm::pdb; 5674e08ca0SZachary Turner 57b9c1b51eSKate Stone namespace { 58b9c1b51eSKate Stone lldb::LanguageType TranslateLanguage(PDB_Lang lang) { 59b9c1b51eSKate Stone switch (lang) { 6054fd7ff6SZachary Turner case PDB_Lang::Cpp: 6174e08ca0SZachary Turner return lldb::LanguageType::eLanguageTypeC_plus_plus; 6254fd7ff6SZachary Turner case PDB_Lang::C: 6374e08ca0SZachary Turner return lldb::LanguageType::eLanguageTypeC; 6474e08ca0SZachary Turner default: 6574e08ca0SZachary Turner return lldb::LanguageType::eLanguageTypeUnknown; 6674e08ca0SZachary Turner } 6774e08ca0SZachary Turner } 687e8c7beaSZachary Turner 69b9c1b51eSKate Stone bool ShouldAddLine(uint32_t requested_line, uint32_t actual_line, 70b9c1b51eSKate Stone uint32_t addr_length) { 71b9c1b51eSKate Stone return ((requested_line == 0 || actual_line == requested_line) && 72b9c1b51eSKate Stone addr_length > 0); 737e8c7beaSZachary Turner } 74c8316ed2SAaron Smith } // namespace 7574e08ca0SZachary Turner 76b9c1b51eSKate Stone void SymbolFilePDB::Initialize() { 77b9c1b51eSKate Stone PluginManager::RegisterPlugin(GetPluginNameStatic(), 78b9c1b51eSKate Stone GetPluginDescriptionStatic(), CreateInstance, 7974e08ca0SZachary Turner DebuggerInitialize); 8074e08ca0SZachary Turner } 8174e08ca0SZachary Turner 82b9c1b51eSKate Stone void SymbolFilePDB::Terminate() { 8374e08ca0SZachary Turner PluginManager::UnregisterPlugin(CreateInstance); 8474e08ca0SZachary Turner } 8574e08ca0SZachary Turner 86b9c1b51eSKate Stone void SymbolFilePDB::DebuggerInitialize(lldb_private::Debugger &debugger) {} 8774e08ca0SZachary Turner 88b9c1b51eSKate Stone lldb_private::ConstString SymbolFilePDB::GetPluginNameStatic() { 8974e08ca0SZachary Turner static ConstString g_name("pdb"); 9074e08ca0SZachary Turner return g_name; 9174e08ca0SZachary Turner } 9274e08ca0SZachary Turner 93b9c1b51eSKate Stone const char *SymbolFilePDB::GetPluginDescriptionStatic() { 9474e08ca0SZachary Turner return "Microsoft PDB debug symbol file reader."; 9574e08ca0SZachary Turner } 9674e08ca0SZachary Turner 9774e08ca0SZachary Turner lldb_private::SymbolFile * 98b9c1b51eSKate Stone SymbolFilePDB::CreateInstance(lldb_private::ObjectFile *obj_file) { 9974e08ca0SZachary Turner return new SymbolFilePDB(obj_file); 10074e08ca0SZachary Turner } 10174e08ca0SZachary Turner 10274e08ca0SZachary Turner SymbolFilePDB::SymbolFilePDB(lldb_private::ObjectFile *object_file) 10310a02577SAaron Smith : SymbolFile(object_file), m_session_up(), m_global_scope_up(), 10410a02577SAaron Smith m_cached_compile_unit_count(0), m_tu_decl_ctx_up() {} 10574e08ca0SZachary Turner 106b9c1b51eSKate Stone SymbolFilePDB::~SymbolFilePDB() {} 10774e08ca0SZachary Turner 108b9c1b51eSKate Stone uint32_t SymbolFilePDB::CalculateAbilities() { 1091f8552abSAaron Smith uint32_t abilities = 0; 1101f8552abSAaron Smith if (!m_obj_file) 1111f8552abSAaron Smith return 0; 1121f8552abSAaron Smith 113b9c1b51eSKate Stone if (!m_session_up) { 11474e08ca0SZachary Turner // Lazily load and match the PDB file, but only do this once. 11574e08ca0SZachary Turner std::string exePath = m_obj_file->GetFileSpec().GetPath(); 116b9c1b51eSKate Stone auto error = loadDataForEXE(PDB_ReaderType::DIA, llvm::StringRef(exePath), 117b9c1b51eSKate Stone m_session_up); 118b9c1b51eSKate Stone if (error) { 1194fd6a960SZachary Turner llvm::consumeError(std::move(error)); 1201f8552abSAaron Smith auto module_sp = m_obj_file->GetModule(); 1211f8552abSAaron Smith if (!module_sp) 1221f8552abSAaron Smith return 0; 1231f8552abSAaron Smith // See if any symbol file is specified through `--symfile` option. 1241f8552abSAaron Smith FileSpec symfile = module_sp->GetSymbolFileFileSpec(); 1251f8552abSAaron Smith if (!symfile) 1261f8552abSAaron Smith return 0; 1271f8552abSAaron Smith error = loadDataForPDB(PDB_ReaderType::DIA, 128c8316ed2SAaron Smith llvm::StringRef(symfile.GetPath()), m_session_up); 1291f8552abSAaron Smith if (error) { 1301f8552abSAaron Smith llvm::consumeError(std::move(error)); 13174e08ca0SZachary Turner return 0; 13274e08ca0SZachary Turner } 133b8d8c62bSPavel Labath } 1341f8552abSAaron Smith } 135d5a925f4SAaron Smith if (!m_session_up) 1361f8552abSAaron Smith return 0; 1371f8552abSAaron Smith 1381f8552abSAaron Smith auto enum_tables_up = m_session_up->getEnumTables(); 1391f8552abSAaron Smith if (!enum_tables_up) 1401f8552abSAaron Smith return 0; 1411f8552abSAaron Smith while (auto table_up = enum_tables_up->getNext()) { 1421f8552abSAaron Smith if (table_up->getItemCount() == 0) 1431f8552abSAaron Smith continue; 1441f8552abSAaron Smith auto type = table_up->getTableType(); 1451f8552abSAaron Smith switch (type) { 1461f8552abSAaron Smith case PDB_TableType::Symbols: 1471f8552abSAaron Smith // This table represents a store of symbols with types listed in 1481f8552abSAaron Smith // PDBSym_Type 149c8316ed2SAaron Smith abilities |= (CompileUnits | Functions | Blocks | GlobalVariables | 150c8316ed2SAaron Smith LocalVariables | VariableTypes); 1511f8552abSAaron Smith break; 1521f8552abSAaron Smith case PDB_TableType::LineNumbers: 1531f8552abSAaron Smith abilities |= LineTables; 1541f8552abSAaron Smith break; 155c8316ed2SAaron Smith default: 156c8316ed2SAaron Smith break; 1571f8552abSAaron Smith } 1581f8552abSAaron Smith } 1591f8552abSAaron Smith return abilities; 16074e08ca0SZachary Turner } 16174e08ca0SZachary Turner 162b9c1b51eSKate Stone void SymbolFilePDB::InitializeObject() { 16374e08ca0SZachary Turner lldb::addr_t obj_load_address = m_obj_file->GetFileOffset(); 164c8316ed2SAaron Smith lldbassert(obj_load_address && obj_load_address != LLDB_INVALID_ADDRESS); 16574e08ca0SZachary Turner m_session_up->setLoadAddress(obj_load_address); 16610a02577SAaron Smith if (!m_global_scope_up) 16710a02577SAaron Smith m_global_scope_up = m_session_up->getGlobalScope(); 16810a02577SAaron Smith lldbassert(m_global_scope_up.get()); 16942dff790SZachary Turner 170b9c1b51eSKate Stone TypeSystem *type_system = 171b9c1b51eSKate Stone GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 172b9c1b51eSKate Stone ClangASTContext *clang_type_system = 173b9c1b51eSKate Stone llvm::dyn_cast_or_null<ClangASTContext>(type_system); 17410a02577SAaron Smith lldbassert(clang_type_system); 175b9c1b51eSKate Stone m_tu_decl_ctx_up = llvm::make_unique<CompilerDeclContext>( 176b9c1b51eSKate Stone type_system, clang_type_system->GetTranslationUnitDecl()); 17774e08ca0SZachary Turner } 17874e08ca0SZachary Turner 179b9c1b51eSKate Stone uint32_t SymbolFilePDB::GetNumCompileUnits() { 180b9c1b51eSKate Stone if (m_cached_compile_unit_count == 0) { 18110a02577SAaron Smith auto compilands = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); 18210a02577SAaron Smith if (!compilands) 18310a02577SAaron Smith return 0; 18410a02577SAaron Smith 18510a02577SAaron Smith // The linker could link *.dll (compiland language = LINK), or import 18605097246SAdrian Prantl // *.dll. For example, a compiland with name `Import:KERNEL32.dll` could be 18705097246SAdrian Prantl // found as a child of the global scope (PDB executable). Usually, such 18805097246SAdrian Prantl // compilands contain `thunk` symbols in which we are not interested for 18905097246SAdrian Prantl // now. However we still count them in the compiland list. If we perform 19005097246SAdrian Prantl // any compiland related activity, like finding symbols through 19105097246SAdrian Prantl // llvm::pdb::IPDBSession methods, such compilands will all be searched 19205097246SAdrian Prantl // automatically no matter whether we include them or not. 19374e08ca0SZachary Turner m_cached_compile_unit_count = compilands->getChildCount(); 19474e08ca0SZachary Turner 195b9c1b51eSKate Stone // The linker can inject an additional "dummy" compilation unit into the 1969d0eb996SAdrian McCarthy // PDB. Ignore this special compile unit for our purposes, if it is there. 1979d0eb996SAdrian McCarthy // It is always the last one. 19810a02577SAaron Smith auto last_compiland_up = 19910a02577SAaron Smith compilands->getChildAtIndex(m_cached_compile_unit_count - 1); 20010a02577SAaron Smith lldbassert(last_compiland_up.get()); 20110a02577SAaron Smith std::string name = last_compiland_up->getName(); 20274e08ca0SZachary Turner if (name == "* Linker *") 20374e08ca0SZachary Turner --m_cached_compile_unit_count; 20474e08ca0SZachary Turner } 20574e08ca0SZachary Turner return m_cached_compile_unit_count; 20674e08ca0SZachary Turner } 20774e08ca0SZachary Turner 20810a02577SAaron Smith void SymbolFilePDB::GetCompileUnitIndex( 209c8316ed2SAaron Smith const llvm::pdb::PDBSymbolCompiland &pdb_compiland, uint32_t &index) { 21010a02577SAaron Smith auto results_up = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); 21110a02577SAaron Smith if (!results_up) 21210a02577SAaron Smith return; 213e664b5dcSAaron Smith auto uid = pdb_compiland.getSymIndexId(); 214fbdf0b93SRaphael Isemann for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) { 21510a02577SAaron Smith auto compiland_up = results_up->getChildAtIndex(cu_idx); 21610a02577SAaron Smith if (!compiland_up) 21710a02577SAaron Smith continue; 21810a02577SAaron Smith if (compiland_up->getSymIndexId() == uid) { 21910a02577SAaron Smith index = cu_idx; 22010a02577SAaron Smith return; 22110a02577SAaron Smith } 22210a02577SAaron Smith } 22310a02577SAaron Smith index = UINT32_MAX; 22410a02577SAaron Smith return; 22510a02577SAaron Smith } 22610a02577SAaron Smith 22710a02577SAaron Smith std::unique_ptr<llvm::pdb::PDBSymbolCompiland> 22810a02577SAaron Smith SymbolFilePDB::GetPDBCompilandByUID(uint32_t uid) { 22910a02577SAaron Smith return m_session_up->getConcreteSymbolById<PDBSymbolCompiland>(uid); 23010a02577SAaron Smith } 23110a02577SAaron Smith 232b9c1b51eSKate Stone lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitAtIndex(uint32_t index) { 23310a02577SAaron Smith if (index >= GetNumCompileUnits()) 23410a02577SAaron Smith return CompUnitSP(); 23574e08ca0SZachary Turner 23610a02577SAaron Smith // Assuming we always retrieve same compilands listed in same order through 23710a02577SAaron Smith // `PDBSymbolExe::findAllChildren` method, otherwise using `index` to get a 23810a02577SAaron Smith // compile unit makes no sense. 23910a02577SAaron Smith auto results = m_global_scope_up->findAllChildren<PDBSymbolCompiland>(); 24010a02577SAaron Smith if (!results) 24110a02577SAaron Smith return CompUnitSP(); 24210a02577SAaron Smith auto compiland_up = results->getChildAtIndex(index); 24310a02577SAaron Smith if (!compiland_up) 24410a02577SAaron Smith return CompUnitSP(); 24510a02577SAaron Smith return ParseCompileUnitForUID(compiland_up->getSymIndexId(), index); 24674e08ca0SZachary Turner } 24774e08ca0SZachary Turner 24874e08ca0SZachary Turner lldb::LanguageType 249b9c1b51eSKate Stone SymbolFilePDB::ParseCompileUnitLanguage(const lldb_private::SymbolContext &sc) { 25074e08ca0SZachary Turner // What fields should I expect to be filled out on the SymbolContext? Is it 25174e08ca0SZachary Turner // safe to assume that `sc.comp_unit` is valid? 25274e08ca0SZachary Turner if (!sc.comp_unit) 25374e08ca0SZachary Turner return lldb::eLanguageTypeUnknown; 25474e08ca0SZachary Turner 25510a02577SAaron Smith auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); 25610a02577SAaron Smith if (!compiland_up) 25774e08ca0SZachary Turner return lldb::eLanguageTypeUnknown; 25810a02577SAaron Smith auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>(); 25974e08ca0SZachary Turner if (!details) 26074e08ca0SZachary Turner return lldb::eLanguageTypeUnknown; 26174e08ca0SZachary Turner return TranslateLanguage(details->getLanguage()); 26274e08ca0SZachary Turner } 26374e08ca0SZachary Turner 264c8316ed2SAaron Smith lldb_private::Function *SymbolFilePDB::ParseCompileUnitFunctionForPDBFunc( 265c8316ed2SAaron Smith const PDBSymbolFunc &pdb_func, const lldb_private::SymbolContext &sc) { 2667ac1c780SAaron Smith lldbassert(sc.comp_unit && sc.module_sp.get()); 2677ac1c780SAaron Smith 268e664b5dcSAaron Smith auto file_vm_addr = pdb_func.getVirtualAddress(); 269308e39caSAaron Smith if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0) 2707ac1c780SAaron Smith return nullptr; 2717ac1c780SAaron Smith 272e664b5dcSAaron Smith auto func_length = pdb_func.getLength(); 273c8316ed2SAaron Smith AddressRange func_range = 274c8316ed2SAaron Smith AddressRange(file_vm_addr, func_length, sc.module_sp->GetSectionList()); 2757ac1c780SAaron Smith if (!func_range.GetBaseAddress().IsValid()) 2767ac1c780SAaron Smith return nullptr; 2777ac1c780SAaron Smith 278e664b5dcSAaron Smith lldb_private::Type *func_type = ResolveTypeUID(pdb_func.getSymIndexId()); 2797ac1c780SAaron Smith if (!func_type) 2807ac1c780SAaron Smith return nullptr; 2817ac1c780SAaron Smith 282e664b5dcSAaron Smith user_id_t func_type_uid = pdb_func.getSignatureId(); 283f76fe682SAaron Smith 2847ac1c780SAaron Smith Mangled mangled = GetMangledForPDBFunc(pdb_func); 2857ac1c780SAaron Smith 286c8316ed2SAaron Smith FunctionSP func_sp = 287c8316ed2SAaron Smith std::make_shared<Function>(sc.comp_unit, pdb_func.getSymIndexId(), 288c8316ed2SAaron Smith func_type_uid, mangled, func_type, func_range); 2897ac1c780SAaron Smith 2907ac1c780SAaron Smith sc.comp_unit->AddFunction(func_sp); 2917ac1c780SAaron Smith return func_sp.get(); 2927ac1c780SAaron Smith } 2937ac1c780SAaron Smith 294b9c1b51eSKate Stone size_t SymbolFilePDB::ParseCompileUnitFunctions( 295b9c1b51eSKate Stone const lldb_private::SymbolContext &sc) { 2967ac1c780SAaron Smith lldbassert(sc.comp_unit); 2977ac1c780SAaron Smith size_t func_added = 0; 2987ac1c780SAaron Smith auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); 2997ac1c780SAaron Smith if (!compiland_up) 3007ac1c780SAaron Smith return 0; 3017ac1c780SAaron Smith auto results_up = compiland_up->findAllChildren<PDBSymbolFunc>(); 3027ac1c780SAaron Smith if (!results_up) 3037ac1c780SAaron Smith return 0; 3047ac1c780SAaron Smith while (auto pdb_func_up = results_up->getNext()) { 3057ac1c780SAaron Smith auto func_sp = 3067ac1c780SAaron Smith sc.comp_unit->FindFunctionByUID(pdb_func_up->getSymIndexId()); 3077ac1c780SAaron Smith if (!func_sp) { 308e664b5dcSAaron Smith if (ParseCompileUnitFunctionForPDBFunc(*pdb_func_up, sc)) 3097ac1c780SAaron Smith ++func_added; 3107ac1c780SAaron Smith } 3117ac1c780SAaron Smith } 3127ac1c780SAaron Smith return func_added; 31374e08ca0SZachary Turner } 31474e08ca0SZachary Turner 315b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitLineTable( 316b9c1b51eSKate Stone const lldb_private::SymbolContext &sc) { 31710a02577SAaron Smith lldbassert(sc.comp_unit); 31810a02577SAaron Smith if (sc.comp_unit->GetLineTable()) 31910a02577SAaron Smith return true; 32074e08ca0SZachary Turner return ParseCompileUnitLineTable(sc, 0); 32174e08ca0SZachary Turner } 32274e08ca0SZachary Turner 323b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitDebugMacros( 324b9c1b51eSKate Stone const lldb_private::SymbolContext &sc) { 32574e08ca0SZachary Turner // PDB doesn't contain information about macros 32674e08ca0SZachary Turner return false; 32774e08ca0SZachary Turner } 32874e08ca0SZachary Turner 329b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitSupportFiles( 330b9c1b51eSKate Stone const lldb_private::SymbolContext &sc, 331b9c1b51eSKate Stone lldb_private::FileSpecList &support_files) { 33210a02577SAaron Smith lldbassert(sc.comp_unit); 33374e08ca0SZachary Turner 334b9c1b51eSKate Stone // In theory this is unnecessary work for us, because all of this information 3359d0eb996SAdrian McCarthy // is easily (and quickly) accessible from DebugInfoPDB, so caching it a 3369d0eb996SAdrian McCarthy // second time seems like a waste. Unfortunately, there's no good way around 3379d0eb996SAdrian McCarthy // this short of a moderate refactor since SymbolVendor depends on being able 3389d0eb996SAdrian McCarthy // to cache this list. 33910a02577SAaron Smith auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); 34010a02577SAaron Smith if (!compiland_up) 34174e08ca0SZachary Turner return false; 34210a02577SAaron Smith auto files = m_session_up->getSourceFilesForCompiland(*compiland_up); 34374e08ca0SZachary Turner if (!files || files->getChildCount() == 0) 34474e08ca0SZachary Turner return false; 34574e08ca0SZachary Turner 346b9c1b51eSKate Stone while (auto file = files->getNext()) { 3472cb7cf8eSPavel Labath FileSpec spec(file->getFileName(), false, FileSpec::Style::windows); 34810a02577SAaron Smith support_files.AppendIfUnique(spec); 34974e08ca0SZachary Turner } 35074e08ca0SZachary Turner return true; 35174e08ca0SZachary Turner } 35274e08ca0SZachary Turner 353b9c1b51eSKate Stone bool SymbolFilePDB::ParseImportedModules( 354b9c1b51eSKate Stone const lldb_private::SymbolContext &sc, 355b9c1b51eSKate Stone std::vector<lldb_private::ConstString> &imported_modules) { 35674e08ca0SZachary Turner // PDB does not yet support module debug info 35774e08ca0SZachary Turner return false; 35874e08ca0SZachary Turner } 35974e08ca0SZachary Turner 360c8316ed2SAaron Smith static size_t ParseFunctionBlocksForPDBSymbol( 361c8316ed2SAaron Smith const lldb_private::SymbolContext &sc, uint64_t func_file_vm_addr, 362c8316ed2SAaron Smith const llvm::pdb::PDBSymbol *pdb_symbol, lldb_private::Block *parent_block, 3637ac1c780SAaron Smith bool is_top_parent) { 3647ac1c780SAaron Smith assert(pdb_symbol && parent_block); 3657ac1c780SAaron Smith 3667ac1c780SAaron Smith size_t num_added = 0; 3677ac1c780SAaron Smith switch (pdb_symbol->getSymTag()) { 3687ac1c780SAaron Smith case PDB_SymType::Block: 3697ac1c780SAaron Smith case PDB_SymType::Function: { 3707ac1c780SAaron Smith Block *block = nullptr; 3717ac1c780SAaron Smith auto &raw_sym = pdb_symbol->getRawSymbol(); 3727ac1c780SAaron Smith if (auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(pdb_symbol)) { 3737ac1c780SAaron Smith if (pdb_func->hasNoInlineAttribute()) 3747ac1c780SAaron Smith break; 3757ac1c780SAaron Smith if (is_top_parent) 3767ac1c780SAaron Smith block = parent_block; 3777ac1c780SAaron Smith else 3787ac1c780SAaron Smith break; 3797ac1c780SAaron Smith } else if (llvm::dyn_cast<PDBSymbolBlock>(pdb_symbol)) { 3807ac1c780SAaron Smith auto uid = pdb_symbol->getSymIndexId(); 3817ac1c780SAaron Smith if (parent_block->FindBlockByID(uid)) 3827ac1c780SAaron Smith break; 3837ac1c780SAaron Smith if (raw_sym.getVirtualAddress() < func_file_vm_addr) 3847ac1c780SAaron Smith break; 3857ac1c780SAaron Smith 3867ac1c780SAaron Smith auto block_sp = std::make_shared<Block>(pdb_symbol->getSymIndexId()); 3877ac1c780SAaron Smith parent_block->AddChild(block_sp); 3887ac1c780SAaron Smith block = block_sp.get(); 3897ac1c780SAaron Smith } else 3907ac1c780SAaron Smith llvm_unreachable("Unexpected PDB symbol!"); 3917ac1c780SAaron Smith 392c8316ed2SAaron Smith block->AddRange(Block::Range( 393c8316ed2SAaron Smith raw_sym.getVirtualAddress() - func_file_vm_addr, raw_sym.getLength())); 3947ac1c780SAaron Smith block->FinalizeRanges(); 3957ac1c780SAaron Smith ++num_added; 3967ac1c780SAaron Smith 3977ac1c780SAaron Smith auto results_up = pdb_symbol->findAllChildren(); 3987ac1c780SAaron Smith if (!results_up) 3997ac1c780SAaron Smith break; 4007ac1c780SAaron Smith while (auto symbol_up = results_up->getNext()) { 401c8316ed2SAaron Smith num_added += ParseFunctionBlocksForPDBSymbol( 402c8316ed2SAaron Smith sc, func_file_vm_addr, symbol_up.get(), block, false); 4037ac1c780SAaron Smith } 4047ac1c780SAaron Smith } break; 405c8316ed2SAaron Smith default: 406c8316ed2SAaron Smith break; 4077ac1c780SAaron Smith } 4087ac1c780SAaron Smith return num_added; 4097ac1c780SAaron Smith } 4107ac1c780SAaron Smith 41174e08ca0SZachary Turner size_t 412b9c1b51eSKate Stone SymbolFilePDB::ParseFunctionBlocks(const lldb_private::SymbolContext &sc) { 4137ac1c780SAaron Smith lldbassert(sc.comp_unit && sc.function); 4147ac1c780SAaron Smith size_t num_added = 0; 4157ac1c780SAaron Smith auto uid = sc.function->GetID(); 4167ac1c780SAaron Smith auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid); 4177ac1c780SAaron Smith if (!pdb_func_up) 4187ac1c780SAaron Smith return 0; 4197ac1c780SAaron Smith Block &parent_block = sc.function->GetBlock(false); 4207ac1c780SAaron Smith num_added = 4217ac1c780SAaron Smith ParseFunctionBlocksForPDBSymbol(sc, pdb_func_up->getVirtualAddress(), 4227ac1c780SAaron Smith pdb_func_up.get(), &parent_block, true); 4237ac1c780SAaron Smith return num_added; 424b9c1b51eSKate Stone } 425b9c1b51eSKate Stone 426b9c1b51eSKate Stone size_t SymbolFilePDB::ParseTypes(const lldb_private::SymbolContext &sc) { 427ec40f818SAaron Smith lldbassert(sc.module_sp.get()); 42866b84079SAaron Smith if (!sc.comp_unit) 429ec40f818SAaron Smith return 0; 43066b84079SAaron Smith 43166b84079SAaron Smith size_t num_added = 0; 43266b84079SAaron Smith auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID()); 43366b84079SAaron Smith if (!compiland) 43466b84079SAaron Smith return 0; 43566b84079SAaron Smith 43666b84079SAaron Smith auto ParseTypesByTagFn = [&num_added, this](const PDBSymbol &raw_sym) { 43766b84079SAaron Smith std::unique_ptr<IPDBEnumSymbols> results; 43866b84079SAaron Smith PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef, 43966b84079SAaron Smith PDB_SymType::UDT}; 44066b84079SAaron Smith for (auto tag : tags_to_search) { 44166b84079SAaron Smith results = raw_sym.findAllChildren(tag); 44266b84079SAaron Smith if (!results || results->getChildCount() == 0) 44366b84079SAaron Smith continue; 44466b84079SAaron Smith while (auto symbol = results->getNext()) { 44566b84079SAaron Smith switch (symbol->getSymTag()) { 446ec40f818SAaron Smith case PDB_SymType::Enum: 447ec40f818SAaron Smith case PDB_SymType::UDT: 448ec40f818SAaron Smith case PDB_SymType::Typedef: 449ec40f818SAaron Smith break; 450ec40f818SAaron Smith default: 451ec40f818SAaron Smith continue; 452ec40f818SAaron Smith } 453ec40f818SAaron Smith 454ec40f818SAaron Smith // This should cause the type to get cached and stored in the `m_types` 455ec40f818SAaron Smith // lookup. 45666b84079SAaron Smith if (!ResolveTypeUID(symbol->getSymIndexId())) 457ec40f818SAaron Smith continue; 458ec40f818SAaron Smith 459ec40f818SAaron Smith ++num_added; 460ec40f818SAaron Smith } 46166b84079SAaron Smith } 46266b84079SAaron Smith }; 46366b84079SAaron Smith 46466b84079SAaron Smith if (sc.function) { 465c8316ed2SAaron Smith auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>( 466c8316ed2SAaron Smith sc.function->GetID()); 46766b84079SAaron Smith if (!pdb_func) 46866b84079SAaron Smith return 0; 46966b84079SAaron Smith ParseTypesByTagFn(*pdb_func); 47066b84079SAaron Smith } else { 47166b84079SAaron Smith ParseTypesByTagFn(*compiland); 47266b84079SAaron Smith 47366b84079SAaron Smith // Also parse global types particularly coming from this compiland. 47405097246SAdrian Prantl // Unfortunately, PDB has no compiland information for each global type. We 47505097246SAdrian Prantl // have to parse them all. But ensure we only do this once. 47666b84079SAaron Smith static bool parse_all_global_types = false; 47766b84079SAaron Smith if (!parse_all_global_types) { 47866b84079SAaron Smith ParseTypesByTagFn(*m_global_scope_up); 47966b84079SAaron Smith parse_all_global_types = true; 48066b84079SAaron Smith } 48166b84079SAaron Smith } 482ec40f818SAaron Smith return num_added; 48374e08ca0SZachary Turner } 48474e08ca0SZachary Turner 48574e08ca0SZachary Turner size_t 486b9c1b51eSKate Stone SymbolFilePDB::ParseVariablesForContext(const lldb_private::SymbolContext &sc) { 487cab0d23fSAaron Smith if (!sc.comp_unit) 488cab0d23fSAaron Smith return 0; 489cab0d23fSAaron Smith 490cab0d23fSAaron Smith size_t num_added = 0; 491cab0d23fSAaron Smith if (sc.function) { 492cab0d23fSAaron Smith auto pdb_func = m_session_up->getConcreteSymbolById<PDBSymbolFunc>( 493cab0d23fSAaron Smith sc.function->GetID()); 494cab0d23fSAaron Smith if (!pdb_func) 495cab0d23fSAaron Smith return 0; 496cab0d23fSAaron Smith 497cab0d23fSAaron Smith num_added += ParseVariables(sc, *pdb_func); 498cab0d23fSAaron Smith sc.function->GetBlock(false).SetDidParseVariables(true, true); 499cab0d23fSAaron Smith } else if (sc.comp_unit) { 500cab0d23fSAaron Smith auto compiland = GetPDBCompilandByUID(sc.comp_unit->GetID()); 501cab0d23fSAaron Smith if (!compiland) 502cab0d23fSAaron Smith return 0; 503cab0d23fSAaron Smith 504cab0d23fSAaron Smith if (sc.comp_unit->GetVariableList(false)) 505cab0d23fSAaron Smith return 0; 506cab0d23fSAaron Smith 507cab0d23fSAaron Smith auto results = m_global_scope_up->findAllChildren<PDBSymbolData>(); 508cab0d23fSAaron Smith if (results && results->getChildCount()) { 509cab0d23fSAaron Smith while (auto result = results->getNext()) { 510cab0d23fSAaron Smith auto cu_id = result->getCompilandId(); 511cab0d23fSAaron Smith // FIXME: We are not able to determine variable's compile unit. 512cab0d23fSAaron Smith if (cu_id == 0) 513cab0d23fSAaron Smith continue; 514cab0d23fSAaron Smith 515cab0d23fSAaron Smith if (cu_id == sc.comp_unit->GetID()) 516cab0d23fSAaron Smith num_added += ParseVariables(sc, *result); 517cab0d23fSAaron Smith } 518cab0d23fSAaron Smith } 519cab0d23fSAaron Smith 520cab0d23fSAaron Smith // FIXME: A `file static` or `global constant` variable appears both in 521cab0d23fSAaron Smith // compiland's children and global scope's children with unexpectedly 522cab0d23fSAaron Smith // different symbol's Id making it ambiguous. 523cab0d23fSAaron Smith 524cab0d23fSAaron Smith // FIXME: 'local constant', for example, const char var[] = "abc", declared 525cab0d23fSAaron Smith // in a function scope, can't be found in PDB. 526cab0d23fSAaron Smith 527cab0d23fSAaron Smith // Parse variables in this compiland. 528cab0d23fSAaron Smith num_added += ParseVariables(sc, *compiland); 529cab0d23fSAaron Smith } 530cab0d23fSAaron Smith 531cab0d23fSAaron Smith return num_added; 53274e08ca0SZachary Turner } 53374e08ca0SZachary Turner 534b9c1b51eSKate Stone lldb_private::Type *SymbolFilePDB::ResolveTypeUID(lldb::user_id_t type_uid) { 53542dff790SZachary Turner auto find_result = m_types.find(type_uid); 53642dff790SZachary Turner if (find_result != m_types.end()) 53742dff790SZachary Turner return find_result->second.get(); 53842dff790SZachary Turner 539b9c1b51eSKate Stone TypeSystem *type_system = 540b9c1b51eSKate Stone GetTypeSystemForLanguage(lldb::eLanguageTypeC_plus_plus); 541b9c1b51eSKate Stone ClangASTContext *clang_type_system = 542b9c1b51eSKate Stone llvm::dyn_cast_or_null<ClangASTContext>(type_system); 54342dff790SZachary Turner if (!clang_type_system) 54474e08ca0SZachary Turner return nullptr; 545b9c1b51eSKate Stone PDBASTParser *pdb = 546b9c1b51eSKate Stone llvm::dyn_cast<PDBASTParser>(clang_type_system->GetPDBParser()); 54742dff790SZachary Turner if (!pdb) 54842dff790SZachary Turner return nullptr; 54942dff790SZachary Turner 55042dff790SZachary Turner auto pdb_type = m_session_up->getSymbolById(type_uid); 55142dff790SZachary Turner if (pdb_type == nullptr) 55242dff790SZachary Turner return nullptr; 55342dff790SZachary Turner 55442dff790SZachary Turner lldb::TypeSP result = pdb->CreateLLDBTypeFromPDBType(*pdb_type); 555d5a925f4SAaron Smith if (result) { 55642dff790SZachary Turner m_types.insert(std::make_pair(type_uid, result)); 557ec40f818SAaron Smith auto type_list = GetTypeList(); 558f76fe682SAaron Smith if (type_list) 559ec40f818SAaron Smith type_list->Insert(result); 560ec40f818SAaron Smith } 56142dff790SZachary Turner return result.get(); 56274e08ca0SZachary Turner } 56374e08ca0SZachary Turner 564b9c1b51eSKate Stone bool SymbolFilePDB::CompleteType(lldb_private::CompilerType &compiler_type) { 56574e08ca0SZachary Turner // TODO: Implement this 56674e08ca0SZachary Turner return false; 56774e08ca0SZachary Turner } 56874e08ca0SZachary Turner 569b9c1b51eSKate Stone lldb_private::CompilerDecl SymbolFilePDB::GetDeclForUID(lldb::user_id_t uid) { 57074e08ca0SZachary Turner return lldb_private::CompilerDecl(); 57174e08ca0SZachary Turner } 57274e08ca0SZachary Turner 57374e08ca0SZachary Turner lldb_private::CompilerDeclContext 574b9c1b51eSKate Stone SymbolFilePDB::GetDeclContextForUID(lldb::user_id_t uid) { 575b9c1b51eSKate Stone // PDB always uses the translation unit decl context for everything. We can 5769d0eb996SAdrian McCarthy // improve this later but it's not easy because PDB doesn't provide a high 5779d0eb996SAdrian McCarthy // enough level of type fidelity in this area. 57842dff790SZachary Turner return *m_tu_decl_ctx_up; 57974e08ca0SZachary Turner } 58074e08ca0SZachary Turner 58174e08ca0SZachary Turner lldb_private::CompilerDeclContext 582b9c1b51eSKate Stone SymbolFilePDB::GetDeclContextContainingUID(lldb::user_id_t uid) { 58342dff790SZachary Turner return *m_tu_decl_ctx_up; 58474e08ca0SZachary Turner } 58574e08ca0SZachary Turner 586b9c1b51eSKate Stone void SymbolFilePDB::ParseDeclsForContext( 587b9c1b51eSKate Stone lldb_private::CompilerDeclContext decl_ctx) {} 58874e08ca0SZachary Turner 58974e08ca0SZachary Turner uint32_t 590b9c1b51eSKate Stone SymbolFilePDB::ResolveSymbolContext(const lldb_private::Address &so_addr, 591b9c1b51eSKate Stone uint32_t resolve_scope, 592b9c1b51eSKate Stone lldb_private::SymbolContext &sc) { 5937ac1c780SAaron Smith uint32_t resolved_flags = 0; 5944d4d63eeSPavel Labath if (resolve_scope & eSymbolContextCompUnit || 5954d4d63eeSPavel Labath resolve_scope & eSymbolContextVariable || 5964d4d63eeSPavel Labath resolve_scope & eSymbolContextFunction || 5974d4d63eeSPavel Labath resolve_scope & eSymbolContextBlock || 5987ac1c780SAaron Smith resolve_scope & eSymbolContextLineEntry) { 5997ac1c780SAaron Smith addr_t file_vm_addr = so_addr.GetFileAddress(); 6007ac1c780SAaron Smith auto symbol_up = 6017ac1c780SAaron Smith m_session_up->findSymbolByAddress(file_vm_addr, PDB_SymType::None); 6027ac1c780SAaron Smith if (!symbol_up) 6037ac1c780SAaron Smith return 0; 6047ac1c780SAaron Smith 6057ac1c780SAaron Smith auto cu_sp = GetCompileUnitContainsAddress(so_addr); 6067ac1c780SAaron Smith if (!cu_sp) { 6077ac1c780SAaron Smith if (resolved_flags | eSymbolContextVariable) { 6087ac1c780SAaron Smith // TODO: Resolve variables 6097ac1c780SAaron Smith } 6107ac1c780SAaron Smith return 0; 6117ac1c780SAaron Smith } 6127ac1c780SAaron Smith sc.comp_unit = cu_sp.get(); 6137ac1c780SAaron Smith resolved_flags |= eSymbolContextCompUnit; 6147ac1c780SAaron Smith lldbassert(sc.module_sp == cu_sp->GetModule()); 6157ac1c780SAaron Smith 6167ac1c780SAaron Smith switch (symbol_up->getSymTag()) { 6177ac1c780SAaron Smith case PDB_SymType::Function: 6187ac1c780SAaron Smith if (resolve_scope & eSymbolContextFunction) { 6197ac1c780SAaron Smith auto *pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get()); 6207ac1c780SAaron Smith assert(pdb_func); 6217ac1c780SAaron Smith auto func_uid = pdb_func->getSymIndexId(); 6227ac1c780SAaron Smith sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get(); 6237ac1c780SAaron Smith if (sc.function == nullptr) 624e664b5dcSAaron Smith sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc); 6257ac1c780SAaron Smith if (sc.function) { 6267ac1c780SAaron Smith resolved_flags |= eSymbolContextFunction; 6277ac1c780SAaron Smith if (resolve_scope & eSymbolContextBlock) { 6287ac1c780SAaron Smith Block &block = sc.function->GetBlock(true); 6297ac1c780SAaron Smith sc.block = block.FindBlockByID(sc.function->GetID()); 6307ac1c780SAaron Smith if (sc.block) 6317ac1c780SAaron Smith resolved_flags |= eSymbolContextBlock; 6327ac1c780SAaron Smith } 6337ac1c780SAaron Smith } 6347ac1c780SAaron Smith } 6357ac1c780SAaron Smith break; 6367ac1c780SAaron Smith default: 6377ac1c780SAaron Smith break; 6387ac1c780SAaron Smith } 6397ac1c780SAaron Smith 6407ac1c780SAaron Smith if (resolve_scope & eSymbolContextLineEntry) { 6417ac1c780SAaron Smith if (auto *line_table = sc.comp_unit->GetLineTable()) { 6427ac1c780SAaron Smith Address addr(so_addr); 6437ac1c780SAaron Smith if (line_table->FindLineEntryByAddress(addr, sc.line_entry)) 6447ac1c780SAaron Smith resolved_flags |= eSymbolContextLineEntry; 6457ac1c780SAaron Smith } 6467ac1c780SAaron Smith } 6477ac1c780SAaron Smith } 6487ac1c780SAaron Smith return resolved_flags; 64974e08ca0SZachary Turner } 65074e08ca0SZachary Turner 651b9c1b51eSKate Stone uint32_t SymbolFilePDB::ResolveSymbolContext( 652b9c1b51eSKate Stone const lldb_private::FileSpec &file_spec, uint32_t line, bool check_inlines, 653b9c1b51eSKate Stone uint32_t resolve_scope, lldb_private::SymbolContextList &sc_list) { 65410a02577SAaron Smith const size_t old_size = sc_list.GetSize(); 655b9c1b51eSKate Stone if (resolve_scope & lldb::eSymbolContextCompUnit) { 656b9c1b51eSKate Stone // Locate all compilation units with line numbers referencing the specified 6579d0eb996SAdrian McCarthy // file. For example, if `file_spec` is <vector>, then this should return 6589d0eb996SAdrian McCarthy // all source files and header files that reference <vector>, either 6599d0eb996SAdrian McCarthy // directly or indirectly. 660b9c1b51eSKate Stone auto compilands = m_session_up->findCompilandsForSourceFile( 661b9c1b51eSKate Stone file_spec.GetPath(), PDB_NameSearchFlags::NS_CaseInsensitive); 66274e08ca0SZachary Turner 66310a02577SAaron Smith if (!compilands) 66410a02577SAaron Smith return 0; 66510a02577SAaron Smith 6669d0eb996SAdrian McCarthy // For each one, either find its previously parsed data or parse it afresh 6679d0eb996SAdrian McCarthy // and add it to the symbol context list. 668b9c1b51eSKate Stone while (auto compiland = compilands->getNext()) { 66905097246SAdrian Prantl // If we're not checking inlines, then don't add line information for 67005097246SAdrian Prantl // this file unless the FileSpec matches. For inline functions, we don't 67105097246SAdrian Prantl // have to match the FileSpec since they could be defined in headers 67205097246SAdrian Prantl // other than file specified in FileSpec. 673b9c1b51eSKate Stone if (!check_inlines) { 674487b0c6bSAaron Smith std::string source_file = compiland->getSourceFileFullPath(); 67510a02577SAaron Smith if (source_file.empty()) 67610a02577SAaron Smith continue; 6772cb7cf8eSPavel Labath FileSpec this_spec(source_file, false, FileSpec::Style::windows); 67810a02577SAaron Smith bool need_full_match = !file_spec.GetDirectory().IsEmpty(); 67910a02577SAaron Smith if (FileSpec::Compare(file_spec, this_spec, need_full_match) != 0) 68074e08ca0SZachary Turner continue; 68174e08ca0SZachary Turner } 68274e08ca0SZachary Turner 68374e08ca0SZachary Turner SymbolContext sc; 68410a02577SAaron Smith auto cu = ParseCompileUnitForUID(compiland->getSymIndexId()); 685d5a925f4SAaron Smith if (!cu) 68610a02577SAaron Smith continue; 68774e08ca0SZachary Turner sc.comp_unit = cu.get(); 68874e08ca0SZachary Turner sc.module_sp = cu->GetModule(); 68974e08ca0SZachary Turner 690b9c1b51eSKate Stone // If we were asked to resolve line entries, add all entries to the line 6919d0eb996SAdrian McCarthy // table that match the requested line (or all lines if `line` == 0). 6927ac1c780SAaron Smith if (resolve_scope & (eSymbolContextFunction | eSymbolContextBlock | 6937ac1c780SAaron Smith eSymbolContextLineEntry)) { 6947ac1c780SAaron Smith bool has_line_table = ParseCompileUnitLineTable(sc, line); 6957ac1c780SAaron Smith 6967ac1c780SAaron Smith if ((resolve_scope & eSymbolContextLineEntry) && !has_line_table) { 6977ac1c780SAaron Smith // The query asks for line entries, but we can't get them for the 69805097246SAdrian Prantl // compile unit. This is not normal for `line` = 0. So just assert 69905097246SAdrian Prantl // it. 700f76fe682SAaron 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 71705097246SAdrian Prantl // If `line `!= 0, see if we can resolve function for each line entry 71805097246SAdrian Prantl // 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(); 726308e39caSAaron Smith if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0) 7277ac1c780SAaron Smith continue; 7287ac1c780SAaron Smith 729c8316ed2SAaron Smith auto symbol_up = m_session_up->findSymbolByAddress( 730c8316ed2SAaron Smith file_vm_addr, PDB_SymType::Function); 7317ac1c780SAaron Smith if (symbol_up) { 7327ac1c780SAaron Smith auto func_uid = symbol_up->getSymIndexId(); 7337ac1c780SAaron Smith sc.function = sc.comp_unit->FindFunctionByUID(func_uid).get(); 7347ac1c780SAaron Smith if (sc.function == nullptr) { 7357ac1c780SAaron Smith auto pdb_func = llvm::dyn_cast<PDBSymbolFunc>(symbol_up.get()); 7367ac1c780SAaron Smith assert(pdb_func); 737e664b5dcSAaron Smith sc.function = ParseCompileUnitFunctionForPDBFunc(*pdb_func, sc); 7387ac1c780SAaron Smith } 7397ac1c780SAaron Smith if (sc.function && (resolve_scope & eSymbolContextBlock)) { 7407ac1c780SAaron Smith Block &block = sc.function->GetBlock(true); 7417ac1c780SAaron Smith sc.block = block.FindBlockByID(sc.function->GetID()); 7427ac1c780SAaron Smith } 7437ac1c780SAaron Smith } 7447ac1c780SAaron Smith sc_list.Append(sc); 7457ac1c780SAaron Smith } 7467ac1c780SAaron Smith } else if (has_line_table) { 7477ac1c780SAaron Smith // We can parse line table for the compile unit. But no query to 7487ac1c780SAaron Smith // resolve function or block. We append `sc` to the list anyway. 7497ac1c780SAaron Smith sc_list.Append(sc); 7507ac1c780SAaron Smith } 7517ac1c780SAaron Smith } else { 7527ac1c780SAaron Smith // No query for line entry, function or block. But we have a valid 7537ac1c780SAaron Smith // compile unit, append `sc` to the list. 7547ac1c780SAaron Smith sc_list.Append(sc); 7557ac1c780SAaron Smith } 75674e08ca0SZachary Turner } 75774e08ca0SZachary Turner } 75810a02577SAaron Smith return sc_list.GetSize() - old_size; 75974e08ca0SZachary Turner } 76074e08ca0SZachary Turner 761cab0d23fSAaron Smith std::string SymbolFilePDB::GetMangledForPDBData(const PDBSymbolData &pdb_data) { 762cab0d23fSAaron Smith std::string decorated_name; 763cab0d23fSAaron Smith auto vm_addr = pdb_data.getVirtualAddress(); 764cab0d23fSAaron Smith if (vm_addr != LLDB_INVALID_ADDRESS && vm_addr) { 765cab0d23fSAaron Smith auto result_up = 766cab0d23fSAaron Smith m_global_scope_up->findAllChildren(PDB_SymType::PublicSymbol); 767cab0d23fSAaron Smith if (result_up) { 768cab0d23fSAaron Smith while (auto symbol_up = result_up->getNext()) { 769cab0d23fSAaron Smith if (symbol_up->getRawSymbol().getVirtualAddress() == vm_addr) { 770cab0d23fSAaron Smith decorated_name = symbol_up->getRawSymbol().getName(); 771cab0d23fSAaron Smith break; 772cab0d23fSAaron Smith } 773cab0d23fSAaron Smith } 774cab0d23fSAaron Smith } 775cab0d23fSAaron Smith } 776cab0d23fSAaron Smith if (!decorated_name.empty()) 777cab0d23fSAaron Smith return decorated_name; 778cab0d23fSAaron Smith 779cab0d23fSAaron Smith return std::string(); 780cab0d23fSAaron Smith } 781cab0d23fSAaron Smith 782cab0d23fSAaron Smith VariableSP SymbolFilePDB::ParseVariableForPDBData( 783cab0d23fSAaron Smith const lldb_private::SymbolContext &sc, 784cab0d23fSAaron Smith const llvm::pdb::PDBSymbolData &pdb_data) { 785cab0d23fSAaron Smith VariableSP var_sp; 786cab0d23fSAaron Smith uint32_t var_uid = pdb_data.getSymIndexId(); 787cab0d23fSAaron Smith auto result = m_variables.find(var_uid); 788cab0d23fSAaron Smith if (result != m_variables.end()) 789cab0d23fSAaron Smith return result->second; 790cab0d23fSAaron Smith 791cab0d23fSAaron Smith ValueType scope = eValueTypeInvalid; 792cab0d23fSAaron Smith bool is_static_member = false; 793cab0d23fSAaron Smith bool is_external = false; 794cab0d23fSAaron Smith bool is_artificial = false; 795cab0d23fSAaron Smith 796cab0d23fSAaron Smith switch (pdb_data.getDataKind()) { 797cab0d23fSAaron Smith case PDB_DataKind::Global: 798cab0d23fSAaron Smith scope = eValueTypeVariableGlobal; 799cab0d23fSAaron Smith is_external = true; 800cab0d23fSAaron Smith break; 801cab0d23fSAaron Smith case PDB_DataKind::Local: 802cab0d23fSAaron Smith scope = eValueTypeVariableLocal; 803cab0d23fSAaron Smith break; 804cab0d23fSAaron Smith case PDB_DataKind::FileStatic: 805cab0d23fSAaron Smith scope = eValueTypeVariableStatic; 806cab0d23fSAaron Smith break; 807cab0d23fSAaron Smith case PDB_DataKind::StaticMember: 808cab0d23fSAaron Smith is_static_member = true; 809cab0d23fSAaron Smith scope = eValueTypeVariableStatic; 810cab0d23fSAaron Smith break; 811cab0d23fSAaron Smith case PDB_DataKind::Member: 812cab0d23fSAaron Smith scope = eValueTypeVariableStatic; 813cab0d23fSAaron Smith break; 814cab0d23fSAaron Smith case PDB_DataKind::Param: 815cab0d23fSAaron Smith scope = eValueTypeVariableArgument; 816cab0d23fSAaron Smith break; 817cab0d23fSAaron Smith case PDB_DataKind::Constant: 818cab0d23fSAaron Smith scope = eValueTypeConstResult; 819cab0d23fSAaron Smith break; 820cab0d23fSAaron Smith default: 821cab0d23fSAaron Smith break; 822cab0d23fSAaron Smith } 823cab0d23fSAaron Smith 824cab0d23fSAaron Smith switch (pdb_data.getLocationType()) { 825cab0d23fSAaron Smith case PDB_LocType::TLS: 826cab0d23fSAaron Smith scope = eValueTypeVariableThreadLocal; 827cab0d23fSAaron Smith break; 828cab0d23fSAaron Smith case PDB_LocType::RegRel: { 829cab0d23fSAaron Smith // It is a `this` pointer. 830cab0d23fSAaron Smith if (pdb_data.getDataKind() == PDB_DataKind::ObjectPtr) { 831cab0d23fSAaron Smith scope = eValueTypeVariableArgument; 832cab0d23fSAaron Smith is_artificial = true; 833cab0d23fSAaron Smith } 834cab0d23fSAaron Smith } break; 835cab0d23fSAaron Smith default: 836cab0d23fSAaron Smith break; 837cab0d23fSAaron Smith } 838cab0d23fSAaron Smith 839cab0d23fSAaron Smith Declaration decl; 840cab0d23fSAaron Smith if (!is_artificial && !pdb_data.isCompilerGenerated()) { 841cab0d23fSAaron Smith if (auto lines = pdb_data.getLineNumbers()) { 842cab0d23fSAaron Smith if (auto first_line = lines->getNext()) { 843cab0d23fSAaron Smith uint32_t src_file_id = first_line->getSourceFileId(); 844cab0d23fSAaron Smith auto src_file = m_session_up->getSourceFileById(src_file_id); 845cab0d23fSAaron Smith if (src_file) { 846cab0d23fSAaron Smith FileSpec spec(src_file->getFileName(), /*resolve_path*/ false); 847cab0d23fSAaron Smith decl.SetFile(spec); 848cab0d23fSAaron Smith decl.SetColumn(first_line->getColumnNumber()); 849cab0d23fSAaron Smith decl.SetLine(first_line->getLineNumber()); 850cab0d23fSAaron Smith } 851cab0d23fSAaron Smith } 852cab0d23fSAaron Smith } 853cab0d23fSAaron Smith } 854cab0d23fSAaron Smith 855cab0d23fSAaron Smith Variable::RangeList ranges; 856cab0d23fSAaron Smith SymbolContextScope *context_scope = sc.comp_unit; 857cab0d23fSAaron Smith if (scope == eValueTypeVariableLocal) { 858cab0d23fSAaron Smith if (sc.function) { 859cab0d23fSAaron Smith context_scope = sc.function->GetBlock(true).FindBlockByID( 860cab0d23fSAaron Smith pdb_data.getClassParentId()); 861cab0d23fSAaron Smith if (context_scope == nullptr) 862cab0d23fSAaron Smith context_scope = sc.function; 863cab0d23fSAaron Smith } 864cab0d23fSAaron Smith } 865cab0d23fSAaron Smith 866cab0d23fSAaron Smith SymbolFileTypeSP type_sp = 867cab0d23fSAaron Smith std::make_shared<SymbolFileType>(*this, pdb_data.getTypeId()); 868cab0d23fSAaron Smith 869cab0d23fSAaron Smith auto var_name = pdb_data.getName(); 870cab0d23fSAaron Smith auto mangled = GetMangledForPDBData(pdb_data); 871cab0d23fSAaron Smith auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str(); 872cab0d23fSAaron Smith 873cab0d23fSAaron Smith DWARFExpression location(nullptr); 874cab0d23fSAaron Smith 875cab0d23fSAaron Smith var_sp = std::make_shared<Variable>( 876cab0d23fSAaron Smith var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope, 877cab0d23fSAaron Smith ranges, &decl, location, is_external, is_artificial, is_static_member); 878cab0d23fSAaron Smith 879cab0d23fSAaron Smith m_variables.insert(std::make_pair(var_uid, var_sp)); 880cab0d23fSAaron Smith return var_sp; 881cab0d23fSAaron Smith } 882cab0d23fSAaron Smith 883cab0d23fSAaron Smith size_t 884cab0d23fSAaron Smith SymbolFilePDB::ParseVariables(const lldb_private::SymbolContext &sc, 885cab0d23fSAaron Smith const llvm::pdb::PDBSymbol &pdb_symbol, 886cab0d23fSAaron Smith lldb_private::VariableList *variable_list) { 887cab0d23fSAaron Smith size_t num_added = 0; 888cab0d23fSAaron Smith 889cab0d23fSAaron Smith if (auto pdb_data = llvm::dyn_cast<PDBSymbolData>(&pdb_symbol)) { 890cab0d23fSAaron Smith VariableListSP local_variable_list_sp; 891cab0d23fSAaron Smith 892cab0d23fSAaron Smith auto result = m_variables.find(pdb_data->getSymIndexId()); 893cab0d23fSAaron Smith if (result != m_variables.end()) { 894cab0d23fSAaron Smith if (variable_list) 895cab0d23fSAaron Smith variable_list->AddVariableIfUnique(result->second); 896cab0d23fSAaron Smith } else { 897cab0d23fSAaron Smith // Prepare right VariableList for this variable. 898cab0d23fSAaron Smith if (auto lexical_parent = pdb_data->getLexicalParent()) { 899cab0d23fSAaron Smith switch (lexical_parent->getSymTag()) { 900cab0d23fSAaron Smith case PDB_SymType::Exe: 901cab0d23fSAaron Smith assert(sc.comp_unit); 902cab0d23fSAaron Smith LLVM_FALLTHROUGH; 903cab0d23fSAaron Smith case PDB_SymType::Compiland: { 904cab0d23fSAaron Smith if (sc.comp_unit) { 905cab0d23fSAaron Smith local_variable_list_sp = sc.comp_unit->GetVariableList(false); 906cab0d23fSAaron Smith if (!local_variable_list_sp) { 907cab0d23fSAaron Smith local_variable_list_sp = std::make_shared<VariableList>(); 908cab0d23fSAaron Smith sc.comp_unit->SetVariableList(local_variable_list_sp); 909cab0d23fSAaron Smith } 910cab0d23fSAaron Smith } 911cab0d23fSAaron Smith } break; 912cab0d23fSAaron Smith case PDB_SymType::Block: 913cab0d23fSAaron Smith case PDB_SymType::Function: { 914cab0d23fSAaron Smith if (sc.function) { 915cab0d23fSAaron Smith Block *block = sc.function->GetBlock(true).FindBlockByID( 916cab0d23fSAaron Smith lexical_parent->getSymIndexId()); 917cab0d23fSAaron Smith if (block) { 918cab0d23fSAaron Smith local_variable_list_sp = block->GetBlockVariableList(false); 919cab0d23fSAaron Smith if (!local_variable_list_sp) { 920cab0d23fSAaron Smith local_variable_list_sp = std::make_shared<VariableList>(); 921cab0d23fSAaron Smith block->SetVariableList(local_variable_list_sp); 922cab0d23fSAaron Smith } 923cab0d23fSAaron Smith } 924cab0d23fSAaron Smith } 925cab0d23fSAaron Smith } break; 926cab0d23fSAaron Smith default: 927cab0d23fSAaron Smith break; 928cab0d23fSAaron Smith } 929cab0d23fSAaron Smith } 930cab0d23fSAaron Smith 931cab0d23fSAaron Smith if (local_variable_list_sp) { 932cab0d23fSAaron Smith if (auto var_sp = ParseVariableForPDBData(sc, *pdb_data)) { 933cab0d23fSAaron Smith local_variable_list_sp->AddVariableIfUnique(var_sp); 934cab0d23fSAaron Smith if (variable_list) 935cab0d23fSAaron Smith variable_list->AddVariableIfUnique(var_sp); 936cab0d23fSAaron Smith ++num_added; 937cab0d23fSAaron Smith } 938cab0d23fSAaron Smith } 939cab0d23fSAaron Smith } 940cab0d23fSAaron Smith } 941cab0d23fSAaron Smith 942cab0d23fSAaron Smith if (auto results = pdb_symbol.findAllChildren()) { 943cab0d23fSAaron Smith while (auto result = results->getNext()) 944cab0d23fSAaron Smith num_added += ParseVariables(sc, *result, variable_list); 945cab0d23fSAaron Smith } 946cab0d23fSAaron Smith 947cab0d23fSAaron Smith return num_added; 948cab0d23fSAaron Smith } 949cab0d23fSAaron Smith 950b9c1b51eSKate Stone uint32_t SymbolFilePDB::FindGlobalVariables( 951b9c1b51eSKate Stone const lldb_private::ConstString &name, 952*34cda14bSPavel Labath const lldb_private::CompilerDeclContext *parent_decl_ctx, 953b9c1b51eSKate Stone uint32_t max_matches, lldb_private::VariableList &variables) { 954cab0d23fSAaron Smith if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) 955cab0d23fSAaron Smith return 0; 956cab0d23fSAaron Smith if (name.IsEmpty()) 957cab0d23fSAaron Smith return 0; 958cab0d23fSAaron Smith 959cab0d23fSAaron Smith auto results = 960cab0d23fSAaron Smith m_global_scope_up->findChildren(PDB_SymType::Data, name.GetStringRef(), 961cab0d23fSAaron Smith PDB_NameSearchFlags::NS_CaseSensitive); 962cab0d23fSAaron Smith if (!results) 963cab0d23fSAaron Smith return 0; 964cab0d23fSAaron Smith 965cab0d23fSAaron Smith uint32_t matches = 0; 966cab0d23fSAaron Smith size_t old_size = variables.GetSize(); 967cab0d23fSAaron Smith while (auto result = results->getNext()) { 968cab0d23fSAaron Smith auto pdb_data = llvm::dyn_cast<PDBSymbolData>(result.get()); 969cab0d23fSAaron Smith if (max_matches > 0 && matches >= max_matches) 970cab0d23fSAaron Smith break; 971cab0d23fSAaron Smith 972cab0d23fSAaron Smith SymbolContext sc; 973cab0d23fSAaron Smith sc.module_sp = m_obj_file->GetModule(); 974cab0d23fSAaron Smith lldbassert(sc.module_sp.get()); 975cab0d23fSAaron Smith 976cab0d23fSAaron Smith sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get(); 977cab0d23fSAaron Smith // FIXME: We are not able to determine the compile unit. 978cab0d23fSAaron Smith if (sc.comp_unit == nullptr) 979cab0d23fSAaron Smith continue; 980cab0d23fSAaron Smith 981cab0d23fSAaron Smith ParseVariables(sc, *pdb_data, &variables); 982cab0d23fSAaron Smith matches = variables.GetSize() - old_size; 983cab0d23fSAaron Smith } 984cab0d23fSAaron Smith 985cab0d23fSAaron Smith return matches; 98674e08ca0SZachary Turner } 98774e08ca0SZachary Turner 98874e08ca0SZachary Turner uint32_t 989b9c1b51eSKate Stone SymbolFilePDB::FindGlobalVariables(const lldb_private::RegularExpression ®ex, 990*34cda14bSPavel Labath uint32_t max_matches, 991b9c1b51eSKate Stone lldb_private::VariableList &variables) { 992cab0d23fSAaron Smith if (!regex.IsValid()) 993cab0d23fSAaron Smith return 0; 994cab0d23fSAaron Smith auto results = m_global_scope_up->findAllChildren<PDBSymbolData>(); 995cab0d23fSAaron Smith if (!results) 996cab0d23fSAaron Smith return 0; 997cab0d23fSAaron Smith 998cab0d23fSAaron Smith uint32_t matches = 0; 999cab0d23fSAaron Smith size_t old_size = variables.GetSize(); 1000cab0d23fSAaron Smith while (auto pdb_data = results->getNext()) { 1001cab0d23fSAaron Smith if (max_matches > 0 && matches >= max_matches) 1002cab0d23fSAaron Smith break; 1003cab0d23fSAaron Smith 1004cab0d23fSAaron Smith auto var_name = pdb_data->getName(); 1005cab0d23fSAaron Smith if (var_name.empty()) 1006cab0d23fSAaron Smith continue; 1007cab0d23fSAaron Smith if (!regex.Execute(var_name)) 1008cab0d23fSAaron Smith continue; 1009cab0d23fSAaron Smith SymbolContext sc; 1010cab0d23fSAaron Smith sc.module_sp = m_obj_file->GetModule(); 1011cab0d23fSAaron Smith lldbassert(sc.module_sp.get()); 1012cab0d23fSAaron Smith 1013cab0d23fSAaron Smith sc.comp_unit = ParseCompileUnitForUID(pdb_data->getCompilandId()).get(); 1014cab0d23fSAaron Smith // FIXME: We are not able to determine the compile unit. 1015cab0d23fSAaron Smith if (sc.comp_unit == nullptr) 1016cab0d23fSAaron Smith continue; 1017cab0d23fSAaron Smith 1018cab0d23fSAaron Smith ParseVariables(sc, *pdb_data, &variables); 1019cab0d23fSAaron Smith matches = variables.GetSize() - old_size; 1020cab0d23fSAaron Smith } 1021cab0d23fSAaron Smith 1022cab0d23fSAaron Smith return matches; 1023b9c1b51eSKate Stone } 1024b9c1b51eSKate Stone 1025e664b5dcSAaron Smith bool SymbolFilePDB::ResolveFunction(const llvm::pdb::PDBSymbolFunc &pdb_func, 10267ac1c780SAaron Smith bool include_inlines, 10277ac1c780SAaron Smith lldb_private::SymbolContextList &sc_list) { 10287ac1c780SAaron Smith lldb_private::SymbolContext sc; 1029a3a8cc80SAaron Smith sc.comp_unit = ParseCompileUnitForUID(pdb_func.getCompilandId()).get(); 10307ac1c780SAaron Smith if (!sc.comp_unit) 10317ac1c780SAaron Smith return false; 10327ac1c780SAaron Smith sc.module_sp = sc.comp_unit->GetModule(); 1033a3a8cc80SAaron Smith sc.function = ParseCompileUnitFunctionForPDBFunc(pdb_func, sc); 10347ac1c780SAaron Smith if (!sc.function) 10357ac1c780SAaron Smith return false; 10367ac1c780SAaron Smith 10377ac1c780SAaron Smith sc_list.Append(sc); 10387ac1c780SAaron Smith return true; 10397ac1c780SAaron Smith } 10407ac1c780SAaron Smith 10417ac1c780SAaron Smith bool SymbolFilePDB::ResolveFunction(uint32_t uid, bool include_inlines, 10427ac1c780SAaron Smith lldb_private::SymbolContextList &sc_list) { 1043c8316ed2SAaron Smith auto pdb_func_up = m_session_up->getConcreteSymbolById<PDBSymbolFunc>(uid); 10447ac1c780SAaron Smith if (!pdb_func_up && !(include_inlines && pdb_func_up->hasInlineAttribute())) 10457ac1c780SAaron Smith return false; 1046e664b5dcSAaron Smith return ResolveFunction(*pdb_func_up, include_inlines, sc_list); 10477ac1c780SAaron Smith } 10487ac1c780SAaron Smith 10497ac1c780SAaron Smith void SymbolFilePDB::CacheFunctionNames() { 10507ac1c780SAaron Smith if (!m_func_full_names.IsEmpty()) 10517ac1c780SAaron Smith return; 10527ac1c780SAaron Smith 10537ac1c780SAaron Smith std::map<uint64_t, uint32_t> addr_ids; 10547ac1c780SAaron Smith 10557ac1c780SAaron Smith if (auto results_up = m_global_scope_up->findAllChildren<PDBSymbolFunc>()) { 10567ac1c780SAaron Smith while (auto pdb_func_up = results_up->getNext()) { 1057f76fe682SAaron Smith if (pdb_func_up->isCompilerGenerated()) 1058f76fe682SAaron Smith continue; 1059f76fe682SAaron Smith 10607ac1c780SAaron Smith auto name = pdb_func_up->getName(); 10617ac1c780SAaron Smith auto demangled_name = pdb_func_up->getUndecoratedName(); 10627ac1c780SAaron Smith if (name.empty() && demangled_name.empty()) 10637ac1c780SAaron Smith continue; 10647ac1c780SAaron Smith 1065f76fe682SAaron Smith auto uid = pdb_func_up->getSymIndexId(); 10667ac1c780SAaron Smith if (!demangled_name.empty() && pdb_func_up->getVirtualAddress()) 10677ac1c780SAaron Smith addr_ids.insert(std::make_pair(pdb_func_up->getVirtualAddress(), uid)); 10687ac1c780SAaron Smith 10697ac1c780SAaron Smith if (auto parent = pdb_func_up->getClassParent()) { 10707ac1c780SAaron Smith 10717ac1c780SAaron Smith // PDB have symbols for class/struct methods or static methods in Enum 10727ac1c780SAaron Smith // Class. We won't bother to check if the parent is UDT or Enum here. 10737ac1c780SAaron Smith m_func_method_names.Append(ConstString(name), uid); 10747ac1c780SAaron Smith 10757ac1c780SAaron Smith ConstString cstr_name(name); 10767ac1c780SAaron Smith 107705097246SAdrian Prantl // To search a method name, like NS::Class:MemberFunc, LLDB searches 107805097246SAdrian Prantl // its base name, i.e. MemberFunc by default. Since PDBSymbolFunc does 107905097246SAdrian Prantl // not have inforamtion of this, we extract base names and cache them 108005097246SAdrian Prantl // by our own effort. 10817ac1c780SAaron Smith llvm::StringRef basename; 10827ac1c780SAaron Smith CPlusPlusLanguage::MethodName cpp_method(cstr_name); 10837ac1c780SAaron Smith if (cpp_method.IsValid()) { 10847ac1c780SAaron Smith llvm::StringRef context; 10857ac1c780SAaron Smith basename = cpp_method.GetBasename(); 10867ac1c780SAaron Smith if (basename.empty()) 10877ac1c780SAaron Smith CPlusPlusLanguage::ExtractContextAndIdentifier(name.c_str(), 10887ac1c780SAaron Smith context, basename); 10897ac1c780SAaron Smith } 10907ac1c780SAaron Smith 10917ac1c780SAaron Smith if (!basename.empty()) 10927ac1c780SAaron Smith m_func_base_names.Append(ConstString(basename), uid); 10937ac1c780SAaron Smith else { 10947ac1c780SAaron Smith m_func_base_names.Append(ConstString(name), uid); 10957ac1c780SAaron Smith } 10967ac1c780SAaron Smith 10977ac1c780SAaron Smith if (!demangled_name.empty()) 10987ac1c780SAaron Smith m_func_full_names.Append(ConstString(demangled_name), uid); 10997ac1c780SAaron Smith 11007ac1c780SAaron Smith } else { 11017ac1c780SAaron Smith // Handle not-method symbols. 11027ac1c780SAaron Smith 11037ac1c780SAaron Smith // The function name might contain namespace, or its lexical scope. It 11047ac1c780SAaron Smith // is not safe to get its base name by applying same scheme as we deal 11057ac1c780SAaron Smith // with the method names. 11067ac1c780SAaron Smith // FIXME: Remove namespace if function is static in a scope. 11077ac1c780SAaron Smith m_func_base_names.Append(ConstString(name), uid); 11087ac1c780SAaron Smith 11097ac1c780SAaron Smith if (name == "main") { 11107ac1c780SAaron Smith m_func_full_names.Append(ConstString(name), uid); 11117ac1c780SAaron Smith 11127ac1c780SAaron Smith if (!demangled_name.empty() && name != demangled_name) { 11137ac1c780SAaron Smith m_func_full_names.Append(ConstString(demangled_name), uid); 11147ac1c780SAaron Smith m_func_base_names.Append(ConstString(demangled_name), uid); 11157ac1c780SAaron Smith } 11167ac1c780SAaron Smith } else if (!demangled_name.empty()) { 11177ac1c780SAaron Smith m_func_full_names.Append(ConstString(demangled_name), uid); 11187ac1c780SAaron Smith } else { 11197ac1c780SAaron Smith m_func_full_names.Append(ConstString(name), uid); 11207ac1c780SAaron Smith } 11217ac1c780SAaron Smith } 11227ac1c780SAaron Smith } 11237ac1c780SAaron Smith } 11247ac1c780SAaron Smith 11257ac1c780SAaron Smith if (auto results_up = 11267ac1c780SAaron Smith m_global_scope_up->findAllChildren<PDBSymbolPublicSymbol>()) { 11277ac1c780SAaron Smith while (auto pub_sym_up = results_up->getNext()) { 11287ac1c780SAaron Smith if (!pub_sym_up->isFunction()) 11297ac1c780SAaron Smith continue; 11307ac1c780SAaron Smith auto name = pub_sym_up->getName(); 11317ac1c780SAaron Smith if (name.empty()) 11327ac1c780SAaron Smith continue; 11337ac1c780SAaron Smith 11347ac1c780SAaron Smith if (CPlusPlusLanguage::IsCPPMangledName(name.c_str())) { 11357ac1c780SAaron Smith auto vm_addr = pub_sym_up->getVirtualAddress(); 11367ac1c780SAaron Smith 11377ac1c780SAaron Smith // PDB public symbol has mangled name for its associated function. 11387ac1c780SAaron Smith if (vm_addr && addr_ids.find(vm_addr) != addr_ids.end()) { 11397ac1c780SAaron Smith // Cache mangled name. 11407ac1c780SAaron Smith m_func_full_names.Append(ConstString(name), addr_ids[vm_addr]); 11417ac1c780SAaron Smith } 11427ac1c780SAaron Smith } 11437ac1c780SAaron Smith } 11447ac1c780SAaron Smith } 11457ac1c780SAaron Smith // Sort them before value searching is working properly 11467ac1c780SAaron Smith m_func_full_names.Sort(); 11477ac1c780SAaron Smith m_func_full_names.SizeToFit(); 11487ac1c780SAaron Smith m_func_method_names.Sort(); 11497ac1c780SAaron Smith m_func_method_names.SizeToFit(); 11507ac1c780SAaron Smith m_func_base_names.Sort(); 11517ac1c780SAaron Smith m_func_base_names.SizeToFit(); 11527ac1c780SAaron Smith } 11537ac1c780SAaron Smith 1154b9c1b51eSKate Stone uint32_t SymbolFilePDB::FindFunctions( 1155b9c1b51eSKate Stone const lldb_private::ConstString &name, 1156b9c1b51eSKate Stone const lldb_private::CompilerDeclContext *parent_decl_ctx, 1157b9c1b51eSKate Stone uint32_t name_type_mask, bool include_inlines, bool append, 1158b9c1b51eSKate Stone lldb_private::SymbolContextList &sc_list) { 11597ac1c780SAaron Smith if (!append) 11607ac1c780SAaron Smith sc_list.Clear(); 11617ac1c780SAaron Smith lldbassert((name_type_mask & eFunctionNameTypeAuto) == 0); 11627ac1c780SAaron Smith 11637ac1c780SAaron Smith if (name_type_mask == eFunctionNameTypeNone) 11647ac1c780SAaron Smith return 0; 11657ac1c780SAaron Smith if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) 11667ac1c780SAaron Smith return 0; 11677ac1c780SAaron Smith if (name.IsEmpty()) 11687ac1c780SAaron Smith return 0; 11697ac1c780SAaron Smith 11707ac1c780SAaron Smith auto old_size = sc_list.GetSize(); 11714d4d63eeSPavel Labath if (name_type_mask & eFunctionNameTypeFull || 11724d4d63eeSPavel Labath name_type_mask & eFunctionNameTypeBase || 11737ac1c780SAaron Smith name_type_mask & eFunctionNameTypeMethod) { 11747ac1c780SAaron Smith CacheFunctionNames(); 11757ac1c780SAaron Smith 11767ac1c780SAaron Smith std::set<uint32_t> resolved_ids; 1177c8316ed2SAaron Smith auto ResolveFn = [include_inlines, &name, &sc_list, &resolved_ids, 1178c8316ed2SAaron Smith this](UniqueCStringMap<uint32_t> &Names) { 11797ac1c780SAaron Smith std::vector<uint32_t> ids; 11807ac1c780SAaron Smith if (Names.GetValues(name, ids)) { 11817ac1c780SAaron Smith for (auto id : ids) { 11827ac1c780SAaron Smith if (resolved_ids.find(id) == resolved_ids.end()) { 11837ac1c780SAaron Smith if (ResolveFunction(id, include_inlines, sc_list)) 11847ac1c780SAaron Smith resolved_ids.insert(id); 11857ac1c780SAaron Smith } 11867ac1c780SAaron Smith } 11877ac1c780SAaron Smith } 11887ac1c780SAaron Smith }; 11897ac1c780SAaron Smith if (name_type_mask & eFunctionNameTypeFull) { 11907ac1c780SAaron Smith ResolveFn(m_func_full_names); 11917ac1c780SAaron Smith } 11927ac1c780SAaron Smith if (name_type_mask & eFunctionNameTypeBase) { 11937ac1c780SAaron Smith ResolveFn(m_func_base_names); 11947ac1c780SAaron Smith } 11957ac1c780SAaron Smith if (name_type_mask & eFunctionNameTypeMethod) { 11967ac1c780SAaron Smith ResolveFn(m_func_method_names); 11977ac1c780SAaron Smith } 11987ac1c780SAaron Smith } 11997ac1c780SAaron Smith return sc_list.GetSize() - old_size; 120074e08ca0SZachary Turner } 120174e08ca0SZachary Turner 120274e08ca0SZachary Turner uint32_t 1203b9c1b51eSKate Stone SymbolFilePDB::FindFunctions(const lldb_private::RegularExpression ®ex, 1204b9c1b51eSKate Stone bool include_inlines, bool append, 1205b9c1b51eSKate Stone lldb_private::SymbolContextList &sc_list) { 12067ac1c780SAaron Smith if (!append) 12077ac1c780SAaron Smith sc_list.Clear(); 12087ac1c780SAaron Smith if (!regex.IsValid()) 12097ac1c780SAaron Smith return 0; 12107ac1c780SAaron Smith 12117ac1c780SAaron Smith auto old_size = sc_list.GetSize(); 12127ac1c780SAaron Smith CacheFunctionNames(); 12137ac1c780SAaron Smith 12147ac1c780SAaron Smith std::set<uint32_t> resolved_ids; 1215c8316ed2SAaron Smith auto ResolveFn = [®ex, include_inlines, &sc_list, &resolved_ids, 1216c8316ed2SAaron Smith this](UniqueCStringMap<uint32_t> &Names) { 12177ac1c780SAaron Smith std::vector<uint32_t> ids; 12187ac1c780SAaron Smith if (Names.GetValues(regex, ids)) { 12197ac1c780SAaron Smith for (auto id : ids) { 12207ac1c780SAaron Smith if (resolved_ids.find(id) == resolved_ids.end()) 12217ac1c780SAaron Smith if (ResolveFunction(id, include_inlines, sc_list)) 12227ac1c780SAaron Smith resolved_ids.insert(id); 12237ac1c780SAaron Smith } 12247ac1c780SAaron Smith } 12257ac1c780SAaron Smith }; 12267ac1c780SAaron Smith ResolveFn(m_func_full_names); 12277ac1c780SAaron Smith ResolveFn(m_func_base_names); 12287ac1c780SAaron Smith 12297ac1c780SAaron Smith return sc_list.GetSize() - old_size; 123074e08ca0SZachary Turner } 123174e08ca0SZachary Turner 1232b9c1b51eSKate Stone void SymbolFilePDB::GetMangledNamesForFunction( 1233b9c1b51eSKate Stone const std::string &scope_qualified_name, 1234b9c1b51eSKate Stone std::vector<lldb_private::ConstString> &mangled_names) {} 123574e08ca0SZachary Turner 1236b9c1b51eSKate Stone uint32_t SymbolFilePDB::FindTypes( 1237b9c1b51eSKate Stone const lldb_private::SymbolContext &sc, 1238b9c1b51eSKate Stone const lldb_private::ConstString &name, 1239b9c1b51eSKate Stone const lldb_private::CompilerDeclContext *parent_decl_ctx, bool append, 1240b9c1b51eSKate Stone uint32_t max_matches, 124174e08ca0SZachary Turner llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, 1242b9c1b51eSKate Stone lldb_private::TypeMap &types) { 124342dff790SZachary Turner if (!append) 124442dff790SZachary Turner types.Clear(); 124542dff790SZachary Turner if (!name) 124642dff790SZachary Turner return 0; 12477ac1c780SAaron Smith if (!DeclContextMatchesThisSymbolFile(parent_decl_ctx)) 12487ac1c780SAaron Smith return 0; 124942dff790SZachary Turner 125042dff790SZachary Turner searched_symbol_files.clear(); 125142dff790SZachary Turner searched_symbol_files.insert(this); 125242dff790SZachary Turner 125342dff790SZachary Turner std::string name_str = name.AsCString(); 125442dff790SZachary Turner 125586e9434dSAaron Smith // There is an assumption 'name' is not a regex 125642dff790SZachary Turner FindTypesByName(name_str, max_matches, types); 125786e9434dSAaron Smith 125842dff790SZachary Turner return types.GetSize(); 125942dff790SZachary Turner } 126042dff790SZachary Turner 1261c8316ed2SAaron Smith void SymbolFilePDB::FindTypesByRegex( 1262c8316ed2SAaron Smith const lldb_private::RegularExpression ®ex, uint32_t max_matches, 1263b9c1b51eSKate Stone lldb_private::TypeMap &types) { 1264b9c1b51eSKate Stone // When searching by regex, we need to go out of our way to limit the search 12659d0eb996SAdrian McCarthy // space as much as possible since this searches EVERYTHING in the PDB, 12669d0eb996SAdrian McCarthy // manually doing regex comparisons. PDB library isn't optimized for regex 12679d0eb996SAdrian McCarthy // searches or searches across multiple symbol types at the same time, so the 1268b9c1b51eSKate Stone // best we can do is to search enums, then typedefs, then classes one by one, 12699d0eb996SAdrian McCarthy // and do a regex comparison against each of them. 1270b9c1b51eSKate Stone PDB_SymType tags_to_search[] = {PDB_SymType::Enum, PDB_SymType::Typedef, 1271b9c1b51eSKate Stone PDB_SymType::UDT}; 127254fd7ff6SZachary Turner std::unique_ptr<IPDBEnumSymbols> results; 127342dff790SZachary Turner 127442dff790SZachary Turner uint32_t matches = 0; 127542dff790SZachary Turner 1276b9c1b51eSKate Stone for (auto tag : tags_to_search) { 127710a02577SAaron Smith results = m_global_scope_up->findAllChildren(tag); 127810a02577SAaron Smith if (!results) 127910a02577SAaron Smith continue; 128010a02577SAaron Smith 1281b9c1b51eSKate Stone while (auto result = results->getNext()) { 128242dff790SZachary Turner if (max_matches > 0 && matches >= max_matches) 128342dff790SZachary Turner break; 128442dff790SZachary Turner 128542dff790SZachary Turner std::string type_name; 128654fd7ff6SZachary Turner if (auto enum_type = llvm::dyn_cast<PDBSymbolTypeEnum>(result.get())) 128742dff790SZachary Turner type_name = enum_type->getName(); 1288b9c1b51eSKate Stone else if (auto typedef_type = 1289b9c1b51eSKate Stone llvm::dyn_cast<PDBSymbolTypeTypedef>(result.get())) 129042dff790SZachary Turner type_name = typedef_type->getName(); 129154fd7ff6SZachary Turner else if (auto class_type = llvm::dyn_cast<PDBSymbolTypeUDT>(result.get())) 129242dff790SZachary Turner type_name = class_type->getName(); 1293b9c1b51eSKate Stone else { 12949d0eb996SAdrian McCarthy // We're looking only for types that have names. Skip symbols, as well 12959d0eb996SAdrian McCarthy // as unnamed types such as arrays, pointers, etc. 129642dff790SZachary Turner continue; 129742dff790SZachary Turner } 129842dff790SZachary Turner 129986e9434dSAaron Smith if (!regex.Execute(type_name)) 130042dff790SZachary Turner continue; 130142dff790SZachary Turner 1302b9c1b51eSKate Stone // This should cause the type to get cached and stored in the `m_types` 1303b9c1b51eSKate Stone // lookup. 130442dff790SZachary Turner if (!ResolveTypeUID(result->getSymIndexId())) 130542dff790SZachary Turner continue; 130642dff790SZachary Turner 130742dff790SZachary Turner auto iter = m_types.find(result->getSymIndexId()); 130842dff790SZachary Turner if (iter == m_types.end()) 130942dff790SZachary Turner continue; 131042dff790SZachary Turner types.Insert(iter->second); 131142dff790SZachary Turner ++matches; 131242dff790SZachary Turner } 131342dff790SZachary Turner } 131442dff790SZachary Turner } 131542dff790SZachary Turner 1316b9c1b51eSKate Stone void SymbolFilePDB::FindTypesByName(const std::string &name, 1317b9c1b51eSKate Stone uint32_t max_matches, 1318b9c1b51eSKate Stone lldb_private::TypeMap &types) { 131954fd7ff6SZachary Turner std::unique_ptr<IPDBEnumSymbols> results; 1320f76fe682SAaron Smith if (name.empty()) 1321f76fe682SAaron Smith return; 132210a02577SAaron Smith results = m_global_scope_up->findChildren(PDB_SymType::None, name, 1323b9c1b51eSKate Stone PDB_NameSearchFlags::NS_Default); 132410a02577SAaron Smith if (!results) 132510a02577SAaron Smith return; 132642dff790SZachary Turner 132742dff790SZachary Turner uint32_t matches = 0; 132842dff790SZachary Turner 1329b9c1b51eSKate Stone while (auto result = results->getNext()) { 133042dff790SZachary Turner if (max_matches > 0 && matches >= max_matches) 133142dff790SZachary Turner break; 1332b9c1b51eSKate Stone switch (result->getSymTag()) { 133354fd7ff6SZachary Turner case PDB_SymType::Enum: 133454fd7ff6SZachary Turner case PDB_SymType::UDT: 133554fd7ff6SZachary Turner case PDB_SymType::Typedef: 133642dff790SZachary Turner break; 133742dff790SZachary Turner default: 133805097246SAdrian Prantl // We're looking only for types that have names. Skip symbols, as well 133905097246SAdrian Prantl // as unnamed types such as arrays, pointers, etc. 134042dff790SZachary Turner continue; 134142dff790SZachary Turner } 134242dff790SZachary Turner 1343b9c1b51eSKate Stone // This should cause the type to get cached and stored in the `m_types` 1344b9c1b51eSKate Stone // lookup. 134542dff790SZachary Turner if (!ResolveTypeUID(result->getSymIndexId())) 134642dff790SZachary Turner continue; 134742dff790SZachary Turner 134842dff790SZachary Turner auto iter = m_types.find(result->getSymIndexId()); 134942dff790SZachary Turner if (iter == m_types.end()) 135042dff790SZachary Turner continue; 135142dff790SZachary Turner types.Insert(iter->second); 135242dff790SZachary Turner ++matches; 135342dff790SZachary Turner } 135474e08ca0SZachary Turner } 135574e08ca0SZachary Turner 1356b9c1b51eSKate Stone size_t SymbolFilePDB::FindTypes( 1357b9c1b51eSKate Stone const std::vector<lldb_private::CompilerContext> &contexts, bool append, 1358b9c1b51eSKate Stone lldb_private::TypeMap &types) { 135942dff790SZachary Turner return 0; 136074e08ca0SZachary Turner } 136174e08ca0SZachary Turner 1362ec40f818SAaron Smith lldb_private::TypeList *SymbolFilePDB::GetTypeList() { 1363ec40f818SAaron Smith return m_obj_file->GetModule()->GetTypeList(); 1364ec40f818SAaron Smith } 136574e08ca0SZachary Turner 1366c8316ed2SAaron Smith void SymbolFilePDB::GetTypesForPDBSymbol(const llvm::pdb::PDBSymbol &pdb_symbol, 13677ac1c780SAaron Smith uint32_t type_mask, 13687ac1c780SAaron Smith TypeCollection &type_collection) { 13697ac1c780SAaron Smith bool can_parse = false; 1370e664b5dcSAaron Smith switch (pdb_symbol.getSymTag()) { 13717ac1c780SAaron Smith case PDB_SymType::ArrayType: 13727ac1c780SAaron Smith can_parse = ((type_mask & eTypeClassArray) != 0); 13737ac1c780SAaron Smith break; 13747ac1c780SAaron Smith case PDB_SymType::BuiltinType: 13757ac1c780SAaron Smith can_parse = ((type_mask & eTypeClassBuiltin) != 0); 13767ac1c780SAaron Smith break; 13777ac1c780SAaron Smith case PDB_SymType::Enum: 13787ac1c780SAaron Smith can_parse = ((type_mask & eTypeClassEnumeration) != 0); 13797ac1c780SAaron Smith break; 13807ac1c780SAaron Smith case PDB_SymType::Function: 13817ac1c780SAaron Smith case PDB_SymType::FunctionSig: 13827ac1c780SAaron Smith can_parse = ((type_mask & eTypeClassFunction) != 0); 13837ac1c780SAaron Smith break; 13847ac1c780SAaron Smith case PDB_SymType::PointerType: 13857ac1c780SAaron Smith can_parse = ((type_mask & (eTypeClassPointer | eTypeClassBlockPointer | 13867ac1c780SAaron Smith eTypeClassMemberPointer)) != 0); 13877ac1c780SAaron Smith break; 13887ac1c780SAaron Smith case PDB_SymType::Typedef: 13897ac1c780SAaron Smith can_parse = ((type_mask & eTypeClassTypedef) != 0); 13907ac1c780SAaron Smith break; 13917ac1c780SAaron Smith case PDB_SymType::UDT: { 1392e664b5dcSAaron Smith auto *udt = llvm::dyn_cast<PDBSymbolTypeUDT>(&pdb_symbol); 13937ac1c780SAaron Smith assert(udt); 13947ac1c780SAaron Smith can_parse = (udt->getUdtKind() != PDB_UdtType::Interface && 13957ac1c780SAaron Smith ((type_mask & (eTypeClassClass | eTypeClassStruct | 13967ac1c780SAaron Smith eTypeClassUnion)) != 0)); 13977ac1c780SAaron Smith } break; 1398c8316ed2SAaron Smith default: 1399c8316ed2SAaron Smith break; 14007ac1c780SAaron Smith } 14017ac1c780SAaron Smith 14027ac1c780SAaron Smith if (can_parse) { 1403e664b5dcSAaron Smith if (auto *type = ResolveTypeUID(pdb_symbol.getSymIndexId())) { 14047ac1c780SAaron Smith auto result = 14057ac1c780SAaron Smith std::find(type_collection.begin(), type_collection.end(), type); 14067ac1c780SAaron Smith if (result == type_collection.end()) 14077ac1c780SAaron Smith type_collection.push_back(type); 14087ac1c780SAaron Smith } 14097ac1c780SAaron Smith } 14107ac1c780SAaron Smith 1411e664b5dcSAaron Smith auto results_up = pdb_symbol.findAllChildren(); 14127ac1c780SAaron Smith while (auto symbol_up = results_up->getNext()) 1413e664b5dcSAaron Smith GetTypesForPDBSymbol(*symbol_up, type_mask, type_collection); 14147ac1c780SAaron Smith } 14157ac1c780SAaron Smith 1416b9c1b51eSKate Stone size_t SymbolFilePDB::GetTypes(lldb_private::SymbolContextScope *sc_scope, 1417b9c1b51eSKate Stone uint32_t type_mask, 1418b9c1b51eSKate Stone lldb_private::TypeList &type_list) { 14197ac1c780SAaron Smith TypeCollection type_collection; 14207ac1c780SAaron Smith uint32_t old_size = type_list.GetSize(); 1421c8316ed2SAaron Smith CompileUnit *cu = 1422c8316ed2SAaron Smith sc_scope ? sc_scope->CalculateSymbolContextCompileUnit() : nullptr; 14237ac1c780SAaron Smith if (cu) { 14247ac1c780SAaron Smith auto compiland_up = GetPDBCompilandByUID(cu->GetID()); 1425e664b5dcSAaron Smith if (!compiland_up) 1426e664b5dcSAaron Smith return 0; 1427e664b5dcSAaron Smith GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection); 14287ac1c780SAaron Smith } else { 14297ac1c780SAaron Smith for (uint32_t cu_idx = 0; cu_idx < GetNumCompileUnits(); ++cu_idx) { 14307ac1c780SAaron Smith auto cu_sp = ParseCompileUnitAtIndex(cu_idx); 1431d5a925f4SAaron Smith if (cu_sp) { 1432e664b5dcSAaron Smith if (auto compiland_up = GetPDBCompilandByUID(cu_sp->GetID())) 1433e664b5dcSAaron Smith GetTypesForPDBSymbol(*compiland_up, type_mask, type_collection); 14347ac1c780SAaron Smith } 14357ac1c780SAaron Smith } 14367ac1c780SAaron Smith } 14377ac1c780SAaron Smith 14387ac1c780SAaron Smith for (auto type : type_collection) { 14397ac1c780SAaron Smith type->GetForwardCompilerType(); 14407ac1c780SAaron Smith type_list.Insert(type->shared_from_this()); 14417ac1c780SAaron Smith } 14427ac1c780SAaron Smith return type_list.GetSize() - old_size; 144374e08ca0SZachary Turner } 144474e08ca0SZachary Turner 144574e08ca0SZachary Turner lldb_private::TypeSystem * 1446b9c1b51eSKate Stone SymbolFilePDB::GetTypeSystemForLanguage(lldb::LanguageType language) { 1447b9c1b51eSKate Stone auto type_system = 1448b9c1b51eSKate Stone m_obj_file->GetModule()->GetTypeSystemForLanguage(language); 144974e08ca0SZachary Turner if (type_system) 145074e08ca0SZachary Turner type_system->SetSymbolFile(this); 145174e08ca0SZachary Turner return type_system; 145274e08ca0SZachary Turner } 145374e08ca0SZachary Turner 1454b9c1b51eSKate Stone lldb_private::CompilerDeclContext SymbolFilePDB::FindNamespace( 1455b9c1b51eSKate Stone const lldb_private::SymbolContext &sc, 1456b9c1b51eSKate Stone const lldb_private::ConstString &name, 1457b9c1b51eSKate Stone const lldb_private::CompilerDeclContext *parent_decl_ctx) { 145874e08ca0SZachary Turner return lldb_private::CompilerDeclContext(); 145974e08ca0SZachary Turner } 146074e08ca0SZachary Turner 1461b9c1b51eSKate Stone lldb_private::ConstString SymbolFilePDB::GetPluginName() { 146274e08ca0SZachary Turner static ConstString g_name("pdb"); 146374e08ca0SZachary Turner return g_name; 146474e08ca0SZachary Turner } 146574e08ca0SZachary Turner 1466b9c1b51eSKate Stone uint32_t SymbolFilePDB::GetPluginVersion() { return 1; } 146774e08ca0SZachary Turner 1468b9c1b51eSKate Stone IPDBSession &SymbolFilePDB::GetPDBSession() { return *m_session_up; } 1469b9c1b51eSKate Stone 1470b9c1b51eSKate Stone const IPDBSession &SymbolFilePDB::GetPDBSession() const { 147142dff790SZachary Turner return *m_session_up; 147242dff790SZachary Turner } 147342dff790SZachary Turner 1474c8316ed2SAaron Smith lldb::CompUnitSP SymbolFilePDB::ParseCompileUnitForUID(uint32_t id, 1475c8316ed2SAaron Smith uint32_t index) { 147674e08ca0SZachary Turner auto found_cu = m_comp_units.find(id); 147774e08ca0SZachary Turner if (found_cu != m_comp_units.end()) 147874e08ca0SZachary Turner return found_cu->second; 147974e08ca0SZachary Turner 148010a02577SAaron Smith auto compiland_up = GetPDBCompilandByUID(id); 148110a02577SAaron Smith if (!compiland_up) 148210a02577SAaron Smith return CompUnitSP(); 148374e08ca0SZachary Turner 148474e08ca0SZachary Turner lldb::LanguageType lang; 148510a02577SAaron Smith auto details = compiland_up->findOneChild<PDBSymbolCompilandDetails>(); 148674e08ca0SZachary Turner if (!details) 148774e08ca0SZachary Turner lang = lldb::eLanguageTypeC_plus_plus; 148874e08ca0SZachary Turner else 148974e08ca0SZachary Turner lang = TranslateLanguage(details->getLanguage()); 149074e08ca0SZachary Turner 1491f76fe682SAaron Smith if (lang == lldb::LanguageType::eLanguageTypeUnknown) 1492f76fe682SAaron Smith return CompUnitSP(); 1493f76fe682SAaron Smith 1494487b0c6bSAaron Smith std::string path = compiland_up->getSourceFileFullPath(); 1495f76fe682SAaron Smith if (path.empty()) 1496f76fe682SAaron Smith return CompUnitSP(); 1497f76fe682SAaron Smith 1498b9c1b51eSKate Stone // Don't support optimized code for now, DebugInfoPDB does not return this 1499b9c1b51eSKate Stone // information. 1500ad2b63cbSGreg Clayton LazyBool optimized = eLazyBoolNo; 1501c8316ed2SAaron Smith auto cu_sp = std::make_shared<CompileUnit>(m_obj_file->GetModule(), nullptr, 1502c8316ed2SAaron Smith path.c_str(), id, lang, optimized); 150310a02577SAaron Smith 150410a02577SAaron Smith if (!cu_sp) 150510a02577SAaron Smith return CompUnitSP(); 150610a02577SAaron Smith 150710a02577SAaron Smith m_comp_units.insert(std::make_pair(id, cu_sp)); 150810a02577SAaron Smith if (index == UINT32_MAX) 1509e664b5dcSAaron Smith GetCompileUnitIndex(*compiland_up, index); 151010a02577SAaron Smith lldbassert(index != UINT32_MAX); 1511c8316ed2SAaron Smith m_obj_file->GetModule()->GetSymbolVendor()->SetCompileUnitAtIndex(index, 1512c8316ed2SAaron Smith cu_sp); 151310a02577SAaron Smith return cu_sp; 151474e08ca0SZachary Turner } 151574e08ca0SZachary Turner 1516b9c1b51eSKate Stone bool SymbolFilePDB::ParseCompileUnitLineTable( 1517b9c1b51eSKate Stone const lldb_private::SymbolContext &sc, uint32_t match_line) { 151810a02577SAaron Smith lldbassert(sc.comp_unit); 151910a02577SAaron Smith 152010a02577SAaron Smith auto compiland_up = GetPDBCompilandByUID(sc.comp_unit->GetID()); 152110a02577SAaron Smith if (!compiland_up) 152210a02577SAaron Smith return false; 152374e08ca0SZachary Turner 1524b9c1b51eSKate Stone // LineEntry needs the *index* of the file into the list of support files 15259d0eb996SAdrian McCarthy // returned by ParseCompileUnitSupportFiles. But the underlying SDK gives us 152605097246SAdrian Prantl // a globally unique idenfitifier in the namespace of the PDB. So, we have 152705097246SAdrian Prantl // to do a mapping so that we can hand out indices. 152842dff790SZachary Turner llvm::DenseMap<uint32_t, uint32_t> index_map; 152910a02577SAaron Smith BuildSupportFileIdToSupportFileIndexMap(*compiland_up, index_map); 153074e08ca0SZachary Turner auto line_table = llvm::make_unique<LineTable>(sc.comp_unit); 153174e08ca0SZachary Turner 153210a02577SAaron Smith // Find contributions to `compiland` from all source and header files. 153374e08ca0SZachary Turner std::string path = sc.comp_unit->GetPath(); 153410a02577SAaron Smith auto files = m_session_up->getSourceFilesForCompiland(*compiland_up); 153510a02577SAaron Smith if (!files) 153610a02577SAaron Smith return false; 153774e08ca0SZachary Turner 153805097246SAdrian Prantl // For each source and header file, create a LineSequence for contributions 153905097246SAdrian Prantl // to the compiland from that file, and add the sequence. 1540b9c1b51eSKate Stone while (auto file = files->getNext()) { 1541b9c1b51eSKate Stone std::unique_ptr<LineSequence> sequence( 1542b9c1b51eSKate Stone line_table->CreateLineSequenceContainer()); 154310a02577SAaron Smith auto lines = m_session_up->findLineNumbers(*compiland_up, *file); 154410a02577SAaron Smith if (!lines) 154510a02577SAaron Smith continue; 154674e08ca0SZachary Turner int entry_count = lines->getChildCount(); 154774e08ca0SZachary Turner 15487e8c7beaSZachary Turner uint64_t prev_addr; 15497e8c7beaSZachary Turner uint32_t prev_length; 15507e8c7beaSZachary Turner uint32_t prev_line; 15517e8c7beaSZachary Turner uint32_t prev_source_idx; 15527e8c7beaSZachary Turner 1553b9c1b51eSKate Stone for (int i = 0; i < entry_count; ++i) { 155474e08ca0SZachary Turner auto line = lines->getChildAtIndex(i); 155574e08ca0SZachary Turner 15567e8c7beaSZachary Turner uint64_t lno = line->getLineNumber(); 15577e8c7beaSZachary Turner uint64_t addr = line->getVirtualAddress(); 15587e8c7beaSZachary Turner uint32_t length = line->getLength(); 155974e08ca0SZachary Turner uint32_t source_id = line->getSourceFileId(); 15607e8c7beaSZachary Turner uint32_t col = line->getColumnNumber(); 156174e08ca0SZachary Turner uint32_t source_idx = index_map[source_id]; 156274e08ca0SZachary Turner 156305097246SAdrian Prantl // There was a gap between the current entry and the previous entry if 156405097246SAdrian Prantl // the addresses don't perfectly line up. 15657e8c7beaSZachary Turner bool is_gap = (i > 0) && (prev_addr + prev_length < addr); 15667e8c7beaSZachary Turner 1567b9c1b51eSKate Stone // Before inserting the current entry, insert a terminal entry at the end 15689d0eb996SAdrian McCarthy // of the previous entry's address range if the current entry resulted in 15699d0eb996SAdrian McCarthy // a gap from the previous entry. 1570b9c1b51eSKate Stone if (is_gap && ShouldAddLine(match_line, prev_line, prev_length)) { 1571b9c1b51eSKate Stone line_table->AppendLineEntryToSequence( 1572b9c1b51eSKate Stone sequence.get(), prev_addr + prev_length, prev_line, 0, 15737e8c7beaSZachary Turner prev_source_idx, false, false, false, false, true); 15747e8c7beaSZachary Turner } 15757e8c7beaSZachary Turner 1576b9c1b51eSKate Stone if (ShouldAddLine(match_line, lno, length)) { 15777e8c7beaSZachary Turner bool is_statement = line->isStatement(); 157874e08ca0SZachary Turner bool is_prologue = false; 157974e08ca0SZachary Turner bool is_epilogue = false; 1580b9c1b51eSKate Stone auto func = 1581b9c1b51eSKate Stone m_session_up->findSymbolByAddress(addr, PDB_SymType::Function); 1582b9c1b51eSKate Stone if (func) { 158354fd7ff6SZachary Turner auto prologue = func->findOneChild<PDBSymbolFuncDebugStart>(); 158410a02577SAaron Smith if (prologue) 15857e8c7beaSZachary Turner is_prologue = (addr == prologue->getVirtualAddress()); 158674e08ca0SZachary Turner 158754fd7ff6SZachary Turner auto epilogue = func->findOneChild<PDBSymbolFuncDebugEnd>(); 158810a02577SAaron Smith if (epilogue) 15897e8c7beaSZachary Turner is_epilogue = (addr == epilogue->getVirtualAddress()); 15907e8c7beaSZachary Turner } 159174e08ca0SZachary Turner 1592b9c1b51eSKate Stone line_table->AppendLineEntryToSequence(sequence.get(), addr, lno, col, 1593b9c1b51eSKate Stone source_idx, is_statement, false, 15947e8c7beaSZachary Turner is_prologue, is_epilogue, false); 15957e8c7beaSZachary Turner } 15967e8c7beaSZachary Turner 15977e8c7beaSZachary Turner prev_addr = addr; 15987e8c7beaSZachary Turner prev_length = length; 15997e8c7beaSZachary Turner prev_line = lno; 16007e8c7beaSZachary Turner prev_source_idx = source_idx; 16017e8c7beaSZachary Turner } 16027e8c7beaSZachary Turner 1603b9c1b51eSKate Stone if (entry_count > 0 && ShouldAddLine(match_line, prev_line, prev_length)) { 16047e8c7beaSZachary Turner // The end is always a terminal entry, so insert it regardless. 1605b9c1b51eSKate Stone line_table->AppendLineEntryToSequence( 1606b9c1b51eSKate Stone sequence.get(), prev_addr + prev_length, prev_line, 0, 16077e8c7beaSZachary Turner prev_source_idx, false, false, false, false, true); 160874e08ca0SZachary Turner } 160974e08ca0SZachary Turner 16107e8c7beaSZachary Turner line_table->InsertSequence(sequence.release()); 161174e08ca0SZachary Turner } 161274e08ca0SZachary Turner 161310a02577SAaron Smith if (line_table->GetSize()) { 161474e08ca0SZachary Turner sc.comp_unit->SetLineTable(line_table.release()); 161574e08ca0SZachary Turner return true; 161674e08ca0SZachary Turner } 161710a02577SAaron Smith return false; 161810a02577SAaron Smith } 161974e08ca0SZachary Turner 1620b9c1b51eSKate Stone void SymbolFilePDB::BuildSupportFileIdToSupportFileIndexMap( 162110a02577SAaron Smith const PDBSymbolCompiland &compiland, 1622b9c1b51eSKate Stone llvm::DenseMap<uint32_t, uint32_t> &index_map) const { 162305097246SAdrian Prantl // This is a hack, but we need to convert the source id into an index into 162405097246SAdrian Prantl // the support files array. We don't want to do path comparisons to avoid 16259d0eb996SAdrian McCarthy // basename / full path issues that may or may not even be a problem, so we 16269d0eb996SAdrian McCarthy // use the globally unique source file identifiers. Ideally we could use the 16279d0eb996SAdrian McCarthy // global identifiers everywhere, but LineEntry currently assumes indices. 162810a02577SAaron Smith auto source_files = m_session_up->getSourceFilesForCompiland(compiland); 162910a02577SAaron Smith if (!source_files) 163010a02577SAaron Smith return; 163174e08ca0SZachary Turner int index = 0; 163274e08ca0SZachary Turner 1633b9c1b51eSKate Stone while (auto file = source_files->getNext()) { 163474e08ca0SZachary Turner uint32_t source_id = file->getUniqueId(); 163574e08ca0SZachary Turner index_map[source_id] = index++; 163674e08ca0SZachary Turner } 163774e08ca0SZachary Turner } 16387ac1c780SAaron Smith 16397ac1c780SAaron Smith lldb::CompUnitSP SymbolFilePDB::GetCompileUnitContainsAddress( 16407ac1c780SAaron Smith const lldb_private::Address &so_addr) { 16417ac1c780SAaron Smith lldb::addr_t file_vm_addr = so_addr.GetFileAddress(); 1642308e39caSAaron Smith if (file_vm_addr == LLDB_INVALID_ADDRESS || file_vm_addr == 0) 16437ac1c780SAaron Smith return nullptr; 16447ac1c780SAaron Smith 1645308e39caSAaron Smith // If it is a PDB function's vm addr, this is the first sure bet. 1646308e39caSAaron Smith if (auto lines = 1647308e39caSAaron Smith m_session_up->findLineNumbersByAddress(file_vm_addr, /*Length=*/1)) { 1648308e39caSAaron Smith if (auto first_line = lines->getNext()) 1649308e39caSAaron Smith return ParseCompileUnitForUID(first_line->getCompilandId()); 16507ac1c780SAaron Smith } 16517ac1c780SAaron Smith 1652308e39caSAaron Smith // Otherwise we resort to section contributions. 1653308e39caSAaron Smith if (auto sec_contribs = m_session_up->getSectionContribs()) { 1654308e39caSAaron Smith while (auto section = sec_contribs->getNext()) { 1655308e39caSAaron Smith auto va = section->getVirtualAddress(); 1656308e39caSAaron Smith if (file_vm_addr >= va && file_vm_addr < va + section->getLength()) 1657308e39caSAaron Smith return ParseCompileUnitForUID(section->getCompilandId()); 1658308e39caSAaron Smith } 1659308e39caSAaron Smith } 16607ac1c780SAaron Smith return nullptr; 16617ac1c780SAaron Smith } 16627ac1c780SAaron Smith 16637ac1c780SAaron Smith Mangled 1664e664b5dcSAaron Smith SymbolFilePDB::GetMangledForPDBFunc(const llvm::pdb::PDBSymbolFunc &pdb_func) { 16657ac1c780SAaron Smith Mangled mangled; 1666e664b5dcSAaron Smith auto func_name = pdb_func.getName(); 1667e664b5dcSAaron Smith auto func_undecorated_name = pdb_func.getUndecoratedName(); 16687ac1c780SAaron Smith std::string func_decorated_name; 16697ac1c780SAaron Smith 16707ac1c780SAaron Smith // Seek from public symbols for non-static function's decorated name if any. 16717ac1c780SAaron Smith // For static functions, they don't have undecorated names and aren't exposed 16727ac1c780SAaron Smith // in Public Symbols either. 16737ac1c780SAaron Smith if (!func_undecorated_name.empty()) { 1674c8316ed2SAaron Smith auto result_up = m_global_scope_up->findChildren( 1675c8316ed2SAaron Smith PDB_SymType::PublicSymbol, func_undecorated_name, 16767ac1c780SAaron Smith PDB_NameSearchFlags::NS_UndecoratedName); 16777ac1c780SAaron Smith if (result_up) { 16787ac1c780SAaron Smith while (auto symbol_up = result_up->getNext()) { 16797ac1c780SAaron Smith // For a public symbol, it is unique. 16807ac1c780SAaron Smith lldbassert(result_up->getChildCount() == 1); 16817ac1c780SAaron Smith if (auto *pdb_public_sym = 1682c8316ed2SAaron Smith llvm::dyn_cast_or_null<PDBSymbolPublicSymbol>( 1683c8316ed2SAaron Smith symbol_up.get())) { 16847ac1c780SAaron Smith if (pdb_public_sym->isFunction()) { 16857ac1c780SAaron Smith func_decorated_name = pdb_public_sym->getName(); 1686f76fe682SAaron Smith break; 16877ac1c780SAaron Smith } 16887ac1c780SAaron Smith } 16897ac1c780SAaron Smith } 16907ac1c780SAaron Smith } 16917ac1c780SAaron Smith } 16927ac1c780SAaron Smith if (!func_decorated_name.empty()) { 16937ac1c780SAaron Smith mangled.SetMangledName(ConstString(func_decorated_name)); 16947ac1c780SAaron Smith 16957ac1c780SAaron Smith // For MSVC, format of C funciton's decorated name depends on calling 16967ac1c780SAaron Smith // conventon. Unfortunately none of the format is recognized by current 16977ac1c780SAaron Smith // LLDB. For example, `_purecall` is a __cdecl C function. From PDB, 169805097246SAdrian Prantl // `__purecall` is retrieved as both its decorated and undecorated name 169905097246SAdrian Prantl // (using PDBSymbolFunc::getUndecoratedName method). However `__purecall` 170005097246SAdrian Prantl // string is not treated as mangled in LLDB (neither `?` nor `_Z` prefix). 170105097246SAdrian Prantl // Mangled::GetDemangledName method will fail internally and caches an 170205097246SAdrian Prantl // empty string as its undecorated name. So we will face a contradition 170305097246SAdrian Prantl // here for the same symbol: 17047ac1c780SAaron Smith // non-empty undecorated name from PDB 17057ac1c780SAaron Smith // empty undecorated name from LLDB 17067ac1c780SAaron Smith if (!func_undecorated_name.empty() && 17077ac1c780SAaron Smith mangled.GetDemangledName(mangled.GuessLanguage()).IsEmpty()) 17087ac1c780SAaron Smith mangled.SetDemangledName(ConstString(func_undecorated_name)); 17097ac1c780SAaron Smith 17107ac1c780SAaron Smith // LLDB uses several flags to control how a C++ decorated name is 171105097246SAdrian Prantl // undecorated for MSVC. See `safeUndecorateName` in Class Mangled. So the 171205097246SAdrian Prantl // yielded name could be different from what we retrieve from 17137ac1c780SAaron Smith // PDB source unless we also apply same flags in getting undecorated 17147ac1c780SAaron Smith // name through PDBSymbolFunc::getUndecoratedNameEx method. 17157ac1c780SAaron Smith if (!func_undecorated_name.empty() && 17167ac1c780SAaron Smith mangled.GetDemangledName(mangled.GuessLanguage()) != 17177ac1c780SAaron Smith ConstString(func_undecorated_name)) 17187ac1c780SAaron Smith mangled.SetDemangledName(ConstString(func_undecorated_name)); 17197ac1c780SAaron Smith } else if (!func_undecorated_name.empty()) { 17207ac1c780SAaron Smith mangled.SetDemangledName(ConstString(func_undecorated_name)); 17217ac1c780SAaron Smith } else if (!func_name.empty()) 17227ac1c780SAaron Smith mangled.SetValue(ConstString(func_name), false); 17237ac1c780SAaron Smith 17247ac1c780SAaron Smith return mangled; 17257ac1c780SAaron Smith } 17267ac1c780SAaron Smith 17277ac1c780SAaron Smith bool SymbolFilePDB::DeclContextMatchesThisSymbolFile( 17287ac1c780SAaron Smith const lldb_private::CompilerDeclContext *decl_ctx) { 17297ac1c780SAaron Smith if (decl_ctx == nullptr || !decl_ctx->IsValid()) 17307ac1c780SAaron Smith return true; 17317ac1c780SAaron Smith 17327ac1c780SAaron Smith TypeSystem *decl_ctx_type_system = decl_ctx->GetTypeSystem(); 17337ac1c780SAaron Smith if (!decl_ctx_type_system) 17347ac1c780SAaron Smith return false; 17357ac1c780SAaron Smith TypeSystem *type_system = GetTypeSystemForLanguage( 17367ac1c780SAaron Smith decl_ctx_type_system->GetMinimumLanguage(nullptr)); 17377ac1c780SAaron Smith if (decl_ctx_type_system == type_system) 17387ac1c780SAaron Smith return true; // The type systems match, return true 17397ac1c780SAaron Smith 17407ac1c780SAaron Smith return false; 17417ac1c780SAaron Smith } 1742