Index: source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h =================================================================== --- source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h +++ source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h @@ -11,8 +11,12 @@ #define LLDB_MANUALDWARFINDEX_H #include "Plugins/SymbolFile/DWARF/DWARFIndex.h" +#include "Plugins/SymbolFile/DWARF/DWARFUnit.h" #include "Plugins/SymbolFile/DWARF/NameToDIE.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/Support/RWMutex.h" + +#include namespace lldb_private { class ManualDWARFIndex : public DWARFIndex { @@ -22,6 +26,8 @@ : DWARFIndex(module), m_debug_info(debug_info), m_units_to_avoid(std::move(units_to_avoid)) {} + ~ManualDWARFIndex() override; + void Preload() override { Index(); } void GetGlobalVariables(ConstString basename, DIEArray &offsets) override; @@ -68,7 +74,19 @@ /// Which dwarf units should we skip while building the index. llvm::DenseSet m_units_to_avoid; + void AddExtractedPU(DWARFUnit &importer, DWARFUnit &importee); + IndexSet m_set; + + // All DW_TAG_partial_unit's extracted for Index-ing this DW_TAG_compile_unit. + struct ExtractedForUnit { + // FIXME: The pointer is already contained in the value; but we wound need + // a combination of DenseSet::insert_as and DenseSet::try_emplace. + std::unordered_map m_map; + llvm::sys::RWMutex m_mutex; + }; + std::unordered_map m_extracted_pu; + llvm::sys::RWMutex m_extracted_pu_mutex; }; } // namespace lldb_private Index: source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -409,6 +409,7 @@ break; } import_cu->SetMainCU(&main_unit); + AddExtractedPU(unit, *import_cu); IndexUnit(*import_cu,set); } break; @@ -433,7 +434,35 @@ void ManualDWARFIndex::GetGlobalVariables(const DWARFUnit &cu, DIEArray &offsets) { Index(); - m_set.globals.FindAllEntriesForCompileUnit(cu.GetOffset(), offsets); + if (m_extracted_pu.empty()) { + m_set.globals.FindAllEntriesForCompileUnit(cu.GetOffset(), offsets); + return; + } + // FIXME: It would be more memory and CPU effective to pack it as compact + // read-only data structure at the end of indexing. + std::deque todo; + std::unordered_set found; + todo.push_back(&cu); + while (!todo.empty()) { + const DWARFUnit *work = todo.front(); + todo.pop_front(); + if (!found.insert(work->GetOffset()).second) { + m_module.GetObjectFile()->GetModule()->ReportError( + "CU 0x%8.8" PRIx32 " leads to duplicate DW_TAG_imported_unit " + "for PU 0x%8.8" PRIx32, + cu.GetOffset(), work->GetOffset()); + continue; + } + const auto it = m_extracted_pu.find(work); + if (it == m_extracted_pu.cend()) + continue; + const ExtractedForUnit &for_unit = it->second; + for (const auto &pair : for_unit.m_map) { + const DWARFUnit *new_work = pair.first; + todo.push_back(new_work); + } + } + m_set.globals.FindAllEntriesForCompileUnit(found, offsets); } void ManualDWARFIndex::GetObjCMethods(ConstString class_name, @@ -546,3 +575,27 @@ s.Printf("\nNamespaces:\n"); m_set.namespaces.Dump(&s); } + +void ManualDWARFIndex::AddExtractedPU( + DWARFUnit &importer, DWARFUnit &importee) { + ExtractedForUnit *for_importer; + { + llvm::sys::ScopedWriter guard_all(m_extracted_pu_mutex); + for_importer = &m_extracted_pu[&importer]; + } + llvm::sys::ScopedWriter guard_for_unit(for_importer->m_mutex); + // It may be already present as we do not clear m_map for ClearDIEsRWLocked() + // as it is required during its later use. + for_importer->m_map.emplace(&importee, &importee); +} + +// We could try to call ClearDIEsRWLocked() on an already destroyed DWARFUnit. +ManualDWARFIndex::~ManualDWARFIndex() { + for (auto &all_pair : m_extracted_pu) { + ExtractedForUnit &for_unit = all_pair.second; + for (auto &unit_pair : for_unit.m_map) { + DWARFUnit::ScopedExtractDIEs &scoped = unit_pair.second; + scoped.Disable(); + } + } +} Index: source/Plugins/SymbolFile/DWARF/NameToDIE.h =================================================================== --- source/Plugins/SymbolFile/DWARF/NameToDIE.h +++ source/Plugins/SymbolFile/DWARF/NameToDIE.h @@ -11,6 +11,7 @@ #define SymbolFileDWARF_NameToDIE_h_ #include +#include #include "DIERef.h" #include "lldb/Core/UniqueCStringMap.h" @@ -39,9 +40,16 @@ size_t Find(const lldb_private::RegularExpression ®ex, DIEArray &info_array) const; + size_t FindAllEntriesForCompileUnit( + std::function compare, DIEArray &info_array) const; + size_t FindAllEntriesForCompileUnit(dw_offset_t cu_offset, DIEArray &info_array) const; + size_t FindAllEntriesForCompileUnit( + const std::unordered_set &cu_offsets, + DIEArray &info_array) const; + void ForEach(std::function const Index: source/Plugins/SymbolFile/DWARF/NameToDIE.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/NameToDIE.cpp +++ source/Plugins/SymbolFile/DWARF/NameToDIE.cpp @@ -39,18 +39,33 @@ return m_map.GetValues(regex, info_array); } -size_t NameToDIE::FindAllEntriesForCompileUnit(dw_offset_t cu_offset, - DIEArray &info_array) const { +size_t NameToDIE::FindAllEntriesForCompileUnit( + std::function compare, DIEArray &info_array) const { const size_t initial_size = info_array.size(); const uint32_t size = m_map.GetSize(); for (uint32_t i = 0; i < size; ++i) { const DIERef &die_ref = m_map.GetValueAtIndexUnchecked(i); - if (cu_offset == die_ref.cu_offset) + if (compare(die_ref.cu_offset)) info_array.push_back(die_ref); } return info_array.size() - initial_size; } +size_t NameToDIE::FindAllEntriesForCompileUnit(dw_offset_t cu_offset, + DIEArray &info_array) const { + return FindAllEntriesForCompileUnit([cu_offset](dw_offset_t offset) { + return offset == cu_offset; + }, info_array); +} + +size_t NameToDIE::FindAllEntriesForCompileUnit( + const std::unordered_set &cu_offsets, + DIEArray &info_array) const { + return FindAllEntriesForCompileUnit([&cu_offsets](dw_offset_t offset) { + return cu_offsets.count(offset) != 0; + }, info_array); +} + void NameToDIE::Dump(Stream *s) { const uint32_t size = m_map.GetSize(); for (uint32_t i = 0; i < size; ++i) {