Skip to content

Commit

Permalink
[lld] enable fixup chains by default (llvm#79894)
Browse files Browse the repository at this point in the history
Enable chained fixups in lld when all platform and version criteria are
met. This is an attempt at simplifying the logic used in ld 907:

https://github.com/apple-oss-distributions/ld64/blob/93d74eafc37c0558b4ffb88a8bc15c17bed44a20/src/ld/Options.cpp#L5458-L5549

Some changes were made to simplify the logic:
- only enable chained fixups for macOS from 13.0 to avoid the arch check
- only enable chained fixups for iphonesimulator from 16.0 to avoid the
arch check
- don't enable chained fixups for not specifically listed platforms
- don't enable chained fixups for arm64_32
  • Loading branch information
rmaz committed Jan 31, 2024
1 parent 151559c commit 775c285
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 44 deletions.
61 changes: 37 additions & 24 deletions lld/MachO/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/TimeProfiler.h"
#include "llvm/TargetParser/Host.h"
#include "llvm/TextAPI/Architecture.h"
#include "llvm/TextAPI/PackedVersion.h"

#include <algorithm>
Expand Down Expand Up @@ -1042,41 +1043,53 @@ static bool shouldEmitChainedFixups(const InputArgList &args) {
if (arg && arg->getOption().matches(OPT_no_fixup_chains))
return false;

bool isRequested = arg != nullptr;

// Version numbers taken from the Xcode 13.3 release notes.
static const std::array<std::pair<PlatformType, VersionTuple>, 4> minVersion =
{{{PLATFORM_MACOS, VersionTuple(11, 0)},
{PLATFORM_IOS, VersionTuple(13, 4)},
{PLATFORM_TVOS, VersionTuple(14, 0)},
{PLATFORM_WATCHOS, VersionTuple(7, 0)}}};
PlatformType platform = removeSimulator(config->platformInfo.target.Platform);
auto it = llvm::find_if(minVersion,
[&](const auto &p) { return p.first == platform; });
if (it != minVersion.end() &&
it->second > config->platformInfo.target.MinDeployment) {
if (!isRequested)
return false;
bool requested = arg && arg->getOption().matches(OPT_fixup_chains);
if (!config->isPic) {
if (requested)
error("-fixup_chains is incompatible with -no_pie");

warn("-fixup_chains requires " + getPlatformName(config->platform()) + " " +
it->second.getAsString() + ", which is newer than target minimum of " +
config->platformInfo.target.MinDeployment.getAsString());
return false;
}

if (!is_contained({AK_x86_64, AK_x86_64h, AK_arm64}, config->arch())) {
if (isRequested)
if (requested)
error("-fixup_chains is only supported on x86_64 and arm64 targets");

return false;
}

if (!config->isPic) {
if (isRequested)
error("-fixup_chains is incompatible with -no_pie");
if (args.hasArg(OPT_preload)) {
if (requested)
error("-fixup_chains is incompatible with -preload");

return false;
}

// TODO: Enable by default once stable.
return isRequested;
if (requested)
return true;

static const std::array<std::pair<PlatformType, VersionTuple>, 7> 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)},
}};
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;
}

