bool gdbIndex;
bool gnuHash = false;
bool gnuUnique;
- bool hasDynamicList = false;
bool hasDynSymTab;
bool ignoreDataAddressEquality;
bool ignoreFunctionAddressEquality;
llvm::Optional<uint32_t> shuffleSectionSeed;
bool singleRoRx;
bool shared;
+ bool symbolic;
bool isStatic = false;
bool sysvHash = false;
bool target1Rel;
error(arg->getSpelling() + ": " + toString(pat.takeError()));
}
- // Parses -dynamic-list and -export-dynamic-symbol. They make some
- // symbols private. Note that -export-dynamic takes precedence over them
- // as it says all symbols should be exported.
- if (!config->exportDynamic) {
- for (auto *arg : args.filtered(OPT_dynamic_list))
- if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
- readDynamicList(*buffer);
-
- for (auto *arg : args.filtered(OPT_export_dynamic_symbol))
- config->dynamicList.push_back(
- {arg->getValue(), /*isExternCpp=*/false, /*hasWildcard=*/false});
- }
+ // When producing an executable, --dynamic-list specifies non-local defined
+ // symbols whith are required to be exported. When producing a shared object,
+ // symbols not specified by --dynamic-list are non-preemptible.
+ config->symbolic =
+ args.hasArg(OPT_Bsymbolic) || args.hasArg(OPT_dynamic_list);
+ for (auto *arg : args.filtered(OPT_dynamic_list))
+ if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
+ readDynamicList(*buffer);
- // If --export-dynamic-symbol=foo is given and symbol foo is defined in
- // an object file in an archive file, that object file should be pulled
- // out and linked. (It doesn't have to behave like that from technical
- // point of view, but this is needed for compatibility with GNU.)
+ // --export-dynamic-symbol specifies additional --dynamic-list symbols if any
+ // other option expresses a symbolic intention: -no-pie, -pie, -Bsymbolic,
+ // -Bsymbolic-functions (if STT_FUNC), --dynamic-list.
for (auto *arg : args.filtered(OPT_export_dynamic_symbol))
- config->undefined.push_back(arg->getValue());
+ config->dynamicList.push_back(
+ {arg->getValue(), /*isExternCpp=*/false, /*hasWildcard=*/true});
for (auto *arg : args.filtered(OPT_version_script))
if (Optional<std::string> path = searchScript(arg->getValue())) {
defm dynamic_linker: Eq<"dynamic-linker", "Which dynamic linker to use">;
-defm dynamic_list: Eq<"dynamic-list", "Read a list of dynamic symbols">;
+defm dynamic_list : Eq<"dynamic-list",
+ "Read a list of dynamic symbols. (executable) Put matched non-local defined"
+ "symbols to the dynamic symbol table. (shared object) References to matched"
+ "non-local STV_DEFAULT symbols shouldn't be bound to definitions within the "
+ "shared object. Implies -Bsymbolic but does not set DF_SYMBOLIC">,
+ MetaVarName<"<file>">;
defm eh_frame_hdr: B<"eh-frame-hdr",
"Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME segment header",
"Put symbols in the dynamic symbol table",
"Do not put symbols in the dynamic symbol table (default)">;
-defm export_dynamic_symbol:
- Eq<"export-dynamic-symbol", "Put a symbol in the dynamic symbol table">;
+defm export_dynamic_symbol : EEq<"export-dynamic-symbol",
+ "(executable) Put matched symbols in the dynamic symbol table. "
+ "(shared object) References to matched non-local STV_DEFAULT symbols "
+ "shouldn't be bound to definitions within the shared object. "
+ "Does not imply -Bsymbolic.">,
+ MetaVarName<"glob">;
defm fatal_warnings: B<"fatal-warnings",
"Treat warnings as errors",
}
void ScriptParser::readDynamicList() {
- config->hasDynamicList = true;
expect("{");
std::vector<SymbolVersion> locals;
std::vector<SymbolVersion> globals;
if (!config->shared)
return false;
- // If the dynamic list is present, it specifies preemptable symbols in a DSO.
- if (config->hasDynamicList)
+ // If -Bsymbolic or --dynamic-list is specified, or -Bsymbolic-functions is
+ // specified and the symbol is STT_FUNC, the symbol is preemptible iff it is
+ // in the dynamic list.
+ if (config->symbolic || (config->bsymbolicFunctions && sym.isFunc()))
return sym.inDynamicList;
-
- // -Bsymbolic means that definitions are not preempted.
- if (config->bsymbolic || (config->bsymbolicFunctions && sym.isFunc()))
- return false;
return true;
}
* One-dash form of some long option (``--thinlto-*``, ``--lto-*``, ``--shuffle-sections=``)
are no longer supported.
+* ``--export-dynamic-symbol`` no longer implies ``-u``.
COFF Improvements
-----------------
.It Fl -dynamic-list Ns = Ns Ar file
Read a list of dynamic symbols from
.Ar file .
+(executable) Put matched non-local defined symbols to the dynamic symbol table.
+(shared object) References to matched non-local STV_DEFAULT symbols shouldn't be bound to definitions within the shared object. Implies
+.Cm -Bsymbolic
+but does not set DF_SYMBOLIC
.It Fl -eh-frame-hdr
Request creation of
.Li .eh_frame_hdr
Exclude static libraries from automatic export.
.It Fl -export-dynamic , Fl E
Put symbols in the dynamic symbol table.
-.It Fl -export-dynamic-symbol Ns = Ns Ar symbol
-Include
-.Ar symbol
-in the dynamic symbol table.
+.It Fl -export-dynamic-symbol Ns = Ns Ar glob
+(executable) Put matched non-local defined symbols to the dynamic symbol table.
+(shared object) References to matched non-local STV_DEFAULT symbols shouldn't be bound to definitions within the shared object even if they would otherwise be due to
+.Cm -Bsymbolic
+,
+.Cm -Bsymbolic-functions
+or
+.Cm --dynamic-list
.It Fl -fatal-warnings
Treat warnings as errors.
.It Fl -filter Ns = Ns Ar value , Fl F Ar value
# REQUIRES: x86
-# RUN: rm -f %t.a
-# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive2.s -o %t1.o
-# RUN: llvm-ar rcs %t.a %t1.o
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
-# RUN: ld.lld -shared -o %t.so --export-dynamic-symbol foo %t.a %t2.o
-# RUN: llvm-readelf -dyn-symbols %t.so | FileCheck %s
+## For an executable, --export-dynamic-symbol exports a symbol if it is non-local and defined.
+# RUN: ld.lld -pie --export-dynamic-symbol foo %t.o -o %t
+# RUN: llvm-nm -D -p %t | FileCheck %s
-# RUN: ld.lld -shared -o %t.so --export-dynamic --export-dynamic-symbol foo %t.a %t2.o
-# RUN: llvm-readelf -dyn-symbols %t.so | FileCheck %s
+## --export-dynamic exports all non-local defined symbols.
+## --export-dynamic-symbol is shadowed.
+# RUN: ld.lld -pie --export-dynamic --export-dynamic-symbol foo %t.o -o %t.start
+# RUN: llvm-nm -D -p %t.start | FileCheck --check-prefixes=CHECK,START %s
-# CHECK: foo
+# CHECK-NOT: .
+# START: T _start
+# CHECK: T foo
+# CHECK-NOT: .
-.global _start
+## --export-dynamic-symbol does not imply -u: %t1.a(%t1.o) is not fetched.
+## This is compatible with GNU ld since binutils 2.35 onwards.
+# RUN: echo '.globl foo, bar; foo: bar:' | llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o
+# RUN: rm -f %t1.a && llvm-ar rc %t1.a %t1.o
+# RUN: ld.lld --export-dynamic-symbol bar %t1.a %t.o -o %t.nofetch
+# RUN: llvm-nm %t.nofetch | FileCheck /dev/null --implicit-check-not=bar
+
+## --export-dynamic-symbol can make a symbol preemptible even if it would be otherwise
+## non-preemptible (due to -Bsymbolic, -Bsymbolic-functions or --dynamic-list).
+# RUN: ld.lld -shared -Bsymbolic --export-dynamic-symbol nomatch %t.o -o %t.nopreempt
+# RUN: llvm-objdump -d %t.nopreempt | FileCheck --check-prefix=NOPLT %s
+# RUN: ld.lld -shared -Bsymbolic --export-dynamic-symbol foo %t.o -o %t.preempt
+# RUN: llvm-objdump -d %t.preempt | FileCheck --check-prefix=PLT %s
+
+## 'nomatch' does not match any symbol. Don't warn.
+# RUN: ld.lld --fatal-warnings -shared -Bsymbolic-functions --export-dynamic-symbol nomatch %t.o -o %t.nopreempt2
+# RUN: llvm-objdump -d %t.nopreempt2 | FileCheck --check-prefix=NOPLT %s
+# RUN: ld.lld -shared -Bsymbolic-functions --export-dynamic-symbol foo %t.o -o %t.preempt2
+# RUN: llvm-objdump -d %t.preempt2 | FileCheck --check-prefix=PLT %s
+
+# RUN: echo '{};' > %t.list
+# RUN: ld.lld -shared --dynamic-list %t.list --export-dynamic-symbol foo %t.o -o %t.preempt3
+# RUN: llvm-objdump -d %t.preempt3 | FileCheck --check-prefix=PLT %s
+
+## The option value is a glob.
+# RUN: ld.lld -shared -Bsymbolic --export-dynamic-symbol 'f*' %t.o -o %t.preempt4
+# RUN: llvm-objdump -d %t.preempt4 | FileCheck --check-prefix=PLT %s
+
+# PLT: <foo@plt>
+# NOPLT-NOT: <foo@plt>
+
+.global _start, foo
+.type foo, @function
_start:
- nop
+ call foo
+foo:
## In GNU linkers, -u does not make a backward reference.
# RUN: ld.lld --fatal-warnings --warn-backrefs -u foo %t2.a %t1.o -o /dev/null
-## In GNU gold, --export-dynamic-symbol does not make a backward reference.
-# RUN: ld.lld --fatal-warnings --warn-backrefs --export-dynamic-symbol foo %t2.a %t1.o -o /dev/null
+## -u does not make a backward reference.
+# RUN: ld.lld --fatal-warnings --warn-backrefs -u foo %t2.a %t1.o -o /dev/null
# RUN: not ld.lld --warn-backrefs-exclude='[' 2>&1 | FileCheck --check-prefix=INVALID %s
# INVALID: error: --warn-backrefs-exclude: invalid glob pattern: [