diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 112eb06e462fc..330e839a7ca13 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1655,22 +1655,62 @@ void SymbolFileNativePDB::DumpClangAST(Stream &s, llvm::StringRef filter) { clang->GetNativePDBParser()->Dump(s, filter); } -void SymbolFileNativePDB::CacheFunctionNames() { - if (!m_func_full_names.IsEmpty()) +void SymbolFileNativePDB::CacheGlobalBaseNames() { + if (!m_func_full_names.IsEmpty() || !m_global_variable_base_names.IsEmpty()) return; // (segment, code offset) -> gid - std::map, uint32_t> addr_ids; + std::map, uint32_t> func_addr_ids; - // First, find all function references in the globals table. + // First, look through all items in the globals table. for (const uint32_t gid : m_index->globals().getGlobalsTable()) { - CVSymbol ref_sym = m_index->symrecords().readRecord(gid); - auto kind = ref_sym.kind(); + CVSymbol sym = m_index->symrecords().readRecord(gid); + auto kind = sym.kind(); + + // If this is a global variable, we only need to look at the name + llvm::StringRef name; + switch (kind) { + case SymbolKind::S_GDATA32: + case SymbolKind::S_LDATA32: { + DataSym data = + llvm::cantFail(SymbolDeserializer::deserializeAs(sym)); + name = data.Name; + break; + } + case SymbolKind::S_GTHREAD32: + case SymbolKind::S_LTHREAD32: { + ThreadLocalDataSym data = llvm::cantFail( + SymbolDeserializer::deserializeAs(sym)); + name = data.Name; + break; + } + case SymbolKind::S_CONSTANT: { + ConstantSym data = + llvm::cantFail(SymbolDeserializer::deserializeAs(sym)); + name = data.Name; + break; + } + default: + break; + } + + if (!name.empty()) { + llvm::StringRef base = MSVCUndecoratedNameParser::DropScope(name); + if (base.empty()) + base = name; + + m_global_variable_base_names.Append(ConstString(base), gid); + continue; + } + if (kind != S_PROCREF && kind != S_LPROCREF) continue; + // For functions, we need to follow the reference to the procedure and look + // at the type + ProcRefSym ref = - llvm::cantFail(SymbolDeserializer::deserializeAs(ref_sym)); + llvm::cantFail(SymbolDeserializer::deserializeAs(sym)); if (ref.Name.empty()) continue; @@ -1694,7 +1734,7 @@ void SymbolFileNativePDB::CacheFunctionNames() { // The function/procedure symbol only contains the demangled name. // The mangled names are in the publics table. Save the address of this // function to lookup the mangled name later. - addr_ids.emplace(std::make_pair(proc.Segment, proc.CodeOffset), gid); + func_addr_ids.emplace(std::make_pair(proc.Segment, proc.CodeOffset), gid); llvm::StringRef basename = MSVCUndecoratedNameParser::DropScope(proc.Name); if (basename.empty()) @@ -1729,8 +1769,8 @@ void SymbolFileNativePDB::CacheFunctionNames() { continue; // Check if this symbol is for one of our functions. - auto it = addr_ids.find({pub.Segment, pub.Offset}); - if (it != addr_ids.end()) + auto it = func_addr_ids.find({pub.Segment, pub.Offset}); + if (it != func_addr_ids.end()) m_func_full_names.Append(ConstString(pub.Name), it->second); } @@ -1741,31 +1781,35 @@ void SymbolFileNativePDB::CacheFunctionNames() { m_func_method_names.SizeToFit(); m_func_base_names.Sort(); m_func_base_names.SizeToFit(); + m_global_variable_base_names.Sort(std::less()); + m_global_variable_base_names.SizeToFit(); } void SymbolFileNativePDB::FindGlobalVariables( ConstString name, const CompilerDeclContext &parent_decl_ctx, uint32_t max_matches, VariableList &variables) { std::lock_guard guard(GetModuleMutex()); - using SymbolAndOffset = std::pair; - std::vector results = m_index->globals().findRecordsByName( - name.GetStringRef(), m_index->symrecords()); - for (const SymbolAndOffset &result : results) { - switch (result.second.kind()) { - case SymbolKind::S_GDATA32: - case SymbolKind::S_LDATA32: - case SymbolKind::S_GTHREAD32: - case SymbolKind::S_LTHREAD32: - case SymbolKind::S_CONSTANT: { - PdbGlobalSymId global(result.first, false); - if (VariableSP var = GetOrCreateGlobalVariable(global)) - variables.AddVariable(var); - break; - } - default: + CacheGlobalBaseNames(); + + std::vector results; + m_global_variable_base_names.GetValues(name, results); + + size_t n_matches = 0; + for (uint32_t gid : results) { + PdbGlobalSymId global(gid, false); + + if (parent_decl_ctx.IsValid() && + GetDeclContextContainingUID(toOpaqueUid(global)) != parent_decl_ctx) continue; - } + + VariableSP var = GetOrCreateGlobalVariable(global); + if (!var) + continue; + variables.AddVariable(var); + + if (++n_matches >= max_matches) + break; } } @@ -1783,7 +1827,7 @@ void SymbolFileNativePDB::FindFunctions( name_type_mask & eFunctionNameTypeBase || name_type_mask & eFunctionNameTypeMethod)) return; - CacheFunctionNames(); + CacheGlobalBaseNames(); std::set resolved_ids; // avoid duplicate lookups auto resolve_from = [&](UniqueCStringMap &Names) { diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index cfa00416d9673..095b40c72c52a 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -260,7 +260,10 @@ class SymbolFileNativePDB : public SymbolFileCommon { std::vector GetContextForType(llvm::codeview::TypeIndex ti); - void CacheFunctionNames(); + /// Caches the basenames of symbols found in the globals stream. + /// + /// This includes functions and global variables + void CacheGlobalBaseNames(); void CacheUdtDeclarations(); llvm::Expected ResolveUdtDeclaration(PdbTypeSymId type_id); @@ -306,6 +309,9 @@ class SymbolFileNativePDB : public SymbolFileCommon { lldb_private::UniqueCStringMap m_func_base_names; /// method basename -> Global ID(s) lldb_private::UniqueCStringMap m_func_method_names; + + /// global variable basename -> Global ID(s) + lldb_private::UniqueCStringMap m_global_variable_base_names; }; } // namespace npdb diff --git a/lldb/test/Shell/SymbolFile/PDB/expressions.test b/lldb/test/Shell/SymbolFile/PDB/expressions.test index 1932be74ca878..33b02e2d67965 100644 --- a/lldb/test/Shell/SymbolFile/PDB/expressions.test +++ b/lldb/test/Shell/SymbolFile/PDB/expressions.test @@ -1,6 +1,7 @@ REQUIRES: target-windows, msvc RUN: %build --compiler=msvc --nodefaultlib --output=%t.exe %S/Inputs/ExpressionsTest.cpp -RUN: not %lldb -b -s %S/Inputs/ExpressionsTest0.script -s %S/Inputs/ExpressionsTest1.script -s %S/Inputs/ExpressionsTest2.script -- %t.exe 2>&1 | FileCheck %s +RUN: env LLDB_USE_NATIVE_PDB_READER=0 not %lldb -b -s %S/Inputs/ExpressionsTest0.script -s %S/Inputs/ExpressionsTest1.script -s %S/Inputs/ExpressionsTest2.script -- %t.exe 2>&1 | FileCheck %s +RUN: env LLDB_USE_NATIVE_PDB_READER=1 not %lldb -b -s %S/Inputs/ExpressionsTest0.script -s %S/Inputs/ExpressionsTest1.script -s %S/Inputs/ExpressionsTest2.script -- %t.exe 2>&1 | FileCheck %s // Check the variable value through `expression` CHECK: (lldb) expression result