|
15 | 15 | #include "lld/Common/Reproduce.h"
|
16 | 16 | #include "llvm/ADT/CachedHashString.h"
|
17 | 17 | #include "llvm/ADT/DenseMap.h"
|
| 18 | +#include "llvm/ADT/StringRef.h" |
18 | 19 | #include "llvm/LTO/LTO.h"
|
19 | 20 | #include "llvm/Option/Arg.h"
|
20 | 21 | #include "llvm/Option/ArgList.h"
|
21 | 22 | #include "llvm/Option/Option.h"
|
22 | 23 | #include "llvm/Support/CommandLine.h"
|
23 | 24 | #include "llvm/Support/FileSystem.h"
|
| 25 | +#include "llvm/Support/MemoryBufferRef.h" |
24 | 26 | #include "llvm/Support/Path.h"
|
25 | 27 | #include "llvm/TextAPI/InterfaceFile.h"
|
26 | 28 | #include "llvm/TextAPI/TextAPIReader.h"
|
@@ -225,21 +227,42 @@ std::optional<StringRef> macho::resolveDylibPath(StringRef dylibPath) {
|
225 | 227 | // especially if it's a commonly re-exported core library.
|
226 | 228 | static DenseMap<CachedHashStringRef, DylibFile *> loadedDylibs;
|
227 | 229 |
|
| 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 | + |
228 | 243 | DylibFile *macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella,
|
229 | 244 | 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()); |
236 | 246 | DylibFile *&file = loadedDylibs[path];
|
237 | 247 | if (file) {
|
238 | 248 | if (explicitlyLinked)
|
239 | 249 | file->setExplicitlyLinked();
|
240 | 250 | return file;
|
241 | 251 | }
|
242 | 252 |
|
| 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 | + |
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.empty()) |
| 321 | + loadedDylibs[CachedHashStringRef(realPath)] = newFile; |
| 322 | + |
295 | 323 | return newFile;
|
296 | 324 | }
|
297 | 325 |
|
|
0 commit comments