jankratochvil updated this revision to Diff 149037. jankratochvil edited the summary of this revision.
https://reviews.llvm.org/D40470 Files: source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp source/Plugins/SymbolFile/DWARF/DWARFUnit.h
Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.h =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -13,6 +13,7 @@ #include "DWARFDIE.h" #include "DWARFDebugInfoEntry.h" #include "lldb/lldb-enumerations.h" +#include "llvm/Support/RWMutex.h" class DWARFUnit; class DWARFCompileUnit; @@ -172,10 +173,17 @@ void *m_user_data = nullptr; // The compile unit debug information entry item DWARFDebugInfoEntry::collection m_die_array; + mutable llvm::sys::RWMutex m_die_array_mutex; + // It gets increased by ExtractDIEsIfNeeded() and decreased by ClearDIEs(). + // BuildAddressRangeTable and SymbolFileDWARF::Index can populate m_die_array + // only temporarily while other functions calling only + // ExtractDIEsIfNeeded() will keep m_die_array populated forever. + uint32_t m_die_array_usecount = 0; // GetUnitDIEPtrOnly() needs to return pointer to the first DIE. // But the first element of m_die_array after ExtractUnitDIEIfNeeded() // would possibly move in memory after later ExtractDIEsIfNeeded(). DWARFDebugInfoEntry m_first_die; + llvm::sys::RWMutex m_first_die_mutex; // A table similar to the .debug_aranges table, but this one points to the // exact DW_TAG_subprogram DIEs std::unique_ptr<DWARFDebugAranges> m_func_aranges_ap; @@ -206,14 +214,17 @@ // if needed. const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() { ExtractUnitDIEIfNeeded(); + // m_first_die_mutex is not required as m_first_die is never cleared. if (!m_first_die) return NULL; return &m_first_die; } // Get all DWARF debug informration entries. Parse all DIEs if needed. const DWARFDebugInfoEntry *DIEPtr() { ExtractDIEsIfNeeded(); + // m_die_array_mutex is not required as ExtractDIEsIfNeeded() has not + // been matched by ClearDIEs(). if (m_die_array.empty()) return NULL; return &m_die_array[0]; Index: source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -39,6 +39,12 @@ // Parses first DIE of a compile unit. //---------------------------------------------------------------------- void DWARFUnit::ExtractUnitDIEIfNeeded() { + { + llvm::sys::ScopedReader lock(m_first_die_mutex); + if (m_first_die) + return; // Already parsed + } + llvm::sys::ScopedWriter lock(m_first_die_mutex); if (m_first_die) return; // Already parsed @@ -69,8 +75,19 @@ // Parses a compile unit and indexes its DIEs if it hasn't already been done. //---------------------------------------------------------------------- bool DWARFUnit::ExtractDIEsIfNeeded() { + { + llvm::sys::ScopedReader lock(m_die_array_mutex); + if (!m_die_array.empty()) + return 0; // Already parsed + } + llvm::sys::ScopedWriter lock(m_die_array_mutex); if (!m_die_array.empty()) return 0; // Already parsed + // Protect against use count overflow. + if (m_die_array_usecount + < std::numeric_limits<decltype(m_die_array_usecount)>::max()) + ++m_die_array_usecount; + llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex); static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); Timer scoped_timer( @@ -227,6 +244,7 @@ } } +// m_die_array_mutex must be already held as read/write. void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { uint64_t base_addr = cu_die.GetAttributeValueAsAddress( m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); @@ -280,11 +298,14 @@ DWARFDIECollection &dies, uint32_t depth) const { size_t old_size = dies.Size(); - DWARFDebugInfoEntry::const_iterator pos; - DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); - for (pos = m_die_array.begin(); pos != end; ++pos) { - if (pos->Tag() == tag) - dies.Append(DWARFDIE(this, &(*pos))); + { + llvm::sys::ScopedReader lock(m_die_array_mutex); + DWARFDebugInfoEntry::const_iterator pos; + DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); + for (pos = m_die_array.begin(); pos != end; ++pos) { + if (pos->Tag() == tag) + dies.Append(DWARFDIE(this, &(*pos))); + } } // Return the number of DIEs added to the collection @@ -325,9 +346,18 @@ m_base_obj_offset = base_obj_offset; } +// It may be called only after: ExtractDIEsIfNeeded() == true void DWARFUnit::ClearDIEs() { - m_die_array.clear(); - m_die_array.shrink_to_fit(); + { + llvm::sys::ScopedWriter lock(m_die_array_mutex); + lldbassert(!m_die_array.empty()); + lldbassert(m_die_array_usecount > 0); + if (--m_die_array_usecount > 0) + return; + + m_die_array.clear(); + m_die_array.shrink_to_fit(); + } if (m_dwo_symbol_file) m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(); @@ -472,6 +502,8 @@ if (ContainsDIEOffset(die_offset)) { ExtractDIEsIfNeeded(); + // m_die_array_mutex is not required as ExtractDIEsIfNeeded() has + // not been matched by ClearDIEs(). DWARFDebugInfoEntry::const_iterator end = m_die_array.cend(); DWARFDebugInfoEntry::const_iterator pos = lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset);
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits