diff options
Diffstat (limited to 'lld')
| -rw-r--r-- | lld/ELF/Symbols.cpp | 15 | ||||
| -rw-r--r-- | lld/test/ELF/bsymbolic-undef.s | 26 | ||||
| -rw-r--r-- | lld/test/ELF/weak-undef.s | 21 |
3 files changed, 55 insertions, 7 deletions
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 5bb6a703383..f75f310f7f7 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -123,14 +123,15 @@ bool SymbolBody::isPreemptible() const { if (!Config->Shared) return false; - // -Bsymbolic means that not even default visibility symbols can be preempted. - if ((Config->Bsymbolic || (Config->BsymbolicFunctions && isFunc())) && - isDefined()) + // Only symbols that appear in dynsym can be preempted. + if (!Backref->includeInDynsym()) return false; - // Only default visibility symbols that appear in the dynamic symbol table can - // be preempted. - return Backref->Visibility == STV_DEFAULT && Backref->includeInDynsym(); + // Normally only default visibility symbols can be preempted, but -Bsymbolic + // means that not even they can be preempted. + if (Config->Bsymbolic || (Config->BsymbolicFunctions && isFunc())) + return !isDefined(); + return Backref->Visibility == STV_DEFAULT; } template <class ELFT> @@ -320,7 +321,7 @@ bool Symbol::includeInDynsym() const { if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) return false; return (ExportDynamic && VersionScriptGlobal) || Body->isShared() || - Body->isUndefined(); + (Body->isUndefined() && Config->Shared); } template uint32_t SymbolBody::template getVA<ELF32LE>(uint32_t) const; diff --git a/lld/test/ELF/bsymbolic-undef.s b/lld/test/ELF/bsymbolic-undef.s new file mode 100644 index 00000000000..6590bbcb50b --- /dev/null +++ b/lld/test/ELF/bsymbolic-undef.s @@ -0,0 +1,26 @@ +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld -shared -Bsymbolic %t.o -o %t.so +# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s + +# CHECK: DynamicSymbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: @ (0) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: undef@ (1) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global (0x1) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: ] + +call undef@PLT diff --git a/lld/test/ELF/weak-undef.s b/lld/test/ELF/weak-undef.s new file mode 100644 index 00000000000..02555535927 --- /dev/null +++ b/lld/test/ELF/weak-undef.s @@ -0,0 +1,21 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld %t.o -o %t -pie +# RUN: llvm-readobj -dyn-symbols %t | FileCheck %s + +# CHECK: DynamicSymbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: @ (0) +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local (0x0) +# CHECK-NEXT: Type: None (0x0) +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined (0x0) +# CHECK-NEXT: } +# CHECK-NEXT: ] + +.weak foo + +.globl _start +_start: |

