[llvm] 499b69c - [DWARFLinker] Fix data race on the per-unit file-name cache (#208967)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 17 07:48:18 PDT 2026
Author: Jonas Devlieghere
Date: 2026-07-17T09:48:12-05:00
New Revision: 499b69cf07e03a23a420ee773261fcfcfc1c3df9
URL: https://github.com/llvm/llvm-project/commit/499b69cf07e03a23a420ee773261fcfcfc1c3df9
DIFF: https://github.com/llvm/llvm-project/commit/499b69cf07e03a23a420ee773261fcfcfc1c3df9.diff
LOG: [DWARFLinker] Fix data race on the per-unit file-name cache (#208967)
CompileUnit::getDirAndFilenameFromLineTable reads and mutates the unit's
FileNames DenseMap without synchronization. During the parallel
type-name assignment phase a unit's cache is touched both by its own
worker and, through cross-unit type-name references
(addReferencedODRDies calling addDieNameFromDeclFileAndDeclLine) by
other units' workers.
The concurrent find/insert/grow corrupts the map and trips the
assertion:
```
Assertion failed: (TheBucket), function findBucketForInsertion, DenseMap.h
```
Guard the cache with a mutex. Store each entry in a heap-allocated pair
so the StringRefs handed back to callers stay valid across a concurrent
rehash. Otherwise a short (small-string-optimized) file name would move
when another insertion grows the map, dangling a StringRef already
returned.
Added:
Modified:
llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp
llvm/lib/DWARFLinker/Parallel/DWARFLinkerUnit.h
Removed:
################################################################################
diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp
index d6fcb557da0f4..5e377d70ea2c8 100644
--- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp
+++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp
@@ -1839,10 +1839,11 @@ CompileUnit::getDirAndFilenameFromLineTable(
std::optional<std::pair<StringRef, StringRef>>
CompileUnit::getDirAndFilenameFromLineTable(uint64_t FileIdx) {
+ std::lock_guard<std::mutex> Guard(FileNamesMutex);
FileNamesCache::iterator FileData = FileNames.find(FileIdx);
if (FileData != FileNames.end())
- return std::make_pair(StringRef(FileData->second.first),
- StringRef(FileData->second.second));
+ return {{StringRef(FileData->second->first),
+ StringRef(FileData->second->second)}};
if (const DWARFDebugLine::LineTable *LineTable =
getOrigUnit().getContext().getLineTableForUnit(&getOrigUnit())) {
@@ -1861,12 +1862,12 @@ CompileUnit::getDirAndFilenameFromLineTable(uint64_t FileIdx) {
if (isPathAbsoluteOnWindowsOrPosix(FileName)) {
FileNamesCache::iterator FileData =
FileNames
- .insert(std::make_pair(
- FileIdx,
- std::make_pair(std::string(""), std::move(FileName))))
+ .insert({FileIdx,
+ std::make_unique<std::pair<std::string, std::string>>(
+ std::string(""), std::move(FileName))})
.first;
- return std::make_pair(StringRef(FileData->second.first),
- StringRef(FileData->second.second));
+ return {{StringRef(FileData->second->first),
+ StringRef(FileData->second->second)}};
}
SmallString<256> FilePath;
@@ -1912,12 +1913,12 @@ CompileUnit::getDirAndFilenameFromLineTable(uint64_t FileIdx) {
FileNamesCache::iterator FileData =
FileNames
- .insert(
- std::make_pair(FileIdx, std::make_pair(std::string(FilePath),
- std::move(FileName))))
+ .insert({FileIdx,
+ std::make_unique<std::pair<std::string, std::string>>(
+ std::string(FilePath), std::move(FileName))})
.first;
- return std::make_pair(StringRef(FileData->second.first),
- StringRef(FileData->second.second));
+ return {{StringRef(FileData->second->first),
+ StringRef(FileData->second->second)}};
}
}
diff --git a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerUnit.h b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerUnit.h
index 18e14495d9645..2bb990593b56a 100644
--- a/llvm/lib/DWARFLinker/Parallel/DWARFLinkerUnit.h
+++ b/llvm/lib/DWARFLinker/Parallel/DWARFLinkerUnit.h
@@ -17,6 +17,8 @@
#include "llvm/DWARFLinker/StringPool.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
#include "llvm/Support/LEB128.h"
+#include <memory>
+#include <mutex>
namespace llvm {
namespace dwarf_linker {
@@ -213,11 +215,18 @@ class DwarfUnit : public OutputSections {
/// Output unit DIE.
DIE *OutUnitDIE = nullptr;
- /// Cache for file names for this unit.
+ /// Cache for file names for this unit. Entries are heap-allocated so the
+ /// StringRefs handed out by getDirAndFilenameFromLineTable keep pointing at
+ /// valid storage when a later insertion rehashes the map.
using FileNamesCache =
- DenseMap<uint64_t, std::pair<std::string, std::string>>;
+ DenseMap<uint64_t, std::unique_ptr<std::pair<std::string, std::string>>>;
FileNamesCache FileNames;
+ /// Guards FileNames. During the parallel type-name assignment phase a unit's
+ /// cache is filled both by its own worker and, through cross-unit type-name
+ /// references, by other units' workers, so access must be serialized.
+ std::mutex FileNamesMutex;
+
/// Maps a string into the index inside .debug_str_offsets section.
IndexedValuesMap<const StringEntry *> DebugStringIndexMap;
};
More information about the llvm-commits
mailing list