[lld] r274863 - Recommit R274836 Add Thunk support framework for ARM and Mips

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 8 22:54:16 PDT 2016


My apologies. this looks like it has been fixed by Rui under r274896.
It looks like the bot is ok now. Will make sure I stick to committing
first thing in Morning.

Thanks to Rui for fixing.

Peter

On 8 July 2016 at 20:12, Peter Collingbourne <peter at pcc.me.uk> wrote:
> Hi Peter, it looks like your change caused a bot failure:
> http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/14493
>
> Can you please take a look?
>
> On Fri, Jul 8, 2016 at 9:10 AM, Peter Smith via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
>>
>> Author: psmith
>> Date: Fri Jul  8 11:10:27 2016
>> New Revision: 274863
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=274863&view=rev
>> Log:
>> Recommit R274836 Add Thunk support framework for ARM and Mips
>>
>> The TinyPtrVector of const Thunk<ELFT>* in InputSections.h can cause
>> build failures on certain compiler/library combinations when Thunk<ELFT>
>> is not a complete type or is an abstract class. Fixed by making
>> Thunk<ELFT>
>> non Abstract.
>>
>> type or is an abstract class
>>
>> Added:
>>     lld/trunk/ELF/Thunks.cpp   (with props)
>>     lld/trunk/ELF/Thunks.h   (with props)
>>     lld/trunk/test/ELF/arm-thumb-interwork-thunk.s   (with props)
>> Modified:
>>     lld/trunk/ELF/CMakeLists.txt
>>     lld/trunk/ELF/InputSection.cpp
>>     lld/trunk/ELF/InputSection.h
>>     lld/trunk/ELF/Relocations.cpp
>>     lld/trunk/ELF/Relocations.h
>>     lld/trunk/ELF/Symbols.cpp
>>     lld/trunk/ELF/Symbols.h
>>     lld/trunk/ELF/Target.cpp
>>     lld/trunk/ELF/Target.h
>>     lld/trunk/test/ELF/arm-mov-relocs.s
>>
>> Modified: lld/trunk/ELF/CMakeLists.txt
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=274863&r1=274862&r2=274863&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/CMakeLists.txt (original)
>> +++ lld/trunk/ELF/CMakeLists.txt Fri Jul  8 11:10:27 2016
>> @@ -21,6 +21,7 @@ add_lld_library(lldELF
>>    SymbolTable.cpp
>>    Symbols.cpp
>>    Target.cpp
>> +  Thunks.cpp
>>    Writer.cpp
>>
>>    LINK_COMPONENTS
>>
>> Modified: lld/trunk/ELF/InputSection.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=274863&r1=274862&r2=274863&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/InputSection.cpp (original)
>> +++ lld/trunk/ELF/InputSection.cpp Fri Jul  8 11:10:27 2016
>> @@ -14,6 +14,7 @@
>>  #include "InputFiles.h"
>>  #include "OutputSections.h"
>>  #include "Target.h"
>> +#include "Thunks.h"
>>
>>  #include "llvm/Support/Compression.h"
>>  #include "llvm/Support/Endian.h"
>> @@ -128,9 +129,9 @@ InputSectionBase<ELFT> *InputSection<ELF
>>    return Sections[this->Header->sh_info];
>>  }
>>
>> -template <class ELFT> void InputSection<ELFT>::addThunk(SymbolBody &Body)
>> {
>> -  Body.ThunkIndex = Thunks.size();
>> -  Thunks.push_back(&Body);
>> +template <class ELFT>
>> +void InputSection<ELFT>::addThunk(const Thunk<ELFT> *T) {
>> +  Thunks.push_back(T);
>>  }
>>
>>  template <class ELFT> uint64_t InputSection<ELFT>::getThunkOff() const {
>> @@ -138,7 +139,10 @@ template <class ELFT> uint64_t InputSect
>>  }
>>
>>  template <class ELFT> uint64_t InputSection<ELFT>::getThunksSize() const
>> {
>> -  return Thunks.size() * Target->ThunkSize;
>> +  uint64_t Total = 0;
>> +  for (const Thunk<ELFT> *T : Thunks)
>> +    Total += T->size();
>> +  return Total;
>>  }
>>
>>  // This is used for -r. We can't use memcpy to copy relocations because
>> we need
>> @@ -183,8 +187,11 @@ getSymVA(uint32_t Type, typename ELFT::u
>>             Out<ELFT>::Got->getNumEntries() * sizeof(uintX_t);
>>    case R_TLSLD_PC:
>>      return Out<ELFT>::Got->getTlsIndexVA() + A - P;
>> -  case R_THUNK:
>> -    return Body.getThunkVA<ELFT>();
>> +  case R_THUNK_ABS:
>> +    return Body.getThunkVA<ELFT>() + A;
>> +  case R_THUNK_PC:
>> +  case R_THUNK_PLT_PC:
>> +    return Body.getThunkVA<ELFT>() + A - P;
>>    case R_PPC_TOC:
>>      return getPPC64TocBase() + A;
>>    case R_TLSGD:
>> @@ -404,9 +411,9 @@ template <class ELFT> void InputSection<
>>    // jump istruction.
>>    if (!Thunks.empty()) {
>>      Buf += OutSecOff + getThunkOff();
>> -    for (const SymbolBody *S : Thunks) {
>> -      Target->writeThunk(Buf, S->getVA<ELFT>());
>> -      Buf += Target->ThunkSize;
>> +    for (const Thunk<ELFT> *T : Thunks) {
>> +      T->writeTo(Buf);
>> +      Buf += T->size();
>>      }
>>    }
>>  }
>>
>> Modified: lld/trunk/ELF/InputSection.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=274863&r1=274862&r2=274863&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/InputSection.h (original)
>> +++ lld/trunk/ELF/InputSection.h Fri Jul  8 11:10:27 2016
>> @@ -12,6 +12,7 @@
>>
>>  #include "Config.h"
>>  #include "Relocations.h"
>> +#include "Thunks.h"
>>  #include "lld/Core/LLVM.h"
>>  #include "llvm/ADT/DenseSet.h"
>>  #include "llvm/ADT/TinyPtrVector.h"
>> @@ -208,8 +209,8 @@ public:
>>
>>    // Register thunk related to the symbol. When the section is written
>>    // to a mmap'ed file, target is requested to write an actual thunk
>> code.
>> -  // Now thunks is supported for MIPS target only.
>> -  void addThunk(SymbolBody &Body);
>> +  // Now thunks is supported for MIPS and ARM target only.
>> +  void addThunk(const Thunk<ELFT> *T);
>>
>>    // The offset of synthetic thunk code from beginning of this section.
>>    uint64_t getThunkOff() const;
>> @@ -230,7 +231,7 @@ private:
>>    // Used by ICF.
>>    uint64_t GroupId = 0;
>>
>> -  llvm::TinyPtrVector<const SymbolBody *> Thunks;
>> +  llvm::TinyPtrVector<const Thunk<ELFT> *> Thunks;
>>  };
>>
>>  // MIPS .reginfo section provides information on the registers used by
>> the code
>>
>> Modified: lld/trunk/ELF/Relocations.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=274863&r1=274862&r2=274863&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Relocations.cpp (original)
>> +++ lld/trunk/ELF/Relocations.cpp Fri Jul  8 11:10:27 2016
>> @@ -46,6 +46,7 @@
>>  #include "OutputSections.h"
>>  #include "SymbolTable.h"
>>  #include "Target.h"
>> +#include "Thunks.h"
>>
>>  #include "llvm/Support/Endian.h"
>>  #include "llvm/Support/raw_ostream.h"
>> @@ -276,14 +277,14 @@ template <class ELFT> static bool isAbso
>>
>>  static bool needsPlt(RelExpr Expr) {
>>    return Expr == R_PLT_PC || Expr == R_PPC_PLT_OPD || Expr == R_PLT ||
>> -         Expr == R_PLT_PAGE_PC;
>> +         Expr == R_PLT_PAGE_PC || Expr == R_THUNK_PLT_PC;
>>  }
>>
>>  // True if this expression is of the form Sym - X, where X is a position
>> in the
>>  // file (PC, or GOT for example).
>>  static bool isRelExpr(RelExpr Expr) {
>>    return Expr == R_PC || Expr == R_GOTREL || Expr == R_PAGE_PC ||
>> -         Expr == R_RELAX_GOT_PC;
>> +         Expr == R_RELAX_GOT_PC || Expr == R_THUNK_PC || Expr ==
>> R_THUNK_PLT_PC;
>>  }
>>
>>  template <class ELFT>
>> @@ -293,7 +294,8 @@ static bool isStaticLinkTimeConstant(Rel
>>    if (E == R_SIZE || E == R_GOT_FROM_END || E == R_GOT_OFF ||
>>        E == R_MIPS_GOT_LOCAL_PAGE || E == R_MIPS_GOT_OFF || E ==
>> R_MIPS_TLSGD ||
>>        E == R_GOT_PAGE_PC || E == R_GOT_PC || E == R_PLT_PC || E ==
>> R_TLSGD_PC ||
>> -      E == R_TLSGD || E == R_PPC_PLT_OPD || E == R_TLSDESC_PAGE || E ==
>> R_HINT)
>> +      E == R_TLSGD || E == R_PPC_PLT_OPD || E == R_TLSDESC_PAGE ||
>> +      E == R_HINT || E == R_THUNK_PC || E == R_THUNK_PLT_PC)
>>      return true;
>>
>>    // These never do, except if the entire file is position dependent or
>> if
>> @@ -402,8 +404,6 @@ template <class ELFT>
>>  static RelExpr adjustExpr(const elf::ObjectFile<ELFT> &File, SymbolBody
>> &Body,
>>                            bool IsWrite, RelExpr Expr, uint32_t Type,
>>                            const uint8_t *Data) {
>> -  if (Target->needsThunk(Type, File, Body))
>> -    return R_THUNK;
>>    bool Preemptible = isPreemptible(Body, Type);
>>    if (Body.isGnuIFunc()) {
>>      Expr = toPlt(Expr);
>> @@ -413,6 +413,7 @@ static RelExpr adjustExpr(const elf::Obj
>>      if (Expr == R_GOT_PC)
>>        Expr = Target->adjustRelaxExpr(Type, Data, Expr);
>>    }
>> +  Expr = Target->getThunkExpr(Expr, Type, File, Body);
>>
>>    if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body))
>>      return Expr;
>> @@ -556,7 +557,8 @@ static void scanRelocs(InputSectionBase<
>>      if (Expr == R_HINT)
>>        continue;
>>
>> -    if (needsPlt(Expr) || Expr == R_THUNK || refersToGotEntry(Expr) ||
>> +    if (needsPlt(Expr) || Expr == R_THUNK_ABS || Expr == R_THUNK_PC ||
>> +        Expr == R_THUNK_PLT_PC || refersToGotEntry(Expr) ||
>>          !isPreemptible(Body, Type)) {
>>        // If the relocation points to something in the file, we can
>> process it.
>>        bool Constant = isStaticLinkTimeConstant<ELFT>(Expr, Type, Body);
>> @@ -600,14 +602,10 @@ static void scanRelocs(InputSectionBase<
>>
>>      // Some targets might require creation of thunks for relocations.
>>      // Now we support only MIPS which requires LA25 thunk to call PIC
>> -    // code from non-PIC one.
>> -    if (Expr == R_THUNK) {
>> -      if (!Body.hasThunk()) {
>> -        auto *Sec = cast<InputSection<ELFT>>(
>> -            cast<DefinedRegular<ELFT>>(&Body)->Section);
>> -        Sec->addThunk(Body);
>> -      }
>> -      continue;
>> +    // code from non-PIC one, and ARM which requires interworking.
>> +    if (Expr == R_THUNK_ABS || Expr == R_THUNK_PC || Expr ==
>> R_THUNK_PLT_PC) {
>> +      auto *Sec = cast<InputSection<ELFT>>(&C);
>> +      addThunk<ELFT>(Type, Body, *Sec);
>>      }
>>
>>      // At this point we are done with the relocated position. Some
>> relocations
>>
>> Modified: lld/trunk/ELF/Relocations.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=274863&r1=274862&r2=274863&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Relocations.h (original)
>> +++ lld/trunk/ELF/Relocations.h Fri Jul  8 11:10:27 2016
>> @@ -52,7 +52,9 @@ enum RelExpr {
>>    R_RELAX_TLS_IE_TO_LE,
>>    R_RELAX_TLS_LD_TO_LE,
>>    R_SIZE,
>> -  R_THUNK,
>> +  R_THUNK_ABS,
>> +  R_THUNK_PC,
>> +  R_THUNK_PLT_PC,
>>    R_TLS,
>>    R_TLSDESC,
>>    R_TLSDESC_PAGE,
>>
>> Modified: lld/trunk/ELF/Symbols.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=274863&r1=274862&r2=274863&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Symbols.cpp (original)
>> +++ lld/trunk/ELF/Symbols.cpp Fri Jul  8 11:10:27 2016
>> @@ -134,6 +134,14 @@ bool SymbolBody::isPreemptible() const {
>>    return true;
>>  }
>>
>> +template <class ELFT> bool SymbolBody::hasThunk() const {
>> +  if (auto *DR = dyn_cast<DefinedRegular<ELFT>>(this))
>> +    return DR->ThunkData != nullptr;
>> +  if (auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
>> +    return S->ThunkData != nullptr;
>> +  return false;
>> +}
>> +
>>  template <class ELFT> InputFile *SymbolBody::getSourceFile() {
>>    if (auto *S = dyn_cast<DefinedRegular<ELFT>>(this))
>>      return S->Section ? S->Section->getFile() : nullptr;
>> @@ -174,10 +182,11 @@ template <class ELFT> typename ELFT::uin
>>  }
>>
>>  template <class ELFT> typename ELFT::uint SymbolBody::getThunkVA() const
>> {
>> -  auto *D = cast<DefinedRegular<ELFT>>(this);
>> -  auto *S = cast<InputSection<ELFT>>(D->Section);
>> -  return S->OutSec->getVA() + S->OutSecOff + S->getThunkOff() +
>> -         ThunkIndex * Target->ThunkSize;
>> +  if (const auto *DR = dyn_cast<DefinedRegular<ELFT>>(this))
>> +    return DR->ThunkData->getVA();
>> +  if (const auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
>> +    return S->ThunkData->getVA();
>> +  fatal("getThunkVA() not supported for Symbol class\n");
>>  }
>>
>>  template <class ELFT> typename ELFT::uint SymbolBody::getSize() const {
>> @@ -250,6 +259,10 @@ bool Symbol::includeInDynsym() const {
>>    return (ExportDynamic && VersionId != VER_NDX_LOCAL) ||
>> body()->isShared() ||
>>           (body()->isUndefined() && Config->Shared);
>>  }
>> +template bool SymbolBody::hasThunk<ELF32LE>() const;
>> +template bool SymbolBody::hasThunk<ELF32BE>() const;
>> +template bool SymbolBody::hasThunk<ELF64LE>() const;
>> +template bool SymbolBody::hasThunk<ELF64BE>() const;
>>
>>  template InputFile *SymbolBody::template getSourceFile<ELF32LE>();
>>  template InputFile *SymbolBody::template getSourceFile<ELF32BE>();
>> @@ -276,6 +289,11 @@ template uint32_t SymbolBody::template g
>>  template uint64_t SymbolBody::template getGotPltVA<ELF64LE>() const;
>>  template uint64_t SymbolBody::template getGotPltVA<ELF64BE>() const;
>>
>> +template uint32_t SymbolBody::template getThunkVA<ELF32LE>() const;
>> +template uint32_t SymbolBody::template getThunkVA<ELF32BE>() const;
>> +template uint64_t SymbolBody::template getThunkVA<ELF64LE>() const;
>> +template uint64_t SymbolBody::template getThunkVA<ELF64BE>() const;
>> +
>>  template uint32_t SymbolBody::template getGotPltOffset<ELF32LE>() const;
>>  template uint32_t SymbolBody::template getGotPltOffset<ELF32BE>() const;
>>  template uint64_t SymbolBody::template getGotPltOffset<ELF64LE>() const;
>> @@ -291,11 +309,6 @@ template uint32_t SymbolBody::template g
>>  template uint64_t SymbolBody::template getSize<ELF64LE>() const;
>>  template uint64_t SymbolBody::template getSize<ELF64BE>() const;
>>
>> -template uint32_t SymbolBody::template getThunkVA<ELF32LE>() const;
>> -template uint32_t SymbolBody::template getThunkVA<ELF32BE>() const;
>> -template uint64_t SymbolBody::template getThunkVA<ELF64LE>() const;
>> -template uint64_t SymbolBody::template getThunkVA<ELF64BE>() const;
>> -
>>  template class elf::DefinedSynthetic<ELF32LE>;
>>  template class elf::DefinedSynthetic<ELF32BE>;
>>  template class elf::DefinedSynthetic<ELF64LE>;
>>
>> Modified: lld/trunk/ELF/Symbols.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=274863&r1=274862&r2=274863&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Symbols.h (original)
>> +++ lld/trunk/ELF/Symbols.h Fri Jul  8 11:10:27 2016
>> @@ -84,11 +84,10 @@ public:
>>    uint32_t GotIndex = -1;
>>    uint32_t GotPltIndex = -1;
>>    uint32_t PltIndex = -1;
>> -  uint32_t ThunkIndex = -1;
>>    uint32_t GlobalDynIndex = -1;
>>    bool isInGot() const { return GotIndex != -1U; }
>>    bool isInPlt() const { return PltIndex != -1U; }
>> -  bool hasThunk() const { return ThunkIndex != -1U; }
>> +  template <class ELFT> bool hasThunk() const;
>>
>>    template <class ELFT>
>>    typename ELFT::uint getVA(typename ELFT::uint Addend = 0) const;
>> @@ -229,6 +228,10 @@ public:
>>    // If this is null, the symbol is an absolute symbol.
>>    InputSectionBase<ELFT> *&Section;
>>
>> +  // If non-null the symbol has a Thunk that may be used as an
>> alternative
>> +  // destination for callers of this Symbol.
>> +  std::unique_ptr<Thunk<ELFT>> ThunkData;
>> +
>>  private:
>>    static InputSectionBase<ELFT> *NullInputSection;
>>  };
>> @@ -301,6 +304,9 @@ public:
>>    // OffsetInBss is significant only when needsCopy() is true.
>>    uintX_t OffsetInBss = 0;
>>
>> +  // If non-null the symbol has a Thunk that may be used as an
>> alternative
>> +  // destination for callers of this Symbol.
>> +  std::unique_ptr<Thunk<ELFT>> ThunkData;
>>    bool needsCopy() const { return this->NeedsCopyOrPltAddr &&
>> !this->isFunc(); }
>>  };
>>
>>
>> Modified: lld/trunk/ELF/Target.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=274863&r1=274862&r2=274863&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Target.cpp (original)
>> +++ lld/trunk/ELF/Target.cpp Fri Jul  8 11:10:27 2016
>> @@ -29,6 +29,7 @@
>>  #include "InputFiles.h"
>>  #include "OutputSections.h"
>>  #include "Symbols.h"
>> +#include "Thunks.h"
>>
>>  #include "llvm/ADT/ArrayRef.h"
>>  #include "llvm/Object/ELF.h"
>> @@ -181,6 +182,9 @@ public:
>>    void writePltHeader(uint8_t *Buf) const override;
>>    void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t
>> PltEntryAddr,
>>                  int32_t Index, unsigned RelOff) const override;
>> +  RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType,
>> +                       const InputFile &File,
>> +                       const SymbolBody &S) const override;
>>    void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const
>> override;
>>  };
>>
>> @@ -197,8 +201,9 @@ public:
>>    void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t
>> PltEntryAddr,
>>                  int32_t Index, unsigned RelOff) const override;
>>    void writeThunk(uint8_t *Buf, uint64_t S) const override;
>> -  bool needsThunk(uint32_t Type, const InputFile &File,
>> -                  const SymbolBody &S) const override;
>> +  RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType,
>> +                       const InputFile &File,
>> +                       const SymbolBody &S) const override;
>>    void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const
>> override;
>>    bool usesOnlyLowPageBits(uint32_t Type) const override;
>>  };
>> @@ -248,9 +253,10 @@ uint64_t TargetInfo::getVAStart() const
>>
>>  bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false;
>> }
>>
>> -bool TargetInfo::needsThunk(uint32_t Type, const InputFile &File,
>> -                            const SymbolBody &S) const {
>> -  return false;
>> +RelExpr TargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
>> +                                 const InputFile &File,
>> +                                 const SymbolBody &S) const {
>> +  return Expr;
>>  }
>>
>>  bool TargetInfo::isTlsInitialExecRel(uint32_t Type) const { return false;
>> }
>> @@ -1483,8 +1489,12 @@ RelExpr ARMTargetInfo::getRelExpr(uint32
>>      // FIXME: currently B(S) assumed to be .got, this may not hold for
>> all
>>      // platforms.
>>      return R_GOTONLY_PC;
>> +  case R_ARM_MOVW_PREL_NC:
>> +  case R_ARM_MOVT_PREL:
>>    case R_ARM_PREL31:
>>    case R_ARM_REL32:
>> +  case R_ARM_THM_MOVW_PREL_NC:
>> +  case R_ARM_THM_MOVT_PREL:
>>      return R_PC;
>>    }
>>  }
>> @@ -1532,6 +1542,34 @@ void ARMTargetInfo::writePlt(uint8_t *Bu
>>    write32le(Buf + 12, GotEntryAddr - L1 - 8);
>>  }
>>
>> +RelExpr ARMTargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
>> +                                    const InputFile &File,
>> +                                    const SymbolBody &S) const {
>> +  // A state change from ARM to Thumb and vice versa must go through an
>> +  // interworking thunk if the relocation type is not R_ARM_CALL or
>> +  // R_ARM_THM_CALL.
>> +  switch (RelocType) {
>> +  case R_ARM_PC24:
>> +  case R_ARM_PLT32:
>> +  case R_ARM_JUMP24:
>> +    // Source is ARM, all PLT entries are ARM so no interworking
>> required.
>> +    // Otherwise we need to interwork if Symbol has bit 0 set (Thumb).
>> +    if (Expr == R_PC && ((S.getVA<ELF32LE>() & 1) == 1))
>> +      return R_THUNK_PC;
>> +    break;
>> +  case R_ARM_THM_JUMP19:
>> +  case R_ARM_THM_JUMP24:
>> +    // Source is Thumb, all PLT entries are ARM so interworking is
>> required.
>> +    // Otherwise we need to interwork if Symbol has bit 0 clear (ARM).
>> +    if (Expr == R_PLT_PC)
>> +      return R_THUNK_PLT_PC;
>> +    if ((S.getVA<ELF32LE>() & 1) == 0)
>> +      return R_THUNK_PC;
>> +    break;
>> +  }
>> +  return Expr;
>> +}
>> +
>>  void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
>>                                  uint64_t Val) const {
>>    switch (Type) {
>> @@ -1615,17 +1653,20 @@ void ARMTargetInfo::relocateOne(uint8_t
>>                    ((Val >> 1) & 0x07ff));                     // imm11
>>      break;
>>    case R_ARM_MOVW_ABS_NC:
>> +  case R_ARM_MOVW_PREL_NC:
>>      write32le(Loc, (read32le(Loc) & ~0x000f0fff) | ((Val & 0xf000) << 4)
>> |
>>                         (Val & 0x0fff));
>>      break;
>>    case R_ARM_MOVT_ABS:
>> -    checkUInt<32>(Val, Type);
>> +  case R_ARM_MOVT_PREL:
>> +    checkInt<32>(Val, Type);
>>      write32le(Loc, (read32le(Loc) & ~0x000f0fff) |
>>                         (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) &
>> 0xfff));
>>      break;
>>    case R_ARM_THM_MOVT_ABS:
>> +  case R_ARM_THM_MOVT_PREL:
>>      // Encoding T1: A = imm4:i:imm3:imm8
>> -    checkUInt<32>(Val, Type);
>> +    checkInt<32>(Val, Type);
>>      write16le(Loc,
>>                0xf2c0 |                     // opcode
>>                    ((Val >> 17) & 0x0400) | // i
>> @@ -1636,6 +1677,7 @@ void ARMTargetInfo::relocateOne(uint8_t
>>                    ((Val >> 16) & 0x00ff));   // imm8
>>      break;
>>    case R_ARM_THM_MOVW_ABS_NC:
>> +  case R_ARM_THM_MOVW_PREL_NC:
>>      // Encoding T3: A = imm4:i:imm3:imm8
>>      write16le(Loc,
>>                0xf240 |                     // opcode
>> @@ -1682,8 +1724,8 @@ uint64_t ARMTargetInfo::getImplicitAdden
>>                              ((Hi & 0x003f) << 12) | // imm6
>>                              ((Lo & 0x07ff) << 1));  // imm11:0
>>    }
>> -  case R_ARM_THM_JUMP24:
>> -  case R_ARM_THM_CALL: {
>> +  case R_ARM_THM_CALL:
>> +  case R_ARM_THM_JUMP24: {
>>      // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0
>>      // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S)
>>      // FIXME: I1 and I2 require v6T2ops
>> @@ -1698,12 +1740,16 @@ uint64_t ARMTargetInfo::getImplicitAdden
>>    // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW
>> and
>>    // MOVT is in the range -32768 <= A < 32768
>>    case R_ARM_MOVW_ABS_NC:
>> -  case R_ARM_MOVT_ABS: {
>> +  case R_ARM_MOVT_ABS:
>> +  case R_ARM_MOVW_PREL_NC:
>> +  case R_ARM_MOVT_PREL: {
>>      uint64_t Val = read32le(Buf) & 0x000f0fff;
>>      return SignExtend64<16>(((Val & 0x000f0000) >> 4) | (Val & 0x00fff));
>>    }
>>    case R_ARM_THM_MOVW_ABS_NC:
>> -  case R_ARM_THM_MOVT_ABS: {
>> +  case R_ARM_THM_MOVT_ABS:
>> +  case R_ARM_THM_MOVW_PREL_NC:
>> +  case R_ARM_THM_MOVT_PREL: {
>>      // Encoding T3: A = imm4:i:imm3:imm8
>>      uint16_t Hi = read16le(Buf);
>>      uint16_t Lo = read16le(Buf + 2);
>> @@ -1720,7 +1766,6 @@ template <class ELFT> MipsTargetInfo<ELF
>>    PageSize = 65536;
>>    PltEntrySize = 16;
>>    PltHeaderSize = 32;
>> -  ThunkSize = 16;
>>    CopyRel = R_MIPS_COPY;
>>    PltRel = R_MIPS_JUMP_SLOT;
>>    if (ELFT::Is64Bits) {
>> @@ -1887,28 +1932,31 @@ void MipsTargetInfo<ELFT>::writeThunk(ui
>>  }
>>
>>  template <class ELFT>
>> -bool MipsTargetInfo<ELFT>::needsThunk(uint32_t Type, const InputFile
>> &File,
>> -                                      const SymbolBody &S) const {
>> +RelExpr MipsTargetInfo<ELFT>::getThunkExpr(RelExpr Expr, uint32_t Type,
>> +                                           const InputFile &File,
>> +                                           const SymbolBody &S) const {
>>    // Any MIPS PIC code function is invoked with its address in register
>> $t9.
>>    // So if we have a branch instruction from non-PIC code to the PIC one
>>    // we cannot make the jump directly and need to create a small stubs
>>    // to save the target function address.
>>    // See page 3-38
>> ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
>>    if (Type != R_MIPS_26)
>> -    return false;
>> +    return Expr;
>>    auto *F = dyn_cast<ELFFileBase<ELFT>>(&File);
>>    if (!F)
>> -    return false;
>> +    return Expr;
>>    // If current file has PIC code, LA25 stub is not required.
>>    if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC)
>> -    return false;
>> +    return Expr;
>>    auto *D = dyn_cast<DefinedRegular<ELFT>>(&S);
>>    if (!D || !D->Section)
>> -    return false;
>> +    return Expr;
>>    // LA25 is required if target file has PIC code
>>    // or target symbol is a PIC symbol.
>> -  return (D->Section->getFile()->getObj().getHeader()->e_flags &
>> EF_MIPS_PIC) ||
>> -         (D->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC;
>> +  const ELFFile<ELFT> &DefFile = D->Section->getFile()->getObj();
>> +  bool PicFile = DefFile.getHeader()->e_flags & EF_MIPS_PIC;
>> +  bool PicSym = (D->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC;
>> +  return (PicFile || PicSym) ? R_THUNK_ABS : Expr;
>>  }
>>
>>  template <class ELFT>
>>
>> Modified: lld/trunk/ELF/Target.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=274863&r1=274862&r2=274863&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Target.h (original)
>> +++ lld/trunk/ELF/Target.h Fri Jul  8 11:10:27 2016
>> @@ -48,11 +48,16 @@ public:
>>    // a dynamic relocation.
>>    virtual bool usesOnlyLowPageBits(uint32_t Type) const;
>>
>> -  virtual bool needsThunk(uint32_t Type, const InputFile &File,
>> -                          const SymbolBody &S) const;
>> -
>> +  // Decide whether a Thunk is needed for the relocation from File
>> +  // targeting S. Returns one of:
>> +  // Expr if there is no Thunk required
>> +  // R_THUNK_ABS if thunk is required and expression is absolute
>> +  // R_THUNK_PC if thunk is required and expression is pc rel
>> +  // R_THUNK_PLT_PC if thunk is required to PLT entry and expression is
>> pc rel
>> +  virtual RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType,
>> +                               const InputFile &File,
>> +                               const SymbolBody &S) const;
>>    virtual void writeThunk(uint8_t *Buf, uint64_t S) const {}
>> -
>>    virtual RelExpr getRelExpr(uint32_t Type, const SymbolBody &S) const =
>> 0;
>>    virtual void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val)
>> const = 0;
>>    virtual ~TargetInfo();
>> @@ -87,8 +92,6 @@ public:
>>    // Set to 0 for variant 2
>>    unsigned TcbSize = 0;
>>
>> -  uint32_t ThunkSize = 0;
>> -
>>    virtual RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data,
>>                                    RelExpr Expr) const;
>>    virtual void relaxGot(uint8_t *Loc, uint64_t Val) const;
>>
>> Added: lld/trunk/ELF/Thunks.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.cpp?rev=274863&view=auto
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Thunks.cpp (added)
>> +++ lld/trunk/ELF/Thunks.cpp Fri Jul  8 11:10:27 2016
>> @@ -0,0 +1,251 @@
>> +//===- Thunks.cpp
>> --------------------------------------------------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===---------------------------------------------------------------------===//
>> +//
>> +// This file contains both the Target independent and Target specific
>> Thunk
>> +// classes
>> +//
>> +// A Thunk Object represents a single Thunk that will be written to an
>> +// InputSection when the InputSection contents are written. The
>> InputSection
>> +// maintains a list of Thunks that it owns.
>>
>> +//===---------------------------------------------------------------------===//
>> +
>> +#include "Thunks.h"
>> +#include "Error.h"
>> +#include "InputFiles.h"
>> +#include "InputSection.h"
>> +#include "OutputSections.h"
>> +#include "Symbols.h"
>> +#include "Target.h"
>> +
>> +#include "llvm/Object/ELF.h"
>> +#include "llvm/Support/ELF.h"
>> +#include "llvm/Support/Endian.h"
>> +
>> +using namespace llvm;
>> +using namespace llvm::object;
>> +using namespace llvm::support::endian;
>> +using namespace llvm::ELF;
>> +
>> +namespace lld {
>> +namespace elf {
>> +
>> +template <class ELFT> Thunk<ELFT>::~Thunk() {}
>> +
>> +template <class ELFT>
>> +Thunk<ELFT>::Thunk(const SymbolBody &D, const InputSection<ELFT> &O)
>> +    : Destination(D), Owner(O), Offset(O.getThunkOff() +
>> O.getThunksSize()) {}
>> +
>> +template <class ELFT> typename ELFT::uint Thunk<ELFT>::getVA() const {
>> +  return Owner.OutSec->getVA() + Owner.OutSecOff + Offset;
>> +}
>> +
>> +// ARM Target Thunks
>> +template <class ELFT> static uint64_t getARMThunkDestVA(const SymbolBody
>> &S) {
>> +  return S.isInPlt() ? S.getPltVA<ELFT>() : S.getVA<ELFT>();
>> +}
>> +
>> +// Specific ARM Thunk implementations. The naming convention is:
>> +// Source State, TargetState, Target Requirement, ABS or PI, Range
>> +namespace {
>> +template <class ELFT>
>> +class ARMToThumbV7ABSLongThunk final : public Thunk<ELFT> {
>> +public:
>> +  uint32_t size() const override { return 12; }
>> +
>> +  void writeTo(uint8_t *Buf) const override {
>> +    const uint8_t ATData[] = {
>> +        0x00, 0xc0, 0x00, 0xe3, // movw         ip,:lower16:S
>> +        0x00, 0xc0, 0x40, 0xe3, // movt         ip,:upper16:S
>> +        0x1c, 0xff, 0x2f, 0xe1, // bx   ip
>> +    };
>> +    uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
>> +    memcpy(Buf, ATData, sizeof(ATData));
>> +    Target->relocateOne(Buf, R_ARM_MOVW_ABS_NC, S);
>> +    Target->relocateOne(Buf + 4, R_ARM_MOVT_ABS, S);
>> +  }
>> +
>> +  ARMToThumbV7ABSLongThunk(const SymbolBody &Destination,
>> +                           const InputSection<ELFT> &Owner)
>> +      : Thunk<ELFT>(Destination, Owner) {}
>> +};
>> +
>> +template <class ELFT> class ARMToThumbV7PILongThunk final : public
>> Thunk<ELFT> {
>> +public:
>> +  uint32_t size() const override { return 16; }
>> +
>> +  void writeTo(uint8_t *Buf) const override {
>> +    const uint8_t ATData[] = {
>> +        0xf0, 0xcf, 0x0f, 0xe3, // P:  movw ip,:lower16:S - (P + (L1-P)
>> +8)
>> +        0x00, 0xc0, 0x40, 0xe3, //     movt ip,:upper16:S - (P + (L1-P+4)
>> +8)
>> +        0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc
>> +        0x1c, 0xff, 0x2f, 0xe1, //     bx r12
>> +    };
>> +    uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
>> +    uint64_t P = this->getVA();
>> +    memcpy(Buf, ATData, sizeof(ATData));
>> +    Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, S - P - 16);
>> +    Target->relocateOne(Buf + 4, R_ARM_MOVT_PREL, S - P - 12);
>> +  }
>> +
>> +  ARMToThumbV7PILongThunk(const SymbolBody &Destination,
>> +                          const InputSection<ELFT> &Owner)
>> +      : Thunk<ELFT>(Destination, Owner) {}
>> +};
>> +
>> +template <class ELFT>
>> +class ThumbToARMV7ABSLongThunk final : public Thunk<ELFT> {
>> +public:
>> +  uint32_t size() const override { return 10; }
>> +
>> +  void writeTo(uint8_t *Buf) const override {
>> +    const uint8_t TAData[] = {
>> +        0x40, 0xf2, 0x00, 0x0c, // movw         ip, :lower16:S
>> +        0xc0, 0xf2, 0x00, 0x0c, // movt         ip, :upper16:S
>> +        0x60, 0x47,             // bx   ip
>> +    };
>> +    uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
>> +    memcpy(Buf, TAData, sizeof(TAData));
>> +    Target->relocateOne(Buf, R_ARM_THM_MOVW_ABS_NC, S);
>> +    Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_ABS, S);
>> +  }
>> +
>> +  ThumbToARMV7ABSLongThunk(const SymbolBody &Destination,
>> +                           const InputSection<ELFT> &Owner)
>> +      : Thunk<ELFT>(Destination, Owner) {}
>> +};
>> +
>> +template <class ELFT> class ThumbToARMV7PILongThunk final : public
>> Thunk<ELFT> {
>> +public:
>> +  uint32_t size() const override { return 12; }
>> +
>> +  void writeTo(uint8_t *Buf) const override {
>> +    const uint8_t TAData[] = {
>> +        0x4f, 0xf6, 0xf4, 0x7c, // P:  movw ip,:lower16:S - (P + (L1-P) +
>> 4)
>> +        0xc0, 0xf2, 0x00, 0x0c, //     movt ip,:upper16:S - (P + (L1-P+4)
>> + 4)
>> +        0xfc, 0x44,             // L1: add  r12, pc
>> +        0x60, 0x47,             //     bx   r12
>> +    };
>> +    uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
>> +    uint64_t P = this->getVA();
>> +    memcpy(Buf, TAData, sizeof(TAData));
>> +    Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, S - P - 12);
>> +    Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, S - P - 8);
>> +  }
>> +
>> +  ThumbToARMV7PILongThunk(const SymbolBody &Destination,
>> +                          const InputSection<ELFT> &Owner)
>> +      : Thunk<ELFT>(Destination, Owner) {}
>> +};
>> +
>> +// Mips Thunks
>> +// Only the MIPS LA25 Thunk is supported, the implementation is delegated
>> +// to the MipsTargetInfo class in Target.cpp
>> +template <class ELFT> class MipsThunk : public Thunk<ELFT> {
>> +public:
>> +  MipsThunk(const SymbolBody &Destination, const InputSection<ELFT>
>> &Owner);
>> +  uint32_t size() const override;
>> +  void writeTo(uint8_t *Buf) const override;
>> +};
>> +
>> +template <class ELFT>
>> +MipsThunk<ELFT>::MipsThunk(const SymbolBody &Destination,
>> +                           const InputSection<ELFT> &Owner)
>> +    : Thunk<ELFT>(Destination, Owner) {}
>> +
>> +template <class ELFT> uint32_t MipsThunk<ELFT>::size() const { return 16;
>> }
>> +
>> +template <class ELFT> void MipsThunk<ELFT>::writeTo(uint8_t *Buf) const {
>> +  const SymbolBody &D = this->Destination;
>> +  uint64_t S = D.getVA<ELFT>();
>> +  Target->writeThunk(Buf, S);
>> +}
>> +}
>> +
>> +template <class ELFT>
>> +static void addThunkARM(uint32_t RelocType, SymbolBody &S,
>> +                        InputSection<ELFT> &IS) {
>> +  if (S.hasThunk<ELFT>())
>> +    // only one Thunk supported per symbol
>> +    return;
>> +
>> +  bool NeedsPI = Config->Pic || Config->Pie || Config->Shared;
>> +  Thunk<ELFT> *thunk;
>> +  // ARM relocations need ARM to Thumb interworking Thunks, Thumb
>> relocations
>> +  // need Thumb to ARM relocations. Use position independent Thunks if we
>> +  // require position independent code.
>> +  switch (RelocType) {
>> +  case R_ARM_PC24:
>> +  case R_ARM_PLT32:
>> +  case R_ARM_JUMP24:
>> +    if (NeedsPI)
>> +      thunk = new ARMToThumbV7PILongThunk<ELFT>(S, IS);
>> +    else
>> +      thunk = new ARMToThumbV7ABSLongThunk<ELFT>(S, IS);
>> +    break;
>> +  case R_ARM_THM_JUMP19:
>> +  case R_ARM_THM_JUMP24:
>> +    if (NeedsPI)
>> +      thunk = new ThumbToARMV7PILongThunk<ELFT>(S, IS);
>> +    else
>> +      thunk = new ThumbToARMV7ABSLongThunk<ELFT>(S, IS);
>> +    break;
>> +  default:
>> +    fatal("Unrecognised Relocation type\n");
>> +  }
>> +  // ARM Thunks are added to the same InputSection as the relocation.
>> This
>> +  // isn't strictly necessary but it makes it more likely that a limited
>> range
>> +  // branch can reach the Thunk, and it makes Thunks to the PLT section
>> easier
>> +  IS.addThunk(thunk);
>> +  if (DefinedRegular<ELFT> *DR = dyn_cast<DefinedRegular<ELFT>>(&S))
>> +    DR->ThunkData.reset(thunk);
>> +  else if (SharedSymbol<ELFT> *SH = dyn_cast<SharedSymbol<ELFT>>(&S))
>> +    SH->ThunkData.reset(thunk);
>> +  else
>> +    fatal("symbol not DefinedRegular or Shared\n");
>> +}
>> +
>> +template <class ELFT>
>> +static void addThunkMips(uint32_t RelocType, SymbolBody &S) {
>> +  if (S.hasThunk<ELFT>())
>> +    // only one Thunk supported per symbol
>> +    return;
>> +  // Mips Thunks are added to the InputSection defining S
>> +  auto *R = cast<DefinedRegular<ELFT>>(&S);
>> +  auto *Sec = cast<InputSection<ELFT>>(R->Section);
>> +  auto *T = new MipsThunk<ELFT>(S, *Sec);
>> +  Sec->addThunk(T);
>> +  R->ThunkData.reset(T);
>> +}
>> +
>> +template <class ELFT>
>> +void addThunk(uint32_t RelocType, SymbolBody &S, InputSection<ELFT> &IS)
>> {
>> +  if (Config->EMachine == EM_ARM)
>> +    addThunkARM<ELFT>(RelocType, S, IS);
>> +  else if (Config->EMachine == EM_MIPS)
>> +    addThunkMips<ELFT>(RelocType, S);
>> +  else
>> +    llvm_unreachable("add Thunk only supported for ARM and Mips");
>> +}
>> +
>> +template void addThunk<ELF32LE>(uint32_t, SymbolBody &,
>> +                                InputSection<ELF32LE> &);
>> +template void addThunk<ELF32BE>(uint32_t, SymbolBody &,
>> +                                InputSection<ELF32BE> &);
>> +template void addThunk<ELF64LE>(uint32_t, SymbolBody &,
>> +                                InputSection<ELF64LE> &);
>> +template void addThunk<ELF64BE>(uint32_t, SymbolBody &,
>> +                                InputSection<ELF64BE> &);
>> +
>> +template uint32_t Thunk<ELF32LE>::getVA() const;
>> +template uint32_t Thunk<ELF32BE>::getVA() const;
>> +template uint64_t Thunk<ELF64LE>::getVA() const;
>> +template uint64_t Thunk<ELF64BE>::getVA() const;
>> +
>> +} // namespace elf
>> +} // namespace lld
>>
>> Propchange: lld/trunk/ELF/Thunks.cpp
>>
>> ------------------------------------------------------------------------------
>>     svn:eol-style = native
>>
>> Propchange: lld/trunk/ELF/Thunks.cpp
>>
>> ------------------------------------------------------------------------------
>>     svn:keywords = Rev Date Author URL Id
>>
>> Added: lld/trunk/ELF/Thunks.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.h?rev=274863&view=auto
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Thunks.h (added)
>> +++ lld/trunk/ELF/Thunks.h Fri Jul  8 11:10:27 2016
>> @@ -0,0 +1,55 @@
>> +//===- Thunks.h
>> --------------------------------------------------------===//
>> +//
>> +//                             The LLVM Linker
>> +//
>> +// This file is distributed under the University of Illinois Open Source
>> +// License. See LICENSE.TXT for details.
>> +//
>>
>> +//===----------------------------------------------------------------------===//
>> +
>> +#ifndef LLD_ELF_THUNKS_H
>> +#define LLD_ELF_THUNKS_H
>> +
>> +#include "Relocations.h"
>> +
>> +namespace lld {
>> +namespace elf {
>> +class SymbolBody;
>> +class InputFile;
>> +template <class ELFT> class InputSection;
>> +template <class ELFT> class InputSectionBase;
>> +
>> +// Class to describe an instance of a Thunk.
>> +// A Thunk is a code-sequence inserted by the linker in between a caller
>> and
>> +// the callee. The relocation to the callee is redirected to the Thunk,
>> which
>> +// after executing transfers control to the callee. Typical uses of
>> Thunks
>> +// include transferring control from non-pi to pi and changing state on
>> +// targets like ARM.
>> +//
>> +// Thunks can be created for DefinedRegular and Shared Symbols. The Thunk
>> +// is stored in a field of the Symbol Destination.
>> +// Thunks to be written to an InputSection are recorded by the
>> InputSection.
>> +template <class ELFT> class Thunk {
>> +public:
>> +  virtual uint32_t size() const { return 0; }
>> +  typename ELFT::uint getVA() const;
>> +  virtual void writeTo(uint8_t *Buf) const {};
>> +  Thunk(const SymbolBody &Destination, const InputSection<ELFT> &Owner);
>> +  virtual ~Thunk();
>> +
>> +protected:
>> +  const SymbolBody &Destination;
>> +  const InputSection<ELFT> &Owner;
>> +  uint64_t Offset;
>> +};
>> +
>> +// For a Relocation to symbol S from InputSection Src, create a Thunk and
>> +// update the fields of S and the InputSection that the Thunk body will
>> be
>> +// written to. At present there are implementations for ARM and Mips
>> Thunks.
>> +template <class ELFT>
>> +void addThunk(uint32_t RelocType, SymbolBody &S, InputSection<ELFT>
>> &Src);
>> +
>> +} // namespace elf
>> +} // namespace lld
>> +
>> +#endif
>>
>> Propchange: lld/trunk/ELF/Thunks.h
>>
>> ------------------------------------------------------------------------------
>>     svn:eol-style = native
>>
>> Propchange: lld/trunk/ELF/Thunks.h
>>
>> ------------------------------------------------------------------------------
>>     svn:keywords = Rev Date Author URL Id
>>
>> Modified: lld/trunk/test/ELF/arm-mov-relocs.s
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-mov-relocs.s?rev=274863&r1=274862&r2=274863&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/test/ELF/arm-mov-relocs.s (original)
>> +++ lld/trunk/test/ELF/arm-mov-relocs.s Fri Jul  8 11:10:27 2016
>> @@ -41,16 +41,53 @@ _start:
>>  // CHECK: movt r3, #2
>>  // CHECK: movt r4, #3
>>
>> +.section .R_ARM_MOVW_PREL_NC, "ax",%progbits
>> + movw r0, :lower16:label - .
>> + movw r1, :lower16:label1 - .
>> + movw r2, :lower16:label2 + 4 - .
>> + movw r3, :lower16:label3 - .
>> + movw r4, :lower16:label3 + 0x103c - .
>> +// 0x20000 - 0x11028 = :lower16:0xefd8 (61400)
>> +// CHECK: 11028:  {{.*}}     movw    r0, #61400
>> +// 0x20004 = 0x1102c = :lower16:0xefd8 (61400)
>> +// CHECK: 1102c:  {{.*}}     movw    r1, #61400
>> +// 0x20008 - 0x11030 + 4 = :lower16:0xefdc (61404)
>> +// CHECK: 11030:  {{.*}}     movw    r2, #61404
>> +// 0x2fffc - 0x11034 = :lower16:0x1efc8 (61384)
>> +// CHECK: 11034:  {{.*}}     movw    r3, #61384
>> +// 0x2fffc - 0x11038 +0x103c :lower16:0x20000 (0)
>> +// CHECK: 11038:  {{.*}}     movw    r4, #0
>> +
>> +.section .R_ARM_MOVT_PREL, "ax",%progbits
>> + movt r0, :upper16:label - .
>> + movt r1, :upper16:label1 - .
>> + movt r2, :upper16:label2 + 0x4 - .
>> + movt r3, :upper16:label3 - .
>> + movt r4, :upper16:label3 + 0x1050 - .
>> +// 0x20000 - 0x1103c = :upper16:0xefc4  = 0
>> +// CHECK: 1103c:  {{.*}}     movt    r0, #0
>> +// 0x20004 - 0x11040 = :upper16:0xefc0 = 0
>> +// CHECK: 11040:  {{.*}}     movt    r1, #0
>> +// 0x20008 - 0x11044 + 4 = :upper16:0xefc8 = 0
>> +// CHECK: 11044:  {{.*}}     movt    r2, #0
>> +// 0x2fffc - 0x11048 = :upper16:0x1efb4 = 1
>> +// CHECK: 11048:  {{.*}}     movt    r3, #1
>> +// 0x2fffc - 0x1104c + 0x1050 = :upper16:0x20000 = 2
>> +// CHECK: 1104c:  {{.*}}     movt    r4, #2
>>   .section .destination, "aw",%progbits
>>   .balign 65536
>> +// 0x20000
>>  label:
>>   .word 0
>> +// 0x20004
>>  label1:
>>   .word 1
>> +// 0x20008
>>  label2:
>>   .word 2
>>  // Test label3 is immediately below 2^16 alignment boundary
>>   .space 65536 - 16
>> +// 0x2fffc
>>  label3:
>>   .word 3
>>  // label3 + 4 is on a 2^16 alignment boundary
>>
>> Added: lld/trunk/test/ELF/arm-thumb-interwork-thunk.s
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-interwork-thunk.s?rev=274863&view=auto
>>
>> ==============================================================================
>> --- lld/trunk/test/ELF/arm-thumb-interwork-thunk.s (added)
>> +++ lld/trunk/test/ELF/arm-thumb-interwork-thunk.s Fri Jul  8 11:10:27
>> 2016
>> @@ -0,0 +1,375 @@
>> +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
>> +// RUN: echo "SECTIONS { \
>> +// RUN:       .R_ARM_JUMP24_callee_1 : { *(.R_ARM_JUMP24_callee_low) } \
>> +// RUN:       .R_ARM_THM_JUMP_callee_1 : { *(.R_ARM_THM_JUMP_callee_low)}
>> \
>> +// RUN:       .text : { *(.text) } \
>> +// RUN:       .arm_caller : { *(.arm_caller) } \
>> +// RUN:       .thumb_caller : { *(.thumb_caller) } \
>> +// RUN:       .R_ARM_JUMP24_callee_2 : { *(.R_ARM_JUMP24_callee_high) } \
>> +// RUN:       .R_ARM_THM_JUMP_callee_2 : { *(.R_ARM_THM_JUMP_callee_high)
>> } } " > %t.script
>> +// RUN: ld.lld --script %t.script %t -o %t2 2>&1
>> +// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 |
>> FileCheck -check-prefix=CHECK-THUMB -check-prefix=CHECK-ABS-THUMB %s
>> +// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck
>> -check-prefix=CHECK-ARM -check-prefix=CHECK-ABS-ARM %s
>> +// RUN: ld.lld --script %t.script %t -pie -o %t3 2>&1
>> +// RUN: ld.lld --script %t.script %t --shared -o %t4 2>&1
>> +// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t3 |
>> FileCheck -check-prefix=CHECK-THUMB -check-prefix=CHECK-PI-THUMB %s
>> +// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck
>> -check-prefix=CHECK-ARM -check-prefix=CHECK-PI-ARM %s
>> +// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t4 |
>> FileCheck -check-prefix=CHECK-THUMB -check-prefix=CHECK-PI-PLT-THUMB %s
>> +// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t4 | FileCheck
>> -check-prefix=CHECK-ARM -check-prefix=CHECK-PI-PLT-ARM %s
>> +// RUN: llvm-readobj -s -r %t4 | FileCheck -check-prefix=CHECK-DSO-REL %s
>> +// REQUIRES: arm
>> +
>> +// Test ARM Thumb Interworking
>> +// The file is linked and checked 3 times to check the following contexts
>> +// - Absolute executables, absolute Thunks are used.
>> +// - Position independent executables, position independent Thunks are
>> used.
>> +// - Shared object, position independent Thunks to PLT entries are used.
>> +
>> + .syntax unified
>> +
>> +// Target Sections for thunks at a lower address than the callers.
>> +.section .R_ARM_JUMP24_callee_low, "ax", %progbits
>> + .thumb
>> + .balign 0x1000
>> + .globl thumb_callee1
>> + .type thumb_callee1, %function
>> +thumb_callee1:
>> + bx lr
>> +
>> +// CHECK-THUMB: Disassembly of section .R_ARM_JUMP24_callee_1:
>> +// CHECK-THUMB: thumb_callee1:
>> +// CHECK-THUMB: 1000:       70 47   bx
>> + .section .R_ARM_THM_JUMP_callee_low, "ax", %progbits
>> + .arm
>> + .balign 0x100
>> + .globl arm_callee1
>> + .type arm_callee1, %function
>> +arm_callee1:
>> + bx lr
>> +// Disassembly of section .R_ARM_THM_JUMP_callee_1:
>> +// CHECK-ARM: arm_callee1:
>> +// CHECK-ARM-NEXT: 1100:         1e ff 2f e1     bx      lr
>> +
>> + // Calling sections
>> + // At present ARM and Thumb interworking thunks are always added to the
>> calling
>> + // section.
>> + .section .arm_caller, "ax", %progbits
>> + .arm
>> + .balign 0x100
>> + .globl arm_caller
>> + .type arm_caller, %function
>> +arm_caller:
>> + // If target supports BLX and target is in range we don't need an
>> + // interworking thunk for a BL or BLX instruction.
>> + bl thumb_callee1
>> + blx thumb_callee1
>> + // A B instruction can't be transformed into a BLX and needs an
>> interworking
>> + // thunk
>> + b thumb_callee1
>> + // As long as the thunk is in range it can be reused
>> + b thumb_callee1
>> + // There can be more than one thunk associated with a section
>> + b thumb_callee2
>> + b thumb_callee3
>> + // In range ARM targets do not require interworking thunks
>> + b arm_callee1
>> + beq arm_callee2
>> + bne arm_callee3
>> + bx lr
>> +// CHECK-ABS-ARM: Disassembly of section .arm_caller:
>> +// CHECK-ABS-ARM-NEXT: arm_caller:
>> +// CHECK-ABS-ARM-NEXT: 1300:       3e ff ff fa     blx     #-776
>> <thumb_callee1>
>> +// CHECK-ABS-ARM-NEXT: 1304:       3d ff ff fa     blx     #-780
>> <thumb_callee1>
>> +// CHECK-ABS-ARM-NEXT: 1308:       06 00 00 ea     b       #24
>> <arm_caller+0x28>
>> +// CHECK-ABS-ARM-NEXT: 130c:       05 00 00 ea     b       #20
>> <arm_caller+0x28>
>> +// CHECK-ABS-ARM-NEXT: 1310:       07 00 00 ea     b       #28
>> <arm_caller+0x34>
>> +// CHECK-ABS-ARM-NEXT: 1314:       09 00 00 ea     b       #36
>> <arm_caller+0x40>
>> +// CHECK-ABS-ARM-NEXT: 1318:       78 ff ff ea     b       #-544
>> <arm_callee1>
>> +// CHECK-ABS-ARM-NEXT: 131c:       b7 00 00 0a     beq     #732
>> <arm_callee2>
>> +// CHECK-ABS-ARM-NEXT: 1320:       b7 00 00 1a     bne     #732
>> <arm_callee3>
>> +// CHECK-ABS-ARM-NEXT: 1324:       1e ff 2f e1     bx      lr
>> +// 0x1001 = thumb_callee1
>> +// CHECK-ABS-ARM-NEXT: 1328:       01 c0 01 e3     movw    r12, #4097
>> +// CHECK-ABS-ARM-NEXT: 132c:       00 c0 40 e3     movt    r12, #0
>> +// CHECK-ABS-ARM-NEXT: 1330:       1c ff 2f e1     bx      r12
>> +// 0x1501 = thumb_callee2
>> +// CHECK-ABS-ARM-NEXT: 1334:       01 c5 01 e3     movw    r12, #5377
>> +// CHECK-ABS-ARM-NEXT: 1338:       00 c0 40 e3     movt    r12, #0
>> +// CHECK-ABS-ARM-NEXT: 133c:       1c ff 2f e1     bx      r12
>> +// 0x1503 = thumb_callee3
>> +// CHECK-ABS-ARM-NEXT: 1340:       03 c5 01 e3     movw    r12, #5379
>> +// CHECK-ABS-ARM-NEXT: 1344:       00 c0 40 e3     movt    r12, #0
>> +// CHECK-ABS-ARM-NEXT: 1348:       1c ff 2f e1     bx      r12
>> +
>> +// CHECK-PI-ARM: Disassembly of section .arm_caller:
>> +// CHECK-PI-ARM-NEXT: arm_caller:
>> +// CHECK-PI-ARM-NEXT: 1300:       3e ff ff fa     blx     #-776
>> <thumb_callee1>
>> +// CHECK-PI-ARM-NEXT: 1304:       3d ff ff fa     blx     #-780
>> <thumb_callee1>
>> +// 0x1308 + 8 + 0x18 = 0x1328
>> +// CHECK-PI-ARM-NEXT: 1308:       06 00 00 ea     b       #24
>> <arm_caller+0x28>
>> +// 0x130c + 8 + 0x14 = 0x1328
>> +// CHECK-PI-ARM-NEXT: 130c:       05 00 00 ea     b       #20
>> <arm_caller+0x28>
>> +// 0x1310 + 8 + 0x20 = 0x1338
>> +// CHECK-PI-ARM-NEXT: 1310:       08 00 00 ea     b       #32
>> <arm_caller+0x38>
>> +// 0x1314 + 8 + 0x2c = 0x1348
>> +// CHECK-PI-ARM-NEXT: 1314:       0b 00 00 ea     b       #44
>> <arm_caller+0x48>
>> +// CHECK-PI-ARM-NEXT: 1318:       78 ff ff ea     b       #-544
>> <arm_callee1>
>> +// CHECK-PI-ARM-NEXT: 131c:       b7 00 00 0a     beq     #732
>> <arm_callee2>
>> +// CHECK-PI-ARM-NEXT: 1320:       b7 00 00 1a     bne     #732
>> <arm_callee3>
>> +// CHECK-PI-ARM-NEXT: 1324:       1e ff 2f e1     bx      lr
>> +// 0x1330 + 8 - 0x337 = 0x1001 = thumb_callee1
>> +// CHECK-PI-ARM-NEXT: 1328:       c9 cc 0f e3     movw    r12, #64713
>> +// CHECK-PI-ARM-NEXT: 132c:       ff cf 4f e3     movt    r12, #65535
>> +// CHECK-PI-ARM-NEXT: 1330:       0f c0 8c e0     add     r12, r12, pc
>> +// CHECK-PI-ARM-NEXT: 1334:       1c ff 2f e1     bx      r12
>> +// 0x1340 + 8 + 0x1b9 = 0x1501
>> +// CHECK-PI-ARM-NEXT: 1338:       b9 c1 00 e3     movw    r12, #441
>> +// CHECK-PI-ARM-NEXT: 133c:       00 c0 40 e3     movt    r12, #0
>> +// CHECK-PI-ARM-NEXT: 1340:       0f c0 8c e0     add     r12, r12, pc
>> +// CHECK-PI-ARM-NEXT: 1344:       1c ff 2f e1     bx      r12
>> +// 1350 + 8 + 0x1ab = 0x1503
>> +// CHECK-PI-ARM-NEXT: 1348:       ab c1 00 e3     movw    r12, #427
>> +// CHECK-PI-ARM-NEXT: 134c:       00 c0 40 e3     movt    r12, #0
>> +// CHECK-PI-ARM-NEXT: 1350:       0f c0 8c e0     add     r12, r12, pc
>> +// CHECK-PI-ARM-NEXT: 1354:       1c ff 2f e1     bx      r12
>> +
>> +// All PLT entries are ARM, no need for interworking thunks
>> +// CHECK-PI-ARM-PLT: Disassembly of section .arm_caller:
>> +// CHECK-PI-ARM-PLT-NEXT: arm_caller:
>> +// 0x17e4 PLT(thumb_callee1)
>> +// CHECK-PI-ARM-PLT-NEXT:    1300:       37 01 00 eb     bl      #1244
>> +// 0x17e4 PLT(thumb_callee1)
>> +// CHECK-PI-ARM-PLT-NEXT:    1304:       36 01 00 eb     bl      #1240
>> +// 0x17e4 PLT(thumb_callee1)
>> +// CHECK-PI-ARM-PLT-NEXT:    1308:       35 01 00 ea     b       #1236
>> +// 0x17e4 PLT(thumb_callee1)
>> +// CHECK-PI-ARM-PLT-NEXT:    130c:       34 01 00 ea     b       #1232
>> +// 0x17f4 PLT(thumb_callee2)
>> +// CHECK-PI-ARM-PLT-NEXT:    1310:       37 01 00 ea     b       #1244
>> +// 0x1804 PLT(thumb_callee3)
>> +// CHECK-PI-ARM-PLT-NEXT:    1314:       3a 01 00 ea     b       #1256
>> +// 0x1814 PLT(arm_callee1)
>> +// CHECK-PI-ARM-PLT-NEXT:    1318:       3d 01 00 ea     b       #1268
>> +// 0x1824 PLT(arm_callee2)
>> +// CHECK-PI-ARM-PLT-NEXT:    131c:       40 01 00 0a     beq     #1280
>> +// 0x1834 PLT(arm_callee3)
>> +// CHECK-PI-ARM-PLT-NEXT:    1320:       43 01 00 1a     bne     #1292
>> +// CHECK-PI-ARM-PLT-NEXT:    1324:       1e ff 2f e1     bx      lr
>> +
>> + .section .thumb_caller, "ax", %progbits
>> + .balign 0x100
>> + .thumb
>> + .globl thumb_caller
>> + .type thumb_caller, %function
>> +thumb_caller:
>> + // If target supports BLX and target is in range we don't need an
>> + // interworking thunk for a BL or BLX instruction.
>> + bl arm_callee1
>> + blx arm_callee1
>> + // A B instruction can't be transformed into a BLX and needs an
>> interworking
>> + // thunk
>> + b.w arm_callee1
>> + // As long as the thunk is in range it can be reused
>> + b.w arm_callee2
>> + // There can be more than one thunk associated with a section
>> + b.w arm_callee3
>> + // Conditional branches also require interworking thunks, they can use
>> the
>> + // same interworking thunks.
>> + beq.w arm_callee1
>> + beq.w arm_callee2
>> + bne.w arm_callee3
>> +// CHECK-ABS-THUMB: Disassembly of section .thumb_caller:
>> +// CHECK-ABS-THUMB-NEXT: thumb_caller:
>> +// 0x1400 + 4 - 0x304 = 0x1100 = arm_callee1
>> +// CHECK-ABS-THUMB-NEXT: 1400:       ff f7 7e ee     blx     #-772
>> +// 0x1404 + 4 - 0x308 = 0x1100 = arm_callee1
>> +// CHECK-ABS-THUMB-NEXT: 1404:       ff f7 7c ee     blx     #-776
>> +// 0x1408 + 4 + 0x14 = 0x520
>> +// CHECK-ABS-THUMB-NEXT: 1408:       00 f0 0a b8     b.w     #20
>> +// 0x140c + 4 + 0x1a = 0x52a
>> +// CHECK-ABS-THUMB-NEXT: 140c:       00 f0 0d b8     b.w     #26
>> +// 0x1410 + 4 + 0x20 = 0x534
>> +// CHECK-ABS-THUMB-NEXT: 1410:       00 f0 10 b8     b.w     #32
>> +// 0x1414 + 4 + 8 = 0x520
>> +// CHECK-ABS-THUMB-NEXT: 1414:       00 f0 04 80     beq.w   #8
>> +// 0x1418 + 4 + 0xe = 0x52a
>> +// CHECK-ABS-THUMB-NEXT: 1418:       00 f0 07 80     beq.w   #14
>> +// 0x141c + 4 + 0x14 = 0x534
>> +// CHECK-ABS-THUMB-NEXT: 141c:       40 f0 0a 80     bne.w   #20
>> +// 0x1100 = arm_callee1
>> +// CHECK-ABS-THUMB-NEXT: 1420:       41 f2 00 1c     movw    r12, #4352
>> +// CHECK-ABS-THUMB-NEXT: 1424:       c0 f2 00 0c     movt    r12, #0
>> +// CHECK-ABS-THUMB-NEXT: 1428:       60 47   bx      r12
>> +// 0x1600 = arm_callee2
>> +// CHECK-ABS-THUMB-NEXT: 142a:       41 f2 00 6c     movw    r12, #5632
>> +// CHECK-ABS-THUMB-NEXT: 142e:       c0 f2 00 0c     movt    r12, #0
>> +// CHECK-ABS-THUMB-NEXT: 1432:       60 47   bx      r12
>> +// 0x1604 = arm_callee3
>> +// CHECK-ABS-THUMB-NEXT: 1434:       41 f2 04 6c     movw    r12, #5636
>> +// CHECK-ABS-THUMB-NEXT: 1438:       c0 f2 00 0c     movt    r12, #0
>> +// CHECK-ABS-THUMB-NEXT: 143c:       60 47   bx      r12
>> +
>> +// CHECK-PI-THUMB: Disassembly of section .thumb_caller:
>> +// CHECK-PI-THUMB-NEXT: thumb_caller:
>> +// CHECK-PI-THUMB-NEXT: 1400:       ff f7 7e ee     blx     #-772
>> +// CHECK-PI-THUMB-NEXT: 1404:       ff f7 7c ee     blx     #-776
>> +// CHECK-PI-THUMB-NEXT: 1408:       00 f0 0a b8     b.w     #20
>> +// CHECK-PI-THUMB-NEXT: 140c:       00 f0 0e b8     b.w     #28
>> +// CHECK-PI-THUMB-NEXT: 1410:       00 f0 12 b8     b.w     #36
>> +// CHECK-PI-THUMB-NEXT: 1414:       00 f0 04 80     beq.w   #8
>> +// CHECK-PI-THUMB-NEXT: 1418:       00 f0 08 80     beq.w   #16
>> +// CHECK-PI-THUMB-NEXT: 141c:       40 f0 0c 80     bne.w   #24
>> +// 0x1428 + 4 - 0x32c = 0x1100 = arm_callee1
>> +// CHECK-PI-THUMB-NEXT: 1420:       4f f6 d4 4c     movw    r12, #64724
>> +// CHECK-PI-THUMB-NEXT: 1424:       cf f6 ff 7c     movt    r12, #65535
>> +// CHECK-PI-THUMB-NEXT: 1428:       fc 44   add     r12, pc
>> +// CHECK-PI-THUMB-NEXT: 142a:       60 47   bx      r12
>> +// 0x1434 + 4 + 0x1c8 = 0x1600 = arm_callee2
>> +// CHECK-PI-THUMB-NEXT: 142c:       40 f2 c8 1c     movw    r12, #456
>> +// CHECK-PI-THUMB-NEXT: 1430:       c0 f2 00 0c     movt    r12, #0
>> +// CHECK-PI-THUMB-NEXT: 1434:       fc 44   add     r12, pc
>> +// CHECK-PI-THUMB-NEXT: 1436:       60 47   bx      r12
>> +// 0x1440 + 4 + 0x1c0 = 0x1604 = arm_callee3
>> +// CHECK-PI-THUMB-NEXT: 1438:       40 f2 c0 1c     movw    r12, #448
>> +// CHECK-PI-THUMB-NEXT: 143c:       c0 f2 00 0c     movt    r12, #0
>> +// CHECK-PI-THUMB-NEXT: 1440:       fc 44   add     r12, pc
>> +// CHECK-PI-THUMB-NEXT: 1442:       60 47   bx      r12
>> +
>> +// CHECK-PI-THUMB-PLT: Disassembly of section .arm_caller:
>> +// CHECK-PI-THUMB-PLT-NEXT: thumb_caller:
>> +// 0x1400 + 4 + 0x410 = 0x1814 = PLT(arm_callee1)
>> +// CHECK-PI-THUMB-PLT-NEXT:    1400:    00 f0 08 ea     blx     #1040
>> +// 0x1404 + 4 + 0x40c = 0x1814 = PLT(arm_callee1)
>> +// CHECK-PI-THUMB-PLT-NEXT:    1404:    00 f0 06 ea     blx     #1036
>> +// 0x1408 + 4 + 0x14 = 0x1420 = IWV(PLT(arm_callee1)
>> +// CHECK-PI-THUMB-PLT-NEXT:    1408:    00 f0 0a b8     b.w     #20
>> +// 0x140c + 4 + 0x1c = 0x142c = IWV(PLT(arm_callee2)
>> +// CHECK-PI-THUMB-PLT-NEXT:    140c:    00 f0 0e b8     b.w     #28
>> +// 0x1410 + 4 + 0x24 = 0x1438 = IWV(PLT(arm_callee3)
>> +// CHECK-PI-THUMB-PLT-NEXT:    1410:    00 f0 12 b8     b.w     #36
>> +// 0x1414 + 4 + 8 = 0x1420    = IWV(PLT(arm_callee1)
>> +// CHECK-PI-THUMB-PLT-NEXT:    1414:    00 f0 04 80     beq.w   #8
>> +// 0x1418 + 4 + 0x10 = 0x142c = IWV(PLT(arm_callee2)
>> +// CHECK-PI-THUMB-PLT-NEXT:    1418:    00 f0 08 80     beq.w   #16
>> +// 0x141c + 4 + 0x18 = 0x1438 = IWV(PLT(arm_callee3)
>> +// CHECK-PI-THUMB-PLT-NEXT:    141c:    40 f0 0c 80     bne.w   #24
>> +// 0x1428 + 4 + 0x3e8 = 0x1814 = PLT(arm_callee1)
>> +// CHECK-PI-THUMB-PLT-NEXT:    1420:    40 f2 e8 3c     movw    r12,
>> #1000
>> +// CHECK-PI-THUMB-PLT-NEXT:    1424:    c0 f2 00 0c     movt    r12, #0
>> +// CHECK-PI-THUMB-PLT-NEXT:    1428:    fc 44   add     r12, pc
>> +// CHECK-PI-THUMB-PLT-NEXT:    142a:    60 47   bx      r12
>> +// 0x1434 + 4 + 0x3ec = 0x1824 = PLT(arm_callee2)
>> +// CHECK-PI-THUMB-PLT-NEXT:    142c:    40 f2 ec 3c     movw    r12,
>> #1004
>> +// CHECK-PI-THUMB-PLT-NEXT:    1430:    c0 f2 00 0c     movt    r12, #0
>> +// CHECK-PI-THUMB-PLT-NEXT:    1434:    fc 44   add     r12, pc
>> +// CHECK-PI-THUMB-PLT-NEXT:    1436:    60 47   bx      r12
>> +// 0x1440 + 4 + 0x3f0 = 0x1834 = PLT(arm_callee3)
>> +// CHECK-PI-THUMB-PLT-NEXT:    1438:    40 f2 f0 3c     movw    r12,
>> #1008
>> +// CHECK-PI-THUMB-PLT-NEXT:    143c:    c0 f2 00 0c     movt    r12, #0
>> +// CHECK-PI-THUMB-PLT-NEXT:    1440:    fc 44   add     r12, pc
>> +// CHECK-PI-THUMB-PLT-NEXT:    1442:    60 47   bx      r12
>> +
>> +// Target Sections for thunks at a higher address than the callers.
>> +.section .R_ARM_JUMP24_callee_high, "ax", %progbits
>> + .thumb
>> + .balign 0x100
>> + .globl thumb_callee2
>> + .type thumb_callee2, %function
>> +thumb_callee2:
>> + bx lr
>> +
>> + .globl thumb_callee3
>> + .type thumb_callee3, %function
>> +thumb_callee3:
>> + bx lr
>> +// CHECK-THUMB:  Disassembly of section .R_ARM_JUMP24_callee_2:
>> +// CHECK-THUMB-NEXT: thumb_callee2:
>> +// CHECK-THUMB-NEXT: 1500:       70 47   bx      lr
>> +// CHECK-THUMB: thumb_callee3:
>> +// CHECK-THUMB-NEXT: 1502:       70 47   bx      lr
>> +
>> + .section .R_ARM_THM_JUMP_callee_high, "ax", %progbits
>> + .arm
>> + .balign 0x100
>> + .globl arm_callee2
>> + .type arm_callee2, %function
>> +arm_callee2:
>> + bx lr
>> + .globl arm_callee3
>> + .type arm_callee3, %function
>> +arm_callee3:
>> + bx lr
>> +// CHECK-ARM: Disassembly of section .R_ARM_THM_JUMP_callee_2:
>> +// CHECK-ARM-NEXT: arm_callee2:
>> +// CHECK-ARM-NEXT:     1600:     1e ff 2f e1     bx      lr
>> +// CHECK-ARM: arm_callee3:
>> +// CHECK-ARM-NEXT:     1604:     1e ff 2f e1     bx      lr
>> +
>> +// _start section just calls the arm and thumb calling sections
>> + .text
>> + .arm
>> + .globl _start
>> + .balign 0x100
>> + .type _start, %function
>> +_start:
>> + bl arm_caller
>> + bl thumb_caller
>> + bx lr
>> +
>> +
>> +// CHECK-PI-ARM-PLT: Disassembly of section .plt:
>> +// CHECK-PI-ARM-PLT-NEXT: .plt:
>> +// CHECK-PI-ARM-PLT-NEXT: 17b0:         04 e0 2d e5     str     lr, [sp,
>> #-4]!
>> +// CHECK-PI-ARM-PLT-NEXT: 17b4:         04 e0 9f e5     ldr     lr, [pc,
>> #4]
>> +// CHECK-PI-ARM-PLT-NEXT: 17b8:         0e e0 8f e0     add     lr, pc,
>> lr
>> +// CHECK-PI-ARM-PLT-NEXT: 17bc:         08 f0 be e5     ldr     pc, [lr,
>> #8]!
>> +// CHECK-PI-ARM-PLT-NEXT: 17c0:         d4 00 00 00
>> +// 0x17c8 + 8 + 0xd0 = 0x18a0 arm_caller
>> +// CHECK-PI-ARM-PLT-NEXT: 17c4:         04 c0 9f e5     ldr     r12, [pc,
>> #4]
>> +// CHECK-PI-ARM-PLT-NEXT: 17c8:         0f c0 8c e0     add     r12, r12,
>> pc
>> +// CHECK-PI-ARM-PLT-NEXT: 17cc:         00 f0 9c e5     ldr     pc, [r12]
>> +// CHECK-PI-ARM-PLT-NEXT: 17d0:         d0 00 00 00
>> +// 0x17d8 + 8 + 0xc4 = 0x18a4 thumb_caller
>> +// CHECK-PI-ARM-PLT-NEXT: 17d4:         04 c0 9f e5     ldr     r12, [pc,
>> #4]
>> +// CHECK-PI-ARM-PLT-NEXT: 17d8:         0f c0 8c e0     add     r12, r12,
>> pc
>> +// CHECK-PI-ARM-PLT-NEXT: 17dc:         00 f0 9c e5     ldr     pc, [r12]
>> +// CHECK-PI-ARM-PLT-NEXT: 17e0:         c4 00 00 00
>> +// 0x17e8 + 8 + 0xb8 = 0x18a8 thumb_callee1
>> +// CHECK-PI-ARM-PLT-NEXT: 17e4:         04 c0 9f e5     ldr     r12, [pc,
>> #4]
>> +// CHECK-PI-ARM-PLT-NEXT: 17e8:         0f c0 8c e0     add     r12, r12,
>> pc
>> +// CHECK-PI-ARM-PLT-NEXT: 17ec:         00 f0 9c e5     ldr     pc, [r12]
>> +// CHECK-PI-ARM-PLT-NEXT: 17f0:         b8 00 00 00
>> +// 0x17f8 + 8 + 0xac = 0x18ac thumb_callee2
>> +// CHECK-PI-ARM-PLT-NEXT: 17f4:         04 c0 9f e5     ldr     r12, [pc,
>> #4]
>> +// CHECK-PI-ARM-PLT-NEXT: 17f8:         0f c0 8c e0     add     r12, r12,
>> pc
>> +// CHECK-PI-ARM-PLT-NEXT: 17fc:         00 f0 9c e5     ldr     pc, [r12]
>> +// CHECK-PI-ARM-PLT-NEXT: 1800:         ac 00 00 00
>> +// 0x1808 + 8 + 0xa0 = 0x18b0 thumb_callee3
>> +// CHECK-PI-ARM-PLT-NEXT: 1804:         04 c0 9f e5     ldr     r12, [pc,
>> #4]
>> +// CHECK-PI-ARM-PLT-NEXT: 1808:         0f c0 8c e0     add     r12, r12,
>> pc
>> +// CHECK-PI-ARM-PLT-NEXT: 180c:         00 f0 9c e5     ldr     pc, [r12]
>> +// CHECK-PI-ARM-PLT-NEXT: 1810:         a0 00 00 00
>> +// 0x1818 + 8 + 0x94 = 0x18b4 arm_callee1
>> +// CHECK-PI-ARM-PLT-NEXT: 1814:         04 c0 9f e5     ldr     r12, [pc,
>> #4]
>> +// CHECK-PI-ARM-PLT-NEXT: 1818:         0f c0 8c e0     add     r12, r12,
>> pc
>> +// CHECK-PI-ARM-PLT-NEXT: 181c:         00 f0 9c e5     ldr     pc, [r12]
>> +// CHECK-PI-ARM-PLT-NEXT: 1820:         94 00 00 00
>> +// 0x1828 + 8 + 0x88 = 0x18b8 arm_callee2
>> +// CHECK-PI-ARM-PLT-NEXT: 1824:         04 c0 9f e5     ldr     r12, [pc,
>> #4]
>> +// CHECK-PI-ARM-PLT-NEXT: 1828:         0f c0 8c e0     add     r12, r12,
>> pc
>> +// CHECK-PI-ARM-PLT-NEXT: 182c:         00 f0 9c e5     ldr     pc, [r12]
>> +// CHECK-PI-ARM-PLT-NEXT: 1830:         88 00 00 00
>> +// 0x1838 + 8 + 0x7c = 0x18bc arm_callee3
>> +// CHECK-PI-ARM-PLT-NEXT: 1834:         04 c0 9f e5     ldr     r12, [pc,
>> #4]
>> +// CHECK-PI-ARM-PLT-NEXT: 1838:         0f c0 8c e0     add     r12, r12,
>> pc
>> +// CHECK-PI-ARM-PLT-NEXT: 183c:         00 f0 9c e5     ldr     pc, [r12]
>> +// CHECK-PI-ARM-PLT-NEXT: 1840:         7c 00 00 00
>> +
>> +// CHECK-DSO-REL:      0x18A0 R_ARM_JUMP_SLOT arm_caller
>> +// CHECK-DSO-REL-NEXT: 0x18A4 R_ARM_JUMP_SLOT thumb_caller
>> +// CHECK-DSO-REL-NEXT: 0x18A8 R_ARM_JUMP_SLOT thumb_callee1
>> +// CHECK-DSO-REL-NEXT: 0x18AC R_ARM_JUMP_SLOT thumb_callee2
>> +// CHECK-DSO-REL-NEXT: 0x18B0 R_ARM_JUMP_SLOT thumb_callee3
>> +// CHECK-DSO-REL-NEXT: 0x18B4 R_ARM_JUMP_SLOT arm_callee1
>> +// CHECK-DSO-REL-NEXT: 0x18B8 R_ARM_JUMP_SLOT arm_callee2
>> +// CHECK-DSO-REL-NEXT: 0x18BC R_ARM_JUMP_SLOT arm_callee3
>>
>> Propchange: lld/trunk/test/ELF/arm-thumb-interwork-thunk.s
>>
>> ------------------------------------------------------------------------------
>>     svn:eol-style = native
>>
>> Propchange: lld/trunk/test/ELF/arm-thumb-interwork-thunk.s
>>
>> ------------------------------------------------------------------------------
>>     svn:keywords = Rev Date Author URL Id
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>
>
>
> --
> --
> Peter


More information about the llvm-commits mailing list