Author: Raphael Isemann
Date: 2026-07-17T08:14:43+01:00
New Revision: 250f791e7002afb308e4a59dc5ef3e1f2e1c10af

URL: 
https://github.com/llvm/llvm-project/commit/250f791e7002afb308e4a59dc5ef3e1f2e1c10af
DIFF: 
https://github.com/llvm/llvm-project/commit/250f791e7002afb308e4a59dc5ef3e1f2e1c10af.diff

LOG: [lldb] Fix tsan error in SymbolLocatorDebugSymbols (#209698)

g_dlsym_DBGCopyFullDSYMURLForUUID and g_dlsym_DBGCopyDSYMPropertyLists
are two globals that are lazily initialized when first used. TSan
complains that this lazy init code is not thread-safe as there is no
synchronization mechanism. In practice, the only race that can happen
here is that we initialize the same values concurrently, which should be
'safe' on any platform.

This patch moves the initialization code into a static local that
returns a const object. This makes this code thread-safe by construction
and fixes the TSan error.

It also fixes that we keep calling dlopen if the initialization fails.
That is, the `g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr` will always
be true on systems where the framework doesn't exist, so this code will
try loading it on every function call and fail.

Added: 
    

Modified: 
    lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp

Removed: 
    


################################################################################
diff  --git 
a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp 
b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
index 7c7facfdbd589..aeb6a07298207 100644
--- 
a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
+++ 
b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
@@ -53,10 +53,37 @@
 using namespace lldb;
 using namespace lldb_private;
 
-static CFURLRef (*g_dlsym_DBGCopyFullDSYMURLForUUID)(
-    CFUUIDRef uuid, CFURLRef exec_url) = nullptr;
-static CFDictionaryRef (*g_dlsym_DBGCopyDSYMPropertyLists)(CFURLRef dsym_url) =
-    nullptr;
+namespace {
+struct DebugSymbolsDylibFunctions {
+  CFURLRef (*DBGCopyFullDSYMURLForUUID)(CFUUIDRef uuid,
+                                        CFURLRef exec_url) = nullptr;
+  CFDictionaryRef (*DBGCopyDSYMPropertyLists)(CFURLRef dsym_url) = nullptr;
+
+  DebugSymbolsDylibFunctions() {
+    void *handle = dlopen(
+        
"/System/Library/PrivateFrameworks/DebugSymbols.framework/DebugSymbols",
+        RTLD_LAZY | RTLD_LOCAL);
+    if (handle) {
+      DBGCopyFullDSYMURLForUUID = (CFURLRef (*)(CFUUIDRef, CFURLRef))dlsym(
+          handle, "DBGCopyFullDSYMURLForUUID");
+      DBGCopyDSYMPropertyLists = (CFDictionaryRef (*)(CFURLRef))dlsym(
+          handle, "DBGCopyDSYMPropertyLists");
+    }
+  }
+
+  /// Returns true if all DebugSymbols functions were found in the framework.
+  bool FoundFunctions() const {
+    return DBGCopyFullDSYMURLForUUID != nullptr &&
+           DBGCopyDSYMPropertyLists != nullptr;
+  }
+};
+} // namespace
+
+static const DebugSymbolsDylibFunctions &GetDebugSymbolsDylibFunctions() {
+  // This is a static local to avoid race conditions.
+  static DebugSymbolsDylibFunctions g_functions;
+  return g_functions;
+}
 
 LLDB_PLUGIN_DEFINE(SymbolLocatorDebugSymbols)
 
@@ -98,24 +125,10 @@ std::optional<ModuleSpec> 
SymbolLocatorDebugSymbols::LocateExecutableObjectFile(
 
   int items_found = 0;
 
-  if (g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr ||
-      g_dlsym_DBGCopyDSYMPropertyLists == nullptr) {
-    void *handle = dlopen(
-        
"/System/Library/PrivateFrameworks/DebugSymbols.framework/DebugSymbols",
-        RTLD_LAZY | RTLD_LOCAL);
-    if (handle) {
-      g_dlsym_DBGCopyFullDSYMURLForUUID =
-          (CFURLRef(*)(CFUUIDRef, CFURLRef))dlsym(handle,
-                                                  "DBGCopyFullDSYMURLForUUID");
-      g_dlsym_DBGCopyDSYMPropertyLists = (CFDictionaryRef(*)(CFURLRef))dlsym(
-          handle, "DBGCopyDSYMPropertyLists");
-    }
-  }
-
-  if (g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr ||
-      g_dlsym_DBGCopyDSYMPropertyLists == nullptr) {
+  const DebugSymbolsDylibFunctions &dylib_functions =
+      GetDebugSymbolsDylibFunctions();
+  if (!dylib_functions.FoundFunctions())
     return {};
-  }
 
   if (uuid && uuid->IsValid()) {
     // Try and locate the dSYM file using DebugSymbols first
@@ -138,8 +151,9 @@ std::optional<ModuleSpec> 
SymbolLocatorDebugSymbols::LocateExecutableObjectFile(
                 FALSE));
         }
 
-        CFCReleaser<CFURLRef> dsym_url(g_dlsym_DBGCopyFullDSYMURLForUUID(
-            module_uuid_ref.get(), exec_url.get()));
+        CFCReleaser<CFURLRef> dsym_url(
+            dylib_functions.DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(),
+                                                      exec_url.get()));
         char path[PATH_MAX];
 
         if (dsym_url.get()) {
@@ -175,7 +189,7 @@ std::optional<ModuleSpec> 
SymbolLocatorDebugSymbols::LocateExecutableObjectFile(
           }
 
           CFCReleaser<CFDictionaryRef> dict(
-              g_dlsym_DBGCopyDSYMPropertyLists(dsym_url.get()));
+              dylib_functions.DBGCopyDSYMPropertyLists(dsym_url.get()));
           CFDictionaryRef uuid_dict = NULL;
           if (dict.get()) {
             CFCString uuid_cfstr(uuid->GetAsString().c_str());
@@ -538,24 +552,10 @@ static int LocateMacOSXFilesUsingDebugSymbols(const 
ModuleSpec &module_spec,
 
   int items_found = 0;
 
-  if (g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr ||
-      g_dlsym_DBGCopyDSYMPropertyLists == nullptr) {
-    void *handle = dlopen(
-        
"/System/Library/PrivateFrameworks/DebugSymbols.framework/DebugSymbols",
-        RTLD_LAZY | RTLD_LOCAL);
-    if (handle) {
-      g_dlsym_DBGCopyFullDSYMURLForUUID =
-          (CFURLRef(*)(CFUUIDRef, CFURLRef))dlsym(handle,
-                                                  "DBGCopyFullDSYMURLForUUID");
-      g_dlsym_DBGCopyDSYMPropertyLists = (CFDictionaryRef(*)(CFURLRef))dlsym(
-          handle, "DBGCopyDSYMPropertyLists");
-    }
-  }
-
-  if (g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr ||
-      g_dlsym_DBGCopyDSYMPropertyLists == nullptr) {
+  const DebugSymbolsDylibFunctions &dylib_functions =
+      GetDebugSymbolsDylibFunctions();
+  if (!dylib_functions.FoundFunctions())
     return items_found;
-  }
 
   if (uuid && uuid->IsValid()) {
     // Try and locate the dSYM file using DebugSymbols first
@@ -578,8 +578,9 @@ static int LocateMacOSXFilesUsingDebugSymbols(const 
ModuleSpec &module_spec,
                 FALSE));
         }
 
-        CFCReleaser<CFURLRef> dsym_url(g_dlsym_DBGCopyFullDSYMURLForUUID(
-            module_uuid_ref.get(), exec_url.get()));
+        CFCReleaser<CFURLRef> dsym_url(
+            dylib_functions.DBGCopyFullDSYMURLForUUID(module_uuid_ref.get(),
+                                                      exec_url.get()));
         char path[PATH_MAX];
 
         if (dsym_url.get()) {
@@ -615,7 +616,7 @@ static int LocateMacOSXFilesUsingDebugSymbols(const 
ModuleSpec &module_spec,
           }
 
           CFCReleaser<CFDictionaryRef> dict(
-              g_dlsym_DBGCopyDSYMPropertyLists(dsym_url.get()));
+              dylib_functions.DBGCopyDSYMPropertyLists(dsym_url.get()));
           CFDictionaryRef uuid_dict = NULL;
           if (dict.get()) {
             CFCString uuid_cfstr(uuid->GetAsString().c_str());


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to