[lld] r261651 - [lld] [ELF/AArch64] Fix R_AARCH64_ABS64 in Shared mode
Rafael EspĂndola via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 23 12:04:22 PST 2016
At the very least the test is wrong. This symbol foo can be preempted
and we cannot use a relative relocation.
Cheers,
Rafael
On 23 February 2016 at 11:54, Adhemerval Zanella via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: azanella
> Date: Tue Feb 23 10:54:40 2016
> New Revision: 261651
>
> URL: http://llvm.org/viewvc/llvm-project?rev=261651&view=rev
> Log:
> [lld] [ELF/AArch64] Fix R_AARCH64_ABS64 in Shared mode
>
> This patch fixes the R_AARCH64_ABS64 relocation when used in shared mode,
> where it requires a dynamic R_AARCH64_RELATIVE relocation. To correct set
> the addend on the dynamic relocation (since it will be used by the dynamic
> linker), a new TargetInfo specific hook was created (getDynRelativeAddend)
> to get the correct addend based on relocation type.
>
> The patch fixes the issues when creating shared library code against
> {init,fini}_array, where it issues R_AARCH64_ABS64 relocation against
> local symbols.
>
> Added:
> lld/trunk/test/ELF/aarch64-abs64-dyn.s
> Modified:
> lld/trunk/ELF/OutputSections.cpp
> lld/trunk/ELF/OutputSections.h
> lld/trunk/ELF/Target.cpp
> lld/trunk/ELF/Writer.cpp
>
> Modified: lld/trunk/ELF/OutputSections.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=261651&r1=261650&r2=261651&view=diff
> ==============================================================================
> --- lld/trunk/ELF/OutputSections.cpp (original)
> +++ lld/trunk/ELF/OutputSections.cpp Tue Feb 23 10:54:40 2016
> @@ -253,11 +253,18 @@ template <class ELFT> void RelocationSec
>
> 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;
> }
>
> @@ -862,7 +869,6 @@ elf2::getLocalRelTarget(const ObjectFile
> 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.
> @@ -875,10 +881,22 @@ elf2::getLocalRelTarget(const ObjectFile
> if (!Sym)
> fatal("Unsupported relocation without symbol");
>
> - InputSectionBase<ELFT> *Section = File.getSection(*Sym);
> + 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;
>
> - 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
> @@ -888,8 +906,8 @@ elf2::getLocalRelTarget(const ObjectFile
> 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;
> }
> @@ -1647,5 +1665,18 @@ template uint64_t getLocalRelTarget(cons
> 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);
> }
> }
>
> Modified: lld/trunk/ELF/OutputSections.h
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=261651&r1=261650&r2=261651&view=diff
> ==============================================================================
> --- lld/trunk/ELF/OutputSections.h (original)
> +++ lld/trunk/ELF/OutputSections.h Tue Feb 23 10:54:40 2016
> @@ -53,6 +53,12 @@ getLocalRelTarget(const ObjectFile<ELFT>
> 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.
> @@ -187,6 +193,7 @@ template <class ELFT> struct DynamicRelo
> } OKind;
>
> SymbolBody *Sym = nullptr;
> + uint32_t SymIndex = 0;
> InputSectionBase<ELFT> *OffsetSec = nullptr;
> uintX_t OffsetInSec = 0;
> bool UseSymVA = false;
> @@ -207,6 +214,12 @@ template <class ELFT> struct DynamicRelo
> 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),
> @@ -254,6 +267,7 @@ 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;
>
> Modified: lld/trunk/ELF/Target.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=261651&r1=261650&r2=261651&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Target.cpp (original)
> +++ lld/trunk/ELF/Target.cpp Tue Feb 23 10:54:40 2016
> @@ -182,6 +182,7 @@ public:
> unsigned getTlsGotRel(unsigned Type) const override;
> bool isTlsDynRel(unsigned Type, const SymbolBody &S) 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,
> @@ -1212,6 +1213,7 @@ void PPC64TargetInfo::relocateOne(uint8_
>
> AArch64TargetInfo::AArch64TargetInfo() {
> CopyRel = R_AARCH64_COPY;
> + RelativeRel = R_AARCH64_RELATIVE;
> IRelativeRel = R_AARCH64_IRELATIVE;
> GotRel = R_AARCH64_GLOB_DAT;
> PltRel = R_AARCH64_JUMP_SLOT;
> @@ -1319,6 +1321,10 @@ bool AArch64TargetInfo::needsCopyRelImpl
> }
> }
>
> +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:
>
> Modified: lld/trunk/ELF/Writer.cpp
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=261651&r1=261650&r2=261651&view=diff
> ==============================================================================
> --- lld/trunk/ELF/Writer.cpp (original)
> +++ lld/trunk/ELF/Writer.cpp Tue Feb 23 10:54:40 2016
> @@ -311,9 +311,16 @@ void Writer<ELFT>::scanRelocs(
> if (handleTlsRelocation<ELFT>(Type, Body, C, RI))
> continue;
>
> - if (Target->needsDynRelative(Type))
> - Out<ELFT>::RelaDyn->addReloc({Target->RelativeRel, &C, RI.r_offset, true,
> - Body, getAddend<ELFT>(RI)});
> + 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)});
> + }
>
> // MIPS has a special rule to create GOTs for local symbols.
> if (Config->EMachine == EM_MIPS && !canBePreempted(Body, true) &&
>
> Added: lld/trunk/test/ELF/aarch64-abs64-dyn.s
> URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/aarch64-abs64-dyn.s?rev=261651&view=auto
> ==============================================================================
> --- lld/trunk/test/ELF/aarch64-abs64-dyn.s (added)
> +++ lld/trunk/test/ELF/aarch64-abs64-dyn.s Tue Feb 23 10:54:40 2016
> @@ -0,0 +1,21 @@
> +// 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
> +
> +// 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: Symbols [
> +// CHECK: Symbol {
> +// CHECK: Name: _foo
> +// CHECK: Value: [[FOO_ADDR]]
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list