Skip to content

Commit 32c5cbf

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

File tree

2 files changed

+108
-6
lines changed

2 files changed

+108
-6
lines changed

lld/MachO/DriverUtils.cpp

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,21 +225,44 @@ std::optional<StringRef> macho::resolveDylibPath(StringRef dylibPath) {
225225
// especially if it's a commonly re-exported core library.
226226
static 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+
228240
DylibFile *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

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# REQUIRES: aarch64, shell
2+
# RUN: rm -rf %t; split-file %s %t
3+
# RUN: ln -s Versions/A/Developer %t/Developer/Library/Frameworks/Developer.framework/
4+
# RUN: llvm-mc -filetype obj -triple arm64-apple-macos11.0 %t/test.s -o %t/test.o
5+
# RUN: %lld -arch arm64 -platform_version macos 11.0 11.0 -o %t/test -framework Developer -F %t/Developer/Library/Frameworks -L %t/Developer/usr/lib %t/test.o -t | FileCheck %s
6+
7+
# CHECK: {{.*}}/Developer/Library/Frameworks/Developer.framework/Developer
8+
# CHECK: {{.*}}/Developer/usr/lib/libDeveloperSupport.tbd(@rpath/libDeveloperSupport.dylib)
9+
# CHECK-NOT: {{.*}}/Developer/Library/Frameworks/Developer.framework/Versions/A/Developer
10+
11+
#--- Developer/Library/Frameworks/Developer.framework/Versions/A/Developer
12+
{
13+
"tapi_tbd_version": 5,
14+
"main_library": {
15+
"target_info": [
16+
{
17+
"target": "arm64-macos"
18+
}
19+
],
20+
"install_names": [
21+
{
22+
"name": "@rpath/Developer.framework/Developer"
23+
}
24+
],
25+
"exported_symbols": [
26+
{
27+
"text": {
28+
"global": ["_funcPublic"]
29+
}
30+
}
31+
]
32+
}
33+
}
34+
#--- Developer/usr/lib/libDeveloperSupport.tbd
35+
{
36+
"tapi_tbd_version": 5,
37+
"main_library": {
38+
"target_info": [
39+
{
40+
"target": "arm64-macos"
41+
}
42+
],
43+
"install_names": [
44+
{
45+
"name": "@rpath/libDeveloperSupport.dylib"
46+
}
47+
],
48+
"reexported_libraries": [
49+
{
50+
"names": [
51+
"@rpath/Developer.framework/Versions/A/Developer"
52+
]
53+
}
54+
],
55+
"exported_symbols": [
56+
{
57+
"text": {
58+
"global": ["_funcSupport"]
59+
}
60+
}
61+
]
62+
}
63+
}
64+
#--- test.s
65+
.text
66+
.globl _main
67+
.linker_option "-lDeveloperSupport"
68+
69+
_main:
70+
ret
71+
72+
.data
73+
.quad _funcPublic
74+
.quad _funcSupport

0 commit comments

Comments
 (0)