[lld] r250808 - [ELF2] - Lazy relocation support for x86_64.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 20 09:43:11 PDT 2015


On Tue, Oct 20, 2015 at 9:27 AM, Rafael EspĂ­ndola <
llvm-commits at lists.llvm.org> wrote:

> Congratulations, this is a pretty big feature!
>
> Would you mind adding a command line option for getting the old
> format? When lazy loading is not used, the old format has a few
> advantages
>
> * Entries are not potentially duplicated in .got and .got.plt
> * PLT entries are smaller
>
> long run we should implement -mno-plt in clang, but this option would
> be useful for experimenting with old .o files.
>

Does that worth to do now? That sounds like an experimental "good to have"
feature. We are probably not going to use that often. (If you want to
resolve all symbols, you can use LD_BIND_NOW.) I actually requested in code
review to not add new code but replace the existing code in order to keep
it simple. I'm not totally against the idea itself, but in general I'm
leaning toward to not do that.


> Thanks,
> Rafael
>
>
>
> On 20 October 2015 at 04:54, George Rimar via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
> > Author: grimar
> > Date: Tue Oct 20 03:54:27 2015
> > New Revision: 250808
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=250808&view=rev
> > Log:
> > [ELF2] - Lazy relocation support for x86_64.
> >
> > Target has supportsLazyRelocations() method which can switch lazy
> relocations on/off (currently all targets are OFF except x64 which is ON).
> So no any other targets are affected now.
> >
> > Differential Revision: http://reviews.llvm.org/D13856?id=37726
> >
> > Modified:
> >     lld/trunk/ELF/OutputSections.cpp
> >     lld/trunk/ELF/OutputSections.h
> >     lld/trunk/ELF/Symbols.h
> >     lld/trunk/ELF/Target.cpp
> >     lld/trunk/ELF/Target.h
> >     lld/trunk/ELF/Writer.cpp
> >     lld/trunk/test/elf2/dynamic-reloc-weak.s
> >     lld/trunk/test/elf2/plt.s
> >     lld/trunk/test/elf2/relocation.s
> >
> > Modified: lld/trunk/ELF/OutputSections.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=250808&r1=250807&r2=250808&view=diff
> >
> ==============================================================================
> > --- lld/trunk/ELF/OutputSections.cpp (original)
> > +++ lld/trunk/ELF/OutputSections.cpp Tue Oct 20 03:54:27 2015
> > @@ -30,6 +30,44 @@ OutputSectionBase<ELFT>::OutputSectionBa
> >  }
> >
> >  template <class ELFT>
> > +GotPltSection<ELFT>::GotPltSection()
> > +    : OutputSectionBase<ELFT>(".got.plt", llvm::ELF::SHT_PROGBITS,
> > +                              llvm::ELF::SHF_ALLOC |
> llvm::ELF::SHF_WRITE) {
> > +  this->Header.sh_addralign = sizeof(uintX_t);
> > +  // .got.plt has 3 reserved entry
> > +  Entries.resize(3);
> > +}
> > +
> > +template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody
> *Sym) {
> > +  Sym->GotPltIndex = Entries.size();
> > +  Entries.push_back(Sym);
> > +}
> > +
> > +template <class ELFT> bool GotPltSection<ELFT>::empty() const {
> > +  return Entries.size() == 3;
> > +}
> > +
> > +template <class ELFT>
> > +typename GotPltSection<ELFT>::uintX_t
> > +GotPltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
> > +  return this->getVA() + B.GotPltIndex * sizeof(uintX_t);
> > +}
> > +
> > +template <class ELFT> void GotPltSection<ELFT>::finalize() {
> > +  this->Header.sh_size = Entries.size() * sizeof(uintX_t);
> > +}
> > +
> > +template <class ELFT> void GotPltSection<ELFT>::writeTo(uint8_t *Buf) {
> > +  write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(
> > +      Buf, Out<ELFT>::Dynamic->getVA());
> > +  for (const SymbolBody *B : Entries) {
> > +    if (B)
> > +      Target->writeGotPltEntry(Buf, Out<ELFT>::Plt->getEntryAddr(*B));
> > +    Buf += sizeof(uintX_t);
> > +  }
> > +}
> > +
> > +template <class ELFT>
> >  GotSection<ELFT>::GotSection()
> >      : OutputSectionBase<ELFT>(".got", llvm::ELF::SHT_PROGBITS,
> >                                llvm::ELF::SHF_ALLOC |
> llvm::ELF::SHF_WRITE) {
> > @@ -67,10 +105,17 @@ PltSection<ELFT>::PltSection()
> >
> >  template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) {
> >    size_t Off = 0;
> > +  bool LazyReloc = Target->supportsLazyRelocations();
> > +  if (LazyReloc) {
> > +    // First write PLT[0] entry which is special.
> > +    Target->writePltZeroEntry(Buf, Out<ELFT>::GotPlt->getVA(),
> this->getVA());
> > +    Off += Target->getPltZeroEntrySize();
> > +  }
> >    for (const SymbolBody *E : Entries) {
> > -    uint64_t Got = Out<ELFT>::Got->getEntryAddr(*E);
> > +    uint64_t Got = LazyReloc ? Out<ELFT>::GotPlt->getEntryAddr(*E)
> > +                             : Out<ELFT>::Got->getEntryAddr(*E);
> >      uint64_t Plt = this->getVA() + Off;
> > -    Target->writePltEntry(Buf + Off, Got, Plt);
> > +    Target->writePltEntry(Buf + Off, Got, Plt, E->PltIndex);
> >      Off += Target->getPltEntrySize();
> >    }
> >  }
> > @@ -83,17 +128,18 @@ template <class ELFT> void PltSection<EL
> >  template <class ELFT>
> >  typename PltSection<ELFT>::uintX_t
> >  PltSection<ELFT>::getEntryAddr(const SymbolBody &B) const {
> > -  return this->getVA() + B.PltIndex * Target->getPltEntrySize();
> > +  return this->getVA() + Target->getPltZeroEntrySize() +
> > +         B.PltIndex * Target->getPltEntrySize();
> >  }
> >
> > -template <class ELFT>
> > -void PltSection<ELFT>::finalize() {
> > -  this->Header.sh_size = Entries.size() * Target->getPltEntrySize();
> > +template <class ELFT> void PltSection<ELFT>::finalize() {
> > +  this->Header.sh_size = Target->getPltZeroEntrySize() +
> > +                         Entries.size() * Target->getPltEntrySize();
> >  }
> >
> >  template <class ELFT>
> > -RelocationSection<ELFT>::RelocationSection(bool IsRela)
> > -    : OutputSectionBase<ELFT>(IsRela ? ".rela.dyn" : ".rel.dyn",
> > +RelocationSection<ELFT>::RelocationSection(StringRef Name, bool IsRela)
> > +    : OutputSectionBase<ELFT>(Name,
> >                                IsRela ? llvm::ELF::SHT_RELA :
> llvm::ELF::SHT_REL,
> >                                llvm::ELF::SHF_ALLOC),
> >        IsRela(IsRela) {
> > @@ -118,11 +164,15 @@ template <class ELFT> void RelocationSec
> >      uint32_t Type = RI.getType(Config->Mips64EL);
> >      bool NeedsGot = Body && Target->relocNeedsGot(Type, *Body);
> >      bool CanBePreempted = canBePreempted(Body, NeedsGot);
> > +    bool LazyReloc = Body && Target->supportsLazyRelocations() &&
> > +                     Target->relocNeedsPlt(Type, *Body);
> >
> >      if (CanBePreempted) {
> >        if (NeedsGot)
> >          P->setSymbolAndType(Body->getDynamicSymbolTableIndex(),
> > -                            Target->getGotReloc(), Config->Mips64EL);
> > +                            LazyReloc ? Target->getPltReloc()
> > +                                      : Target->getGotReloc(),
> > +                            Config->Mips64EL);
> >        else
> >          P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Type,
> >                              Config->Mips64EL);
> > @@ -130,10 +180,14 @@ template <class ELFT> void RelocationSec
> >        P->setSymbolAndType(0, Target->getRelativeReloc(),
> Config->Mips64EL);
> >      }
> >
> > -    if (NeedsGot)
> > -      P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
> > -    else
> > +    if (NeedsGot) {
> > +      if (LazyReloc)
> > +        P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body);
> > +      else
> > +        P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
> > +    } else {
> >        P->r_offset = RI.r_offset + C.OutSec->getVA() + C.OutSecOff;
> > +    }
> >
> >      uintX_t OrigAddend = 0;
> >      if (IsRela && !NeedsGot)
> > @@ -256,6 +310,13 @@ template <class ELFT> void DynamicSectio
> >      ++NumEntries; // DT_RELASZ / DT_RELSZ
> >      ++NumEntries; // DT_RELAENT / DT_RELENT
> >    }
> > +  if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
> > +    ++NumEntries; // DT_JMPREL
> > +    ++NumEntries; // DT_PLTRELSZ
> > +    ++NumEntries; // DT_PLTGOT
> > +    ++NumEntries; // DT_PLTREL
> > +  }
> > +
> >    ++NumEntries; // DT_SYMTAB
> >    ++NumEntries; // DT_SYMENT
> >    ++NumEntries; // DT_STRTAB
> > @@ -325,6 +386,12 @@ template <class ELFT> void DynamicSectio
> >      WriteVal(IsRela ? DT_RELAENT : DT_RELENT,
> >               IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel));
> >    }
> > +  if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
> > +    WritePtr(DT_JMPREL, Out<ELFT>::RelaPlt->getVA());
> > +    WriteVal(DT_PLTRELSZ, Out<ELFT>::RelaPlt->getSize());
> > +    WritePtr(DT_PLTGOT, Out<ELFT>::GotPlt->getVA());
> > +    WriteVal(DT_PLTREL, Out<ELFT>::RelaPlt->isRela() ? DT_RELA :
> DT_REL);
> > +  }
> >
> >    WritePtr(DT_SYMTAB, Out<ELFT>::DynSymTab->getVA());
> >    WritePtr(DT_SYMENT, sizeof(Elf_Sym));
> > @@ -765,6 +832,11 @@ template class OutputSectionBase<ELF32BE
> >  template class OutputSectionBase<ELF64LE>;
> >  template class OutputSectionBase<ELF64BE>;
> >
> > +template class GotPltSection<ELF32LE>;
> > +template class GotPltSection<ELF32BE>;
> > +template class GotPltSection<ELF64LE>;
> > +template class GotPltSection<ELF64BE>;
> > +
> >  template class GotSection<ELF32LE>;
> >  template class GotSection<ELF32BE>;
> >  template class GotSection<ELF64LE>;
> >
> > Modified: lld/trunk/ELF/OutputSections.h
> > URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.h?rev=250808&r1=250807&r2=250808&view=diff
> >
> ==============================================================================
> > --- lld/trunk/ELF/OutputSections.h (original)
> > +++ lld/trunk/ELF/OutputSections.h Tue Oct 20 03:54:27 2015
> > @@ -122,6 +122,22 @@ private:
> >    std::vector<const SymbolBody *> Entries;
> >  };
> >
> > +template <class ELFT>
> > +class GotPltSection final : public OutputSectionBase<ELFT> {
> > +  typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
> > +
> > +public:
> > +  GotPltSection();
> > +  void finalize() override;
> > +  void writeTo(uint8_t *Buf) override;
> > +  void addEntry(SymbolBody *Sym);
> > +  bool empty() const;
> > +  uintX_t getEntryAddr(const SymbolBody &B) const;
> > +
> > +private:
> > +  std::vector<const SymbolBody *> Entries;
> > +};
> > +
> >  template <class ELFT> class PltSection final : public
> OutputSectionBase<ELFT> {
> >    typedef OutputSectionBase<ELFT> Base;
> >    typedef typename Base::uintX_t uintX_t;
> > @@ -177,7 +193,7 @@ class RelocationSection final : public O
> >    typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
> >
> >  public:
> > -  RelocationSection(bool IsRela);
> > +  RelocationSection(StringRef Name, bool IsRela);
> >    void addReloc(const DynamicReloc<ELFT> &Reloc) {
> Relocs.push_back(Reloc); }
> >    void finalize() override;
> >    void writeTo(uint8_t *Buf) override;
> > @@ -294,6 +310,7 @@ private:
> >  // until Writer is initialized.
> >  template <class ELFT> struct Out {
> >    static DynamicSection<ELFT> *Dynamic;
> > +  static GotPltSection<ELFT> *GotPlt;
> >    static GotSection<ELFT> *Got;
> >    static HashTableSection<ELFT> *HashTab;
> >    static InterpSection<ELFT> *Interp;
> > @@ -302,6 +319,7 @@ template <class ELFT> struct Out {
> >    static uint8_t *OpdBuf;
> >    static PltSection<ELFT> *Plt;
> >    static RelocationSection<ELFT> *RelaDyn;
> > +  static RelocationSection<ELFT> *RelaPlt;
> >    static StringTableSection<ELFT> *DynStrTab;
> >    static StringTableSection<ELFT> *StrTab;
> >    static SymbolTableSection<ELFT> *DynSymTab;
> > @@ -309,6 +327,7 @@ template <class ELFT> struct Out {
> >  };
> >
> >  template <class ELFT> DynamicSection<ELFT> *Out<ELFT>::Dynamic;
> > +template <class ELFT> GotPltSection<ELFT> *Out<ELFT>::GotPlt;
> >  template <class ELFT> GotSection<ELFT> *Out<ELFT>::Got;
> >  template <class ELFT> HashTableSection<ELFT> *Out<ELFT>::HashTab;
> >  template <class ELFT> InterpSection<ELFT> *Out<ELFT>::Interp;
> > @@ -317,6 +336,7 @@ template <class ELFT> OutputSectionBase<
> >  template <class ELFT> uint8_t *Out<ELFT>::OpdBuf;
> >  template <class ELFT> PltSection<ELFT> *Out<ELFT>::Plt;
> >  template <class ELFT> RelocationSection<ELFT> *Out<ELFT>::RelaDyn;
> > +template <class ELFT> RelocationSection<ELFT> *Out<ELFT>::RelaPlt;
> >  template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::DynStrTab;
> >  template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::StrTab;
> >  template <class ELFT> SymbolTableSection<ELFT> *Out<ELFT>::DynSymTab;
> >
> > Modified: lld/trunk/ELF/Symbols.h
> > URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=250808&r1=250807&r2=250808&view=diff
> >
> ==============================================================================
> > --- lld/trunk/ELF/Symbols.h (original)
> > +++ lld/trunk/ELF/Symbols.h Tue Oct 20 03:54:27 2015
> > @@ -93,8 +93,10 @@ public:
> >    void setDynamicSymbolTableIndex(unsigned V) { DynamicSymbolTableIndex
> = V; }
> >
> >    uint32_t GotIndex = -1;
> > +  uint32_t GotPltIndex = -1;
> >    uint32_t PltIndex = -1;
> >    bool isInGot() const { return GotIndex != -1U; }
> > +  bool isInGotPlt() const { return GotPltIndex != -1U; }
> >    bool isInPlt() const { return PltIndex != -1U; }
> >
> >    // A SymbolBody has a backreference to a Symbol. Originally they are
> >
> > Modified: lld/trunk/ELF/Target.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=250808&r1=250807&r2=250808&view=diff
> >
> ==============================================================================
> > --- lld/trunk/ELF/Target.cpp (original)
> > +++ lld/trunk/ELF/Target.cpp Tue Oct 20 03:54:27 2015
> > @@ -47,8 +47,11 @@ namespace {
> >  class X86TargetInfo final : public TargetInfo {
> >  public:
> >    X86TargetInfo();
> > +  void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
> > +  void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > +                         uint64_t PltEntryAddr) const override;
> >    void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > -                     uint64_t PltEntryAddr) const override;
> > +                     uint64_t PltEntryAddr, int32_t Index) const
> override;
> >    bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
> >    bool relocPointsToGot(uint32_t Type) const override;
> >    bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
> > @@ -61,8 +64,11 @@ class X86_64TargetInfo final : public Ta
> >  public:
> >    X86_64TargetInfo();
> >    unsigned getPLTRefReloc(unsigned Type) const override;
> > +  void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
> > +  void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > +                         uint64_t PltEntryAddr) const override;
> >    void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > -                     uint64_t PltEntryAddr) const override;
> > +                     uint64_t PltEntryAddr, int32_t Index) const
> override;
> >    bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
> >    bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
> >    void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
> > @@ -74,8 +80,11 @@ public:
> >  class PPC64TargetInfo final : public TargetInfo {
> >  public:
> >    PPC64TargetInfo();
> > +  void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
> > +  void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > +                         uint64_t PltEntryAddr) const override;
> >    void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > -                     uint64_t PltEntryAddr) const override;
> > +                     uint64_t PltEntryAddr, int32_t Index) const
> override;
> >    bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
> >    bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
> >    void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
> > @@ -87,8 +96,11 @@ public:
> >  class AArch64TargetInfo final : public TargetInfo {
> >  public:
> >    AArch64TargetInfo();
> > +  void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
> > +  void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > +                         uint64_t PltEntryAddr) const override;
> >    void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > -                     uint64_t PltEntryAddr) const override;
> > +                     uint64_t PltEntryAddr, int32_t Index) const
> override;
> >    bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
> >    bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
> >    void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
> > @@ -99,8 +111,11 @@ public:
> >  template <class ELFT> class MipsTargetInfo final : public TargetInfo {
> >  public:
> >    MipsTargetInfo();
> > +  void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
> > +  void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > +                         uint64_t PltEntryAddr) const override;
> >    void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > -                     uint64_t PltEntryAddr) const override;
> > +                     uint64_t PltEntryAddr, int32_t Index) const
> override;
> >    bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
> >    bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
> >    void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
> > @@ -144,10 +159,15 @@ X86TargetInfo::X86TargetInfo() {
> >    PCRelReloc = R_386_PC32;
> >    GotReloc = R_386_GLOB_DAT;
> >    GotRefReloc = R_386_GOT32;
> > +  PltReloc = R_386_JUMP_SLOT;
> >  }
> >
> > +void X86TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const
> {}
> > +void X86TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t
> GotEntryAddr,
> > +                                      uint64_t PltEntryAddr) const {}
> > +
> >  void X86TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > -                                  uint64_t PltEntryAddr) const {
> > +                                  uint64_t PltEntryAddr, int32_t Index)
> const {
> >    // jmpl *val; nop; nop
> >    const uint8_t Inst[] = {0xff, 0x25, 0, 0, 0, 0, 0x90, 0x90};
> >    memcpy(Buf, Inst, sizeof(Inst));
> > @@ -194,19 +214,43 @@ X86_64TargetInfo::X86_64TargetInfo() {
> >    PCRelReloc = R_X86_64_PC32;
> >    GotReloc = R_X86_64_GLOB_DAT;
> >    GotRefReloc = R_X86_64_PC32;
> > +  PltReloc = R_X86_64_JUMP_SLOT;
> >    RelativeReloc = R_X86_64_RELATIVE;
> > +  LazyRelocations = true;
> > +  PltEntrySize = 16;
> > +  PltZeroEntrySize = 16;
> > +}
> > +
> > +void X86_64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt)
> const {
> > +  // Skip 6 bytes of "jmpq *got(%rip)"
> > +  write32le(Buf, Plt + 6);
> > +}
> > +
> > +void X86_64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t
> GotEntryAddr,
> > +                                         uint64_t PltEntryAddr) const {
> > +  const uint8_t PltData[] = {
> > +      0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOT+8(%rip)
> > +      0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOT+16(%rip)
> > +      0x0f, 0x1f, 0x40, 0x00              // nopl 0x0(rax)
> > +  };
> > +  memcpy(Buf, PltData, sizeof(PltData));
> > +  write32le(Buf + 2, GotEntryAddr - PltEntryAddr + 2); // GOT+8
> > +  write32le(Buf + 8, GotEntryAddr - PltEntryAddr + 4); // GOT+16
> >  }
> >
> >  void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t
> GotEntryAddr,
> > -                                     uint64_t PltEntryAddr) const {
> > -  // jmpq *val(%rip); nop; nop
> > -  const uint8_t Inst[] = {0xff, 0x25, 0, 0, 0, 0, 0x90, 0x90};
> > +                                     uint64_t PltEntryAddr,
> > +                                     int32_t Index) const {
> > +  const uint8_t Inst[] = {
> > +      0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip)
> > +      0x68, 0x00, 0x00, 0x00, 0x00,       // pushq <relocation index>
> > +      0xe9, 0x00, 0x00, 0x00, 0x00        // jmpq plt[0]
> > +  };
> >    memcpy(Buf, Inst, sizeof(Inst));
> >
> > -  uint64_t NextPC = PltEntryAddr + 6;
> > -  int64_t Delta = GotEntryAddr - NextPC;
> > -  assert(isInt<32>(Delta));
> > -  write32le(Buf + 2, Delta);
> > +  write32le(Buf + 2, GotEntryAddr - PltEntryAddr - 6);
> > +  write32le(Buf + 7, Index);
> > +  write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 16);
> >  }
> >
> >  bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody
> &S) const {
> > @@ -364,8 +408,11 @@ uint64_t getPPC64TocBase() {
> >    return TocVA + 0x8000;
> >  }
> >
> > +void PPC64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt)
> const {}
> > +void PPC64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t
> GotEntryAddr,
> > +                                        uint64_t PltEntryAddr) const {}
> >  void PPC64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > -                                    uint64_t PltEntryAddr) const {
> > +                                    uint64_t PltEntryAddr, int32_t
> Index) const {
> >    uint64_t Off = GotEntryAddr - getPPC64TocBase();
> >
> >    // FIXME: What we should do, in theory, is get the offset of the
> function
> > @@ -548,8 +595,12 @@ AArch64TargetInfo::AArch64TargetInfo() {
> >    // PCRelReloc = FIXME
> >    // GotReloc = FIXME
> >  }
> > +
> > +void AArch64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt)
> const {}
> > +void AArch64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t
> GotEntryAddr,
> > +                                          uint64_t PltEntryAddr) const
> {}
> >  void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t
> GotEntryAddr,
> > -                                      uint64_t PltEntryAddr) const {}
> > +                                      uint64_t PltEntryAddr, int32_t
> Index) const {}
> >  bool AArch64TargetInfo::relocNeedsGot(uint32_t Type,
> >                                        const SymbolBody &S) const {
> >    return false;
> > @@ -630,8 +681,13 @@ template <class ELFT> MipsTargetInfo<ELF
> >  }
> >
> >  template <class ELFT>
> > +void MipsTargetInfo<ELFT>::writeGotPltEntry(uint8_t *Buf, uint64_t Plt)
> const {}
> > +template <class ELFT>
> > +void MipsTargetInfo<ELFT>::writePltZeroEntry(uint8_t *Buf, uint64_t
> GotEntryAddr,
> > +                                       uint64_t PltEntryAddr) const {}
> > +template <class ELFT>
> >  void MipsTargetInfo<ELFT>::writePltEntry(uint8_t *Buf, uint64_t
> GotEntryAddr,
> > -                                         uint64_t PltEntryAddr) const {}
> > +                                         uint64_t PltEntryAddr, int32_t
> Index) const {}
> >
> >  template <class ELFT>
> >  bool MipsTargetInfo<ELFT>::relocNeedsGot(uint32_t Type,
> >
> > Modified: lld/trunk/ELF/Target.h
> > URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=250808&r1=250807&r2=250808&view=diff
> >
> ==============================================================================
> > --- lld/trunk/ELF/Target.h (original)
> > +++ lld/trunk/ELF/Target.h Tue Oct 20 03:54:27 2015
> > @@ -24,12 +24,18 @@ public:
> >    uint64_t getVAStart() const { return VAStart; }
> >    unsigned getPCRelReloc() const { return PCRelReloc; }
> >    unsigned getGotReloc() const { return GotReloc; }
> > +  unsigned getPltReloc() const { return PltReloc; }
> >    unsigned getGotRefReloc() const { return GotRefReloc; }
> >    unsigned getRelativeReloc() const { return RelativeReloc; }
> > +  unsigned getPltZeroEntrySize() const { return PltZeroEntrySize; }
> >    unsigned getPltEntrySize() const { return PltEntrySize; }
> > +  bool supportsLazyRelocations() const { return LazyRelocations; }
> >    virtual unsigned getPLTRefReloc(unsigned Type) const;
> > +  virtual void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const = 0;
> > +  virtual void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > +                                 uint64_t PltEntryAddr) const = 0;
> >    virtual void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
> > -                             uint64_t PltEntryAddr) const = 0;
> > +                             uint64_t PltEntryAddr, int32_t Index)
> const = 0;
> >    virtual bool isRelRelative(uint32_t Type) const;
> >    virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const
> = 0;
> >    virtual bool relocPointsToGot(uint32_t Type) const;
> > @@ -54,8 +60,11 @@ protected:
> >    unsigned PCRelReloc;
> >    unsigned GotRefReloc;
> >    unsigned GotReloc;
> > +  unsigned PltReloc;
> >    unsigned RelativeReloc;
> >    unsigned PltEntrySize = 8;
> > +  unsigned PltZeroEntrySize = 0;
> > +  bool LazyRelocations = false;
> >  };
> >
> >  uint64_t getPPC64TocBase();
> >
> > Modified: lld/trunk/ELF/Writer.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=250808&r1=250807&r2=250808&view=diff
> >
> ==============================================================================
> > --- lld/trunk/ELF/Writer.cpp (original)
> > +++ lld/trunk/ELF/Writer.cpp Tue Oct 20 03:54:27 2015
> > @@ -102,6 +102,9 @@ template <class ELFT> void lld::elf2::wr
> >    Out<ELFT>::Bss = &Bss;
> >    GotSection<ELFT> Got;
> >    Out<ELFT>::Got = &Got;
> > +  GotPltSection<ELFT> GotPlt;
> > +  if (Target->supportsLazyRelocations())
> > +    Out<ELFT>::GotPlt = &GotPlt;
> >    PltSection<ELFT> Plt;
> >    Out<ELFT>::Plt = &Plt;
> >    SymbolTableSection<ELFT> SymTab(*Symtab, *Out<ELFT>::StrTab);
> > @@ -110,8 +113,12 @@ template <class ELFT> void lld::elf2::wr
> >    Out<ELFT>::DynSymTab = &DynSymTab;
> >    HashTableSection<ELFT> HashTab;
> >    Out<ELFT>::HashTab = &HashTab;
> > -  RelocationSection<ELFT> RelaDyn(Symtab->shouldUseRela());
> > +  bool IsRela = Symtab->shouldUseRela();
> > +  RelocationSection<ELFT> RelaDyn(IsRela ? ".rela.dyn" : ".rel.dyn",
> IsRela);
> >    Out<ELFT>::RelaDyn = &RelaDyn;
> > +  RelocationSection<ELFT> RelaPlt(IsRela ? ".rela.plt" : ".rel.plt",
> IsRela);
> > +  if (Target->supportsLazyRelocations())
> > +    Out<ELFT>::RelaPlt = &RelaPlt;
> >    DynamicSection<ELFT> Dynamic(*Symtab);
> >    Out<ELFT>::Dynamic = &Dynamic;
> >
> > @@ -189,17 +196,23 @@ void Writer<ELFT>::scanRelocs(
> >      if (Body)
> >        Body = Body->repl();
> >      bool NeedsGot = false;
> > +    bool NeedsPlt = false;
> >      if (Body) {
> > -      if (Target->relocNeedsPlt(Type, *Body)) {
> > +      NeedsPlt = Target->relocNeedsPlt(Type, *Body);
> > +      if (NeedsPlt) {
> >          if (Body->isInPlt())
> >            continue;
> >          Out<ELFT>::Plt->addEntry(Body);
> >        }
> >        NeedsGot = Target->relocNeedsGot(Type, *Body);
> >        if (NeedsGot) {
> > -        if (Body->isInGot())
> > -          continue;
> > -        Out<ELFT>::Got->addEntry(Body);
> > +        if (NeedsPlt && Target->supportsLazyRelocations()) {
> > +          Out<ELFT>::GotPlt->addEntry(Body);
> > +        } else {
> > +          if (Body->isInGot())
> > +            continue;
> > +          Out<ELFT>::Got->addEntry(Body);
> > +        }
> >        }
> >      }
> >
> > @@ -208,7 +221,10 @@ void Writer<ELFT>::scanRelocs(
> >        continue;
> >      if (CBP)
> >        Body->setUsedInDynamicReloc();
> > -    Out<ELFT>::RelaDyn->addReloc({C, RI});
> > +    if (NeedsPlt && Target->supportsLazyRelocations())
> > +      Out<ELFT>::RelaPlt->addReloc({C, RI});
> > +    else
> > +      Out<ELFT>::RelaDyn->addReloc({C, RI});
> >    }
> >  }
> >
> > @@ -508,9 +524,13 @@ template <class ELFT> void Writer<ELFT>:
> >      OutputSections.push_back(Out<ELFT>::DynStrTab);
> >      if (Out<ELFT>::RelaDyn->hasRelocs())
> >        OutputSections.push_back(Out<ELFT>::RelaDyn);
> > +    if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs())
> > +      OutputSections.push_back(Out<ELFT>::RelaPlt);
> >    }
> >    if (!Out<ELFT>::Got->empty())
> >      OutputSections.push_back(Out<ELFT>::Got);
> > +  if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
> > +    OutputSections.push_back(Out<ELFT>::GotPlt);
> >    if (!Out<ELFT>::Plt->empty())
> >      OutputSections.push_back(Out<ELFT>::Plt);
> >
> >
> > Modified: lld/trunk/test/elf2/dynamic-reloc-weak.s
> > URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/dynamic-reloc-weak.s?rev=250808&r1=250807&r2=250808&view=diff
> >
> ==============================================================================
> > --- lld/trunk/test/elf2/dynamic-reloc-weak.s (original)
> > +++ lld/trunk/test/elf2/dynamic-reloc-weak.s Tue Oct 20 03:54:27 2015
> > @@ -26,6 +26,8 @@ _start:
> >  // CHECK:      Relocations [
> >  // CHECK-NEXT:   Section ({{.*}}) .rela.dyn {
> >  // CHECK-NEXT:     0x{{.*}} R_X86_64_GLOB_DAT sym1 0x0
> > -// CHECK-NEXT:     0x{{.*}} R_X86_64_GLOB_DAT sym2 0x0
> >  // CHECK-NEXT:   }
> > -// CHECK-NEXT: ]
> > +// CHECK-NEXT:   Section ({{.*}}) .rela.plt {
> > +// CHECK-NEXT:     0x{{.*}} R_X86_64_JUMP_SLOT sym2 0x0
> > +// CHECK-NEXT:   }
> > +// CHECK-NEXT: ]
> > \ No newline at end of file
> >
> > Modified: lld/trunk/test/elf2/plt.s
> > URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/plt.s?rev=250808&r1=250807&r2=250808&view=diff
> >
> ==============================================================================
> > --- lld/trunk/test/elf2/plt.s (original)
> > +++ lld/trunk/test/elf2/plt.s Tue Oct 20 03:54:27 2015
> > @@ -18,16 +18,16 @@
> >  // CHECK-NEXT: ]
> >  // CHECK-NEXT: Address: 0x1020
> >  // CHECK-NEXT: Offset:
> > -// CHECK-NEXT: Size: 24
> > +// CHECK-NEXT: Size: 64
> >  // CHECK-NEXT: Link: 0
> >  // CHECK-NEXT: Info: 0
> >  // CHECK-NEXT: AddressAlignment: 16
> >
> >  // CHECK:      Relocations [
> > -// CHECK-NEXT:   Section ({{.*}}) .rela.dyn {
> > -// CHECK-NEXT:     0x20A0 R_X86_64_GLOB_DAT bar 0x0
> > -// CHECK-NEXT:     0x20A8 R_X86_64_GLOB_DAT zed 0x0
> > -// CHECK-NEXT:     0x20B0 R_X86_64_GLOB_DAT _start 0x0
> > +// CHECK-NEXT:   Section ({{.*}}) .rela.plt {
> > +// CHECK-NEXT:     0x20C8 R_X86_64_JUMP_SLOT bar 0x0
> > +// CHECK-NEXT:     0x20D0 R_X86_64_JUMP_SLOT zed 0x0
> > +// CHECK-NEXT:     0x20D8 R_X86_64_JUMP_SLOT _start 0x0
> >  // CHECK-NEXT:   }
> >  // CHECK-NEXT: ]
> >
> > @@ -39,67 +39,76 @@
> >  // CHECK2-NEXT: ]
> >  // CHECK2-NEXT: Address: 0x11020
> >  // CHECK2-NEXT: Offset:
> > -// CHECK2-NEXT: Size: 16
> > +// CHECK2-NEXT: Size: 48
> >  // CHECK2-NEXT: Link: 0
> >  // CHECK2-NEXT: Info: 0
> >  // CHECK2-NEXT: AddressAlignment: 16
> >
> >  // CHECK2:      Relocations [
> > -// CHECK2-NEXT:   Section ({{.*}}) .rela.dyn {
> > -// CHECK2-NEXT:     0x120A0 R_X86_64_GLOB_DAT bar 0x0
> > -// CHECK2-NEXT:     0x120A8 R_X86_64_GLOB_DAT zed 0x0
> > +// CHECK2-NEXT:   Section ({{.*}}) .rela.plt {
> > +// CHECK2-NEXT:     0x120C8 R_X86_64_JUMP_SLOT bar 0x0
> > +// CHECK2-NEXT:     0x120D0 R_X86_64_JUMP_SLOT zed 0x0
> >  // CHECK2-NEXT:   }
> >  // CHECK2-NEXT: ]
> >
> >  // Unfortunately FileCheck can't do math, so we have to check for
> explicit
> >  // values:
> >
> > -// 0x1020 - (0x1000 + 1) - 4 = 27
> > -// 0x1020 - (0x1005 + 1) - 4 = 22
> > -// 0x1028 - (0x100a + 1) - 4 = 25
> > -// 0x1030 - (0x100f + 1) - 4 = 28
> > +// 0x1030 - (0x1000 + 5) = 43
> > +// 0x1030 - (0x1005 + 5) = 38
> > +// 0x1040 - (0x100a + 5) = 49
> > +// 0x1048 - (0x100a + 5) = 60
> >
> >  // DISASM:      _start:
> > -// DISASM-NEXT:   1000:  e9 {{.*}}       jmp  27
> > -// DISASM-NEXT:   1005:  e9 {{.*}}       jmp  22
> > -// DISASM-NEXT:   100a:  e9 {{.*}}       jmp  25
> > -// DISASM-NEXT:   100f:  e9 {{.*}}       jmp  28
> > -
> > -// 0x20A0 - 0x1026  = 4218
> > -// 0x20A8 - 0x102e  = 4218
> > -// 0x20B0 - 0x1036  = 4218
> > +// DISASM-NEXT:   1000:  e9 {{.*}}       jmp  43
> > +// DISASM-NEXT:   1005:  e9 {{.*}}       jmp  38
> > +// DISASM-NEXT:   100a:  e9 {{.*}}       jmp  49
> > +// DISASM-NEXT:   100f:  e9 {{.*}}       jmp  60
> > +
> > +// 0x20C8 - 0x1036  = 4242
> > +// 0x20D0 - 0x1046  = 4234
> > +// 0x20D8 - 0x1056  = 4226
> >
> >  // DISASM:      Disassembly of section .plt:
> >  // DISASM-NEXT: .plt:
> > -// DISASM-NEXT:   1020:  ff 25 {{.*}}       jmpq *4218(%rip)
> > -// DISASM-NEXT:   1026:  90                 nop
> > -// DISASM-NEXT:   1027:  90                 nop
> > -// DISASM-NEXT:   1028:  ff 25 {{.*}}       jmpq *4218(%rip)
> > -// DISASM-NEXT:   102e:  90                 nop
> > -// DISASM-NEXT:   102f:  90                 nop
> > -// DISASM-NEXT:   1030:  ff 25 {{.*}}       jmpq *4218(%rip)
> > -// DISASM-NEXT:   1036:  90                 nop
> > -// DISASM-NEXT:   1037:  90                 nop
> > -
> > -// 0x11020 - (0x11000 + 1) - 4 = 27
> > -// 0x11020 - (0x11005 + 1) - 4 = 22
> > -// 0x11028 - (0x1100a + 1) - 4 = 25
> > +// DISASM-NEXT:   1020:  ff 35 92 10 00 00  pushq 4242(%rip)
> > +// DISASM-NEXT:   1026:  ff 25 94 10 00 00  jmpq *4244(%rip)
> > +// DISASM-NEXT:   102c:  0f 1f 40 00        nopl (%rax)
> > +// DISASM-NEXT:   1030:  ff 25 92 10 00 00  jmpq *4242(%rip)
> > +// DISASM-NEXT:   1036:  68 00 00 00 00     pushq $0
> > +// DISASM-NEXT:   103b:  e9 e0 ff ff ff     jmp -32 <bar+1020>
> > +// DISASM-NEXT:   1040:  ff 25 8a 10 00 00  jmpq *4234(%rip)
> > +// DISASM-NEXT:   1046:  68 01 00 00 00     pushq $1
> > +// DISASM-NEXT:   104b:  e9 d0 ff ff ff     jmp -48 <bar+1020>
> > +// DISASM-NEXT:   1050:  ff 25 82 10 00 00  jmpq *4226(%rip)
> > +// DISASM-NEXT:   1056:  68 02 00 00 00     pushq $2
> > +// DISASM-NEXT:   105b:  e9 c0 ff ff ff     jmp -64 <bar+1020>
> > +
> > +// 0x11030 - (0x11000 + 1) - 4 = 43
> > +// 0x11030 - (0x11005 + 1) - 4 = 38
> > +// 0x11040 - (0x1100a + 1) - 4 = 49
> >  // 0x11000 - (0x1100f + 1) - 4 = -20
> >
> >  // DISASM2:      _start:
> > -// DISASM2-NEXT:   11000:  e9 {{.*}}     jmp  27
> > -// DISASM2-NEXT:   11005:  e9 {{.*}}     jmp  22
> > -// DISASM2-NEXT:   1100a:  e9 {{.*}}     jmp  25
> > +// DISASM2-NEXT:   11000:  e9 {{.*}}     jmp  43
> > +// DISASM2-NEXT:   11005:  e9 {{.*}}     jmp  38
> > +// DISASM2-NEXT:   1100a:  e9 {{.*}}     jmp  49
> >  // DISASM2-NEXT:   1100f:  e9 {{.*}}     jmp  -20
> >
> > +// 0x120C8 - 0x11036  = 4242
> > +// 0x120D0 - 0x11046  = 4234
> > +
> >  // DISASM2:      Disassembly of section .plt:
> >  // DISASM2-NEXT: .plt:
> > -// DISASM2-NEXT:     11020:  ff 25 7a 10 00 00 jmpq *4218(%rip)
> > -// DISASM2-NEXT:     11026:  90                nop
> > -// DISASM2-NEXT:     11027:  90                nop
> > -// DISASM2-NEXT:     11028:  ff 25 7a 10 00 00 jmpq *4218(%rip)
> > -// DISASM2-NEXT:     1102e:  90                nop
> > -// DISASM2-NEXT:     1102f:  90                nop
> > +// DISASM2-NEXT:  11020:  ff 35 92 10 00 00   pushq 4242(%rip)
> > +// DISASM2-NEXT:  11026:  ff 25 94 10 00 00   jmpq *4244(%rip)
> > +// DISASM2-NEXT:  1102c:  0f 1f 40 00         nopl  (%rax)
> > +// DISASM2-NEXT:  11030:  ff 25 92 10 00 00   jmpq *4242(%rip)
> > +// DISASM2-NEXT:  11036:  68 00 00 00 00      pushq $0
> > +// DISASM2-NEXT:  1103b:  e9 e0 ff ff ff      jmp -32 <bar+11020>
> > +// DISASM2-NEXT:  11040:  ff 25 8a 10 00 00   jmpq *4234(%rip)
> > +// DISASM2-NEXT:  11046:  68 01 00 00 00      pushq $1
> > +// DISASM2-NEXT:  1104b:  e9 d0 ff ff ff      jmp -48 <bar+11020>
> >  // DISASM2-NEXT-NOT: 110C0
> >
> >  .global _start
> >
> > Modified: lld/trunk/test/elf2/relocation.s
> > URL:
> http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/relocation.s?rev=250808&r1=250807&r2=250808&view=diff
> >
> ==============================================================================
> > --- lld/trunk/test/elf2/relocation.s (original)
> > +++ lld/trunk/test/elf2/relocation.s Tue Oct 20 03:54:27 2015
> > @@ -14,7 +14,7 @@
> >  // SEC-NEXT: ]
> >  // SEC-NEXT: Address: 0x11030
> >  // SEC-NEXT: Offset: 0x1030
> > -// SEC-NEXT: Size: 8
> > +// SEC-NEXT: Size: 32
> >
> >  // SEC:         Name: .got
> >  // SEC-NEXT:   Type: SHT_PROGBITS
> > @@ -22,15 +22,30 @@
> >  // SEC-NEXT:     SHF_ALLOC
> >  // SEC-NEXT:     SHF_WRITE
> >  // SEC-NEXT:   ]
> > -// SEC-NEXT:   Address: 0x120A0
> > +// SEC-NEXT:   Address: 0x120E0
> >  // SEC-NEXT:   Offset:
> > -// SEC-NEXT:   Size: 16
> > +// SEC-NEXT:   Size: 8
> >  // SEC-NEXT:   Link: 0
> >  // SEC-NEXT:   Info: 0
> >  // SEC-NEXT:   AddressAlignment: 8
> >  // SEC-NEXT:   EntrySize: 0
> >  // SEC-NEXT: }
> >
> > +// SEC:        Name: .got.plt
> > +// SEC-NEXT:   Type: SHT_PROGBITS
> > +// SEC-NEXT:   Flags [
> > +// SEC-NEXT:     SHF_ALLOC
> > +// SEC-NEXT:     SHF_WRITE
> > +// SEC-NEXT:   ]
> > +// SEC-NEXT:   Address: 0x120E8
> > +// SEC-NEXT:   Offset: 0x20E8
> > +// SEC-NEXT:   Size: 32
> > +// SEC-NEXT:   Link: 0
> > +// SEC-NEXT:   Info: 0
> > +// SEC-NEXT:   AddressAlignment: 8
> > +// SEC-NEXT:   EntrySize: 0
> > +// SEC-NEXT:   }
> > +
> >  .section       .text,"ax", at progbits,unique,1
> >  .global _start
> >  _start:
> > @@ -76,12 +91,12 @@ R_X86_64_32S:
> >  R_X86_64_PC32:
> >   call bar
> >   movl $bar, %eax
> > -// 0x11030 - (0x11017 + 5) = 20
> > -// 0x11030 = 69680
> > +//16 is a size of PLT[0]
> > +// 0x11030 + 16 - (0x11017 + 5) = 20
> >  // CHECK:      Disassembly of section .R_X86_64_PC32:
> >  // CHECK-NEXT: R_X86_64_PC32:
> > -// CHECK-NEXT:  11017:   {{.*}}  callq  20
> > -// CHECK-NEXT:  1101c:   {{.*}}  movl $69680, %eax
> > +// CHECK-NEXT:  11017:   {{.*}}  callq  36
> > +// CHECK-NEXT:  1101c:   {{.*}}  movl $69696, %eax
> >
> >  .section .R_X86_64_64,"a", at progbits
> >  .global R_X86_64_64
> > @@ -99,4 +114,4 @@ R_X86_64_GOTPCREL:
> >  // 0x120A8 - 0x10160 = 8008
> >  // 8008 = 0x481f0000   in little endian
> >  // CHECK:      Contents of section .R_X86_64_GOTPCREL
> > -// CHECK-NEXT:   10160 481f0000
> > +// CHECK-NEXT:   10160 801f0000
> >
> >
> > _______________________________________________
> > llvm-commits mailing list
> > llvm-commits at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20151020/7f5471f3/attachment-0001.html>


More information about the llvm-commits mailing list