jankratochvil updated this revision to Diff 146523.
jankratochvil retitled this revision from "DWZ 03/07: Protect 
DWARFCompileUnit::m_die_array by a new mutex" to "Protect 
DWARFCompileUnit::m_die_array by a new mutex".
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;
@@ -196,6 +197,12 @@
   // If this is a dwo compile unit this is the offset of the base compile unit
   // in the main object file
   dw_offset_t m_base_obj_offset = DW_INVALID_OFFSET;
+  mutable llvm::sys::RWMutex m_extractdies_mutex;
+  // It gets increased by ExtractDIEsIfNeeded(false) and decreased by ClearDIEs.
+  // BuildAddressRangeTable and SymbolFileDWARF::Index can populate m_die_array
+  // only temporarily while other functions calling only
+  // ExtractDIEsIfNeeded(false) will keep m_die_array populated forever.
+  uint32_t m_extractdies_count = 0;
 
   static void
   IndexPrivate(DWARFUnit *dwarf_cu, const lldb::LanguageType cu_language,
@@ -215,14 +222,17 @@
   // if needed.
   const DWARFDebugInfoEntry *GetUnitDIEPtrOnly() {
     ExtractDIEsIfNeeded(true);
+    // m_extractdies_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(false);
+    // m_extractdies_mutex is not required as ExtractDIEsIfNeeded(false) 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
@@ -41,9 +41,24 @@
 // Parses a compile unit and indexes its DIEs if it hasn't already been done.
 //----------------------------------------------------------------------
 size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) {
-  const size_t initial_die_array_size = m_die_array_size();
-  if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1)
-    return 0; // Already parsed
+  size_t initial_die_array_size;
+  auto already_parsed = [cu_die_only, &initial_die_array_size, this]() -> bool {
+    initial_die_array_size = m_die_array_size();
+    return (cu_die_only && initial_die_array_size > 0)
+        || initial_die_array_size > 1;
+  };
+  {
+    llvm::sys::ScopedReader lock(m_extractdies_mutex);
+    if (already_parsed())
+      return 0;
+  }
+  llvm::sys::ScopedWriter lock(m_extractdies_mutex);
+  if (already_parsed())
+    return 0;
+  // Protect against use count overflow.
+  if (!cu_die_only && m_extractdies_count
+      < std::numeric_limits<decltype(m_extractdies_count)>::max())
+    ++m_extractdies_count;
 
   static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
   Timer scoped_timer(
@@ -213,6 +228,7 @@
   return m_first_die ? 1 : 0;
 }
 
+// m_extractdies_mutex must be already held as read/write.
 void DWARFUnit::AddUnitDIE(DWARFDebugInfoEntry &die) {
   assert(m_die_array.empty() && "Compile unit DIE already added");
   assert(!m_first_die);
@@ -265,11 +281,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_extractdies_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
@@ -310,9 +329,18 @@
   m_base_obj_offset = base_obj_offset;
 }
 
+// It may be called only after: ExtractDIEsIfNeeded(false) > 1
 void DWARFUnit::ClearDIEs(bool keep_compile_unit_die) {
-  m_die_array.clear();
-  m_die_array.shrink_to_fit();
+  {
+    llvm::sys::ScopedWriter lock(m_extractdies_mutex);
+    lldbassert(m_die_array.size() > 1);
+    lldbassert(m_extractdies_count > 0);
+    if (--m_extractdies_count > 0)
+      return;
+
+    m_die_array.clear();
+    m_die_array.shrink_to_fit();
+  }
 
   if (m_dwo_symbol_file)
     m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(keep_compile_unit_die);
@@ -434,7 +462,10 @@
 
 void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; }
 
-bool DWARFUnit::HasDIEsParsed() const { return m_die_array.size() > 1; }
+bool DWARFUnit::HasDIEsParsed() const {
+  llvm::sys::ScopedReader lock(m_extractdies_mutex);
+  return m_die_array.size() > 1;
+}
 
 //----------------------------------------------------------------------
 // Compare function DWARFDebugAranges::Range structures
@@ -459,6 +490,8 @@
 
     if (ContainsDIEOffset(die_offset)) {
       ExtractDIEsIfNeeded(false);
+      // m_extractdies_mutex is not required as ExtractDIEsIfNeeded(false) 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

Reply via email to