[lld] [lld] handle re-exports for full framework paths (PR #137989)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 30 09:45:58 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld-macho
Author: Richard Howell (rmaz)
<details>
<summary>Changes</summary>
Framework load paths can be either the top level framework name, or subpaths of the framework bundle pointing to specific framework binary versions. Extend the framework lookup logic to handle the latter case.
---
Full diff: https://github.com/llvm/llvm-project/pull/137989.diff
2 Files Affected:
- (modified) lld/MachO/InputFiles.cpp (+24-5)
- (added) lld/test/MachO/reexport-without-rpath.s (+119)
``````````diff
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 83bc246a39f4f..a48dfb774de43 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -1566,6 +1566,25 @@ static DylibFile *loadDylib(StringRef path, DylibFile *umbrella) {
return loadDylib(*mbref, umbrella);
}
+static StringRef findFramework(StringRef path, StringRef frameworkName) {
+ // Framework names can be in multiple formats:
+ // - Foo.framework/Foo
+ // - Foo.framework/Versions/A/Foo
+ size_t start;
+ size_t end = path.size();
+ while (true) {
+ start = path.rfind('/', end);
+ if (start == StringRef::npos)
+ return StringRef();
+
+ StringRef component = path.substr(start + 1, end - start - 1);
+ if (component == frameworkName)
+ return path.substr(start + 1);
+
+ end = start;
+ }
+}
+
// TBD files are parsed into a series of TAPI documents (InterfaceFiles), with
// the first document storing child pointers to the rest of them. When we are
// processing a given TBD file, we store that top-level document in
@@ -1581,13 +1600,13 @@ static DylibFile *findDylib(StringRef path, DylibFile *umbrella,
// 1. Install name basename in -F / -L directories.
{
StringRef stem = path::stem(path);
- SmallString<128> frameworkName;
- path::append(frameworkName, path::Style::posix, stem + ".framework", stem);
- bool isFramework = path.ends_with(frameworkName);
- if (isFramework) {
+ SmallString<128> frameworkName(stem);
+ frameworkName += ".framework";
+ StringRef frameworkPath = findFramework(path, frameworkName);
+ if (!frameworkPath.empty()) {
for (StringRef dir : config->frameworkSearchPaths) {
SmallString<128> candidate = dir;
- path::append(candidate, frameworkName);
+ path::append(candidate, frameworkPath);
if (std::optional<StringRef> dylibPath =
resolveDylibPath(candidate.str()))
return loadDylib(*dylibPath, umbrella);
diff --git a/lld/test/MachO/reexport-without-rpath.s b/lld/test/MachO/reexport-without-rpath.s
new file mode 100644
index 0000000000000..741c33e81630d
--- /dev/null
+++ b/lld/test/MachO/reexport-without-rpath.s
@@ -0,0 +1,119 @@
+# REQUIRES: aarch64, shell
+# RUN: rm -rf %t; split-file %s %t
+# RUN: ln -s Versions/A/Developer %t/Developer/Library/Frameworks/Developer.framework/
+# RUN: ln -s Versions/A/DeveloperCore %t/Developer/Library/PrivateFrameworks/DeveloperCore.framework/
+# RUN: llvm-mc -filetype obj -triple arm64-apple-macos11.0 %t/test.s -o %t/test.o
+# 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
+# RUN: llvm-objdump --bind --no-show-raw-insn -d %t/test | FileCheck %s
+# CHECK: Bind table:
+# CHECK-DAG: __DATA __data {{.*}} pointer 0 Developer _funcPublic
+# CHECK-DAG: __DATA __data {{.*}} pointer 0 Developer _funcCore
+# CHECK-DAG: __DATA __data {{.*}} pointer 0 libDeveloperSupport _funcSupport
+
+#--- Developer/Library/Frameworks/Developer.framework/Versions/A/Developer
+{
+ "tapi_tbd_version": 5,
+ "main_library": {
+ "target_info": [
+ {
+ "target": "arm64-macos"
+ }
+ ],
+ "install_names": [
+ {
+ "name": "@rpath/Developer.framework/Versions/A/Developer"
+ }
+ ],
+ "rpaths": [
+ {
+ "paths": [
+ "@loader_path/../../../../PrivateFrameworks/"
+ ]
+ }
+ ],
+ "reexported_libraries": [
+ {
+ "names": [
+ "@rpath/DeveloperCore.framework/Versions/A/DeveloperCore"
+ ]
+ }
+ ],
+ "exported_symbols": [
+ {
+ "text": {
+ "global": ["_funcPublic"]
+ }
+ }
+ ]
+ }
+}
+#--- Developer/Library/PrivateFrameworks/DeveloperCore.framework/Versions/A/DeveloperCore
+{
+ "tapi_tbd_version": 5,
+ "main_library": {
+ "target_info": [
+ {
+ "target": "arm64-macos"
+ }
+ ],
+ "install_names": [
+ {
+ "name": "@rpath/DeveloperCore.framework/Versions/A/DeveloperCore"
+ }
+ ],
+ "allowable_clients": [
+ {
+ "clients": ["Developer"]
+ }
+ ],
+ "exported_symbols": [
+ {
+ "text": {
+ "global": ["_funcCore"]
+ }
+ }
+ ]
+ }
+}
+#--- Developer/usr/lib/libDeveloperSupport.tbd
+{
+ "tapi_tbd_version": 5,
+ "main_library": {
+ "target_info": [
+ {
+ "target": "arm64-macos"
+ }
+ ],
+ "install_names": [
+ {
+ "name": "@rpath/libDeveloperSupport.dylib"
+ }
+ ],
+ "reexported_libraries": [
+ {
+ "names": [
+ "@rpath/Developer.framework/Versions/A/Developer"
+ ]
+ }
+ ],
+ "exported_symbols": [
+ {
+ "text": {
+ "global": ["_funcSupport"]
+ }
+ }
+ ]
+ }
+}
+#--- test.s
+.text
+.globl _main
+.linker_option "-lDeveloperSupport"
+
+_main:
+ ret
+
+.data
+ .quad _funcPublic
+ .quad _funcCore
+ .quad _funcSupport
``````````
</details>
https://github.com/llvm/llvm-project/pull/137989
More information about the llvm-commits
mailing list