diff options
| author | Rafael Espindola <rafael.espindola@gmail.com> | 2016-02-23 20:19:44 +0000 |
|---|---|---|
| committer | Rafael Espindola <rafael.espindola@gmail.com> | 2016-02-23 20:19:44 +0000 |
| commit | 435c00f39ca6039a4f95aeb9d4916baf3c591528 (patch) | |
| tree | 35c5fe933c884f811477ccecf93021f76e8fdbd2 | |
| parent | 16b8eddcac086d69d0dfa502464b54f840e4306c (diff) | |
| download | bcm5719-llvm-435c00f39ca6039a4f95aeb9d4916baf3c591528.tar.gz bcm5719-llvm-435c00f39ca6039a4f95aeb9d4916baf3c591528.zip | |
Fix the aarch64 logic for dynamic relocations.
There is nothing aarch64 specific in here. If a symbol can be preempted,
we need to copy the full relocation to the dynamic linker.
If a symbol cannot be preempted, we can make the dynamic linker life
easier and produce a relative relocation.
This is directly equivalent to R_X86_64_64 to R_x86_64_RELATIVE
conversion.
llvm-svn: 261678
| -rw-r--r-- | lld/ELF/OutputSections.cpp | 47 | ||||
| -rw-r--r-- | lld/ELF/OutputSections.h | 14 | ||||
| -rw-r--r-- | lld/ELF/Target.cpp | 8 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 13 | ||||
| -rw-r--r-- | lld/test/ELF/aarch64-abs64-dyn.s | 32 |
5 files changed, 33 insertions, 81 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 3945d880ebf..c7fd9919091 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -253,18 +253,11 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { if (IsRela) { uintX_t VA = 0; - if (Rel.UseSymVA) { + if (Rel.UseSymVA) VA = Sym->getVA<ELFT>(); - } else if (Rel.TargetSec) { + else if (Rel.TargetSec) VA = Rel.TargetSec->getOffset(Rel.OffsetInTargetSec) + Rel.TargetSec->OutSec->getVA(); - } else if (!Sym && Rel.OffsetSec) { - // Sym equal to nullptr means the dynamic relocation is against a - // local symbol represented by Rel.SymIndex. - ObjectFile<ELFT> *File = Rel.OffsetSec->getFile(); - const Elf_Sym *LocalSym = File->getLocalSymbol(Rel.SymIndex); - VA = getLocalTarget(*File, *LocalSym, 0); - } reinterpret_cast<Elf_Rela *>(P)->r_addend = Rel.Addend + VA; } @@ -869,6 +862,7 @@ elf2::getLocalRelTarget(const ObjectFile<ELFT> &File, const Elf_Rel_Impl<ELFT, IsRela> &RI, typename ELFFile<ELFT>::uintX_t Addend) { typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym; + typedef typename ELFFile<ELFT>::uintX_t uintX_t; // PPC64 has a special relocation representing the TOC base pointer // that does not have a corresponding symbol. @@ -881,22 +875,10 @@ elf2::getLocalRelTarget(const ObjectFile<ELFT> &File, if (!Sym) fatal("Unsupported relocation without symbol"); - return getLocalTarget(File, *Sym, Addend); -} - -template <class ELFT> -typename ELFFile<ELFT>::uintX_t -elf2::getLocalTarget(const ObjectFile<ELFT> &File, - const typename ELFFile<ELFT>::Elf_Sym &Sym, - typename ELFFile<ELFT>::uintX_t Addend) { - typedef typename ELFFile<ELFT>::uintX_t uintX_t; - - InputSectionBase<ELFT> *Section = File.getSection(Sym); - if (!Section) - return Addend; + InputSectionBase<ELFT> *Section = File.getSection(*Sym); - if (Sym.getType() == STT_TLS) - return (Section->OutSec->getVA() + Section->getOffset(Sym) + Addend) - + if (Sym->getType() == STT_TLS) + return (Section->OutSec->getVA() + Section->getOffset(*Sym) + Addend) - Out<ELFT>::TlsPhdr->p_vaddr; // According to the ELF spec reference to a local symbol from outside @@ -906,8 +888,8 @@ elf2::getLocalTarget(const ObjectFile<ELFT> &File, if (Section == &InputSection<ELFT>::Discarded || !Section->isLive()) return Addend; - uintX_t Offset = Sym.st_value; - if (Sym.getType() == STT_SECTION) { + uintX_t Offset = Sym->st_value; + if (Sym->getType() == STT_SECTION) { Offset += Addend; Addend = 0; } @@ -1665,18 +1647,5 @@ template uint64_t getLocalRelTarget(const ObjectFile<ELF64LE> &, template uint64_t getLocalRelTarget(const ObjectFile<ELF64BE> &, const ELFFile<ELF64BE>::Elf_Rela &, uint64_t); - -template uint32_t getLocalTarget(const ObjectFile<ELF32LE> &, - const ELFFile<ELF32LE>::Elf_Sym &Sym, - uint32_t); -template uint32_t getLocalTarget(const ObjectFile<ELF32BE> &, - const ELFFile<ELF32BE>::Elf_Sym &Sym, - uint32_t); -template uint64_t getLocalTarget(const ObjectFile<ELF64LE> &, - const ELFFile<ELF64LE>::Elf_Sym &Sym, - uint64_t); -template uint64_t getLocalTarget(const ObjectFile<ELF64BE> &, - const ELFFile<ELF64BE>::Elf_Sym &Sym, - uint64_t); } } diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 8b0b54dcdfc..a3a80db42ea 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -53,12 +53,6 @@ getLocalRelTarget(const ObjectFile<ELFT> &File, const llvm::object::Elf_Rel_Impl<ELFT, IsRela> &Rel, typename llvm::object::ELFFile<ELFT>::uintX_t Addend); -template <class ELFT> -typename llvm::object::ELFFile<ELFT>::uintX_t -getLocalTarget(const ObjectFile<ELFT> &File, - const typename llvm::object::ELFFile<ELFT>::Elf_Sym &Sym, - typename llvm::object::ELFFile<ELFT>::uintX_t Addend); - bool canBePreempted(const SymbolBody *Body, bool NeedsGot); // This represents a section in an output file. @@ -193,7 +187,6 @@ template <class ELFT> struct DynamicReloc { } OKind; SymbolBody *Sym = nullptr; - uint32_t SymIndex = 0; InputSectionBase<ELFT> *OffsetSec = nullptr; uintX_t OffsetInSec = 0; bool UseSymVA = false; @@ -214,12 +207,6 @@ template <class ELFT> struct DynamicReloc { OffsetInSec(OffsetInSec), UseSymVA(UseSymVA), Addend(Addend) {} DynamicReloc(uint32_t Type, InputSectionBase<ELFT> *OffsetSec, - uintX_t OffsetInSec, bool UseSymVA, uint32_t SymIndex, - uintX_t Addend) - : Type(Type), OKind(Off_Sec), SymIndex(SymIndex), OffsetSec(OffsetSec), - OffsetInSec(OffsetInSec), UseSymVA(UseSymVA), Addend(Addend) {} - - DynamicReloc(uint32_t Type, InputSectionBase<ELFT> *OffsetSec, uintX_t OffsetInSec, InputSectionBase<ELFT> *TargetSec, uintX_t OffsetInTargetSec, uintX_t Addend) : Type(Type), OKind(Off_Sec), OffsetSec(OffsetSec), @@ -267,7 +254,6 @@ private: template <class ELFT> class RelocationSection final : public OutputSectionBase<ELFT> { - typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym; typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel Elf_Rel; typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela Elf_Rela; typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t; diff --git a/lld/ELF/Target.cpp b/lld/ELF/Target.cpp index 01baba91d44..a2a609cdd58 100644 --- a/lld/ELF/Target.cpp +++ b/lld/ELF/Target.cpp @@ -181,8 +181,8 @@ public: int32_t Index, unsigned RelOff) const override; unsigned getTlsGotRel(unsigned Type) const override; bool isTlsDynRel(unsigned Type, const SymbolBody &S) const override; + bool isRelRelative(uint32_t Type) const override; bool needsCopyRelImpl(uint32_t Type) const override; - bool needsDynRelative(unsigned Type) const override; bool needsGot(uint32_t Type, SymbolBody &S) const override; PltNeed needsPlt(uint32_t Type, const SymbolBody &S) const override; void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P, @@ -1209,6 +1209,8 @@ AArch64TargetInfo::AArch64TargetInfo() { PltZeroSize = 32; } +bool AArch64TargetInfo::isRelRelative(uint32_t Type) const { return false; } + bool AArch64TargetInfo::isTlsGlobalDynamicRel(unsigned Type) const { return Type == R_AARCH64_TLSDESC_ADR_PAGE21 || Type == R_AARCH64_TLSDESC_LD64_LO12_NC || @@ -1305,10 +1307,6 @@ bool AArch64TargetInfo::needsCopyRelImpl(uint32_t Type) const { } } -bool AArch64TargetInfo::needsDynRelative(unsigned Type) const { - return Config->Shared && Type == R_AARCH64_ABS64; -} - bool AArch64TargetInfo::needsGot(uint32_t Type, SymbolBody &S) const { switch (Type) { case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index ab844d368e1..0f7edf80e8e 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -311,16 +311,9 @@ void Writer<ELFT>::scanRelocs( if (handleTlsRelocation<ELFT>(Type, Body, C, RI)) continue; - if (Target->needsDynRelative(Type)) { - // If Body is null it means the relocation is against a local symbol - // and thus we need to pass the local symbol index instead. - if (Body) - Out<ELFT>::RelaDyn->addReloc({Target->RelativeRel, &C, RI.r_offset, true, - Body, getAddend<ELFT>(RI)}); - else - Out<ELFT>::RelaDyn->addReloc({Target->RelativeRel, &C, RI.r_offset, false, - SymIndex, getAddend<ELFT>(RI)}); - } + if (Target->needsDynRelative(Type)) + Out<ELFT>::RelaDyn->addReloc({Target->RelativeRel, &C, RI.r_offset, true, + Body, getAddend<ELFT>(RI)}); // MIPS has a special rule to create GOTs for local symbols. if (Config->EMachine == EM_MIPS && !canBePreempted(Body, true) && diff --git a/lld/test/ELF/aarch64-abs64-dyn.s b/lld/test/ELF/aarch64-abs64-dyn.s index f9605efd3a1..d1242c22869 100644 --- a/lld/test/ELF/aarch64-abs64-dyn.s +++ b/lld/test/ELF/aarch64-abs64-dyn.s @@ -1,21 +1,27 @@ // REQUIRES: aarch64 // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o -// Creates a R_AARCH64_ABS64 relocation against _foo. It will be used on a -// shared object to check for a dynamic relocation creation. -.globl _foo -_foo: - ret -_foo_init_array: - .xword _foo +// Creates a R_AARCH64_ABS64 relocation against foo and bar + .globl foo +foo: + + .global bar + .hidden bar +bar: + + .data + .xword foo + .xword bar // RUN: ld.lld -shared -o %t.so %t.o // RUN: llvm-readobj -symbols -dyn-relocations %t.so | FileCheck %s -// CHECK: Dynamic Relocations { -// CHECK-NEXT: {{.*}} R_AARCH64_RELATIVE - [[FOO_ADDR:[0-9xa-f]+]] +// CHECK: Dynamic Relocations { +// CHECK-NEXT: {{.*}} R_AARCH64_ABS64 foo 0x0 +// CHECK-NEXT: {{.*}} R_AARCH64_RELATIVE - [[BAR_ADDR:.*]] +// CHECK-NEXT: } -// CHECK: Symbols [ -// CHECK: Symbol { -// CHECK: Name: _foo -// CHECK: Value: [[FOO_ADDR]] +// CHECK: Symbols [ +// CHECK: Symbol { +// CHECK: Name: bar +// CHECK-NEXT: Value: [[BAR_ADDR]] |

