forked from OSchip/llvm-project
[ELF] Implement --[no-]apply-dynamic-relocs option.
When resolving dynamic RELA relocations the addend is taken from the relocation and not the place being relocated. Accordingly lld does not write the addend field to the place like it would for a REL relocation. Unfortunately there is some system software, in particlar dynamic loaders such as Bionic's linker64 that use the value of the place prior to relocation to find the offset that they have been loaded at. Both gold and bfd control this behavior with the --[no-]apply-dynamic-relocs option. This change implements the option and defaults it to true for compatibility with gold and bfd. Differential Revision: https://reviews.llvm.org/D42797 llvm-svn: 324221
This commit is contained in:
parent
d86ad2e359
commit
64f65b02d2
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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">;
|
||||
|
|
|
@ -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});
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue