diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index f3d2a93914f717..e5cba4dadc246c 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1042,20 +1042,36 @@ static bool shouldAdhocSignByDefault(Architecture arch, PlatformType platform) { platform == PLATFORM_XROS_SIMULATOR; } -static bool dataConstDefault(const InputArgList &args) { - static const std::array, 6> minVersion = - {{{PLATFORM_MACOS, VersionTuple(10, 15)}, - {PLATFORM_IOS, VersionTuple(13, 0)}, - {PLATFORM_TVOS, VersionTuple(13, 0)}, - {PLATFORM_WATCHOS, VersionTuple(6, 0)}, - {PLATFORM_XROS, VersionTuple(1, 0)}, - {PLATFORM_BRIDGEOS, VersionTuple(4, 0)}}}; - PlatformType platform = removeSimulator(config->platformInfo.target.Platform); - auto it = llvm::find_if(minVersion, +template +using MinVersions = std::array, N>; + +/// Returns true if the platform is greater than the min version. +/// Returns false if the platform does not exist. +template +static bool greaterEqMinVersion(const MinVersions &minVersions, + bool ignoreSimulator) { + PlatformType platform = config->platformInfo.target.Platform; + if (ignoreSimulator) + platform = removeSimulator(platform); + auto it = llvm::find_if(minVersions, [&](const auto &p) { return p.first == platform; }); - if (it != minVersion.end()) - if (config->platformInfo.target.MinDeployment < it->second) - return false; + if (it != minVersions.end()) + if (config->platformInfo.target.MinDeployment >= it->second) + return true; + return false; +} + +static bool dataConstDefault(const InputArgList &args) { + static const MinVersions<6> minVersion = {{ + {PLATFORM_MACOS, VersionTuple(10, 15)}, + {PLATFORM_IOS, VersionTuple(13, 0)}, + {PLATFORM_TVOS, VersionTuple(13, 0)}, + {PLATFORM_WATCHOS, VersionTuple(6, 0)}, + {PLATFORM_XROS, VersionTuple(1, 0)}, + {PLATFORM_BRIDGEOS, VersionTuple(4, 0)}, + }}; + if (!greaterEqMinVersion(minVersion, true)) + return false; switch (config->outputType) { case MH_EXECUTE: @@ -1106,30 +1122,18 @@ static bool shouldEmitChainedFixups(const InputArgList &args) { if (requested) return true; - static const std::array, 9> minVersion = - {{ - {PLATFORM_IOS, VersionTuple(13, 4)}, - {PLATFORM_IOSSIMULATOR, VersionTuple(16, 0)}, - {PLATFORM_MACOS, VersionTuple(13, 0)}, - {PLATFORM_TVOS, VersionTuple(14, 0)}, - {PLATFORM_TVOSSIMULATOR, VersionTuple(15, 0)}, - {PLATFORM_WATCHOS, VersionTuple(7, 0)}, - {PLATFORM_WATCHOSSIMULATOR, VersionTuple(8, 0)}, - {PLATFORM_XROS, VersionTuple(1, 0)}, - {PLATFORM_XROS_SIMULATOR, VersionTuple(1, 0)}, - }}; - PlatformType platform = config->platformInfo.target.Platform; - auto it = llvm::find_if(minVersion, - [&](const auto &p) { return p.first == platform; }); - - // We don't know the versions for other platforms, so default to disabled. - if (it == minVersion.end()) - return false; - - if (it->second > config->platformInfo.target.MinDeployment) - return false; - - return true; + static const MinVersions<9> minVersion = {{ + {PLATFORM_IOS, VersionTuple(13, 4)}, + {PLATFORM_IOSSIMULATOR, VersionTuple(16, 0)}, + {PLATFORM_MACOS, VersionTuple(13, 0)}, + {PLATFORM_TVOS, VersionTuple(14, 0)}, + {PLATFORM_TVOSSIMULATOR, VersionTuple(15, 0)}, + {PLATFORM_WATCHOS, VersionTuple(7, 0)}, + {PLATFORM_WATCHOSSIMULATOR, VersionTuple(8, 0)}, + {PLATFORM_XROS, VersionTuple(1, 0)}, + {PLATFORM_XROS_SIMULATOR, VersionTuple(1, 0)}, + }}; + return greaterEqMinVersion(minVersion, false); } static bool shouldEmitRelativeMethodLists(const InputArgList &args) { @@ -1140,12 +1144,20 @@ static bool shouldEmitRelativeMethodLists(const InputArgList &args) { if (arg && arg->getOption().getID() == OPT_no_objc_relative_method_lists) return false; - // TODO: If no flag is specified, don't default to false, but instead: - // - default false on < ios14 - // - default true on >= ios14 - // For now, until this feature is confirmed stable, default to false if no - // flag is explicitly specified - return false; + // If no flag is specified, enable this on newer versions by default. + // The min versions is taken from + // ld64(https://github.com/apple-oss-distributions/ld64/blob/47f477cb721755419018f7530038b272e9d0cdea/src/ld/ld.hpp#L310) + // to mimic to operation of ld64 + // [here](https://github.com/apple-oss-distributions/ld64/blob/47f477cb721755419018f7530038b272e9d0cdea/src/ld/Options.cpp#L6085-L6101) + static const MinVersions<6> minVersion = {{ + {PLATFORM_MACOS, VersionTuple(10, 16)}, + {PLATFORM_IOS, VersionTuple(14, 0)}, + {PLATFORM_WATCHOS, VersionTuple(7, 0)}, + {PLATFORM_TVOS, VersionTuple(14, 0)}, + {PLATFORM_BRIDGEOS, VersionTuple(5, 0)}, + {PLATFORM_XROS, VersionTuple(1, 0)}, + }}; + return greaterEqMinVersion(minVersion, true); } void SymbolPatterns::clear() { diff --git a/lld/test/MachO/objc-category-conflicts.s b/lld/test/MachO/objc-category-conflicts.s index eb4c0adfd9e934..e64a9eedcde136 100644 --- a/lld/test/MachO/objc-category-conflicts.s +++ b/lld/test/MachO/objc-category-conflicts.s @@ -1,3 +1,6 @@ +# `-no_objc_relative_method_lists` needs to be explicitly added to this test to avoid crashing after `-objc_relative_method_lists` was made default. +# TODO: Make this test compatible with default `-objc_relative_method_lists` and remove the `-no_objc_relative_method_lists` flag. Issue #101419 + # REQUIRES: x86 # RUN: rm -rf %t; split-file %s %t # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s -o %t/cat1.o @@ -10,31 +13,31 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s --defsym MAKE_LOAD_METHOD=1 -o %t/cat2-with-load.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s --defsym MAKE_LOAD_METHOD=1 -o %t/klass-with-load.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass-with-no-rodata.s -o %t/klass-with-no-rodata.o -# RUN: %lld -dylib -lobjc %t/klass.o -o %t/libklass.dylib +# RUN: %lld -no_objc_relative_method_lists -dylib -lobjc %t/klass.o -o %t/libklass.dylib -# RUN: %no-fatal-warnings-lld --check-category-conflicts -dylib -lobjc %t/klass.o %t/cat1.o %t/cat2.o -o \ +# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass.o %t/cat1.o %t/cat2.o -o \ # RUN: /dev/null 2>&1 | FileCheck %s --check-prefixes=CATCLS,CATCAT -# RUN: %no-fatal-warnings-lld --check-category-conflicts -dylib -lobjc %t/libklass.dylib %t/cat1.o \ +# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/libklass.dylib %t/cat1.o \ # RUN: %t/cat2.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CATCAT -# RUN: %no-fatal-warnings-lld --check-category-conflicts -dylib -lobjc %t/klass_w_sym.o %t/cat1_w_sym.o %t/cat2_w_sym.o -o \ +# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass_w_sym.o %t/cat1_w_sym.o %t/cat2_w_sym.o -o \ # RUN: /dev/null 2>&1 | FileCheck %s --check-prefixes=CATCLS_W_SYM,CATCAT_W_SYM -# RUN: %no-fatal-warnings-lld --check-category-conflicts -dylib -lobjc %t/libklass.dylib %t/cat1_w_sym.o \ +# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/libklass.dylib %t/cat1_w_sym.o \ # RUN: %t/cat2_w_sym.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CATCAT_W_SYM ## Check that we don't emit spurious warnings around the +load method while ## still emitting the other warnings. Note that we have made separate ## `*-with-load.s` files for ease of comparison with ld64; ld64 will not warn ## at all if multiple +load methods are present. -# RUN: %no-fatal-warnings-lld --check-category-conflicts -dylib -lobjc %t/klass-with-load.o \ +# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass-with-load.o \ # RUN: %t/cat1-with-load.o %t/cat2-with-load.o -o /dev/null 2>&1 | \ # RUN: FileCheck %s --check-prefixes=CATCLS,CATCAT --implicit-check-not '+load' ## Regression test: Check that we don't crash. -# RUN: %no-fatal-warnings-lld --check-category-conflicts -dylib -lobjc %t/klass-with-no-rodata.o -o /dev/null +# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists --check-category-conflicts -dylib -lobjc %t/klass-with-no-rodata.o -o /dev/null ## Check that we don't emit any warnings without --check-category-conflicts. -# RUN: %no-fatal-warnings-lld -dylib -lobjc %t/klass.o %t/cat1.o %t/cat2.o -o \ +# RUN: %no-fatal-warnings-lld -no_objc_relative_method_lists -dylib -lobjc %t/klass.o %t/cat1.o %t/cat2.o -o \ # RUN: /dev/null 2>&1 | FileCheck %s --implicit-check-not 'warning' --allow-empty # CATCLS: warning: method '+s1' has conflicting definitions: diff --git a/lld/test/MachO/objc-category-merging-complete-test.s b/lld/test/MachO/objc-category-merging-complete-test.s index cb112073eb8710..95b80967fdcb3a 100644 --- a/lld/test/MachO/objc-category-merging-complete-test.s +++ b/lld/test/MachO/objc-category-merging-complete-test.s @@ -1,3 +1,6 @@ +# `-no_objc_relative_method_lists` needs to be explicitly added to this test to avoid crashing after `-objc_relative_method_lists` was made default. +# TODO: Make this test compatible with default `-objc_relative_method_lists` and remove the `-no_objc_relative_method_lists` flag. Issue #101419 + # REQUIRES: aarch64 # RUN: rm -rf %t; split-file %s %t && cd %t @@ -7,10 +10,10 @@ # RUN: %lld -arch arm64 a64_file1.o -o a64_file1.dylib -dylib # RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o a64_file2.o a64_file2.s -# RUN: %lld -arch arm64 -o a64_file2_no_merge.exe a64_file1.dylib a64_file2.o -# RUN: %lld -arch arm64 -o a64_file2_no_merge_v2.exe a64_file1.dylib a64_file2.o -no_objc_category_merging -# RUN: %lld -arch arm64 -o a64_file2_no_merge_v3.exe a64_file1.dylib a64_file2.o -objc_category_merging -no_objc_category_merging -# RUN: %lld -arch arm64 -o a64_file2_merge.exe -objc_category_merging a64_file1.dylib a64_file2.o +# RUN: %lld -no_objc_relative_method_lists -arch arm64 -o a64_file2_no_merge.exe a64_file1.dylib a64_file2.o +# RUN: %lld -no_objc_relative_method_lists -arch arm64 -o a64_file2_no_merge_v2.exe a64_file1.dylib a64_file2.o -no_objc_category_merging +# RUN: %lld -no_objc_relative_method_lists -arch arm64 -o a64_file2_no_merge_v3.exe a64_file1.dylib a64_file2.o -objc_category_merging -no_objc_category_merging +# RUN: %lld -no_objc_relative_method_lists -arch arm64 -o a64_file2_merge.exe -objc_category_merging a64_file1.dylib a64_file2.o # RUN: llvm-objdump --objc-meta-data --macho a64_file2_no_merge.exe | FileCheck %s --check-prefixes=NO_MERGE_CATS # RUN: llvm-objdump --objc-meta-data --macho a64_file2_no_merge_v2.exe | FileCheck %s --check-prefixes=NO_MERGE_CATS @@ -18,7 +21,7 @@ # RUN: llvm-objdump --objc-meta-data --macho a64_file2_merge.exe | FileCheck %s --check-prefixes=MERGE_CATS ############ Test merging multiple categories into the base class ############ -# RUN: %lld -arch arm64 -o a64_file2_merge_into_class.exe -objc_category_merging a64_file1.o a64_file2.o +# RUN: %lld -no_objc_relative_method_lists -arch arm64 -o a64_file2_merge_into_class.exe -objc_category_merging a64_file1.o a64_file2.o # RUN: llvm-objdump --objc-meta-data --macho a64_file2_merge_into_class.exe | FileCheck %s --check-prefixes=MERGE_CATS_CLS diff --git a/lld/test/MachO/objc-category-merging-erase-objc-name-test.s b/lld/test/MachO/objc-category-merging-erase-objc-name-test.s index aeb2395b3a8580..869632da34b21c 100644 --- a/lld/test/MachO/objc-category-merging-erase-objc-name-test.s +++ b/lld/test/MachO/objc-category-merging-erase-objc-name-test.s @@ -1,3 +1,6 @@ +# `-no_objc_relative_method_lists` needs to be explicitly added to this test to avoid crashing after `-objc_relative_method_lists` was made default. +# TODO: Make this test compatible with default `-objc_relative_method_lists` and remove the `-no_objc_relative_method_lists` flag. Issue #101419 + ; REQUIRES: aarch64 ; Here we test that if we defined a protocol MyTestProtocol and also a category MyTestProtocol @@ -5,7 +8,7 @@ ; delete the 'MyTestProtocol' name ; RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o %T/erase-objc-name.o %s -; RUN: %lld -arch arm64 -dylib -o %T/erase-objc-name.dylib %T/erase-objc-name.o -objc_category_merging +; RUN: %lld -no_objc_relative_method_lists -arch arm64 -dylib -o %T/erase-objc-name.dylib %T/erase-objc-name.o -objc_category_merging ; RUN: llvm-objdump --objc-meta-data --macho %T/erase-objc-name.dylib | FileCheck %s --check-prefixes=MERGE_CATS ; === Check merge categories enabled === diff --git a/lld/test/MachO/objc-category-merging-minimal.s b/lld/test/MachO/objc-category-merging-minimal.s index 527493303c583e..5cfe5e03def730 100644 --- a/lld/test/MachO/objc-category-merging-minimal.s +++ b/lld/test/MachO/objc-category-merging-minimal.s @@ -1,3 +1,6 @@ +# `-no_objc_relative_method_lists` needs to be explicitly added to this test to avoid crashing after `-objc_relative_method_lists` was made default. +# TODO: Make this test compatible with default `-objc_relative_method_lists` and remove the `-no_objc_relative_method_lists` flag. Issue #101419 + # REQUIRES: aarch64 # RUN: rm -rf %t; split-file %s %t && cd %t @@ -9,7 +12,7 @@ ## Create our main testing dylib - linking against the fake dylib above # RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o merge_cat_minimal.o merge_cat_minimal.s # RUN: %lld -arch arm64 -dylib -o merge_cat_minimal_no_merge.dylib a64_fakedylib.dylib merge_cat_minimal.o -# RUN: %lld -arch arm64 -dylib -o merge_cat_minimal_merge.dylib -objc_category_merging a64_fakedylib.dylib merge_cat_minimal.o +# RUN: %lld -no_objc_relative_method_lists -arch arm64 -dylib -o merge_cat_minimal_merge.dylib -objc_category_merging a64_fakedylib.dylib merge_cat_minimal.o ## Now verify that the flag caused category merging to happen appropriatelly # RUN: llvm-objdump --objc-meta-data --macho merge_cat_minimal_no_merge.dylib | FileCheck %s --check-prefixes=NO_MERGE_CATS @@ -17,7 +20,7 @@ ############ Test merging multiple categories into the base class ############ # RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o merge_base_class_minimal.o merge_base_class_minimal.s -# RUN: %lld -arch arm64 -dylib -o merge_base_class_minimal_yes_merge.dylib -objc_category_merging merge_base_class_minimal.o merge_cat_minimal.o +# RUN: %lld -no_objc_relative_method_lists -arch arm64 -dylib -o merge_base_class_minimal_yes_merge.dylib -objc_category_merging merge_base_class_minimal.o merge_cat_minimal.o # RUN: %lld -arch arm64 -dylib -o merge_base_class_minimal_no_merge.dylib merge_base_class_minimal.o merge_cat_minimal.o # RUN: llvm-objdump --objc-meta-data --macho merge_base_class_minimal_no_merge.dylib | FileCheck %s --check-prefixes=NO_MERGE_INTO_BASE @@ -25,7 +28,7 @@ ############ Test merging swift category into the base class ############ # RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o MyBaseClassSwiftExtension.o MyBaseClassSwiftExtension.s -# RUN: %lld -arch arm64 -dylib -o merge_base_class_swift_minimal_yes_merge.dylib -objc_category_merging MyBaseClassSwiftExtension.o merge_base_class_minimal.o +# RUN: %lld -no_objc_relative_method_lists -arch arm64 -dylib -o merge_base_class_swift_minimal_yes_merge.dylib -objc_category_merging MyBaseClassSwiftExtension.o merge_base_class_minimal.o # RUN: llvm-objdump --objc-meta-data --macho merge_base_class_swift_minimal_yes_merge.dylib | FileCheck %s --check-prefixes=YES_MERGE_INTO_BASE_SWIFT #### Check merge categories enabled ### diff --git a/lld/test/MachO/objc-relative-method-lists-simple.s b/lld/test/MachO/objc-relative-method-lists-simple.s index 9f54b5ad828a07..c8646f59603b3f 100644 --- a/lld/test/MachO/objc-relative-method-lists-simple.s +++ b/lld/test/MachO/objc-relative-method-lists-simple.s @@ -3,20 +3,28 @@ # RUN: rm -rf %t; split-file %s %t && cd %t ## Compile a64_rel_dylib.o -# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos -o a64_rel_dylib.o a64_simple_class.s +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macos10.15 -o a64_rel_dylib.o a64_simple_class.s ## Test arm64 + relative method lists -# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -objc_relative_method_lists +# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 # RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_REL ## Test arm64 + relative method lists + dead-strip -# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -objc_relative_method_lists -dead_strip +# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -dead_strip # RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_REL ## Test arm64 + traditional method lists (no relative offsets) # RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -no_objc_relative_method_lists # RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_NO_REL +## Test arm64 + relative method lists by explicitly adding `-objc_relative_method_lists`. +# RUN: %lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -platform_version macOS 10.15 10.15 -objc_relative_method_lists +# RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_REL + +## Test arm64 + no relative method lists by default. +# RUN: %lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -platform_version macOS 10.15 10.15 +# RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_NO_REL + CHK_REL: Contents of (__DATA_CONST,__objc_classlist) section CHK_REL-NEXT: _OBJC_CLASS_$_MyClass @@ -125,7 +133,7 @@ CHK_NO_REL-NEXT: imp +[MyClass class_method_02] .include "objc-macros.s" .section __TEXT,__text,regular,pure_instructions -.build_version macos, 11, 0 +.build_version macos, 10, 15 .objc_selector_def "-[MyClass instance_method_00]" .objc_selector_def "-[MyClass instance_method_01]"