[lld] [lld] recursively call loadDylib for symlinks (PR #143595)

Richard Howell via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 11 10:03:20 PDT 2025


https://github.com/rmaz updated https://github.com/llvm/llvm-project/pull/143595

>From 276ce5d6156ffde61148d3c5b5a2789d75968caf Mon Sep 17 00:00:00 2001
From: Richard Howell <rhow at meta.com>
Date: Tue, 10 Jun 2025 12:35:38 -0700
Subject: [PATCH] [lld] check cache in loadDylib before real_path

---
 lld/MachO/DriverUtils.cpp | 40 +++++++++++++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 6 deletions(-)

diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp
index f7f6be049f0e1..345a7cbda66b3 100644
--- a/lld/MachO/DriverUtils.cpp
+++ b/lld/MachO/DriverUtils.cpp
@@ -15,12 +15,14 @@
 #include "lld/Common/Reproduce.h"
 #include "llvm/ADT/CachedHashString.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/LTO/LTO.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/Support/Path.h"
 #include "llvm/TextAPI/InterfaceFile.h"
 #include "llvm/TextAPI/TextAPIReader.h"
@@ -225,14 +227,22 @@ std::optional<StringRef> macho::resolveDylibPath(StringRef dylibPath) {
 // especially if it's a commonly re-exported core library.
 static DenseMap<CachedHashStringRef, DylibFile *> loadedDylibs;
 
+static StringRef realPathIfDifferent(StringRef path) {
+  SmallString<128> realPathBuf;
+  std::error_code err = fs::real_path(path, realPathBuf);
+  if (err)
+    return StringRef();
+
+  StringRef realPath(realPathBuf);
+  if (realPath.ends_with(path))
+    return StringRef();
+
+  return uniqueSaver().save(realPath);
+}
+
 DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
                             bool isBundleLoader, bool explicitlyLinked) {
-  // Frameworks can be found from different symlink paths, so resolve
-  // symlinks before looking up in the dylib cache.
-  SmallString<128> realPath;
-  std::error_code err = fs::real_path(mbref.getBufferIdentifier(), realPath);
-  CachedHashStringRef path(!err ? uniqueSaver().save(StringRef(realPath))
-                                : mbref.getBufferIdentifier());
+  CachedHashStringRef path(mbref.getBufferIdentifier());
   DylibFile *&file = loadedDylibs[path];
   if (file) {
     if (explicitlyLinked)
@@ -240,6 +250,19 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
     return file;
   }
 
+  // Frameworks can be found from different symlink paths, so resolve
+  // symlinks and look up in the dylib cache.
+  StringRef realPath = realPathIfDifferent(mbref.getBufferIdentifier());
+  if (!realPath.empty()) {
+    CachedHashStringRef cachedRealPath(realPath);
+    if (loadedDylibs.contains(cachedRealPath)) {
+      DylibFile *realfile = loadedDylibs.at(cachedRealPath);
+      if (explicitlyLinked)
+        realfile->setExplicitlyLinked();
+      return realfile;
+    }
+  }
+
   DylibFile *newFile;
   file_magic magic = identify_magic(mbref.getBuffer());
   if (magic == file_magic::tapi_file) {
@@ -292,6 +315,11 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
             sys::path::filename(newFile->installName) + "' because " +
             config->clientName + " is not an allowed client");
   }
+
+  // If the load path was a symlink, cache the real path too.
+  if (!realPath.empty())
+    loadedDylibs[CachedHashStringRef(realPath)] = newFile;
+
   return newFile;
 }
 



More information about the llvm-commits mailing list