@@ -225,21 +225,44 @@ std::optional<StringRef> macho::resolveDylibPath(StringRef dylibPath) {
225225// especially if it's a commonly re-exported core library.
226226static DenseMap<CachedHashStringRef, DylibFile *> loadedDylibs;
227227
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+
228240DylibFile *macho::loadDylib (MemoryBufferRef mbref, DylibFile *umbrella,
229241 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 ());
236243 DylibFile *&file = loadedDylibs[path];
237244 if (file) {
238245 if (explicitlyLinked)
239246 file->setExplicitlyLinked ();
240247 return file;
241248 }
242249
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+
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.val ().empty ())
321+ loadedDylibs[realPath] = newFile;
322+
295323 return newFile;
296324}
297325
0 commit comments