void SymbolPatterns::clear() {
Expand Down
2 changes: 1 addition & 1 deletion lld/test/MachO/arm64-32-stubs.s
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-watchos %t/test.s -o %t/test.o
# RUN: %lld-watchos -dylib -install_name @executable_path/libfoo.dylib %t/foo.o -o %t/libfoo.dylib
# RUN: %lld-watchos -dylib -install_name @executable_path/libbar.dylib %t/bar.o -o %t/libbar.dylib
# RUN: %lld-watchos -lSystem %t/libfoo.dylib %t/libbar.dylib %t/test.o -o %t/test
# RUN: %lld-watchos -lSystem %t/libfoo.dylib %t/libbar.dylib %t/test.o -o %t/test -no_fixup_chains

# RUN: llvm-objdump --no-print-imm-hex --macho -d --no-show-raw-insn --section="__TEXT,__stubs" --section="__TEXT,__stub_helper" %t/test | FileCheck %s

Expand Down
2 changes: 1 addition & 1 deletion lld/test/MachO/arm64-stubs.s
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %t/test.s -o %t/test.o
# RUN: %lld -arch arm64 -dylib -install_name @executable_path/libfoo.dylib %t/foo.o -o %t/libfoo.dylib
# RUN: %lld -arch arm64 -dylib -install_name @executable_path/libbar.dylib %t/bar.o -o %t/libbar.dylib
# RUN: %lld -arch arm64 -lSystem %t/libfoo.dylib %t/libbar.dylib %t/test.o -o %t/test
# RUN: %lld -arch arm64 -lSystem %t/libfoo.dylib %t/libbar.dylib %t/test.o -o %t/test -no_fixup_chains

# RUN: llvm-objdump --no-print-imm-hex --macho -d --no-show-raw-insn --section="__TEXT,__stubs" --section="__TEXT,__stub_helper" %t/test | FileCheck %s

Expand Down
14 changes: 7 additions & 7 deletions lld/test/MachO/dyld-stub-binder.s
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,27 @@
# RUN: %lld -arch arm64 -lSystem -dylib %t/foo.o -o %t/libfoo.dylib
# RUN: llvm-nm -m %t/libfoo.dylib | FileCheck --check-prefix=STUB %s


## Dylibs that do lazy dynamic calls do need dyld_stub_binder.
# RUN: not %no-lsystem-lld -arch arm64 -dylib %t/bar.o %t/libfoo.dylib \
# RUN: -o %t/libbar.dylib 2>&1 | FileCheck --check-prefix=MISSINGSTUB %s
# RUN: -o %t/libbar.dylib -no_fixup_chains 2>&1 | \
# RUN: FileCheck --check-prefix=MISSINGSTUB %s
# RUN: %lld -arch arm64 -lSystem -dylib %t/bar.o %t/libfoo.dylib \
# RUN: -o %t/libbar.dylib
# RUN: -o %t/libbar.dylib -no_fixup_chains
# RUN: llvm-nm -m %t/libbar.dylib | FileCheck --check-prefix=STUB %s

## As do executables.
# RUN: not %no-lsystem-lld -arch arm64 %t/libfoo.dylib %t/libbar.dylib %t/test.o \
# RUN: -o %t/test 2>&1 | FileCheck --check-prefix=MISSINGSTUB %s
# RUN: -o %t/test -no_fixup_chains 2>&1 | FileCheck --check-prefix=MISSINGSTUB %s
# RUN: %lld -arch arm64 -lSystem %t/libfoo.dylib %t/libbar.dylib %t/test.o \
# RUN: -o %t/test
# RUN: -o %t/test -no_fixup_chains
# RUN: llvm-nm -m %t/test | FileCheck --check-prefix=STUB %s

## Test dynamic lookup of dyld_stub_binder.
# RUN: %no-lsystem-lld -arch arm64 %t/libfoo.dylib %t/libbar.dylib %t/test.o \
# RUN: -o %t/test -undefined dynamic_lookup
# RUN: -o %t/test -undefined dynamic_lookup -no_fixup_chains
# RUN: llvm-nm -m %t/test | FileCheck --check-prefix=DYNSTUB %s
# RUN: %no-lsystem-lld -arch arm64 %t/libfoo.dylib %t/libbar.dylib %t/test.o \
# RUN: -o %t/test -U dyld_stub_binder
# RUN: -o %t/test -U dyld_stub_binder -no_fixup_chains
# RUN: llvm-nm -m %t/test | FileCheck --check-prefix=DYNSTUB %s

# MISSINGSTUB: error: undefined symbol: dyld_stub_binder
Expand Down
8 changes: 4 additions & 4 deletions lld/test/MachO/icf-safe.ll
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
; RUN: rm -rf %t; mkdir %t

; RUN: llc -filetype=obj %s -O3 -o %t/icf-obj.o -enable-machine-outliner=never -mtriple arm64-apple-macos -addrsig
; RUN: %lld -arch arm64 -lSystem --icf=safe -dylib -o %t/icf-safe.dylib %t/icf-obj.o
; RUN: %lld -arch arm64 -lSystem --icf=all -dylib -o %t/icf-all.dylib %t/icf-obj.o
; RUN: %lld -arch arm64 -lSystem --icf=safe -dylib -o %t/icf-safe.dylib %t/icf-obj.o -no_fixup_chains
; RUN: %lld -arch arm64 -lSystem --icf=all -dylib -o %t/icf-all.dylib %t/icf-obj.o -no_fixup_chains
; RUN: llvm-objdump %t/icf-safe.dylib -d --macho | FileCheck %s --check-prefix=ICFSAFE
; RUN: llvm-objdump %t/icf-all.dylib -d --macho | FileCheck %s --check-prefix=ICFALL

; RUN: llvm-as %s -o %t/icf-bitcode.o
; RUN: %lld -arch arm64 -lSystem --icf=safe -dylib -o %t/icf-safe-bitcode.dylib %t/icf-bitcode.o
; RUN: %lld -arch arm64 -lSystem --icf=all -dylib -o %t/icf-all-bitcode.dylib %t/icf-bitcode.o
; RUN: %lld -arch arm64 -lSystem --icf=safe -dylib -o %t/icf-safe-bitcode.dylib %t/icf-bitcode.o -no_fixup_chains
; RUN: %lld -arch arm64 -lSystem --icf=all -dylib -o %t/icf-all-bitcode.dylib %t/icf-bitcode.o -no_fixup_chains
; RUN: llvm-objdump %t/icf-safe-bitcode.dylib -d --macho | FileCheck %s --check-prefix=ICFSAFE
; RUN: llvm-objdump %t/icf-all-bitcode.dylib -d --macho | FileCheck %s --check-prefix=ICFALL

Expand Down
4 changes: 0 additions & 4 deletions lld/test/MachO/invalid/chained-fixups-incompatible.s
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,13 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
# RUN: not %lld -lSystem -no_pie -fixup_chains %t.o -o /dev/null 2>&1 | \
# RUN: FileCheck %s --check-prefix=NO-PIE
# RUN: %no-fatal-warnings-lld -fixup_chains %t.o -o /dev/null \
# RUN: -lSystem -platform_version macos 10.15 10.15 2>&1 | \
# RUN: FileCheck %s --check-prefix=VERSION
# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-darwin %s -o %t-arm64_32.o
# RUN: not %lld-watchos -lSystem -fixup_chains %t-arm64_32.o -o /dev/null 2>&1 | \
# RUN: FileCheck %s --check-prefix=ARCH

## Check that we emit diagnostics when -fixup_chains is explicitly specified,
## but we don't support creating chained fixups for said configuration.
# NO-PIE: error: -fixup_chains is incompatible with -no_pie
# VERSION: warning: -fixup_chains requires macOS 11.0, which is newer than target minimum of 10.15
# ARCH: error: -fixup_chains is only supported on x86_64 and arm64 targets

.globl _main
Expand Down
7 changes: 4 additions & 3 deletions lld/test/MachO/objc-selrefs.s
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
# RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %t/implicit-selrefs.s -o %t/implicit-selrefs.o

# RUN: %lld -dylib -arch arm64 -lSystem -o %t/explicit-only-no-icf \
# RUN: %t/explicit-selrefs-1.o %t/explicit-selrefs-2.o
# RUN: %t/explicit-selrefs-1.o %t/explicit-selrefs-2.o -no_fixup_chains
# RUN: llvm-otool -vs __DATA __objc_selrefs %t/explicit-only-no-icf | \
# RUN: FileCheck %s --check-prefix=EXPLICIT-NO-ICF

## NOTE: ld64 always dedups the selrefs unconditionally, but we only do it when
## ICF is enabled.
# RUN: %lld -dylib -arch arm64 -lSystem -o %t/explicit-only-with-icf \
# RUN: %t/explicit-selrefs-1.o %t/explicit-selrefs-2.o
# RUN: %t/explicit-selrefs-1.o %t/explicit-selrefs-2.o -no_fixup_chains
# RUN: llvm-otool -vs __DATA __objc_selrefs %t/explicit-only-with-icf \
# RUN: | FileCheck %s --check-prefix=EXPLICIT-WITH-ICF

Expand All @@ -26,7 +26,8 @@

## We don't yet support dedup'ing implicitly-defined selrefs.
# RUN: %lld -dylib -arch arm64 -lSystem --icf=all -o %t/explicit-and-implicit \
# RUN: %t/explicit-selrefs-1.o %t/explicit-selrefs-2.o %t/implicit-selrefs.o
# RUN: %t/explicit-selrefs-1.o %t/explicit-selrefs-2.o %t/implicit-selrefs.o \
# RUN: -no_fixup_chains
# RUN: llvm-otool -vs __DATA __objc_selrefs %t/explicit-and-implicit \
# RUN: | FileCheck %s --check-prefix=EXPLICIT-AND-IMPLICIT

Expand Down

0 comments on commit 775c285

Please sign in to comment.