From 47f9722c32be4b05a7b958a945d86d408607092d Mon Sep 17 00:00:00 2001 From: Keith Smiley Date: Sat, 8 Oct 2022 21:28:02 -0700 Subject: [PATCH] [lld-macho] Add --ignore-auto-link-option This provides a workaround for a small difference in ld64 behavior where ld64 ignores invalid LC_LINKER_OPTIONS unless the link fails. Instead of fully adopting that behavior, this provides an escape hatch by allowing users to specify `--ignore-auto-link-option` passing the invalid library or framework name Fixes https://github.com/llvm/llvm-project/issues/56939 Differential Revision: https://reviews.llvm.org/D135530 --- lld/MachO/Config.h | 5 +++++ lld/MachO/Driver.cpp | 6 ++++++ lld/MachO/Options.td | 6 ++++++ lld/test/MachO/lc-linker-option.ll | 2 ++ 4 files changed, 19 insertions(+) diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h index 3d5f4cb..fff740e 100644 --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -169,6 +169,11 @@ struct Configuration { bool deadStrip = false; bool errorForArchMismatch = false; bool ignoreAutoLink = false; + // ld64 allows invalid auto link options as long as the link succeeds. LLD + // does not, but there are cases in the wild where the invalid linker options + // exist. This allows users to ignore the specific invalid options in the case + // they can't easily fix them. + llvm::StringSet<> ignoreAutoLinkOptions; PlatformInfo platformInfo; llvm::Optional secondaryPlatformInfo; NamespaceKind namespaceKind = NamespaceKind::twolevel; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index 29472f2..8ef2a36 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -478,11 +478,15 @@ void macho::parseLCLinkerOption(InputFile *f, unsigned argc, StringRef data) { unsigned i = 0; StringRef arg = argv[i]; if (arg.consume_front("-l")) { + if (config->ignoreAutoLinkOptions.contains(arg)) + return; addLibrary(arg, /*isNeeded=*/false, /*isWeak=*/false, /*isReexport=*/false, /*isHidden=*/false, /*isExplicit=*/false, LoadType::LCLinkerOption); } else if (arg == "-framework") { StringRef name = argv[++i]; + if (config->ignoreAutoLinkOptions.contains(name)) + return; addFramework(name, /*isNeeded=*/false, /*isWeak=*/false, /*isReexport=*/false, /*isExplicit=*/false, LoadType::LCLinkerOption); @@ -1543,6 +1547,8 @@ bool macho::link(ArrayRef argsArr, llvm::raw_ostream &stdoutOS, getenv("LD_DYLIB_CPU_SUBTYPES_MUST_MATCH"); config->objcStubsMode = getObjCStubsMode(args); config->ignoreAutoLink = args.hasArg(OPT_ignore_auto_link); + for (const Arg *arg : args.filtered(OPT_ignore_auto_link_option)) + config->ignoreAutoLinkOptions.insert(arg->getValue()); for (const Arg *arg : args.filtered(OPT_alias)) { config->aliasedSymbols.push_back( diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td index fda7ae3..2871091 100644 --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -95,6 +95,12 @@ def no_call_graph_profile_sort : Flag<["--"], "no-call-graph-profile-sort">, def print_symbol_order_eq: Joined<["--"], "print-symbol-order=">, HelpText<"Print a symbol order specified by --call-graph-profile-sort into the specified file">, Group; +def ignore_auto_link_option : Separate<["--"], "ignore-auto-link-option">, + Group; +def ignore_auto_link_option_eq : Joined<["--"], "ignore-auto-link-option=">, + Alias(ignore_auto_link_option)>, + HelpText<"Ignore a single auto-linked library or framework. Useful to ignore invalid options that ld64 ignores">, + Group; // This is a complete Options.td compiled from Apple's ld(1) manpage // dated 2018-03-07 and cross checked with ld64 source code in repo diff --git a/lld/test/MachO/lc-linker-option.ll b/lld/test/MachO/lc-linker-option.ll index 48dd5b9..f7060e0 100644 --- a/lld/test/MachO/lc-linker-option.ll +++ b/lld/test/MachO/lc-linker-option.ll @@ -13,6 +13,8 @@ ; FRAME-NEXT: name /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation ; RUN: not %lld %t/framework.o -o %t/frame_no_autolink -ignore_auto_link 2>&1 | FileCheck --check-prefix=NO_AUTOLINK %s +; RUN: not %lld %t/framework.o -o %t/frame_no_autolink --ignore-auto-link-option CoreFoundation 2>&1 | FileCheck --check-prefix=NO_AUTOLINK %s +; RUN: not %lld %t/framework.o -o %t/frame_no_autolink --ignore-auto-link-option=CoreFoundation 2>&1 | FileCheck --check-prefix=NO_AUTOLINK %s ; NO_AUTOLINK: error: undefined symbol: __CFBigNumGetInt128 ; RUN: llvm-as %t/l.ll -o %t/l.o -- 2.7.4