[ELF] Default to --no-allow-shlib-undefined for executables

Summary:
This follows the ld.bfd/gold behavior.

The error check is useful as it captures a common type of ld.so undefined symbol errors as link-time errors:

    // a.cc => a.so (not linked with -z defs)
    void f(); // f is undefined
    void g() { f(); }

    // b.cc => executable with a DT_NEEDED entry on a.so
    void g();
    int main() { g(); }

    // ld.so errors when g() is executed (lazy binding) or when the program is started (-z now)
    // symbol lookup error: ... undefined symbol: f

Reviewers: ruiu, grimar, pcc, espindola

Reviewed By: ruiu

Subscribers: llvm-commits, emaste, arichardson

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D57569

llvm-svn: 352943
This commit is contained in:
Fangrui Song 2019-02-02 00:34:28 +00:00
parent 1bccafe4f6
commit ae0294375f
6 changed files with 19 additions and 9 deletions

View File

@ -756,8 +756,9 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Args.hasFlag(OPT_allow_multiple_definition, Args.hasFlag(OPT_allow_multiple_definition,
OPT_no_allow_multiple_definition, false) || OPT_no_allow_multiple_definition, false) ||
hasZOption(Args, "muldefs"); hasZOption(Args, "muldefs");
Config->AllowShlibUndefined = Args.hasFlag( Config->AllowShlibUndefined =
OPT_allow_shlib_undefined, OPT_no_allow_shlib_undefined, true); Args.hasFlag(OPT_allow_shlib_undefined, OPT_no_allow_shlib_undefined,
Args.hasArg(OPT_shared));
Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary); Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary);
Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);

View File

@ -64,8 +64,8 @@ defm allow_multiple_definition: B<"allow-multiple-definition",
"Do not allow multiple definitions (default)">; "Do not allow multiple definitions (default)">;
defm allow_shlib_undefined: B<"allow-shlib-undefined", defm allow_shlib_undefined: B<"allow-shlib-undefined",
"Allow unresolved references in shared libraries (default)", "Allow unresolved references in shared libraries (default when linking a shared library)",
"Do not allow unresolved references in shared libraries">; "Do not allow unresolved references in shared libraries (default when linking an executable)">;
defm apply_dynamic_relocs: B<"apply-dynamic-relocs", defm apply_dynamic_relocs: B<"apply-dynamic-relocs",
"Apply link-time values for dynamic relocations", "Apply link-time values for dynamic relocations",

View File

@ -46,6 +46,9 @@ as a native linker as well as a cross linker.
.It Fl -allow-multiple-definition .It Fl -allow-multiple-definition
Do not error if a symbol is defined multiple times. Do not error if a symbol is defined multiple times.
The first definition will be used. The first definition will be used.
.It Fl -allow-shlib-undefined
Allow unresolved references in shared libraries.
This option is enabled by default when linking a shared library.
.It Fl -apply-dynamic-relocs .It Fl -apply-dynamic-relocs
Apply link-time values for dynamic relocations. Apply link-time values for dynamic relocations.
.It Fl -as-needed .It Fl -as-needed
@ -242,6 +245,9 @@ Set target emulation.
.It Fl -Map Ns = Ns Ar file , Fl M Ar file .It Fl -Map Ns = Ns Ar file , Fl M Ar file
Print a link map to Print a link map to
.Ar file . .Ar file .
.It Fl -no-allow-shlib-undefined
Do not allow unresolved references in shared libraries.
This option is enabled by default when linking an executable.
.It Fl -no-as-needed .It Fl -no-as-needed
Always set Always set
.Dv DT_NEEDED .Dv DT_NEEDED

View File

@ -6,9 +6,12 @@
# RUN: %p/Inputs/allow-shlib-undefined.s -o %t1.o # RUN: %p/Inputs/allow-shlib-undefined.s -o %t1.o
# RUN: ld.lld -shared %t1.o -o %t.so # RUN: ld.lld -shared %t1.o -o %t.so
# RUN: ld.lld %t.o %t.so -o /dev/null
# RUN: ld.lld --allow-shlib-undefined %t.o %t.so -o /dev/null # RUN: ld.lld --allow-shlib-undefined %t.o %t.so -o /dev/null
# RUN: not ld.lld --no-allow-shlib-undefined %t.o %t.so -o /dev/null 2>&1 | FileCheck %s # RUN: not ld.lld --no-allow-shlib-undefined %t.o %t.so -o /dev/null 2>&1 | FileCheck %s
# Executable defaults to --no-allow-shlib-undefined
# RUN: not ld.lld %t.o %t.so -o /dev/null 2>&1 | FileCheck %s
# -shared defaults to --allow-shlib-undefined
# RUN: ld.lld -shared %t.o %t.so -o /dev/null
# RUN: echo | llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %tempty.o # RUN: echo | llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %tempty.o
# RUN: ld.lld -shared %tempty.o -o %tempty.so # RUN: ld.lld -shared %tempty.o -o %tempty.so

