Index: lldb/trunk/lit/SymbolFile/DWARF/dwarf5-partial-index.cpp =================================================================== --- lldb/trunk/lit/SymbolFile/DWARF/dwarf5-partial-index.cpp +++ lldb/trunk/lit/SymbolFile/DWARF/dwarf5-partial-index.cpp @@ -0,0 +1,25 @@ +// Test that we return complete results when only a part of the binary is built +// with an index. + +// REQUIRES: lld + +// RUN: clang %s -g -c -emit-llvm -o - --target=x86_64-pc-linux -DONE | \ +// RUN: llc -accel-tables=Dwarf -filetype=obj -o %t-1.o +// RUN: clang %s -g -c -emit-llvm -o - --target=x86_64-pc-linux -DTWO | \ +// RUN: llc -accel-tables=Disable -filetype=obj -o %t-2.o +// RUN: ld.lld %t-1.o %t-2.o -o %t +// RUN: lldb-test symbols --find=variable --name=foo %t | FileCheck %s + +// CHECK: Found 2 variables: +#ifdef ONE +namespace one { +int foo; +// CHECK-DAG: name = "foo", {{.*}} decl = dwarf5-partial-index.cpp:[[@LINE-1]] +} // namespace one +extern "C" void _start() {} +#else +namespace two { +int foo; +// CHECK-DAG: name = "foo", {{.*}} decl = dwarf5-partial-index.cpp:[[@LINE-1]] +} // namespace two +#endif 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 @@ -12,6 +12,7 @@ #include "Plugins/SymbolFile/DWARF/DWARFIndex.h" #include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" +#include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h" #include "lldb/Utility/ConstString.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" @@ -22,7 +23,7 @@ Create(Module &module, DWARFDataExtractor debug_names, DWARFDataExtractor debug_str, DWARFDebugInfo *debug_info); - void Preload() override {} + void Preload() override { m_fallback.Preload(); } void GetGlobalVariables(ConstString basename, DIEArray &offsets) override; void GetGlobalVariables(const RegularExpression ®ex, @@ -51,7 +52,8 @@ DWARFDataExtractor debug_names_data, DWARFDataExtractor debug_str_data, DWARFDebugInfo *debug_info) - : DWARFIndex(module), m_debug_names_up(std::move(debug_names_up)) {} + : DWARFIndex(module), m_debug_names_up(std::move(debug_names_up)), + m_fallback(module, debug_info, GetUnits(*m_debug_names_up)) {} // LLVM DWARFDebugNames will hold a non-owning reference to this data, so keep // track of the ownership here. @@ -60,10 +62,13 @@ using DebugNames = llvm::DWARFDebugNames; std::unique_ptr m_debug_names_up; + ManualDWARFIndex m_fallback; void Append(const DebugNames::Entry &entry, DIEArray &offsets); void MaybeLogLookupError(llvm::Error error, const DebugNames::NameIndex &ni, llvm::StringRef name); + + static llvm::DenseSet GetUnits(const DebugNames &debug_names); }; } // 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 @@ -34,6 +34,16 @@ module, std::move(index_up), debug_names, debug_str, debug_info)); } +llvm::DenseSet +DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) { + llvm::DenseSet result; + for (const DebugNames::NameIndex &ni : debug_names) { + for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu) + result.insert(ni.getCUOffset(cu)); + } + return result; +} + void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry, DIEArray &offsets) { llvm::Optional cu_offset = entry.getCUOffset(); @@ -55,6 +65,8 @@ void DebugNamesDWARFIndex::GetGlobalVariables(ConstString basename, DIEArray &offsets) { + m_fallback.GetGlobalVariables(basename, offsets); + for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(basename.GetStringRef())) { if (entry.tag() != DW_TAG_variable) @@ -66,6 +78,8 @@ void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, DIEArray &offsets) { + m_fallback.GetGlobalVariables(regex, offsets); + for (const DebugNames::NameIndex &ni: *m_debug_names_up) { for (DebugNames::NameTableEntry nte: ni) { if (!regex.Execute(nte.getString())) @@ -85,6 +99,8 @@ } void DebugNamesDWARFIndex::Dump(Stream &s) { + m_fallback.Dump(s); + std::string data; llvm::raw_string_ostream os(data); m_debug_names_up->dump(os); 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 @@ -12,12 +12,15 @@ #include "Plugins/SymbolFile/DWARF/DWARFIndex.h" #include "Plugins/SymbolFile/DWARF/NameToDIE.h" +#include "llvm/ADT/DenseSet.h" namespace lldb_private { class ManualDWARFIndex : public DWARFIndex { public: - ManualDWARFIndex(Module &module, DWARFDebugInfo *debug_info) - : DWARFIndex(module), m_debug_info(debug_info) {} + ManualDWARFIndex(Module &module, DWARFDebugInfo *debug_info, + llvm::DenseSet units_to_avoid = {}) + : DWARFIndex(module), m_debug_info(debug_info), + m_units_to_avoid(std::move(units_to_avoid)) {} void Preload() override { Index(); } @@ -62,6 +65,8 @@ /// Non-null value means we haven't built the index yet. DWARFDebugInfo *m_debug_info; + /// Which dwarf units should we skip while building the index. + llvm::DenseSet m_units_to_avoid; IndexSet m_set; }; 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 @@ -32,28 +32,30 @@ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer(func_cat, "%p", static_cast(&debug_info)); - const uint32_t num_compile_units = debug_info.GetNumCompileUnits(); - if (num_compile_units == 0) + std::vector units_to_index; + units_to_index.reserve(debug_info.GetNumCompileUnits()); + for (size_t U = 0; U < debug_info.GetNumCompileUnits(); ++U) { + DWARFUnit *unit = debug_info.GetCompileUnitAtIndex(U); + if (unit && m_units_to_avoid.count(unit->GetOffset()) == 0) + units_to_index.push_back(unit); + } + if (units_to_index.empty()) return; - std::vector sets(num_compile_units); + std::vector sets(units_to_index.size()); //---------------------------------------------------------------------- // Keep memory down by clearing DIEs for any compile units if indexing // caused us to load the compile unit's DIEs. //---------------------------------------------------------------------- - std::vector> - clear_cu_dies(num_compile_units); + std::vector> clear_cu_dies( + units_to_index.size()); auto parser_fn = [&](size_t cu_idx) { - DWARFUnit *dwarf_cu = debug_info.GetCompileUnitAtIndex(cu_idx); - if (dwarf_cu) - IndexUnit(*dwarf_cu, sets[cu_idx]); + IndexUnit(*units_to_index[cu_idx], sets[cu_idx]); }; - auto extract_fn = [&debug_info, &clear_cu_dies](size_t cu_idx) { - DWARFUnit *dwarf_cu = debug_info.GetCompileUnitAtIndex(cu_idx); - if (dwarf_cu) - clear_cu_dies[cu_idx] = dwarf_cu->ExtractDIEsScoped(); + auto extract_fn = [&units_to_index, &clear_cu_dies](size_t cu_idx) { + clear_cu_dies[cu_idx] = units_to_index[cu_idx]->ExtractDIEsScoped(); }; // Create a task runner that extracts dies for each DWARF compile unit in a @@ -66,12 +68,12 @@ // to wait until all compile units have been indexed in case a DIE in one // compile unit refers to another and the indexes accesses those DIEs. //---------------------------------------------------------------------- - TaskMapOverInt(0, num_compile_units, extract_fn); + TaskMapOverInt(0, units_to_index.size(), extract_fn); // Now create a task runner that can index each DWARF compile unit in a // separate thread so we can index quickly. - TaskMapOverInt(0, num_compile_units, parser_fn); + TaskMapOverInt(0, units_to_index.size(), parser_fn); auto finalize_fn = [this, &sets](NameToDIE(IndexSet::*index)) { NameToDIE &result = m_set.*index;