diff options
| author | Mingming Liu <mingmingl@google.com> | 2025-09-10 15:25:31 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-10 15:25:31 -0700 |
| commit | 1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch) | |
| tree | 57f4b1f313c8cf74eed8819870f39c36ea263c68 /lldb/source/Plugins/SymbolFile | |
| parent | 898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff) | |
| parent | b8cefcb601ddaa18482555c4ff363c01a270c2fe (diff) | |
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'lldb/source/Plugins/SymbolFile')
8 files changed, 269 insertions, 74 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index a429ea848b7f..5ffb4423969c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -252,7 +252,7 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE &subprogram, } static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) { - char const *name = die.GetMangledName(/*substitute_name_allowed*/ false); + const char *name = die.GetMangledName(/*substitute_name_allowed*/ false); if (!name) return {}; @@ -286,7 +286,9 @@ static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) { if (die_id == LLDB_INVALID_UID) return {}; - return FunctionCallLabel{/*module_id=*/module_id, + // Note, discriminator is added by Clang during mangling. + return FunctionCallLabel{/*discriminator=*/{}, + /*module_id=*/module_id, /*symbol_id=*/die_id, /*.lookup_name=*/name} .toString(); @@ -2230,6 +2232,18 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, for (DelayedAddObjCClassProperty &property : delayed_properties) property.Finalize(); } + } else if (Language::LanguageIsObjC( + static_cast<LanguageType>(die.GetAttributeValueAsUnsigned( + DW_AT_APPLE_runtime_class, eLanguageTypeUnknown)))) { + /// The forward declaration was C++ but the definition is Objective-C. + /// We currently don't handle such situations. In such cases, keep the + /// forward declaration without a definition to avoid violating Clang AST + /// invariants. + LLDB_LOG(GetLog(LLDBLog::Expressions), + "WARNING: Type completion aborted because forward declaration for " + "'{0}' is C++ while definition is Objective-C.", + llvm::StringRef(die.GetName())); + return {}; } if (!bases.empty()) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index b15e0c15fedb..d3d0110d5e30 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -7,11 +7,14 @@ //===----------------------------------------------------------------------===// #include "SymbolFileDWARF.h" +#include "clang/Basic/ABI.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/Support/Casting.h" +#include "llvm/Support/Error.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/FormatAdapters.h" #include "llvm/Support/Threading.h" @@ -23,6 +26,7 @@ #include "lldb/Core/Progress.h" #include "lldb/Core/Section.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/Expression.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/RegularExpression.h" @@ -79,6 +83,7 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" +#include "llvm/Demangle/Demangle.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatVariadic.h" @@ -2484,34 +2489,148 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, return false; } -DWARFDIE -SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel &label) { - DWARFDIE definition; - Module::LookupInfo info(ConstString(label.lookup_name), - lldb::eFunctionNameTypeFull, - lldb::eLanguageTypeUnknown); - - m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) { - if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) - return IterationAction::Continue; +static llvm::StringRef ClangToItaniumCtorKind(clang::CXXCtorType kind) { + switch (kind) { + case clang::CXXCtorType::Ctor_Complete: + return "C1"; + case clang::CXXCtorType::Ctor_Base: + return "C2"; + case clang::CXXCtorType::Ctor_Unified: + return "C4"; + case clang::CXXCtorType::Ctor_CopyingClosure: + case clang::CXXCtorType::Ctor_DefaultClosure: + case clang::CXXCtorType::Ctor_Comdat: + llvm_unreachable("Unexpected constructor kind."); + } +} - // We don't check whether the specification DIE for this function - // corresponds to the declaration DIE because the declaration might be in - // a type-unit but the definition in the compile-unit (and it's - // specifcation would point to the declaration in the compile-unit). We - // rely on the mangled name within the module to be enough to find us the - // unique definition. - definition = entry; - return IterationAction::Stop; - }); +static llvm::StringRef ClangToItaniumDtorKind(clang::CXXDtorType kind) { + switch (kind) { + case clang::CXXDtorType::Dtor_Deleting: + return "D0"; + case clang::CXXDtorType::Dtor_Complete: + return "D1"; + case clang::CXXDtorType::Dtor_Base: + return "D2"; + case clang::CXXDtorType::Dtor_Unified: + return "D4"; + case clang::CXXDtorType::Dtor_Comdat: + llvm_unreachable("Unexpected destructor kind."); + } +} + +static llvm::StringRef +GetItaniumCtorDtorVariant(llvm::StringRef discriminator) { + const bool is_ctor = discriminator.consume_front("C"); + if (!is_ctor && !discriminator.consume_front("D")) + return {}; + + uint64_t structor_kind; + if (!llvm::to_integer(discriminator, structor_kind)) + return {}; + + if (is_ctor) { + if (structor_kind > clang::CXXCtorType::Ctor_Unified) + return {}; + + return ClangToItaniumCtorKind( + static_cast<clang::CXXCtorType>(structor_kind)); + } + + if (structor_kind > clang::CXXDtorType::Dtor_Unified) + return {}; + + return ClangToItaniumDtorKind(static_cast<clang::CXXDtorType>(structor_kind)); +} + +llvm::Expected<DWARFDIE> +SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel &label, + const DWARFDIE &declaration) { + auto do_lookup = [this](llvm::StringRef lookup_name) -> DWARFDIE { + DWARFDIE found; + Module::LookupInfo info(ConstString(lookup_name), + lldb::eFunctionNameTypeFull, + lldb::eLanguageTypeUnknown); + + m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) { + if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) + return IterationAction::Continue; + + found = entry; + return IterationAction::Stop; + }); + + return found; + }; + + DWARFDIE definition = do_lookup(label.lookup_name); + if (definition.IsValid()) + return definition; + + // This is not a structor lookup. Nothing else to be done here. + if (label.discriminator.empty()) + return llvm::createStringError( + "no definition DIE found in this SymbolFile"); + + // We're doing a structor lookup. Maybe we didn't find the structor variant + // because the complete object structor was aliased to the base object + // structor. Try finding the alias instead. + // + // TODO: there are other reasons for why a subprogram definition might be + // missing. Ideally DWARF would tell us more details about which structor + // variant a DIE corresponds to and whether it's an alias. + auto subst_or_err = + CPlusPlusLanguage::SubstituteStructorAliases_ItaniumMangle( + label.lookup_name); + if (!subst_or_err) + return subst_or_err.takeError(); + + definition = do_lookup(*subst_or_err); + + if (!definition.IsValid()) + return llvm::createStringError( + "failed to find definition DIE for structor alias in fallback lookup"); return definition; } llvm::Expected<SymbolContext> -SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) { +SymbolFileDWARF::ResolveFunctionCallLabel(FunctionCallLabel &label) { std::lock_guard<std::recursive_mutex> guard(GetModuleMutex()); + if (!label.discriminator.empty()) { + llvm::StringRef from = label.discriminator[0] == 'C' ? "C4" : "D4"; + + llvm::StringRef variant = GetItaniumCtorDtorVariant(label.discriminator); + if (variant.empty()) + return llvm::createStringError( + "failed to get Itanium variant for discriminator"); + + if (from == variant) + return llvm::createStringError( + "tried substituting unified structor variant into label"); + + // If we failed to substitute unified mangled name, don't try to do a lookup + // using the unified name because there may be multiple definitions for it + // in the index, and we wouldn't know which one to choose. + auto subst_or_err = CPlusPlusLanguage::SubstituteStructor_ItaniumMangle( + label.lookup_name, from, variant); + if (!subst_or_err) + return llvm::joinErrors( + llvm::createStringError(llvm::formatv( + "failed to substitute {0} for {1} in mangled name {2}:", from, + variant, label.lookup_name)), + subst_or_err.takeError()); + + if (!*subst_or_err) + return llvm::createStringError( + llvm::formatv("got invalid substituted mangled named (substituted " + "{0} for {1} in mangled name {2})", + from, variant, label.lookup_name)); + + label.lookup_name = subst_or_err->GetStringRef(); + } + DWARFDIE die = GetDIE(label.symbol_id); if (!die.IsValid()) return llvm::createStringError( @@ -2520,11 +2639,13 @@ SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) { // Label was created using a declaration DIE. Need to fetch the definition // to resolve the function call. if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) { - auto definition = FindFunctionDefinition(label); - if (!definition) - return llvm::createStringError("failed to find definition DIE"); + auto die_or_err = FindFunctionDefinition(label, die); + if (!die_or_err) + return llvm::joinErrors( + llvm::createStringError("failed to find definition DIE:"), + die_or_err.takeError()); - die = std::move(definition); + die = std::move(*die_or_err); } SymbolContextList sc_list; @@ -4502,9 +4623,8 @@ void SymbolFileDWARF::GetCompileOptions( } } -std::pair<uint32_t, uint32_t> SymbolFileDWARF::GetDwoFileCounts() { - uint32_t total_dwo_count = 0; - uint32_t loaded_dwo_count = 0; +DWOStats SymbolFileDWARF::GetDwoStats() { + DWOStats stats; DWARFDebugInfo &info = DebugInfo(); const size_t num_cus = info.GetNumUnits(); @@ -4517,16 +4637,21 @@ std::pair<uint32_t, uint32_t> SymbolFileDWARF::GetDwoFileCounts() { if (!dwarf_cu->GetDWOId().has_value()) continue; - total_dwo_count++; + stats.dwo_file_count++; // If we have a DWO symbol file, that means we were able to successfully // load it. SymbolFile *dwo_symfile = dwarf_cu->GetDwoSymbolFile(/*load_all_debug_info=*/false); if (dwo_symfile) { - loaded_dwo_count++; + stats.loaded_dwo_file_count++; } + + // Check if this unit has a DWO load error, false by default. + const Status &dwo_error = dwarf_cu->GetDwoError(); + if (dwo_error.Fail()) + stats.dwo_error_count++; } - return {loaded_dwo_count, total_dwo_count}; + return stats; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index d7db8a3c0869..85306d8b4fb5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -283,10 +283,11 @@ public: bool GetSeparateDebugInfo(StructuredData::Dictionary &d, bool errors_only, bool load_all_debug_info = false) override; - // Gets a pair of loaded and total dwo file counts. - // For split-dwarf files, this reports the counts for successfully loaded DWO - // CUs and total DWO CUs. For non-split-dwarf files, this reports 0 for both. - std::pair<uint32_t, uint32_t> GetDwoFileCounts() override; + /// Gets statistics about dwo files associated with this symbol file. + /// For split-dwarf files, this reports the counts for successfully loaded DWO + /// CUs, total DWO CUs, and the number of DWO CUs with loading errors. + /// For non-split-dwarf files, this reports 0 for all. + DWOStats GetDwoStats() override; DWARFContext &GetDWARFContext() { return m_context; } @@ -378,7 +379,9 @@ private: /// SymbolFile. /// /// \returns A valid definition DIE on success. - DWARFDIE FindFunctionDefinition(const FunctionCallLabel &label); + llvm::Expected<DWARFDIE> + FindFunctionDefinition(const FunctionCallLabel &label, + const DWARFDIE &declaration); protected: SymbolFileDWARF(const SymbolFileDWARF &) = delete; @@ -445,7 +448,7 @@ protected: DIEArray &&variable_dies); llvm::Expected<SymbolContext> - ResolveFunctionCallLabel(const FunctionCallLabel &label) override; + ResolveFunctionCallLabel(FunctionCallLabel &label) override; // Given a die_offset, figure out the symbol context representing that die. bool ResolveFunction(const DWARFDIE &die, bool include_inlines, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 9d7452a1988f..8b8229a7020c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1603,8 +1603,8 @@ void SymbolFileDWARFDebugMap::GetCompileOptions( }); } -llvm::Expected<SymbolContext> SymbolFileDWARFDebugMap::ResolveFunctionCallLabel( - const FunctionCallLabel &label) { +llvm::Expected<SymbolContext> +SymbolFileDWARFDebugMap::ResolveFunctionCallLabel(FunctionCallLabel &label) { const uint64_t oso_idx = GetOSOIndexFromUserID(label.symbol_id); SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); if (!oso_dwarf) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index e1f1df23951c..bce1ed2671af 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -145,7 +145,7 @@ public: GetCompileOptions(std::unordered_map<lldb::CompUnitSP, Args> &args) override; llvm::Expected<SymbolContext> - ResolveFunctionCallLabel(const FunctionCallLabel &label) override; + ResolveFunctionCallLabel(FunctionCallLabel &label) override; protected: enum { kHaveInitializedOSOs = (1 << 0), kNumFlags }; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 709281cb3270..933c4361d93d 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -1169,6 +1169,7 @@ clang::QualType PdbAstBuilder::CreateEnumType(PdbTypeSymId id, clang::QualType PdbAstBuilder::CreateArrayType(const ArrayRecord &ar) { clang::QualType element_type = GetOrCreateType(ar.ElementType); + TypeSystemClang::RequireCompleteType(ToCompilerType(element_type)); SymbolFileNativePDB *pdb = static_cast<SymbolFileNativePDB *>( m_clang.GetSymbolFile()->GetBackingSymbolFile()); diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp index 112eb06e462f..e99c585d7eb1 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp @@ -1624,6 +1624,8 @@ size_t SymbolFileNativePDB::ParseBlocksRecursive(Function &func) { for (uint64_t uid : remove_uids) { m_inline_sites.erase(uid); } + + func.GetBlock(false).SetBlockInfoHasBeenParsed(true, true); return count; } @@ -1655,22 +1657,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<std::pair<uint16_t, uint32_t>, uint32_t> addr_ids; + std::map<std::pair<uint16_t, uint32_t>, 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<DataSym>(sym)); + name = data.Name; + break; + } + case SymbolKind::S_GTHREAD32: + case SymbolKind::S_LTHREAD32: { + ThreadLocalDataSym data = llvm::cantFail( + SymbolDeserializer::deserializeAs<ThreadLocalDataSym>(sym)); + name = data.Name; + break; + } + case SymbolKind::S_CONSTANT: { + ConstantSym data = + llvm::cantFail(SymbolDeserializer::deserializeAs<ConstantSym>(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<ProcRefSym>(ref_sym)); + llvm::cantFail(SymbolDeserializer::deserializeAs<ProcRefSym>(sym)); if (ref.Name.empty()) continue; @@ -1694,7 +1736,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,43 +1771,47 @@ 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); } // Sort them before value searching is working properly. - m_func_full_names.Sort(); + m_func_full_names.Sort(std::less<uint32_t>()); m_func_full_names.SizeToFit(); - m_func_method_names.Sort(); + m_func_method_names.Sort(std::less<uint32_t>()); m_func_method_names.SizeToFit(); - m_func_base_names.Sort(); + m_func_base_names.Sort(std::less<uint32_t>()); m_func_base_names.SizeToFit(); + m_global_variable_base_names.Sort(std::less<uint32_t>()); + 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<std::recursive_mutex> guard(GetModuleMutex()); - using SymbolAndOffset = std::pair<uint32_t, llvm::codeview::CVSymbol>; - std::vector<SymbolAndOffset> 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<uint32_t> 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 +1829,7 @@ void SymbolFileNativePDB::FindFunctions( name_type_mask & eFunctionNameTypeBase || name_type_mask & eFunctionNameTypeMethod)) return; - CacheFunctionNames(); + CacheGlobalBaseNames(); std::set<uint32_t> resolved_ids; // avoid duplicate lookups auto resolve_from = [&](UniqueCStringMap<uint32_t> &Names) { @@ -2426,7 +2472,7 @@ void SymbolFileNativePDB::BuildParentMap() { // After calling Append(), the type-name map needs to be sorted again to be // able to look up a type by its name. - m_type_base_names.Sort(); + m_type_base_names.Sort(std::less<uint32_t>()); // Now that we know the forward -> full mapping of all type indices, we can // re-write all the indices. At the end of this process, we want a mapping diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h index cfa00416d967..095b40c72c52 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h @@ -260,7 +260,10 @@ private: std::vector<CompilerContext> 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<Declaration> ResolveUdtDeclaration(PdbTypeSymId type_id); @@ -306,6 +309,9 @@ private: lldb_private::UniqueCStringMap<uint32_t> m_func_base_names; /// method basename -> Global ID(s) lldb_private::UniqueCStringMap<uint32_t> m_func_method_names; + + /// global variable basename -> Global ID(s) + lldb_private::UniqueCStringMap<uint32_t> m_global_variable_base_names; }; } // namespace npdb |
