https://github.com/dyung updated https://github.com/llvm/llvm-project/pull/210832
>From e241e1868b010e36813b4ba26da5f10a6ee096f7 Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere <[email protected]> Date: Fri, 17 Jul 2026 07:48:12 -0700 Subject: [PATCH] [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. (cherry picked from commit 499b69cf07e03a23a420ee773261fcfcfc1c3df9) --- .../Parallel/DWARFLinkerCompileUnit.cpp | 25 ++++++++++--------- .../DWARFLinker/Parallel/DWARFLinkerUnit.h | 13 ++++++++-- 2 files changed, 24 insertions(+), 14 deletions(-) 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; }; _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
