@@ -225,21 +225,42 @@ std::optional<StringRef> macho::resolveDylibPath(StringRef dylibPath) {
225
225
// especially if it's a commonly re-exported core library.
226
226
static DenseMap<CachedHashStringRef, DylibFile *> loadedDylibs;
227
227
228
+ static StringRef realPathIfDifferent (StringRef path) {
229
+ SmallString<128 > realPathBuf;
230
+ std::error_code err = fs::real_path (path, realPathBuf);
231
+ if (err)
232
+ return StringRef ();
233
+
234
+ StringRef realPath (realPathBuf);
235
+ if (realPath.ends_with (path))
236
+ return StringRef ();
237
+
238
+ return uniqueSaver ().save (realPath);
239
+ }
240
+
228
241
DylibFile *macho::loadDylib (MemoryBufferRef mbref, DylibFile *umbrella,
229
242
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 ());
243
+ CachedHashStringRef path (mbref.getBufferIdentifier ());
236
244
DylibFile *&file = loadedDylibs[path];
237
245
if (file) {
238
246
if (explicitlyLinked)
239
247
file->setExplicitlyLinked ();
240
248
return file;
241
249
}
242
250
251
+ // Frameworks can be found from different symlink paths, so resolve
252
+ // symlinks and look up in the dylib cache.
253
+ StringRef realPath = realPathIfDifferent (mbref.getBufferIdentifier ());
254
+ if (!realPath.empty ()) {
255
+ CachedHashStringRef cachedRealPath (realPath);
256
+ if (loadedDylibs.contains (cachedRealPath)) {
257
+ DylibFile *realfile = loadedDylibs.at (cachedRealPath);
258
+ if (explicitlyLinked)
259
+ realfile->setExplicitlyLinked ();
260
+ return realfile;
261
+ }
262
+ }
263
+
243
264
DylibFile *newFile;
244
265
file_magic magic = identify_magic (mbref.getBuffer ());
245
266
if (magic == file_magic::tapi_file) {
@@ -292,6 +313,11 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
292
313
sys::path::filename (newFile->installName ) + " ' because " +
293
314
config->clientName + " is not an allowed client" );
294
315
}
316
+
317
+ // If the load path was a symlink, cache the real path too.
318
+ if (!realPath.empty ())
319
+ loadedDylibs[CachedHashStringRef (realPath)] = newFile;
320
+
295
321
return newFile;
296
322
}
297
323
0 commit comments