@@ -225,21 +225,44 @@ 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
+ if (fs::real_path (path, realPathBuf))
231
+ return StringRef ();
232
+
233
+ SmallString<128 > absPathBuf = path;
234
+ if (!fs::make_absolute (absPathBuf) && realPathBuf == absPathBuf)
235
+ return StringRef ();
236
+
237
+ return uniqueSaver ().save (StringRef (realPathBuf));
238
+ }
239
+
228
240
DylibFile *macho::loadDylib (MemoryBufferRef mbref, DylibFile *umbrella,
229
241
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 ());
242
+ CachedHashStringRef path (mbref.getBufferIdentifier ());
236
243
DylibFile *&file = loadedDylibs[path];
237
244
if (file) {
238
245
if (explicitlyLinked)
239
246
file->setExplicitlyLinked ();
240
247
return file;
241
248
}
242
249
250
+ // Frameworks can be found from different symlink paths, so resolve
251
+ // symlinks and look up in the dylib cache.
252
+ CachedHashStringRef realPath (
253
+ realPathIfDifferent (mbref.getBufferIdentifier ()));
254
+ if (!realPath.val ().empty ()) {
255
+ // Avoid map insertions here so that we do not invalidate the "file"
256
+ // reference.
257
+ auto it = loadedDylibs.find (realPath);
258
+ if (it != loadedDylibs.end ()) {
259
+ DylibFile *realfile = it->second ;
260
+ if (explicitlyLinked)
261
+ realfile->setExplicitlyLinked ();
262
+ return realfile;
263
+ }
264
+ }
265
+
243
266
DylibFile *newFile;
244
267
file_magic magic = identify_magic (mbref.getBuffer ());
245
268
if (magic == file_magic::tapi_file) {
@@ -292,6 +315,11 @@ DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
292
315
sys::path::filename (newFile->installName ) + " ' because " +
293
316
config->clientName + " is not an allowed client" );
294
317
}
318
+
319
+ // If the load path was a symlink, cache the real path too.
320
+ if (!realPath.val ().empty ())
321
+ loadedDylibs[realPath] = newFile;
322
+
295
323
return newFile;
296
324
}
297
325
0 commit comments