summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2017-09-15 18:05:02 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2017-09-15 18:05:02 +0000
commite05e2f8b3459d580c68451c184497fe31693bd05 (patch)
treec6c3d995efc9180b7c15ba9b9998f88515781524
parent576628bdd77f5e14fe063d521c67d36eda0bc203 (diff)
downloadbcm5719-llvm-e05e2f8b3459d580c68451c184497fe31693bd05.tar.gz
bcm5719-llvm-e05e2f8b3459d580c68451c184497fe31693bd05.zip
Keep some relocations with undefined weak symbols.
This fixes pr34301. As the bug points out, we want to keep some relocations with undefined weak symbols. This means that we cannot always claim that these symbols are not preemptible as we do now. Unfortunately, we cannot also just always claim that they are preemptible. Doing so would, for example, cause us to try to create a plt entry when we don't even have a dynamic symbol table. What almost works is to say that weak undefined symbols are preemptible if and only if we have a dynamic symbol table. Almost because we don't want to fail the build trying to create a copy relocation to a weak undefined. llvm-svn: 313372
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp9
-rw-r--r--lld/ELF/Relocations.cpp13
-rw-r--r--lld/ELF/Symbols.cpp4
-rw-r--r--lld/ELF/Writer.cpp6
-rw-r--r--lld/test/ELF/no-inhibit-exec.s2
-rw-r--r--lld/test/ELF/pie-weak.s5
-rw-r--r--lld/test/ELF/relocation-relative-weak.s1
-rw-r--r--lld/test/ELF/weak-undef-export.s9
-rw-r--r--lld/test/ELF/weak-undef-val.s26
-rw-r--r--lld/test/ELF/weak-undef.s9
11 files changed, 75 insertions, 10 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 831854eba11..ecc339972a4 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -127,6 +127,7 @@ struct Configuration {
bool GdbIndex;
bool GnuHash;
bool HasDynamicList = false;
+ bool HasDynSymTab;
bool ICF;
bool MipsN32Abi = false;
bool NoGnuUnique;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index edd94d5d54c..853ca9513e2 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1009,6 +1009,15 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
for (InputFile *F : Files)
Symtab->addFile<ELFT>(F);
+ // Now that we have every file, we can decide if we will need a
+ // dynamic symbol table.
+ // We need one if we were asked to export dynamic symbols or if we are
+ // producing a shared library.
+ // We also need one if any shared libraries are used and for pie executables
+ // (probably because the dynamic linker needs it).
+ Config->HasDynSymTab = !SharedFile<ELFT>::Instances.empty() || Config->Pic ||
+ Config->ExportDynamic;
+
// Some symbols (such as __ehdr_start) are defined lazily only when there
// are undefined symbols for them, so we add these to trigger that logic.
for (StringRef Sym : Script->Opt.ReferencedSymbols)
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 20b506d20d8..47774e937ab 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -568,8 +568,17 @@ static RelExpr adjustExpr(SymbolBody &Body, RelExpr Expr, uint32_t Type,
if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body, S, RelOff))
return Expr;
- // This relocation would require the dynamic linker to write a value to read
- // only memory. We can hack around it if we are producing an executable and
+ // If we got here we know that this relocation would require the dynamic
+ // linker to write a value to read only memory.
+
+ // If the relocation is to a weak undef, give up on it and produce a
+ // non preemptible 0.
+ if (Body.isUndefWeak()) {
+ Body.IsPreemptible = false;
+ return Expr;
+ }
+
+ // We can hack around it if we are producing an executable and
// the refered symbol can be preemepted to refer to the executable.
if (Config->Shared || (Config->Pic && !isRelExpr(Expr))) {
error("can't create dynamic relocation " + toString(Type) + " against " +
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 51253f3a924..08e5d9495e5 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -344,10 +344,10 @@ uint8_t Symbol::computeBinding() const {
}
bool Symbol::includeInDynsym() const {
+ if (!Config->HasDynSymTab)
+ return false;
if (computeBinding() == STB_LOCAL)
return false;
- if (body()->isUndefWeak())
- return Config->Shared;
if (!body()->isInCurrentDSO())
return true;
return ExportDynamic;
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index d2e0078264b..a7c9191af39 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -299,10 +299,8 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
Add(InX::BssRelRo);
// Add MIPS-specific sections.
- bool HasDynSymTab = !SharedFile<ELFT>::Instances.empty() || Config->Pic ||
- Config->ExportDynamic;
if (Config->EMachine == EM_MIPS) {
- if (!Config->Shared && HasDynSymTab) {
+ if (!Config->Shared && Config->HasDynSymTab) {
InX::MipsRldMap = make<MipsRldMapSection>();
Add(InX::MipsRldMap);
}
@@ -314,7 +312,7 @@ template <class ELFT> void Writer<ELFT>::createSyntheticSections() {
Add(Sec);
}
- if (HasDynSymTab) {
+ if (Config->HasDynSymTab) {
InX::DynSymTab = make<SymbolTableSection<ELFT>>(*InX::DynStrTab);
Add(InX::DynSymTab);
diff --git a/lld/test/ELF/no-inhibit-exec.s b/lld/test/ELF/no-inhibit-exec.s
index ad60f1c652f..afb7aed94c1 100644
--- a/lld/test/ELF/no-inhibit-exec.s
+++ b/lld/test/ELF/no-inhibit-exec.s
@@ -7,7 +7,7 @@
# CHECK: Disassembly of section .text:
# CHECK-NEXT: _start
-# CHECK-NEXT: 201000: {{.*}} callq 0
+# CHECK-NEXT: 201000: {{.*}} callq -2101253
# RELOC: Relocations [
# RELOC-NEXT: ]
diff --git a/lld/test/ELF/pie-weak.s b/lld/test/ELF/pie-weak.s
index 99dbd47488f..1a024b916bc 100644
--- a/lld/test/ELF/pie-weak.s
+++ b/lld/test/ELF/pie-weak.s
@@ -5,6 +5,9 @@
# RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
# RELOCS: Relocations [
+# RELOCS-NEXT: Section ({{.*}}) .rela.dyn {
+# RELOCS-NEXT: R_X86_64_GLOB_DAT foo 0x0
+# RELOCS-NEXT: }
# RELOCS-NEXT: ]
.weak foo
@@ -12,6 +15,6 @@
.globl _start
_start:
# DISASM: _start:
-# DISASM-NEXT: 1000: 48 8b 05 69 10 00 00 movq 4201(%rip), %rax
+# DISASM-NEXT: 1000: 48 8b 05 99 10 00 00 movq 4249(%rip), %rax
# ^ .got - (.text + 7)
mov foo@gotpcrel(%rip), %rax
diff --git a/lld/test/ELF/relocation-relative-weak.s b/lld/test/ELF/relocation-relative-weak.s
index c525012acf6..7f28fced711 100644
--- a/lld/test/ELF/relocation-relative-weak.s
+++ b/lld/test/ELF/relocation-relative-weak.s
@@ -4,6 +4,7 @@
# RUN: llvm-readobj -dyn-relocations %t | FileCheck %s
# CHECK: Dynamic Relocations {
+# CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT w 0x0
# CHECK-NEXT: }
.globl _start
diff --git a/lld/test/ELF/weak-undef-export.s b/lld/test/ELF/weak-undef-export.s
index 6780e31a7bd..164bc173083 100644
--- a/lld/test/ELF/weak-undef-export.s
+++ b/lld/test/ELF/weak-undef-export.s
@@ -16,6 +16,15 @@
# CHECK-NEXT: Other: 0
# CHECK-NEXT: Section: Undefined (0x0)
# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: foo@ (1)
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Weak (0x2)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined (0x0)
+# CHECK-NEXT: }
# CHECK-NEXT: ]
.weak foo
diff --git a/lld/test/ELF/weak-undef-val.s b/lld/test/ELF/weak-undef-val.s
new file mode 100644
index 00000000000..acd42f4845d
--- /dev/null
+++ b/lld/test/ELF/weak-undef-val.s
@@ -0,0 +1,26 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t --export-dynamic
+# RUN: llvm-readobj -s -section-data %t | FileCheck %s
+
+# CHECK: Name: .text
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: SHF_EXECINSTR
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x201000
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: SectionData (
+# CHECK-NEXT: 0000: 00F0DFFF |
+# CHECK-NEXT: )
+
+ .global _start
+_start:
+ .weak foobar
+ .long foobar - .
diff --git a/lld/test/ELF/weak-undef.s b/lld/test/ELF/weak-undef.s
index b6340339eba..7ee505be6ad 100644
--- a/lld/test/ELF/weak-undef.s
+++ b/lld/test/ELF/weak-undef.s
@@ -13,6 +13,15 @@
# CHECK-NEXT: Other: 0
# CHECK-NEXT: Section: Undefined (0x0)
# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: foo@
+# CHECK-NEXT: Value: 0x0
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Weak
+# CHECK-NEXT: Type: None
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: Undefined
+# CHECK-NEXT: }
# CHECK-NEXT: ]
.weak foo
OpenPOWER on IntegriCloud