Index: lld/MachO/Config.h =================================================================== --- lld/MachO/Config.h +++ lld/MachO/Config.h @@ -96,6 +96,7 @@ bool hasReexports = false; bool allLoad = false; bool archMultiple = false; + bool exportDynamic = false; bool forceLoadObjC = false; bool forceLoadSwift = false; bool staticLink = false; Index: lld/MachO/Driver.cpp =================================================================== --- lld/MachO/Driver.cpp +++ lld/MachO/Driver.cpp @@ -525,6 +525,14 @@ } static void compileBitcodeFiles() { + // FIXME: Remove this once LTO.cpp honors config->exportDynamic. + if (config->exportDynamic) + for (InputFile *file : inputFiles) + if (auto *bitcodeFile = dyn_cast(file)) { + warn("the effect of -export_dynamic on LTO is not yet implemented"); + break; + } + TimeTraceScope timeScope("LTO"); auto *lto = make(); for (InputFile *file : inputFiles) @@ -1140,6 +1148,7 @@ config->runtimePaths = args::getStrings(args, OPT_rpath); config->allLoad = args.hasArg(OPT_all_load); config->archMultiple = args.hasArg(OPT_arch_multiple); + config->exportDynamic = args.hasArg(OPT_export_dynamic); config->forceLoadObjC = args.hasArg(OPT_ObjC); config->forceLoadSwift = args.hasArg(OPT_force_load_swift_libs); config->deadStripDylibs = args.hasArg(OPT_dead_strip_dylibs); Index: lld/MachO/LTO.cpp =================================================================== --- lld/MachO/LTO.cpp +++ lld/MachO/LTO.cpp @@ -76,6 +76,7 @@ // FIXME: What about other output types? And we can probably be less // restrictive with -flat_namespace, but it's an infrequent use case. + // FIXME: Honor config->exportDynamic. r.VisibleToRegularObj = config->outputType != MH_EXECUTE || config->namespaceKind == NamespaceKind::flat || sym->isUsedInRegularObj; Index: lld/MachO/MarkLive.cpp =================================================================== --- lld/MachO/MarkLive.cpp +++ lld/MachO/MarkLive.cpp @@ -79,9 +79,11 @@ // * -alias(-list) // * -init - // In dylibs and bundles, all external functions are GC roots. - // FIXME: -export_dynamic should enable this for executables too. - if (config->outputType != MH_EXECUTE && !defined->privateExtern) { + // In dylibs and bundles and in executables with -export_dynamic, + // all external functions are GC roots. + bool externsAreRoots = + config->outputType != MH_EXECUTE || config->exportDynamic; + if (externsAreRoots && !defined->privateExtern) { addSym(defined); continue; } Index: lld/MachO/Options.td =================================================================== --- lld/MachO/Options.td +++ lld/MachO/Options.td @@ -424,8 +424,7 @@ Flags<[HelpHidden]>, Group; def export_dynamic : Flag<["-"], "export_dynamic">, - HelpText<"Preserve all global symbols during LTO">, - Flags<[HelpHidden]>, + HelpText<"Preserve all global symbols during LTO and when dead-stripping executables">, Group; def grp_bundle : OptionGroup<"bundle">, HelpText<"CREATING A BUNDLE">; Index: lld/test/MachO/dead-strip.s =================================================================== --- lld/test/MachO/dead-strip.s +++ lld/test/MachO/dead-strip.s @@ -65,6 +65,32 @@ # DYLIB-NEXT: g {{.*}} _unref_extern # DYLIB-NEXT: g {{.*}} _no_dead_strip_globl +## Extern symbols aren't stripped from executables with -export_dynamic +# RUN: ld -lSystem -dead_strip -export_dynamic -u _ref_private_extern_u \ +# RUN: %t/basics.o -o %t/basics +# RUN: llvm-objdump --syms --section-headers %t/basics | \ +# RUN: FileCheck --check-prefix=EXECDYN %s +# EXECDYN-LABEL: Sections: +# EXECDYN-LABEL: Name +# EXECDYN-NEXT: __text +# EXECDYN-NEXT: __got +# EXECDYN-NEXT: __ref_section +# EXECDYN-NEXT: __common +# EXECDYN-LABEL: SYMBOL TABLE: +# EXECDYN-NEXT: l {{.*}} _ref_data +# EXECDYN-NEXT: l {{.*}} _ref_local +# EXECDYN-NEXT: l {{.*}} _ref_from_no_dead_strip_globl +# EXECDYN-NEXT: l {{.*}} _no_dead_strip_local +# EXECDYN-NEXT: l {{.*}} _ref_from_no_dead_strip_local +# EXECDYN-NEXT: l {{.*}} _ref_private_extern_u +# EXECDYN-NEXT: l {{.*}} _main +# EXECDYN-NEXT: l {{.*}} _ref_private_extern +# EXECDYN-NEXT: g {{.*}} _ref_com +# EXECDYN-NEXT: g {{.*}} _unref_com +# EXECDYN-NEXT: g {{.*}} _unref_extern +# EXECDYN-NEXT: g {{.*}} _no_dead_strip_globl +# EXECDYN-NEXT: g {{.*}} __mh_execute_header + ## Absolute symbol handling. # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos \ # RUN: %t/abs.s -o %t/abs.o