diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -1059,6 +1059,12 @@ ">>> ignoring unexports"); config->unexportedSymbols.clear(); } + // Explicitly-exported literal symbols must be defined, but might + // languish in an archive if unreferenced elsewhere. Light a fire + // under those lazy symbols! + for (const CachedHashStringRef &cachedName : config->exportedSymbols.literals) + symtab->addUndefined(cachedName.val(), /*file=*/nullptr, + /*isWeakRef=*/false); config->saveTemps = args.hasArg(OPT_save_temps); @@ -1156,7 +1162,7 @@ if (const Symbol *sym = symtab->find(cachedName)) if (isa(sym)) continue; - error("undefined symbol " + cachedName.val() + + error("undefined symbol: " + cachedName.val() + "\n>>> referenced from option -exported_symbol(s_list)"); } 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 @@ -1,7 +1,9 @@ # REQUIRES: x86 -# RUN: split-file %s %t +# RUN: rm -rf %t; split-file %s %t # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos %t/default.s -o %t/default.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos %t/lazydef.s -o %t/lazydef.o +# RUN: llvm-ar --format=darwin rcs %t/lazydef.a %t/lazydef.o ## Check that mixing exported and unexported symbol options yields an error # RUN: not %lld -dylib %t/default.o -o /dev/null \ @@ -11,16 +13,28 @@ # CONFLICT: error: cannot use both -exported_symbol* and -unexported_symbol* options # CONFLICT-NEXT: >>> ignoring unexports -## Check that exported literal symbol name is present in symbol table +## 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 # RUN: not %lld -dylib %t/default.o -o /dev/null \ # RUN: -exported_symbol absent_literal \ # RUN: -exported_symbol absent_gl?b 2>&1 | \ # RUN: FileCheck --check-prefix=UNDEF %s -# UNDEF: error: undefined symbol absent_literal +# UNDEF: error: undefined symbol: absent_literal # UNDEF-NEXT: >>> referenced from option -exported_symbol(s_list) # UNDEF-NOT: error: {{.*}} absent_gl{{.}}b +## Check that exported literal symbols are present in output's +## symbol table, even lazy symbols which would otherwise be omitted +# RUN: %lld -dylib %t/default.o %t/lazydef.a -o %t/lazydef \ +# RUN: -exported_symbol _keep_globl \ +# RUN: -exported_symbol _keep_lazy +# RUN: llvm-objdump --syms %t/lazydef | \ +# RUN: FileCheck --check-prefix=EXPORT %s + +# EXPORT-DAG: g F __TEXT,__text _keep_globl +# EXPORT-DAG: g F __TEXT,__text _keep_lazy + ## Check that exported symbol is global # RUN: not %lld -dylib %t/default.o -o /dev/null \ # RUN: -exported_symbol _private_extern 2>&1 | \ @@ -28,19 +42,6 @@ # PRIVATE: error: cannot export hidden symbol _private_extern -#--- default.s - -.globl _keep_globl, _hide_globl -_keep_globl: - retq -_hide_globl: - retq -.private_extern _private_extern -_private_extern: - retq -_private: - retq - ## Check that the export trie is unaltered # RUN: %lld -dylib %t/default.o -o %t/default # RUN: llvm-objdump --macho --exports-trie %t/default | \ @@ -82,6 +83,49 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos \ # RUN: %t/symdefs.s -o %t/symdefs.o +## Check that only string-literal patterns match +## Check that comments and blank lines are stripped from symbol list +# RUN: %lld -dylib %t/symdefs.o -o %t/literal \ +# RUN: -exported_symbols_list %t/literals.txt +# RUN: llvm-objdump --macho --exports-trie %t/literal | \ +# RUN: FileCheck --check-prefix=LITERAL %s + +# LITERAL-DAG: literal_only +# LITERAL-DAG: literal_also +# LITERAL-DAG: globby_also +# LITERAL-NOT: globby_only + +## Check that only glob patterns match +## Check that comments and blank lines are stripped from symbol list +# RUN: %lld -dylib %t/symdefs.o -o %t/globby \ +# RUN: -exported_symbols_list %t/globbys.txt +# RUN: llvm-objdump --macho --exports-trie %t/globby | \ +# RUN: FileCheck --check-prefix=GLOBBY %s + +# GLOBBY-DAG: literal_also +# GLOBBY-DAG: globby_only +# GLOBBY-DAG: globby_also +# GLOBBY-NOT: literal_only + +#--- default.s + +.globl _keep_globl, _hide_globl +_keep_globl: + retq +_hide_globl: + retq +.private_extern _private_extern +_private_extern: + retq +_private: + retq + +#--- lazydef.s + +.globl _keep_lazy +_keep_lazy: + retq + #--- symdefs.s .globl literal_only, literal_also, globby_only, globby_also @@ -102,33 +146,9 @@ # globby_only globby_also -## Check that only string-literal patterns match -## Check that comments and blank lines are stripped from symbol list -# RUN: %lld -dylib %t/symdefs.o -o %t/literal \ -# RUN: -exported_symbols_list %t/literals.txt -# RUN: llvm-objdump --macho --exports-trie %t/literal | \ -# RUN: FileCheck --check-prefix=LITERAL %s - -# LITERAL-DAG: literal_only -# LITERAL-DAG: literal_also -# LITERAL-DAG: globby_also -# LITERAL-NOT: globby_only - #--- globbys.txt # literal_only l?ter[aeiou]l_*[^y] # comment *gl?bby_* - -## Check that only glob patterns match -## Check that comments and blank lines are stripped from symbol list -# RUN: %lld -dylib %t/symdefs.o -o %t/globby \ -# RUN: -exported_symbols_list %t/globbys.txt -# RUN: llvm-objdump --macho --exports-trie %t/globby | \ -# RUN: FileCheck --check-prefix=GLOBBY %s - -# GLOBBY-DAG: literal_also -# GLOBBY-DAG: globby_only -# GLOBBY-DAG: globby_also -# GLOBBY-NOT: literal_only