[llvm] [DebugInfo/DWARF] Fix data race in DWARFUnit DIE extraction (PR #180470)

Shivam Kunwar via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 8 21:50:32 PST 2026


https://github.com/phyBrackets created https://github.com/llvm/llvm-project/pull/180470

Add reader-writer mutex to protect `DieArray` from concurrent access, when multiple threads call `getLineInfoForAddress()` on a thread-safe DWARFContext.

Fixes #167285"

>From 9b3aa9a3222aa44c04670b4eaca446a652b1147d Mon Sep 17 00:00:00 2001
From: Shivam Kunwar <shivam.kunwar at kdab.com>
Date: Mon, 9 Feb 2026 11:16:12 +0530
Subject: [PATCH] [DebugInfo/DWARF] Fix data race in DWARFUnit DIE extraction

---
 llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h |  9 +++++++--
 llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp        | 10 +++++++++-
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index bd204f626ac01..292adb7675a4c 100644
--- a/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -23,6 +23,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/RWMutex.h"
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
@@ -246,7 +247,9 @@ class LLVM_ABI DWARFUnit {
 
   mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
   std::optional<object::SectionedAddress> BaseAddr;
+
   /// The compile unit debug information entry items.
+  mutable sys::RWMutex DieArrayMutex;
   std::vector<DWARFDebugInfoEntry> DieArray;
 
   /// Map from range's start address to end address and corresponding DIE.
@@ -538,9 +541,10 @@ class LLVM_ABI DWARFUnit {
   /// Return the DIE object for a given offset \p Offset inside the
   /// unit's DIE vector.
   DWARFDie getDIEForOffset(uint64_t Offset) {
-    if (std::optional<uint32_t> DieIdx = getDIEIndexForOffset(Offset))
+    if (std::optional<uint32_t> DieIdx = getDIEIndexForOffset(Offset)) {
+      sys::ScopedReader ReadLock(DieArrayMutex);
       return DWARFDie(this, &DieArray[*DieIdx]);
-
+    }
     return DWARFDie();
   }
 
@@ -548,6 +552,7 @@ class LLVM_ABI DWARFUnit {
   /// unit's DIE vector.
   std::optional<uint32_t> getDIEIndexForOffset(uint64_t Offset) {
     extractDIEsIfNeeded(false);
+    sys::ScopedReader ReadLock(DieArrayMutex);
     auto It =
         llvm::partition_point(DieArray, [=](const DWARFDebugInfoEntry &DIE) {
           return DIE.getOffset() < Offset;
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
index b8fbdfc8c1d70..f45de29adc580 100644
--- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
+++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -504,8 +504,15 @@ void DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
 }
 
 Error DWARFUnit::tryExtractDIEsIfNeeded(bool CUDieOnly) {
+  {
+    sys::ScopedReader ReadLock(DieArrayMutex);
+    if ((CUDieOnly && !DieArray.empty()) || DieArray.size() > 1)
+      return Error::success(); // Already parsed.
+  }
+
+  sys::ScopedWriter WriteLock(DieArrayMutex);
   if ((CUDieOnly && !DieArray.empty()) || DieArray.size() > 1)
-    return Error::success(); // Already parsed.
+    return Error::success(); // Another therad parsed while we waited
 
   bool HasCUDie = !DieArray.empty();
   extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
@@ -660,6 +667,7 @@ bool DWARFUnit::parseDWO(StringRef DWOAlternativeLocation) {
 }
 
 void DWARFUnit::clearDIEs(bool KeepCUDie) {
+  sys::ScopedWriter WriteLock(DieArrayMutex);
   // Do not use resize() + shrink_to_fit() to free memory occupied by dies.
   // shrink_to_fit() is a *non-binding* request to reduce capacity() to size().
   // It depends on the implementation whether the request is fulfilled.



More information about the llvm-commits mailing list