diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -68,6 +68,7 @@ std::vector librarySearchPaths; std::vector frameworkSearchPaths; std::vector runtimePaths; + std::vector explicitUndefineds; llvm::DenseMap priorities; }; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -734,6 +734,10 @@ config->entry = symtab->addUndefined(args.getLastArgValue(OPT_e, "_main"), /*file=*/nullptr, /*isWeakRef=*/false); + for (auto *arg : args.filtered(OPT_u)) { + config->explicitUndefineds.push_back(symtab->addUndefined( + arg->getValue(), /*file=*/nullptr, /*isWeakRef=*/false)); + } config->outputFile = args.getLastArgValue(OPT_o, "a.out"); config->installName = args.getLastArgValue(OPT_install_name, config->outputFile); @@ -864,6 +868,15 @@ error("undefined symbol: " + toString(*config->entry)); return false; } + // FIXME: This prints symbols that are undefined both in input files and + // via -u flag twice. + for (const auto *undefined : config->explicitUndefineds) { + if (isa(undefined)) { + error("undefined symbol: " + toString(*undefined) + + "\n>>> referenced by flag -u " + toString(*undefined)); + return false; + } + } createSyntheticSections(); symtab->addDSOHandle(in.header); diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -454,7 +454,6 @@ def u : Separate<["-"], "u">, MetaVarName<"">, HelpText<"Require that be defined for the link to succeed">, - Flags<[HelpHidden]>, Group; def U : Separate<["-"], "U">, MetaVarName<"">, diff --git a/lld/test/MachO/u.s b/lld/test/MachO/u.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/u.s @@ -0,0 +1,32 @@ +# REQUIRES: x86 +# RUN: rm -rf %t +# RUN: split-file %s %t + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/foo.o %t/foo.s +# RUN: llvm-ar csr %t/lib.a %t/foo.o + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t/main.o %t/main.s + +# RUN: %lld %t/main.o %t/lib.a -o /dev/null -why_load | \ +# RUN: FileCheck %s --check-prefix=NOFOO --allow-empty + +# RUN: %lld %t/main.o %t/lib.a -u _foo -o /dev/null -why_load | \ +# RUN: FileCheck %s --check-prefix=FOO + +# RUN: not %lld %t/main.o %t/lib.a -u _asdf -o /dev/null 2>&1 | \ +# RUN: FileCheck %s --check-prefix=UNDEF + +# NOFOO-NOT: _foo forced load of lib.a(foo.o) +# FOO: _foo forced load of lib.a(foo.o) +# UNDEF: error: undefined symbol: _asdf + +#--- foo.s +.globl _foo +_foo: + ret + +#--- main.s +.globl _main +_main: + ret +