Skip to content

Commit 276ce5d

Browse files
committed
[lld] check cache in loadDylib before real_path
1 parent adfea33 commit 276ce5d

File tree

1 file changed

+34
-6
lines changed

1 file changed

+34
-6
lines changed

lld/MachO/DriverUtils.cpp

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,14 @@
1515
#include "lld/Common/Reproduce.h"
1616
#include "llvm/ADT/CachedHashString.h"
1717
#include "llvm/ADT/DenseMap.h"
18+
#include "llvm/ADT/StringRef.h"
1819
#include "llvm/LTO/LTO.h"
1920
#include "llvm/Option/Arg.h"
2021
#include "llvm/Option/ArgList.h"
2122
#include "llvm/Option/Option.h"
2223
#include "llvm/Support/CommandLine.h"
2324
#include "llvm/Support/FileSystem.h"
25+
#include "llvm/Support/MemoryBufferRef.h"
2426
#include "llvm/Support/Path.h"
2527
#include "llvm/TextAPI/InterfaceFile.h"
2628
#include "llvm/TextAPI/TextAPIReader.h"
@@ -225,21 +227,42 @@ std::optional<StringRef> macho::resolveDylibPath(StringRef dylibPath) {
225227
// especially if it's a commonly re-exported core library.
226228
static DenseMap<CachedHashStringRef, DylibFile *> loadedDylibs;
227229

230+
static StringRef realPathIfDifferent(StringRef path) {
231+
SmallString<128> realPathBuf;
232+
std::error_code err = fs::real_path(path, realPathBuf);
233+
if (err)
234+
return StringRef();
235+
236+
StringRef realPath(realPathBuf);
237+
if (realPath.ends_with(path))
238+
return StringRef();
239+
240+
return uniqueSaver().save(realPath);
241+
}
242+
228243
DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
229244
bool isBundleLoader, bool explicitlyLinked) {
230-
// Frameworks can be found from different symlink paths, so resolve
231-
// symlinks before looking up in the dylib cache.
232-
SmallString<128> realPath;
233-
std::error_code err = fs::real_path(mbref.getBufferIdentifier(), realPath);
234-
CachedHashStringRef path(!err ? uniqueSaver().save(StringRef(realPath))
235-
: mbref.getBufferIdentifier());
245+
CachedHashStringRef path(mbref.getBufferIdentifier());
236246
DylibFile *&file = loadedDylibs[path];
237247
if (file) {
238248
if (explicitlyLinked)
239249
file->setExplicitlyLinked();
240250
return file;
241251
}
242252

253+
// Frameworks can be found from different symlink paths, so resolve
254+
// symlinks and look up in the dylib cache.
255+
StringRef realPath = realPathIfDifferent(mbref.getBufferIdentifier());
256+
if (!realPath.empty()) {
257+
CachedHashStringRef cachedRealPath(realPath);
258+
if (loadedDylibs.contains(cachedRealPath)) {
259+
DylibFile *realfile = loadedDylibs.at(cachedRealPath);
260+
if (explicitlyLinked)
261+
realfile->setExplicitlyLinked();
262+
return realfile;
263+
}
264+
}
265+
243266
DylibFile *newFile;
244267
file_magic magic = identify_magic(mbref.getBuffer());
245268
if (magic == file_magic::tapi_file) {
@@ -292,6 +315,11 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
292315
sys::path::filename(newFile->installName) + "' because " +
293316
config->clientName + " is not an allowed client");
294317
}
318+
319+
// If the load path was a symlink, cache the real path too.
320+
if (!realPath.empty())
321+
loadedDylibs[CachedHashStringRef(realPath)] = newFile;
322+
295323
return newFile;
296324
}
297325

0 commit comments

Comments
 (0)