Index: lldb/trunk/lit/SymbolFile/DWARF/dwarf5-index-is-used.cpp =================================================================== --- lldb/trunk/lit/SymbolFile/DWARF/dwarf5-index-is-used.cpp +++ lldb/trunk/lit/SymbolFile/DWARF/dwarf5-index-is-used.cpp @@ -0,0 +1,14 @@ +// Test that we use the DWARF v5 name indexes. + +// REQUIRES: lld + +// RUN: clang %s -g -c -emit-llvm -o - --target=x86_64-pc-linux | \ +// RUN: llc -accel-tables=Dwarf -filetype=obj -o %t.o +// RUN: ld.lld %t.o -o %t +// RUN: lldb-test symbols %t | FileCheck %s + +// CHECK: Name Index +// CHECK: String: 0x{{.*}} "_start" +// CHECK: Tag: DW_TAG_subprogram + +extern "C" void _start() {} Index: lldb/trunk/lit/SymbolFile/DWARF/find-basic-variable.cpp =================================================================== --- lldb/trunk/lit/SymbolFile/DWARF/find-basic-variable.cpp +++ lldb/trunk/lit/SymbolFile/DWARF/find-basic-variable.cpp @@ -20,6 +20,18 @@ // RUN: FileCheck --check-prefix=REGEX %s // RUN: lldb-test symbols --name=not_there --find=variable %t | \ // RUN: FileCheck --check-prefix=EMPTY %s +// +// RUN: clang %s -g -c -emit-llvm -o - --target=x86_64-pc-linux | \ +// RUN: llc -accel-tables=Dwarf -filetype=obj -o %t.o +// RUN: ld.lld %t.o -o %t +// RUN: lldb-test symbols --name=foo --find=variable --context=context %t | \ +// RUN: FileCheck --check-prefix=CONTEXT %s +// RUN: lldb-test symbols --name=foo --find=variable %t | \ +// RUN: FileCheck --check-prefix=NAME %s +// RUN: lldb-test symbols --regex --name=foo --find=variable %t | \ +// RUN: FileCheck --check-prefix=REGEX %s +// RUN: lldb-test symbols --name=not_there --find=variable %t | \ +// RUN: FileCheck --check-prefix=EMPTY %s // EMPTY: Found 0 variables: // NAME: Found 4 variables: Index: lldb/trunk/lit/SymbolFile/DWARF/find-qualified-variable.cpp =================================================================== --- lldb/trunk/lit/SymbolFile/DWARF/find-qualified-variable.cpp +++ lldb/trunk/lit/SymbolFile/DWARF/find-qualified-variable.cpp @@ -0,0 +1,15 @@ +// RUN: clang %s -g -c -o %t --target=x86_64-apple-macosx +// RUN: lldb-test symbols --name=A::foo --find=variable %t | FileCheck %s + +// CHECK: Found 1 variables: + +struct A { + static int foo; +}; +int A::foo; +// NAME-DAG: name = "foo", {{.*}} decl = find-qualified-variable.cpp:[[@LINE-1]] + +struct B { + static int foo; +}; +int B::foo; Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h @@ -33,7 +33,7 @@ void Preload() override {} - void GetGlobalVariables(ConstString name, DIEArray &offsets) override; + void GetGlobalVariables(ConstString basename, DIEArray &offsets) override; void GetGlobalVariables(const RegularExpression ®ex, DIEArray &offsets) override; void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override; Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -13,7 +13,6 @@ #include "Plugins/SymbolFile/DWARF/DWARFUnit.h" #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" -#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" #include "Plugins/Language/ObjC/ObjCLanguage.h" #include "lldb/Core/Module.h" #include "lldb/Symbol/Function.h" @@ -56,19 +55,9 @@ return nullptr; } -void AppleDWARFIndex::GetGlobalVariables(ConstString name, DIEArray &offsets) { - if (!m_apple_names_up) - return; - - const char *name_cstr = name.GetCString(); - llvm::StringRef basename; - llvm::StringRef context; - - if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name_cstr, context, - basename)) - basename = name_cstr; - - m_apple_names_up->FindByName(basename, offsets); +void AppleDWARFIndex::GetGlobalVariables(ConstString basename, DIEArray &offsets) { + if (m_apple_names_up) + m_apple_names_up->FindByName(basename.GetStringRef(), offsets); } void AppleDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFIndex.h =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFIndex.h +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFIndex.h @@ -25,7 +25,11 @@ virtual void Preload() = 0; - virtual void GetGlobalVariables(ConstString name, DIEArray &offsets) = 0; + /// Finds global variables with the given base name. Any additional filtering + /// (e.g., to only retrieve variables from a given context) should be done by + /// the consumer. + virtual void GetGlobalVariables(ConstString basename, DIEArray &offsets) = 0; + virtual void GetGlobalVariables(const RegularExpression ®ex, DIEArray &offsets) = 0; virtual void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) = 0; Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h @@ -11,6 +11,7 @@ #define LLDB_DEBUGNAMESDWARFINDEX_H #include "Plugins/SymbolFile/DWARF/DWARFIndex.h" +#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" #include "lldb/Utility/ConstString.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" @@ -23,9 +24,9 @@ void Preload() override {} - void GetGlobalVariables(ConstString name, DIEArray &offsets) override {} + void GetGlobalVariables(ConstString basename, DIEArray &offsets) override; void GetGlobalVariables(const RegularExpression ®ex, - DIEArray &offsets) override {} + DIEArray &offsets) override; void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override {} void GetObjCMethods(ConstString class_name, DIEArray &offsets) override {} void GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, @@ -42,7 +43,7 @@ void ReportInvalidDIEOffset(dw_offset_t offset, llvm::StringRef name) override {} - void Dump(Stream &s) override {} + void Dump(Stream &s) override; private: DebugNamesDWARFIndex(Module &module, @@ -57,7 +58,12 @@ DWARFDataExtractor m_debug_names_data; DWARFDataExtractor m_debug_str_data; - std::unique_ptr m_debug_names_up; + using DebugNames = llvm::DWARFDebugNames; + std::unique_ptr m_debug_names_up; + + void Append(const DebugNames::Entry &entry, DIEArray &offsets); + void MaybeLogLookupError(llvm::Error error, const DebugNames::NameIndex &ni, + llvm::StringRef name); }; } // namespace lldb_private Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -8,6 +8,8 @@ //===----------------------------------------------------------------------===// #include "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h" +#include "lldb/Utility/RegularExpression.h" +#include "lldb/Utility/Stream.h" using namespace lldb_private; using namespace lldb; @@ -23,11 +25,68 @@ DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, DWARFDataExtractor debug_str, DWARFDebugInfo *debug_info) { - auto index_up = llvm::make_unique(ToLLVM(debug_names), - ToLLVM(debug_str)); + auto index_up = + llvm::make_unique(ToLLVM(debug_names), ToLLVM(debug_str)); if (llvm::Error E = index_up->extract()) return std::move(E); return std::unique_ptr(new DebugNamesDWARFIndex( module, std::move(index_up), debug_names, debug_str, debug_info)); } + +void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry, + DIEArray &offsets) { + llvm::Optional cu_offset = entry.getCUOffset(); + llvm::Optional die_offset = entry.getDIESectionOffset(); + if (cu_offset && die_offset) + offsets.emplace_back(*cu_offset, *die_offset); +} + +void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error, + const DebugNames::NameIndex &ni, + llvm::StringRef name) { + // Ignore SentinelErrors, log everything else. + LLDB_LOG_ERROR( + LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS), + handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}), + "Failed to parse index entries for index at {1:x}, name {2}: {0}", + ni.getUnitOffset(), name); +} + +void DebugNamesDWARFIndex::GetGlobalVariables(ConstString basename, + DIEArray &offsets) { + for (const DebugNames::Entry &entry : + m_debug_names_up->equal_range(basename.GetStringRef())) { + if (entry.tag() != DW_TAG_variable) + continue; + + Append(entry, offsets); + } +} + +void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, + DIEArray &offsets) { + for (const DebugNames::NameIndex &ni: *m_debug_names_up) { + for (DebugNames::NameTableEntry nte: ni) { + if (!regex.Execute(nte.getString())) + continue; + + uint32_t entry_offset = nte.getEntryOffset(); + llvm::Expected entry_or = ni.getEntry(&entry_offset); + for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { + if (entry_or->tag() != DW_TAG_variable) + continue; + + Append(*entry_or, offsets); + } + MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); + } + } +} + +void DebugNamesDWARFIndex::Dump(Stream &s) { + std::string data; + llvm::raw_string_ostream os(data); + m_debug_names_up->dump(os); + s.PutCString(os.str()); +} Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h @@ -21,7 +21,7 @@ void Preload() override { Index(); } - void GetGlobalVariables(ConstString name, DIEArray &offsets) override; + void GetGlobalVariables(ConstString basename, DIEArray &offsets) override; void GetGlobalVariables(const RegularExpression ®ex, DIEArray &offsets) override; void GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) override; Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -345,12 +345,8 @@ // entries if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { - Mangled mangled(ConstString(mangled_cstr), true); - set.globals.Insert(mangled.GetMangledName(), + set.globals.Insert(ConstString(mangled_cstr), DIERef(cu_offset, die.GetOffset())); - ConstString demangled = mangled.GetDemangledName(cu_language); - if (demangled) - set.globals.Insert(demangled, DIERef(cu_offset, die.GetOffset())); } } break; @@ -361,9 +357,9 @@ } } -void ManualDWARFIndex::GetGlobalVariables(ConstString name, DIEArray &offsets) { +void ManualDWARFIndex::GetGlobalVariables(ConstString basename, DIEArray &offsets) { Index(); - m_set.globals.Find(name, offsets); + m_set.globals.Find(basename, offsets); } void ManualDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -27,6 +27,7 @@ #include "lldb/Utility/Timer.h" #include "Plugins/ExpressionParser/Clang/ClangModulesDeclVendor.h" +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" @@ -2024,14 +2025,25 @@ // Remember how many variables are in the list before we search. const uint32_t original_size = variables.GetSize(); + llvm::StringRef basename; + llvm::StringRef context; + + if (!CPlusPlusLanguage::ExtractContextAndIdentifier(name.GetCString(), + context, basename)) + basename = name.GetStringRef(); + DIEArray die_offsets; - m_index->GetGlobalVariables(name, die_offsets); + m_index->GetGlobalVariables(ConstString(basename), die_offsets); const size_t num_die_matches = die_offsets.size(); if (num_die_matches) { SymbolContext sc; sc.module_sp = m_obj_file->GetModule(); assert(sc.module_sp); + // Loop invariant: Variables up to this index have been checked for context + // matches. + uint32_t pruned_idx = original_size; + bool done = false; for (size_t i = 0; i < num_die_matches && !done; ++i) { const DIERef &die_ref = die_offsets[i]; @@ -2062,6 +2074,13 @@ ParseVariables(sc, die, LLDB_INVALID_ADDRESS, false, false, &variables); + while (pruned_idx < variables.GetSize()) { + VariableSP var_sp = variables.GetVariableAtIndex(pruned_idx); + if (var_sp->GetName().GetStringRef().contains(name.GetStringRef())) + ++pruned_idx; + else + variables.RemoveVariableAtIndex(pruned_idx); + } if (variables.GetSize() - original_size >= max_matches) done = true;