[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