View File

@ -3,7 +3,7 @@
# RUN: llvm-mc %p/Inputs/undefined-error.s -filetype=obj \ # RUN: llvm-mc %p/Inputs/undefined-error.s -filetype=obj \
# RUN: -triple=x86_64-pc-linux -o %t2.o # RUN: -triple=x86_64-pc-linux -o %t2.o
# RUN: ld.lld -shared %t2.o -o %t2.so # RUN: ld.lld -shared %t2.o -o %t2.so
# RUN: not ld.lld %t2.so %t.o -o /dev/null 2>&1 | FileCheck %s # RUN: not ld.lld --allow-shlib-undefined %t2.so %t.o -o /dev/null 2>&1 | FileCheck %s
# CHECK: undefined symbol: fmod # CHECK: undefined symbol: fmod
# Check we're not emitting other diagnostics for this symbol. # Check we're not emitting other diagnostics for this symbol.

View File

@ -27,21 +27,21 @@
# ERRUND: >>> referenced by {{.*}}:(.text+0x1) # ERRUND: >>> referenced by {{.*}}:(.text+0x1)
## Also ignore all should not produce error for symbols from DSOs. ## Also ignore all should not produce error for symbols from DSOs.
# RUN: ld.lld %t1.o %t.so -o %t1_3 --unresolved-symbols=ignore-all # RUN: ld.lld %t1.o %t.so -o %t1_3 --allow-shlib-undefined --unresolved-symbols=ignore-all
# RUN: llvm-readobj %t1_3 > /dev/null 2>&1 # RUN: llvm-readobj %t1_3 > /dev/null 2>&1
## Ignoring undefines in objects should not produce error for symbol from object. ## Ignoring undefines in objects should not produce error for symbol from object.
# RUN: ld.lld %t1.o %t2.o -o %t2 --unresolved-symbols=ignore-in-object-files # RUN: ld.lld %t1.o %t2.o -o %t2 --unresolved-symbols=ignore-in-object-files
# RUN: llvm-readobj %t2 > /dev/null 2>&1 # RUN: llvm-readobj %t2 > /dev/null 2>&1
## And still should not should produce for undefines from DSOs. ## And still should not should produce for undefines from DSOs.
# RUN: ld.lld %t1.o %t.so -o /dev/null --unresolved-symbols=ignore-in-object-files # RUN: ld.lld %t1.o %t.so -o /dev/null --allow-shlib-undefined --unresolved-symbols=ignore-in-object-files
# RUN: llvm-readobj %t2 > /dev/null 2>&1 # RUN: llvm-readobj %t2 > /dev/null 2>&1
## Ignoring undefines in shared should produce error for symbol from object. ## Ignoring undefines in shared should produce error for symbol from object.
# RUN: not ld.lld %t2.o -o /dev/null --unresolved-symbols=ignore-in-shared-libs 2>&1 | \ # RUN: not ld.lld %t2.o -o /dev/null --unresolved-symbols=ignore-in-shared-libs 2>&1 | \
# RUN: FileCheck -check-prefix=ERRUND %s # RUN: FileCheck -check-prefix=ERRUND %s
## And should not produce errors for symbols from DSO. ## And should not produce errors for symbols from DSO.
# RUN: ld.lld %t1.o %t.so -o %t3_1 --unresolved-symbols=ignore-in-shared-libs # RUN: ld.lld %t1.o %t.so -o %t3_1 --allow-shlib-undefined --unresolved-symbols=ignore-in-shared-libs
# RUN: llvm-readobj %t3_1 > /dev/null 2>&1 # RUN: llvm-readobj %t3_1 > /dev/null 2>&1
## Ignoring undefines in shared libs should not produce error for symbol from object ## Ignoring undefines in shared libs should not produce error for symbol from object