summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp2
-rw-r--r--lld/ELF/Options.td4
-rw-r--r--lld/ELF/SyntheticSections.cpp9
-rw-r--r--lld/test/ELF/dynamic-got-rela.s53
-rw-r--r--lld/test/ELF/relocation-non-alloc.s54
6 files changed, 85 insertions, 38 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 756ee4decfc..673300dfd21 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -106,6 +106,7 @@ struct Configuration {
std::vector<uint8_t> BuildIdVector;
bool AllowMultipleDefinition;
bool AndroidPackDynRelocs = false;
+ bool ApplyDynamicRelocs;
bool ARMHasBlx = false;
bool ARMHasMovtMovw = false;
bool ARMJ1J2BranchEncoding = false;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 4256491fe03..65aa6bdb9a0 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -597,6 +597,8 @@ static int parseInt(StringRef S, opt::Arg *Arg) {
void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->AllowMultipleDefinition =
Args.hasArg(OPT_allow_multiple_definition) || hasZOption(Args, "muldefs");
+ Config->ApplyDynamicRelocs = Args.hasFlag(OPT_apply_dynamic_relocs,
+ OPT_no_apply_dynamic_relocs, true);
Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary);
Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 521e25de8e8..505e7790182 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -57,6 +57,10 @@ defm Ttext: Eq<"Ttext">,
def allow_multiple_definition: F<"allow-multiple-definition">,
HelpText<"Allow multiple definitions">;
+defm apply_dynamic_relocs: B<"apply-dynamic-relocs",
+ "Apply dynamic relocations to place",
+ "Do not apply dynamic relocations to place">;
+
defm as_needed: B<"as-needed",
"Only set DT_NEEDED for shared libraries if used",
"Always set DT_NEEDED for shared libraries">;
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 453f0688f08..722705b348d 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -1207,10 +1207,11 @@ void RelocationBaseSection::addReloc(uint32_t DynType,
uint64_t OffsetInSec, bool UseSymVA,
Symbol *Sym, int64_t Addend, RelExpr Expr,
RelType Type) {
- // REL type relocations don't have addend fields unlike RELAs, and
- // their addends are stored to the section to which they are applied.
- // So, store addends if we need to.
- if (!Config->IsRela && UseSymVA)
+ // We store the addends for dynamic relocations for both REL and RELA
+ // relocations for compatibility with GNU Linkers. There is some system
+ // software such as the Bionic dynamic linker that uses the addend prior
+ // to dynamic relocation resolution.
+ if ((!Config->IsRela || Config->ApplyDynamicRelocs) && UseSymVA)
InputSec->Relocations.push_back({Expr, Type, OffsetInSec, Addend, Sym});
addReloc({DynType, InputSec, OffsetInSec, UseSymVA, Sym, Addend});
}
diff --git a/lld/test/ELF/dynamic-got-rela.s b/lld/test/ELF/dynamic-got-rela.s
index 0aeb6d477a2..a39f07dfde8 100644
--- a/lld/test/ELF/dynamic-got-rela.s
+++ b/lld/test/ELF/dynamic-got-rela.s
@@ -1,24 +1,43 @@
// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
// RUN: ld.lld %t.o -o %t.so -shared
-// RUN: llvm-readobj -r -s -l -section-data %t.so | FileCheck %s
+// RUN: llvm-readobj -r -s -l -section-data %t.so | FileCheck -check-prefix CHECK -check-prefix APPLYDYNREL %s
+// RUN: ld.lld %t.o -o %t2.so -shared --no-apply-dynamic-relocs
+// RUN: llvm-readobj -r -s -l -section-data %t2.so | FileCheck -check-prefix CHECK -check-prefix NOAPPLYDYNREL %s
-// CHECK: Name: .got
-// CHECK-NEXT: Type: SHT_PROGBITS
-// CHECK-NEXT: Flags [
-// CHECK-NEXT: SHF_ALLOC
-// CHECK-NEXT: SHF_WRITE
-// CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x[[GOT:.*]]
-// CHECK-NEXT: Offset:
-// CHECK-NEXT: Size:
-// CHECK-NEXT: Link:
-// CHECK-NEXT: Info:
-// CHECK-NEXT: AddressAlignment:
-// CHECK-NEXT: EntrySize:
-// CHECK-NEXT: SectionData (
-// CHECK-NEXT: 0000: 00000000 00000000 |
-// CHECK-NEXT: )
+// APPLYDYNREL: Name: .got
+// APPLYDYNREL-NEXT: Type: SHT_PROGBITS
+// APPLYDYNREL-NEXT: Flags [
+// APPLYDYNREL-NEXT: SHF_ALLOC
+// APPLYDYNREL-NEXT: SHF_WRITE
+// APPLYDYNREL-NEXT: ]
+// APPLYDYNREL-NEXT: Address: 0x[[GOT:.*]]
+// APPLYDYNREL-NEXT: Offset:
+// APPLYDYNREL-NEXT: Size:
+// APPLYDYNREL-NEXT: Link:
+// APPLYDYNREL-NEXT: Info:
+// APPLYDYNREL-NEXT: AddressAlignment:
+// APPLYDYNREL-NEXT: EntrySize:
+// APPLYDYNREL-NEXT: SectionData (
+// APPLYDYNREL-NEXT: 0000: 00200000 00000000 |
+// APPLYDYNREL-NEXT: )
+
+// NOAPPLYDYNREL: Name: .got
+// NOAPPLYDYNREL-NEXT: Type: SHT_PROGBITS
+// NOAPPLYDYNREL-NEXT: Flags [
+// NOAPPLYDYNREL-NEXT: SHF_ALLOC
+// NOAPPLYDYNREL-NEXT: SHF_WRITE
+// NOAPPLYDYNREL-NEXT: ]
+// NOAPPLYDYNREL-NEXT: Address: 0x[[GOT:.*]]
+// NOAPPLYDYNREL-NEXT: Offset:
+// NOAPPLYDYNREL-NEXT: Size:
+// NOAPPLYDYNREL-NEXT: Link:
+// NOAPPLYDYNREL-NEXT: Info:
+// NOAPPLYDYNREL-NEXT: AddressAlignment:
+// NOAPPLYDYNREL-NEXT: EntrySize:
+// NOAPPLYDYNREL-NEXT: SectionData (
+// NOAPPLYDYNREL-NEXT: 0000: 00000000 00000000 |
+// NOAPPLYDYNREL-NEXT: )
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
diff --git a/lld/test/ELF/relocation-non-alloc.s b/lld/test/ELF/relocation-non-alloc.s
index 1ad15a4e578..68020528aeb 100644
--- a/lld/test/ELF/relocation-non-alloc.s
+++ b/lld/test/ELF/relocation-non-alloc.s
@@ -2,24 +2,44 @@
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
// RUN: ld.lld %t -o %t2 -shared
-// RUN: llvm-readobj -s -section-data -r %t2 | FileCheck %s
+// RUN: llvm-readobj -s -section-data -r %t2 | FileCheck -check-prefix CHECK -check-prefix APPLYDYNREL %s
-// CHECK: Name: .data
-// CHECK-NEXT: Type: SHT_PROGBITS
-// CHECK-NEXT: Flags [
-// CHECK-NEXT: SHF_ALLOC
-// CHECK-NEXT: SHF_WRITE
-// CHECK-NEXT: ]
-// CHECK-NEXT: Address: 0x1000
-// CHECK-NEXT: Offset: 0x1000
-// CHECK-NEXT: Size: 16
-// CHECK-NEXT: Link: 0
-// CHECK-NEXT: Info: 0
-// CHECK-NEXT: AddressAlignment: 1
-// CHECK-NEXT: EntrySize: 0
-// CHECK-NEXT: SectionData (
-// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000
-// CHECK-NEXT: )
+// RUN: ld.lld %t -o %t2 -shared --no-apply-dynamic-relocs
+// RUN: llvm-readobj -s -section-data -r %t2 | FileCheck -check-prefix CHECK -check-prefix NOAPPLYDYNREL %s
+
+// APPLYDYNREL: Name: .data
+// APPLYDYNREL-NEXT: Type: SHT_PROGBITS
+// APPLYDYNREL-NEXT: Flags [
+// APPLYDYNREL-NEXT: SHF_ALLOC
+// APPLYDYNREL-NEXT: SHF_WRITE
+// APPLYDYNREL-NEXT: ]
+// APPLYDYNREL-NEXT: Address: 0x1000
+// APPLYDYNREL-NEXT: Offset: 0x1000
+// APPLYDYNREL-NEXT: Size: 16
+// APPLYDYNREL-NEXT: Link: 0
+// APPLYDYNREL-NEXT: Info: 0
+// APPLYDYNREL-NEXT: AddressAlignment: 1
+// APPLYDYNREL-NEXT: EntrySize: 0
+// APPLYDYNREL-NEXT: SectionData (
+// APPLYDYNREL-NEXT: 0000: 00100000 00000000 00000000 00000000
+// APPLYDYNREL-NEXT: )
+
+// NOAPPLYDYNREL: Name: .data
+// NOAPPLYDYNREL-NEXT: Type: SHT_PROGBITS
+// NOAPPLYDYNREL-NEXT: Flags [
+// NOAPPLYDYNREL-NEXT: SHF_ALLOC
+// NOAPPLYDYNREL-NEXT: SHF_WRITE
+// NOAPPLYDYNREL-NEXT: ]
+// NOAPPLYDYNREL-NEXT: Address: 0x1000
+// NOAPPLYDYNREL-NEXT: Offset: 0x1000
+// NOAPPLYDYNREL-NEXT: Size: 16
+// NOAPPLYDYNREL-NEXT: Link: 0
+// NOAPPLYDYNREL-NEXT: Info: 0
+// NOAPPLYDYNREL-NEXT: AddressAlignment: 1
+// NOAPPLYDYNREL-NEXT: EntrySize: 0
+// NOAPPLYDYNREL-NEXT: SectionData (
+// NOAPPLYDYNREL-NEXT: 0000: 00000000 00000000 00000000 00000000
+// NOAPPLYDYNREL-NEXT: )
// CHECK: Name: foo
// CHECK-NEXT: Type: SHT_PROGBITS
OpenPOWER on IntegriCloud