[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:24:52 PST 2016


Fixed in r261678.

On 23 February 2016 at 15:04, Rafael EspĂ­ndola
<rafael.espindola at gmail.com> wrote:
> 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