diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -185,6 +185,7 @@ SectionRenameMap sectionRenameMap; SegmentRenameMap segmentRenameMap; + bool hasExplicitExports = false; SymbolPatterns exportedSymbols; SymbolPatterns unexportedSymbols; SymbolPatterns whyLive; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1403,15 +1403,18 @@ config->segmentProtections.push_back({segName, maxProt, initProt}); } + config->hasExplicitExports = + args.hasArg(OPT_no_exported_symbols) || + args.hasArgNoClaim(OPT_exported_symbol, OPT_exported_symbols_list); handleSymbolPatterns(args, config->exportedSymbols, OPT_exported_symbol, OPT_exported_symbols_list); handleSymbolPatterns(args, config->unexportedSymbols, OPT_unexported_symbol, OPT_unexported_symbols_list); - if (!config->exportedSymbols.empty() && !config->unexportedSymbols.empty()) { - error("cannot use both -exported_symbol* and -unexported_symbol* options\n" - ">>> ignoring unexports"); - config->unexportedSymbols.clear(); - } + if (config->hasExplicitExports && !config->unexportedSymbols.empty()) + error("cannot use both -exported_symbol* and -unexported_symbol* options"); + + if (args.hasArg(OPT_no_exported_symbols) && !config->exportedSymbols.empty()) + error("cannot use both -exported_symbol* and -no_exported_symbols options"); // Imitating LD64's: // -non_global_symbols_no_strip_list and -non_global_symbols_strip_list can't @@ -1555,7 +1558,7 @@ createSyntheticSections(); createSyntheticSymbols(); - if (!config->exportedSymbols.empty()) { + if (config->hasExplicitExports) { parallelForEach(symtab->getSymbols(), [](Symbol *sym) { if (auto *defined = dyn_cast(sym)) { StringRef symbolName = defined->getName(); diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -483,6 +483,9 @@ MetaVarName<"">, HelpText<"Symbols specified in remain global, while others become private externs">, Group; +def no_exported_symbols : Flag<["-"], "no_exported_symbols">, + HelpText<"Don't export any symbols from the binary, useful for main executables that don't have plugins">, + Group; def unexported_symbol : Separate<["-"], "unexported_symbol">, MetaVarName<"">, HelpText<"Global becomes private extern">, diff --git a/lld/test/MachO/export-options.s b/lld/test/MachO/export-options.s --- a/lld/test/MachO/export-options.s +++ b/lld/test/MachO/export-options.s @@ -9,9 +9,26 @@ # RUN: not %lld -dylib %t/default.o -o /dev/null \ # RUN: -exported_symbol a -unexported_symbol b 2>&1 | \ # RUN: FileCheck --check-prefix=CONFLICT %s +# +# RUN: not %lld -dylib %t/default.o -o /dev/null \ +# RUN: -exported_symbols_list /dev/null -unexported_symbol b 2>&1 | \ +# RUN: FileCheck --check-prefix=CONFLICT %s +# +# RUN: not %lld -dylib %t/default.o -o /dev/null \ +# RUN: -no_exported_symbols -unexported_symbol b 2>&1 | \ +# RUN: FileCheck --check-prefix=CONFLICT %s +# +# RUN: not %lld -dylib %t/default.o -o /dev/null \ +# RUN: -no_exported_symbols -exported_symbol b 2>&1 | \ +# RUN: FileCheck --check-prefix=CONFLICT-NO-EXPORTS %s +# +# RUN: not %lld -dylib %t/default.o -o /dev/null \ +# RUN: -no_exported_symbols -exported_symbols_list %t/literals.txt 2>&1 | \ +# RUN: FileCheck --check-prefix=CONFLICT-NO-EXPORTS %s # CONFLICT: error: cannot use both -exported_symbol* and -unexported_symbol* options -# CONFLICT-NEXT: >>> ignoring unexports + +# CONFLICT-NO-EXPORTS: error: cannot use both -exported_symbol* and -no_exported_symbols options ## Check that an exported literal name with no symbol definition yields an error ## but that an exported glob-pattern with no matching symbol definition is OK @@ -162,6 +179,17 @@ # AUTOHIDE-PRIVATE: error: cannot export hidden symbol _foo # AUTOHIDE-PRIVATE-DEAD-STRIP: (__TEXT,__text) non-external (was a private external) _foo +## Test not exporting any symbols +# RUN: %lld -dylib %t/symdefs.o -o %t/noexports -exported_symbols_list /dev/null +# RUN: llvm-objdump --macho --exports-trie %t/noexports | FileCheck --check-prefix=NOEXPORTS %s +# RUN: %lld -dylib %t/symdefs.o -o %t/noexports -no_exported_symbols +# RUN: llvm-objdump --macho --exports-trie %t/noexports | FileCheck --check-prefix=NOEXPORTS %s + +# NOEXPORTS-NOT: globby_also +# NOEXPORTS-NOT: globby_only +# NOEXPORTS-NOT: literal_also +# NOEXPORTS-NOT: literal_only + #--- default.s .globl _keep_globl, _hide_globl