[lld] r293283 - [ELF][ARM] Use SyntheticSections for Thunks

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 31 06:44:49 PST 2017


I've reworked the comparison routine and resubmitted the patch for
review https://reviews.llvm.org/D29327

Thanks for your patience

Peter

On 30 January 2017 at 20:25, Peter Smith <peter.smith at linaro.org> wrote:
> Apologies again, it is worse than I thought. After making the change
> the build passes, but the Thunk tests fail with assertion failures in
> the Mips Thunk test.
>
> The MSVC debug implementation of merge uses the _same_ predicate to
> check that both sets of input iterators are ordered before even doing
> the merge.
>
> This means that the predicate has to work on both the InputSections
> with prior to inserting the thunks, the thunks and the combination of
> thunks and no-thunks. In particular a 0 sized section in the Mips
> Thunk implementation trips this up.
>
> I'll need to either:
> - Provide a handwritten implementation of merge that only does what a
> release build does.
> - Disable the debug iterators in MSVC by undefining the macros before
> calling merge, then re-enabling them.
> - Make a comparison operator that works.
>
> I'll send out what I come up with for review again. This is more than
> just a trivial change.
>
> Peter
>
> On 30 January 2017 at 17:55, Peter Smith <peter.smith at linaro.org> wrote:
>> Apologies for the delay, it took a while to get a Windows environment setup.
>>
>> I've tracked it down to the MSVC _Debug_lt_pred which does an
>> additional A < B and B < A. This won't compile for:
>> auto MergeCmp = [](const ThunkSection<ELFT> *Thunk,
>>                                  const InputSection<ELFT> *IS)
>> as InputSection<ELFT> *IS can't be cast to ThunkSection<ELFT>* for the
>> additional debug pred test.
>>
>> This can be fixed by changing ThunkSection<ELFT> *Thunk to
>> InputSection<ELFT> *Thunk.
>>
>> I'll rebase and recommit tomorrow morning (UK time).
>>
>> Peter
>>
>> On 30 January 2017 at 10:20, Peter Smith <peter.smith at linaro.org> wrote:
>>> My apologies, thanks for reverting it.
>>>
>>> It looks like I'm going to have to set up a MSVC debug build to
>>> reproduce and make sure it is fixed as I can't immediately see the
>>> problem from the message above. Will resubmit as soon as I can.
>>>
>>> Peter
>>>
>>> On 28 January 2017 at 01:01, Rui Ueyama <ruiu at google.com> wrote:
>>>> Peter,
>>>>
>>>> I had to roll back this in r293352 because it broke MSVC debug build and I
>>>> couldn't fix it immediately. Please take a look and re-submit.
>>>>
>>>>
>>>> D:\llvm-project\lld\ELF\Relocations.cpp(833): note: see reference to
>>>> function template instantiation '_OutIt
>>>> std::merge<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<lld::elf::InputSection<ELFT>
>>>>>>>,std::_Vector_iterator<std::_V
>>>> ector_val<std::_Simple_types<lld::elf::ThunkSection<ELFT>
>>>> *>>>,std::back_insert_iterator<std::vector<lld::elf::InputSection<ELFT>
>>>> *,std::allocator<_Ty>>>,lld::elf::mergeThunks::<lambda_b339caca889e68d37c4499c447b8b3c1>>(_InIt1,_InIt1,_InIt2,_InIt2,_OutIt,_Pr)'
>>>> being compiled
>>>>         with
>>>>         [
>>>>
>>>> _OutIt=std::back_insert_iterator<std::vector<lld::elf::InputSection<llvm::object::ELF32BE>
>>>> *,std::allocator<lld::elf::InputSection<llvm::object::ELF32BE> >>>,
>>>>             ELFT=llvm::object::ELF32BE,
>>>>             _Ty=lld::elf::InputSection<llvm::object::ELF32BE> *,
>>>>
>>>> _InIt1=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<lld::elf::InputSection<llvm::object::ELF32BE>
>>>>>>>,
>>>>
>>>> _InIt2=std::_Vector_iterator<std::_Vector_val<std::_Simple_types<lld::elf::ThunkSection<llvm::object::ELF32BE>
>>>>>>>,
>>>>
>>>> _Pr=lld::elf::mergeThunks::<lambda_b339caca889e68d37c4499c447b8b3c1>
>>>>         ]
>>>> D:\llvm-project\lld\ELF\Relocations.cpp(924): note: see reference to
>>>> function template instantiation 'void
>>>> lld::elf::mergeThunks<ELFT>(lld::elf::OutputSection<ELFT>
>>>> *,std::vector<lld::elf::ThunkSection<ELFT> *,std::allocator<_Ty>> &)' being
>>>> compiled
>>>>         with
>>>>         [
>>>>             ELFT=llvm::object::ELF32BE,
>>>>             _Ty=lld::elf::ThunkSection<llvm::object::ELF32BE> *
>>>>         ]
>>>>
>>>>
>>>> On Fri, Jan 27, 2017 at 12:02 PM, Rafael Avila de Espindola via llvm-commits
>>>> <llvm-commits at lists.llvm.org> wrote:
>>>>>
>>>>> This is really nice. Thanks!
>>>>>
>>>>> Peter Smith via llvm-commits <llvm-commits at lists.llvm.org> writes:
>>>>>
>>>>> > Author: psmith
>>>>> > Date: Fri Jan 27 07:10:16 2017
>>>>> > New Revision: 293283
>>>>> >
>>>>> > URL: http://llvm.org/viewvc/llvm-project?rev=293283&view=rev
>>>>> > Log:
>>>>> > [ELF][ARM] Use SyntheticSections for Thunks
>>>>> >
>>>>> > Thunks are now implemented by redirecting the relocation to the
>>>>> > symbol S, to a symbol TS in a Thunk. The Thunk will transfer control
>>>>> > to S. This has the following implications:
>>>>> > - All the side-effects of Thunks happen within createThunks()
>>>>> > - Thunks are no longer stored in InputSections and Symbols no longer
>>>>> >   need to hold a pointer to a Thunk
>>>>> > - The synthetic Thunk sections need to be merged into OutputSections
>>>>> >
>>>>> > This implementation is almost a direct conversion of the existing
>>>>> > Thunks with the following exceptions:
>>>>> > - Mips LA25 Thunks are placed before the InputSection that defines
>>>>> >   the symbol that needs a Thunk.
>>>>> > - All ARM Thunks are placed at the end of the OutputSection of the
>>>>> >   first caller to the Thunk.
>>>>> >
>>>>> > Range extension Thunks are not supported yet so it is optimistically
>>>>> > assumed that all Thunks can be reused.
>>>>> >
>>>>> > Differential Revision:  https://reviews.llvm.org/D29129
>>>>> >
>>>>> >
>>>>> > Modified:
>>>>> >     lld/trunk/ELF/InputFiles.cpp
>>>>> >     lld/trunk/ELF/InputSection.cpp
>>>>> >     lld/trunk/ELF/InputSection.h
>>>>> >     lld/trunk/ELF/LTO.cpp
>>>>> >     lld/trunk/ELF/LTO.h
>>>>> >     lld/trunk/ELF/Relocations.cpp
>>>>> >     lld/trunk/ELF/Relocations.h
>>>>> >     lld/trunk/ELF/SymbolTable.cpp
>>>>> >     lld/trunk/ELF/Symbols.cpp
>>>>> >     lld/trunk/ELF/Symbols.h
>>>>> >     lld/trunk/ELF/SyntheticSections.cpp
>>>>> >     lld/trunk/ELF/SyntheticSections.h
>>>>> >     lld/trunk/ELF/Target.cpp
>>>>> >     lld/trunk/ELF/Target.h
>>>>> >     lld/trunk/ELF/Thunks.cpp
>>>>> >     lld/trunk/ELF/Thunks.h
>>>>> >     lld/trunk/ELF/Writer.cpp
>>>>> >     lld/trunk/test/ELF/arm-thumb-interwork-shared.s
>>>>> >     lld/trunk/test/ELF/arm-thumb-interwork-thunk.s
>>>>> >     lld/trunk/test/ELF/mips-npic-call-pic.s
>>>>> >
>>>>> > Modified: lld/trunk/ELF/InputFiles.cpp
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/InputFiles.cpp (original)
>>>>> > +++ lld/trunk/ELF/InputFiles.cpp Fri Jan 27 07:10:16 2017
>>>>> > @@ -488,7 +488,7 @@ SymbolBody *elf::ObjectFile<ELFT>::creat
>>>>> >      StringRefZ Name = this->StringTable.data() + Sym->st_name;
>>>>> >      if (Sym->st_shndx == SHN_UNDEF)
>>>>> >        return new (BAlloc)
>>>>> > -          Undefined<ELFT>(Name, /*IsLocal=*/true, StOther, Type, this);
>>>>> > +          Undefined(Name, /*IsLocal=*/true, StOther, Type, this);
>>>>> >
>>>>> >      return new (BAlloc) DefinedRegular<ELFT>(Name, /*IsLocal=*/true,
>>>>> > StOther,
>>>>> >                                               Type, Value, Size, Sec,
>>>>> > this);
>>>>> >
>>>>> > Modified: lld/trunk/ELF/InputSection.cpp
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/InputSection.cpp (original)
>>>>> > +++ lld/trunk/ELF/InputSection.cpp Fri Jan 27 07:10:16 2017
>>>>> > @@ -99,10 +99,6 @@ template <class ELFT> size_t InputSectio
>>>>> >    if (auto *S = dyn_cast<SyntheticSection<ELFT>>(this))
>>>>> >      return S->getSize();
>>>>> >
>>>>> > -  if (auto *D = dyn_cast<InputSection<ELFT>>(this))
>>>>> > -    if (D->getThunksSize() > 0)
>>>>> > -      return D->getThunkOff() + D->getThunksSize();
>>>>> > -
>>>>> >    return Data.size();
>>>>> >  }
>>>>> >
>>>>> > @@ -214,21 +210,6 @@ InputSectionBase<ELFT> *InputSection<ELF
>>>>> >    return Sections[this->Info];
>>>>> >  }
>>>>> >
>>>>> > -template <class ELFT> void InputSection<ELFT>::addThunk(const
>>>>> > Thunk<ELFT> *T) {
>>>>> > -  Thunks.push_back(T);
>>>>> > -}
>>>>> > -
>>>>> > -template <class ELFT> uint64_t InputSection<ELFT>::getThunkOff() const
>>>>> > {
>>>>> > -  return this->Data.size();
>>>>> > -}
>>>>> > -
>>>>> > -template <class ELFT> uint64_t InputSection<ELFT>::getThunksSize()
>>>>> > const {
>>>>> > -  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
>>>>> >  // to update symbol table offset and section index for each relocation.
>>>>> > So we
>>>>> >  // copy relocations one by one.
>>>>> > @@ -302,11 +283,6 @@ getRelocTargetVA(uint32_t Type, typename
>>>>> >      return In<ELFT>::Got->getTlsIndexOff() + A -
>>>>> > In<ELFT>::Got->getSize();
>>>>> >    case R_TLSLD_PC:
>>>>> >      return In<ELFT>::Got->getTlsIndexVA() + A - P;
>>>>> > -  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:
>>>>> > @@ -551,19 +527,6 @@ template <class ELFT> void InputSection<
>>>>> >    // Iterate over all relocation sections that apply to this section.
>>>>> >    uint8_t *BufEnd = Buf + OutSecOff + Data.size();
>>>>> >    this->relocate(Buf, BufEnd);
>>>>> > -
>>>>> > -  // The section might have a data/code generated by the linker and
>>>>> > need
>>>>> > -  // to be written after the section. Usually these are thunks - small
>>>>> > piece
>>>>> > -  // of code used to jump between "incompatible" functions like PIC and
>>>>> > non-PIC
>>>>> > -  // or if the jump target too far and its address does not fit to the
>>>>> > short
>>>>> > -  // jump istruction.
>>>>> > -  if (!Thunks.empty()) {
>>>>> > -    Buf += OutSecOff + getThunkOff();
>>>>> > -    for (const Thunk<ELFT> *T : Thunks) {
>>>>> > -      T->writeTo(Buf);
>>>>> > -      Buf += T->size();
>>>>> > -    }
>>>>> > -  }
>>>>> >  }
>>>>> >
>>>>> >  template <class ELFT>
>>>>> >
>>>>> > Modified: lld/trunk/ELF/InputSection.h
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/InputSection.h (original)
>>>>> > +++ lld/trunk/ELF/InputSection.h Fri Jan 27 07:10:16 2017
>>>>> > @@ -280,17 +280,6 @@ public:
>>>>> >
>>>>> >    InputSectionBase<ELFT> *getRelocatedSection();
>>>>> >
>>>>> > -  // 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 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;
>>>>> > -
>>>>> > -  // Size of chunk with thunks code.
>>>>> > -  uint64_t getThunksSize() const;
>>>>> > -
>>>>> >    template <class RelTy>
>>>>> >    void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
>>>>> >
>>>>> > @@ -303,8 +292,6 @@ public:
>>>>> >  private:
>>>>> >    template <class RelTy>
>>>>> >    void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);
>>>>> > -
>>>>> > -  llvm::TinyPtrVector<const Thunk<ELFT> *> Thunks;
>>>>> >  };
>>>>> >
>>>>> >  template <class ELFT> InputSection<ELFT> InputSection<ELFT>::Discarded;
>>>>> >
>>>>> > Modified: lld/trunk/ELF/LTO.cpp
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.cpp?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/LTO.cpp (original)
>>>>> > +++ lld/trunk/ELF/LTO.cpp Fri Jan 27 07:10:16 2017
>>>>> > @@ -96,12 +96,12 @@ BitcodeCompiler::BitcodeCompiler() : LTO
>>>>> >
>>>>> >  BitcodeCompiler::~BitcodeCompiler() = default;
>>>>> >
>>>>> > -template <class ELFT> static void undefine(Symbol *S) {
>>>>> > -  replaceBody<Undefined<ELFT>>(S, S->body()->getName(),
>>>>> > /*IsLocal=*/false,
>>>>> > -                               STV_DEFAULT, S->body()->Type, nullptr);
>>>>> > +static void undefine(Symbol *S) {
>>>>> > +  replaceBody<Undefined>(S, S->body()->getName(), /*IsLocal=*/false,
>>>>> > +                         STV_DEFAULT, S->body()->Type, nullptr);
>>>>> >  }
>>>>> >
>>>>> > -template <class ELFT> void BitcodeCompiler::add(BitcodeFile &F) {
>>>>> > +void BitcodeCompiler::add(BitcodeFile &F) {
>>>>> >    lto::InputFile &Obj = *F.Obj;
>>>>> >    unsigned SymNum = 0;
>>>>> >    std::vector<Symbol *> Syms = F.getSymbols();
>>>>> > @@ -126,7 +126,7 @@ template <class ELFT> void BitcodeCompil
>>>>> >      R.VisibleToRegularObj =
>>>>> >          Sym->IsUsedInRegularObj || (R.Prevailing &&
>>>>> > Sym->includeInDynsym());
>>>>> >      if (R.Prevailing)
>>>>> > -      undefine<ELFT>(Sym);
>>>>> > +      undefine(Sym);
>>>>> >    }
>>>>> >    checkError(LTOObj->add(std::move(F.Obj), Resols));
>>>>> >  }
>>>>> > @@ -157,8 +157,3 @@ std::vector<InputFile *> BitcodeCompiler
>>>>> >    }
>>>>> >    return Ret;
>>>>> >  }
>>>>> > -
>>>>> > -template void BitcodeCompiler::template add<ELF32LE>(BitcodeFile &);
>>>>> > -template void BitcodeCompiler::template add<ELF32BE>(BitcodeFile &);
>>>>> > -template void BitcodeCompiler::template add<ELF64LE>(BitcodeFile &);
>>>>> > -template void BitcodeCompiler::template add<ELF64BE>(BitcodeFile &);
>>>>> >
>>>>> > Modified: lld/trunk/ELF/LTO.h
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LTO.h?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/LTO.h (original)
>>>>> > +++ lld/trunk/ELF/LTO.h Fri Jan 27 07:10:16 2017
>>>>> > @@ -43,7 +43,7 @@ public:
>>>>> >    BitcodeCompiler();
>>>>> >    ~BitcodeCompiler();
>>>>> >
>>>>> > -  template <class ELFT> void add(BitcodeFile &F);
>>>>> > +  void add(BitcodeFile &F);
>>>>> >    std::vector<InputFile *> compile();
>>>>> >
>>>>> >  private:
>>>>> >
>>>>> > Modified: lld/trunk/ELF/Relocations.cpp
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.cpp?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/Relocations.cpp (original)
>>>>> > +++ lld/trunk/ELF/Relocations.cpp Fri Jan 27 07:10:16 2017
>>>>> > @@ -43,6 +43,7 @@
>>>>> >
>>>>> >  #include "Relocations.h"
>>>>> >  #include "Config.h"
>>>>> > +#include "Memory.h"
>>>>> >  #include "OutputSections.h"
>>>>> >  #include "Strings.h"
>>>>> >  #include "SymbolTable.h"
>>>>> > @@ -52,6 +53,7 @@
>>>>> >
>>>>> >  #include "llvm/Support/Endian.h"
>>>>> >  #include "llvm/Support/raw_ostream.h"
>>>>> > +#include <algorithm>
>>>>> >
>>>>> >  using namespace llvm;
>>>>> >  using namespace llvm::ELF;
>>>>> > @@ -300,16 +302,14 @@ template <class ELFT> static bool isAbso
>>>>> >  }
>>>>> >
>>>>> >  static bool needsPlt(RelExpr Expr) {
>>>>> > -  return isRelExprOneOf<R_PLT_PC, R_PPC_PLT_OPD, R_PLT, R_PLT_PAGE_PC,
>>>>> > -                        R_THUNK_PLT_PC>(Expr);
>>>>> > +  return isRelExprOneOf<R_PLT_PC, R_PPC_PLT_OPD, R_PLT,
>>>>> > R_PLT_PAGE_PC>(Expr);
>>>>> >  }
>>>>> >
>>>>> >  // 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 isRelExprOneOf<R_PC, R_GOTREL, R_GOTREL_FROM_END,
>>>>> > R_MIPS_GOTREL,
>>>>> > -                        R_PAGE_PC, R_RELAX_GOT_PC, R_THUNK_PC,
>>>>> > R_THUNK_PLT_PC>(
>>>>> > -      Expr);
>>>>> > +                        R_PAGE_PC, R_RELAX_GOT_PC>(Expr);
>>>>> >  }
>>>>> >
>>>>> >  template <class ELFT>
>>>>> > @@ -321,8 +321,7 @@ static bool isStaticLinkTimeConstant(Rel
>>>>> >    if (isRelExprOneOf<R_SIZE, R_GOT_FROM_END, R_GOT_OFF,
>>>>> > R_MIPS_GOT_LOCAL_PAGE,
>>>>> >                       R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_TLSGD,
>>>>> >                       R_GOT_PAGE_PC, R_GOT_PC, R_PLT_PC, R_TLSGD_PC,
>>>>> > R_TLSGD,
>>>>> > -                     R_PPC_PLT_OPD, R_TLSDESC_CALL, R_TLSDESC_PAGE,
>>>>> > R_HINT,
>>>>> > -                     R_THUNK_PC, R_THUNK_PLT_PC>(E))
>>>>> > +                     R_PPC_PLT_OPD, R_TLSDESC_CALL, R_TLSDESC_PAGE,
>>>>> > R_HINT>(E))
>>>>> >      return true;
>>>>> >
>>>>> >    // These never do, except if the entire file is position dependent or
>>>>> > if
>>>>> > @@ -467,7 +466,6 @@ static RelExpr adjustExpr(const elf::Obj
>>>>> >      if (Expr == R_GOT_PC && !isAbsoluteValue<ELFT>(Body))
>>>>> >        Expr = Target->adjustRelaxExpr(Type, Data, Expr);
>>>>> >    }
>>>>> > -  Expr = Target->getThunkExpr(Expr, Type, &File, Body);
>>>>> >
>>>>> >    if (IsWrite || isStaticLinkTimeConstant<ELFT>(Expr, Type, Body, S,
>>>>> > RelOff))
>>>>> >      return Expr;
>>>>> > @@ -685,7 +683,6 @@ static void scanRelocs(InputSectionBase<
>>>>> >        continue;
>>>>> >
>>>>> >      if (needsPlt(Expr) ||
>>>>> > -        isRelExprOneOf<R_THUNK_ABS, R_THUNK_PC, R_THUNK_PLT_PC>(Expr)
>>>>> > ||
>>>>> >          refersToGotEntry(Expr) || !isPreemptible(Body, Type)) {
>>>>> >        // If the relocation points to something in the file, we can
>>>>> > process it.
>>>>> >        bool Constant =
>>>>> > @@ -805,33 +802,126 @@ template <class ELFT> void scanRelocatio
>>>>> >      scanRelocs(S, S.rels());
>>>>> >  }
>>>>> >
>>>>> > +// Insert the Thunks for OutputSection OS into their designated place
>>>>> > +// in the Sections vector, and recalculate the InputSection output
>>>>> > section
>>>>> > +// offsets.
>>>>> > +// This may invalidate any output section offsets stored outside of
>>>>> > InputSection
>>>>> > +template <class ELFT>
>>>>> > +static void mergeThunks(OutputSection<ELFT> *OS,
>>>>> > +                        std::vector<ThunkSection<ELFT> *> &Thunks) {
>>>>> > +  // Order Thunks in ascending OutSecOff
>>>>> > +  auto ThunkCmp = [](const ThunkSection<ELFT> *A, const
>>>>> > ThunkSection<ELFT> *B) {
>>>>> > +    return A->OutSecOff < B->OutSecOff;
>>>>> > +  };
>>>>> > +  std::stable_sort(Thunks.begin(), Thunks.end(), ThunkCmp);
>>>>> > +
>>>>> > +  // Merge sorted vectors of Thunks and InputSections by OutSecOff
>>>>> > +  std::vector<InputSection<ELFT> *> Tmp;
>>>>> > +  Tmp.reserve(OS->Sections.size() + Thunks.size());
>>>>> > +  auto MergeCmp = [](const ThunkSection<ELFT> *Thunk,
>>>>> > +                     const InputSection<ELFT> *IS) {
>>>>> > +    // All thunks go before any non-executable InputSections
>>>>> > +    if ((IS->Flags & SHF_EXECINSTR) == 0)
>>>>> > +      return true;
>>>>> > +    // Some Thunk Sections such as the Mips LA25 thunk must be placed
>>>>> > before
>>>>> > +    // the InputSections that they target. We represent this by
>>>>> > assigning the
>>>>> > +    // ThunkSection the same OutSecOff and always placing the Thunk
>>>>> > first if
>>>>> > +    // the OutSecOff values are the same.
>>>>> > +    return Thunk->OutSecOff <= IS->OutSecOff;
>>>>> > +  };
>>>>> > +  std::merge(OS->Sections.begin(), OS->Sections.end(), Thunks.begin(),
>>>>> > +             Thunks.end(), std::back_inserter(Tmp), MergeCmp);
>>>>> > +  OS->Sections = std::move(Tmp);
>>>>> > +  OS->Size = 0;
>>>>> > +  OS->assignOffsets();
>>>>> > +}
>>>>> > +
>>>>> > +// Process all relocations from the InputSections that have been
>>>>> > assigned
>>>>> > +// to OutputSections and redirect through Thunks if needed.
>>>>> > +//
>>>>> > +// createThunks must be called after scanRelocs has created the
>>>>> > Relocations for
>>>>> > +// each InputSection. It must be called before the static symbol table
>>>>> > is
>>>>> > +// finalized. If any Thunks are added to an OutputSection the output
>>>>> > section
>>>>> > +// offsets of the InputSections will change.
>>>>> > +//
>>>>> > +// FIXME: All Thunks are assumed to be in range of the relocation.
>>>>> > Range
>>>>> > +// extension Thunks are not yet supported.
>>>>> >  template <class ELFT>
>>>>> >  void createThunks(ArrayRef<OutputSectionBase *> OutputSections) {
>>>>> > +  // Track Symbols that already have a Thunk
>>>>> > +  DenseMap<SymbolBody *, Thunk<ELFT> *> ThunkedSymbols;
>>>>> > +  // Track InputSections that have a ThunkSection placed in front
>>>>> > +  DenseMap<InputSection<ELFT> *, ThunkSection<ELFT> *> ThunkedSections;
>>>>> > +  // Track the ThunksSections that need to be inserted into an
>>>>> > OutputSection
>>>>> > +  std::map<OutputSection<ELFT> *, std::vector<ThunkSection<ELFT> *>>
>>>>> > +      ThunkSections;
>>>>> > +
>>>>> > +  // Find or create a Thunk for Body for relocation Type
>>>>> > +  auto GetThunk = [&](SymbolBody &Body, uint32_t Type) {
>>>>> > +    auto res = ThunkedSymbols.insert({&Body, nullptr});
>>>>> > +    if (res.second == true)
>>>>> > +      res.first->second = addThunk<ELFT>(Type, Body);
>>>>> > +    return std::make_pair(res.first->second, res.second);
>>>>> > +  };
>>>>> > +
>>>>> > +  // Find or create a ThunkSection to be placed immediately before IS
>>>>> > +  auto GetISThunkSec = [&](InputSection<ELFT> *IS, OutputSection<ELFT>
>>>>> > *OS) {
>>>>> > +    ThunkSection<ELFT> *TS = ThunkedSections.lookup(IS);
>>>>> > +    if (TS)
>>>>> > +      return TS;
>>>>> > +    auto *TOS = cast<OutputSection<ELFT>>(IS->OutSec);
>>>>> > +    TS = make<ThunkSection<ELFT>>(TOS, IS->OutSecOff);
>>>>> > +    ThunkSections[OS].push_back(TS);
>>>>> > +    ThunkedSections[IS] = TS;
>>>>> > +    return TS;
>>>>> > +  };
>>>>> > +  // Find or create a ThunkSection to be placed at the end of OS
>>>>> > +  auto GetOSThunkSec = [&](ThunkSection<ELFT> *&TS, OutputSection<ELFT>
>>>>> > *OS) {
>>>>> > +    if (TS == nullptr) {
>>>>> > +      TS = make<ThunkSection<ELFT>>(OS, OS->Size);
>>>>> > +      ThunkSections[OS].push_back(TS);
>>>>> > +    }
>>>>> > +    return TS;
>>>>> > +  };
>>>>> > +  // Create all the Thunks and insert them into synthetic
>>>>> > ThunkSections. The
>>>>> > +  // ThunkSections are later inserted back into the OutputSection.
>>>>> > +
>>>>> > +  // We separate the creation of ThunkSections from the insertion of
>>>>> > the
>>>>> > +  // ThunkSections back into the OutputSection as ThunkSections are not
>>>>> > always
>>>>> > +  // inserted into the same OutputSection as the caller.
>>>>> >    for (OutputSectionBase *Base : OutputSections) {
>>>>> >      auto *OS = dyn_cast<OutputSection<ELFT>>(Base);
>>>>> >      if (OS == nullptr)
>>>>> >        continue;
>>>>> > +
>>>>> > +    ThunkSection<ELFT> *OSTS = nullptr;
>>>>> >      for (InputSection<ELFT> *IS : OS->Sections) {
>>>>> > -      for (const Relocation &Rel : IS->Relocations) {
>>>>> > -        if (Rel.Sym == nullptr)
>>>>> > -          continue;
>>>>> > -        RelExpr Expr = Rel.Expr;
>>>>> > -        // 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, and ARM which requires interworking.
>>>>> > -        if (Expr == R_THUNK_ABS || Expr == R_THUNK_PC ||
>>>>> > -            Expr == R_THUNK_PLT_PC)
>>>>> > -          addThunk<ELFT>(Rel.Type, *Rel.Sym, *IS);
>>>>> > +      for (Relocation &Rel : IS->Relocations) {
>>>>> > +        SymbolBody &Body = *Rel.Sym;
>>>>> > +        if (Target->needsThunk(Rel.Expr, Rel.Type, IS->getFile(),
>>>>> > Body)) {
>>>>> > +          Thunk<ELFT> *T;
>>>>> > +          bool IsNew;
>>>>> > +          std::tie(T, IsNew) = GetThunk(Body, Rel.Type);
>>>>> > +          if (IsNew) {
>>>>> > +            // Find or create a ThunkSection for the new Thunk
>>>>> > +            ThunkSection<ELFT> *TS;
>>>>> > +            if (auto *TIS = T->getTargetInputSection())
>>>>> > +              TS = GetISThunkSec(TIS, OS);
>>>>> > +            else
>>>>> > +              TS = GetOSThunkSec(OSTS, OS);
>>>>> > +            TS->addThunk(T);
>>>>> > +          }
>>>>> > +          // Redirect relocation to Thunk, we never go via the PLT to a
>>>>> > Thunk
>>>>> > +          Rel.Sym = T->ThunkSym;
>>>>> > +          Rel.Expr = fromPlt(Rel.Expr);
>>>>> > +        }
>>>>> >        }
>>>>> >      }
>>>>> >    }
>>>>> > -  // Added thunks may affect the output section offset
>>>>> > -  for (OutputSectionBase *Base : OutputSections)
>>>>> > -    if (auto *OS = dyn_cast<OutputSection<ELFT>>(Base))
>>>>> > -      if (OS->Type == SHT_PROGBITS) {
>>>>> > -        OS->Size = 0;
>>>>> > -        OS->assignOffsets();
>>>>> > -      }
>>>>> > +
>>>>> > +  // Merge all created synthetic ThunkSections back into OutputSection
>>>>> > +  for (auto &KV : ThunkSections)
>>>>> > +    mergeThunks<ELFT>(KV.first, KV.second);
>>>>> >  }
>>>>> >
>>>>> >  template void scanRelocations<ELF32LE>(InputSectionBase<ELF32LE> &);
>>>>> >
>>>>> > Modified: lld/trunk/ELF/Relocations.h
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Relocations.h?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/Relocations.h (original)
>>>>> > +++ lld/trunk/ELF/Relocations.h Fri Jan 27 07:10:16 2017
>>>>> > @@ -61,9 +61,6 @@ enum RelExpr {
>>>>> >    R_RELAX_TLS_IE_TO_LE,
>>>>> >    R_RELAX_TLS_LD_TO_LE,
>>>>> >    R_SIZE,
>>>>> > -  R_THUNK_ABS,
>>>>> > -  R_THUNK_PC,
>>>>> > -  R_THUNK_PLT_PC,
>>>>> >    R_TLS,
>>>>> >    R_TLSDESC,
>>>>> >    R_TLSDESC_PAGE,
>>>>> >
>>>>> > Modified: lld/trunk/ELF/SymbolTable.cpp
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/SymbolTable.cpp (original)
>>>>> > +++ lld/trunk/ELF/SymbolTable.cpp Fri Jan 27 07:10:16 2017
>>>>> > @@ -115,7 +115,7 @@ template <class ELFT> void SymbolTable<E
>>>>> >    // Compile bitcode files and replace bitcode symbols.
>>>>> >    LTO.reset(new BitcodeCompiler);
>>>>> >    for (BitcodeFile *F : BitcodeFiles)
>>>>> > -    LTO->add<ELFT>(*F);
>>>>> > +    LTO->add(*F);
>>>>> >
>>>>> >    for (InputFile *File : LTO->compile()) {
>>>>> >      ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(File);
>>>>> > @@ -256,7 +256,7 @@ Symbol *SymbolTable<ELFT>::addUndefined(
>>>>> >        insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym,
>>>>> > File);
>>>>> >    if (WasInserted) {
>>>>> >      S->Binding = Binding;
>>>>> > -    replaceBody<Undefined<ELFT>>(S, Name, IsLocal, StOther, Type,
>>>>> > File);
>>>>> > +    replaceBody<Undefined>(S, Name, IsLocal, StOther, Type, File);
>>>>> >      return S;
>>>>> >    }
>>>>> >    if (Binding != STB_WEAK) {
>>>>> > @@ -428,7 +428,7 @@ void SymbolTable<ELFT>::addShared(Shared
>>>>> >    // Make sure we preempt DSO symbols with default visibility.
>>>>> >    if (Sym.getVisibility() == STV_DEFAULT)
>>>>> >      S->ExportDynamic = true;
>>>>> > -  if (WasInserted || isa<Undefined<ELFT>>(S->body())) {
>>>>> > +  if (WasInserted || isa<Undefined>(S->body())) {
>>>>> >      replaceBody<SharedSymbol<ELFT>>(S, F, Name, Sym, Verdef);
>>>>> >      if (!S->isWeak())
>>>>> >        F->IsUsed = true;
>>>>> >
>>>>> > Modified: lld/trunk/ELF/Symbols.cpp
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/Symbols.cpp (original)
>>>>> > +++ lld/trunk/ELF/Symbols.cpp Fri Jan 27 07:10:16 2017
>>>>> > @@ -132,14 +132,6 @@ 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>
>>>>> >  typename ELFT::uint SymbolBody::getVA(typename ELFT::uint Addend) const
>>>>> > {
>>>>> >    typename ELFT::uint OutVA = getSymVA<ELFT>(*this, Addend);
>>>>> > @@ -171,16 +163,6 @@ template <class ELFT> typename ELFT::uin
>>>>> >           PltIndex * Target->PltEntrySize;
>>>>> >  }
>>>>> >
>>>>> > -template <class ELFT> typename ELFT::uint SymbolBody::getThunkVA()
>>>>> > const {
>>>>> > -  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();
>>>>> > -  if (const auto *S = dyn_cast<Undefined<ELFT>>(this))
>>>>> > -    return S->ThunkData->getVA();
>>>>> > -  fatal("getThunkVA() not supported for Symbol class\n");
>>>>> > -}
>>>>> > -
>>>>> >  template <class ELFT> typename ELFT::uint SymbolBody::getSize() const {
>>>>> >    if (const auto *C = dyn_cast<DefinedCommon>(this))
>>>>> >      return C->Size;
>>>>> > @@ -241,9 +223,8 @@ template <class ELFT> bool DefinedRegula
>>>>> >           (Section->getFile()->getObj().getHeader()->e_flags &
>>>>> > EF_MIPS_PIC);
>>>>> >  }
>>>>> >
>>>>> > -template <typename ELFT>
>>>>> > -Undefined<ELFT>::Undefined(StringRefZ Name, bool IsLocal, uint8_t
>>>>> > StOther,
>>>>> > -                           uint8_t Type, InputFile *File)
>>>>> > +Undefined::Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther,
>>>>> > +                     uint8_t Type, InputFile *File)
>>>>> >      : SymbolBody(SymbolBody::UndefinedKind, Name, IsLocal, StOther,
>>>>> > Type) {
>>>>> >    this->File = File;
>>>>> >  }
>>>>> > @@ -338,11 +319,6 @@ std::string lld::toString(const SymbolBo
>>>>> >    return B.getName();
>>>>> >  }
>>>>> >
>>>>> > -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 uint32_t SymbolBody::template getVA<ELF32LE>(uint32_t) const;
>>>>> >  template uint32_t SymbolBody::template getVA<ELF32BE>(uint32_t) const;
>>>>> >  template uint64_t SymbolBody::template getVA<ELF64LE>(uint64_t) const;
>>>>> > @@ -363,11 +339,6 @@ 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;
>>>>> > @@ -383,11 +354,6 @@ template uint32_t SymbolBody::template g
>>>>> >  template uint64_t SymbolBody::template getSize<ELF64LE>() const;
>>>>> >  template uint64_t SymbolBody::template getSize<ELF64BE>() const;
>>>>> >
>>>>> > -template class elf::Undefined<ELF32LE>;
>>>>> > -template class elf::Undefined<ELF32BE>;
>>>>> > -template class elf::Undefined<ELF64LE>;
>>>>> > -template class elf::Undefined<ELF64BE>;
>>>>> > -
>>>>> >  template class elf::SharedSymbol<ELF32LE>;
>>>>> >  template class elf::SharedSymbol<ELF32BE>;
>>>>> >  template class elf::SharedSymbol<ELF64LE>;
>>>>> >
>>>>> > Modified: lld/trunk/ELF/Symbols.h
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/Symbols.h (original)
>>>>> > +++ lld/trunk/ELF/Symbols.h Fri Jan 27 07:10:16 2017
>>>>> > @@ -76,7 +76,6 @@ public:
>>>>> >
>>>>> >    bool isInGot() const { return GotIndex != -1U; }
>>>>> >    bool isInPlt() const { return PltIndex != -1U; }
>>>>> > -  template <class ELFT> bool hasThunk() const;
>>>>> >
>>>>> >    template <class ELFT>
>>>>> >    typename ELFT::uint getVA(typename ELFT::uint Addend = 0) const;
>>>>> > @@ -86,7 +85,6 @@ public:
>>>>> >    template <class ELFT> typename ELFT::uint getGotPltOffset() const;
>>>>> >    template <class ELFT> typename ELFT::uint getGotPltVA() const;
>>>>> >    template <class ELFT> typename ELFT::uint getPltVA() const;
>>>>> > -  template <class ELFT> typename ELFT::uint getThunkVA() const;
>>>>> >    template <class ELFT> typename ELFT::uint getSize() const;
>>>>> >
>>>>> >    // The file from which this symbol was created.
>>>>> > @@ -210,10 +208,6 @@ 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.
>>>>> > -  Thunk<ELFT> *ThunkData = nullptr;
>>>>> > -
>>>>> >  private:
>>>>> >    static InputSectionBase<ELFT> *NullInputSection;
>>>>> >  };
>>>>> > @@ -242,7 +236,7 @@ public:
>>>>> >    const OutputSectionBase *Section;
>>>>> >  };
>>>>> >
>>>>> > -template <class ELFT> class Undefined : public SymbolBody {
>>>>> > +class Undefined : public SymbolBody {
>>>>> >  public:
>>>>> >    Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t
>>>>> > Type,
>>>>> >              InputFile *F);
>>>>> > @@ -251,12 +245,6 @@ public:
>>>>> >      return S->kind() == UndefinedKind;
>>>>> >    }
>>>>> >
>>>>> > -  // If non-null the symbol has a Thunk that may be used as an
>>>>> > alternative
>>>>> > -  // destination for callers of this Symbol. When linking a DSO
>>>>> > undefined
>>>>> > -  // symbols are implicitly imported, the symbol lookup will be
>>>>> > performed by
>>>>> > -  // the dynamic loader. A call to an undefined symbol will be given a
>>>>> > PLT
>>>>> > -  // entry and on ARM this may need a Thunk if the caller is in Thumb
>>>>> > state.
>>>>> > -  Thunk<ELFT> *ThunkData = nullptr;
>>>>> >    InputFile *file() { return this->File; }
>>>>> >  };
>>>>> >
>>>>> > @@ -291,9 +279,6 @@ public:
>>>>> >    // CopyOffset is significant only when needsCopy() is true.
>>>>> >    uintX_t CopyOffset = 0;
>>>>> >
>>>>> > -  // If non-null the symbol has a Thunk that may be used as an
>>>>> > alternative
>>>>> > -  // destination for callers of this Symbol.
>>>>> > -  Thunk<ELFT> *ThunkData = nullptr;
>>>>> >    bool needsCopy() const { return this->NeedsCopyOrPltAddr &&
>>>>> > !this->isFunc(); }
>>>>> >
>>>>> >    OutputSection<ELFT> *getBssSectionForCopy() const;
>>>>> > @@ -431,8 +416,7 @@ struct Symbol {
>>>>> >    // ELFT, and we verify this with the static_asserts in replaceBody.
>>>>> >    llvm::AlignedCharArrayUnion<
>>>>> >        DefinedCommon, DefinedRegular<llvm::object::ELF64LE>,
>>>>> > DefinedSynthetic,
>>>>> > -      Undefined<llvm::object::ELF64LE>,
>>>>> > SharedSymbol<llvm::object::ELF64LE>,
>>>>> > -      LazyArchive, LazyObject>
>>>>> > +      Undefined, SharedSymbol<llvm::object::ELF64LE>, LazyArchive,
>>>>> > LazyObject>
>>>>> >        Body;
>>>>> >
>>>>> >    SymbolBody *body() { return reinterpret_cast<SymbolBody
>>>>> > *>(Body.buffer); }
>>>>> >
>>>>> > Modified: lld/trunk/ELF/SyntheticSections.cpp
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/SyntheticSections.cpp (original)
>>>>> > +++ lld/trunk/ELF/SyntheticSections.cpp Fri Jan 27 07:10:16 2017
>>>>> > @@ -1904,6 +1904,27 @@ void ARMExidxSentinelSection<ELFT>::writ
>>>>> >    write32le(Buf + 4, 0x1);
>>>>> >  }
>>>>> >
>>>>> > +template <class ELFT>
>>>>> > +ThunkSection<ELFT>::ThunkSection(OutputSectionBase *OS, uint64_t Off)
>>>>> > +    : SyntheticSection<ELFT>(SHF_ALLOC, SHT_PROGBITS,
>>>>> > +                             sizeof(typename ELFT::uint),
>>>>> > ".text.thunk") {
>>>>> > +  this->OutSec = OS;
>>>>> > +  this->OutSecOff = Off;
>>>>> > +}
>>>>> > +
>>>>> > +template <class ELFT> void ThunkSection<ELFT>::addThunk(Thunk<ELFT> *T)
>>>>> > {
>>>>> > +  uint64_t Off = alignTo(Size, T->alignment);
>>>>> > +  T->Offset = Off;
>>>>> > +  Thunks.push_back(T);
>>>>> > +  T->addSymbols(*this);
>>>>> > +  Size = Off + T->size();
>>>>> > +}
>>>>> > +
>>>>> > +template <class ELFT> void ThunkSection<ELFT>::writeTo(uint8_t *Buf) {
>>>>> > +  for (const Thunk<ELFT> *T : Thunks)
>>>>> > +    T->writeTo(Buf + T->Offset, *this);
>>>>> > +}
>>>>> > +
>>>>> >  template InputSection<ELF32LE> *elf::createCommonSection();
>>>>> >  template InputSection<ELF32BE> *elf::createCommonSection();
>>>>> >  template InputSection<ELF64LE> *elf::createCommonSection();
>>>>> > @@ -2046,3 +2067,8 @@ template class elf::ARMExidxSentinelSect
>>>>> >  template class elf::ARMExidxSentinelSection<ELF32BE>;
>>>>> >  template class elf::ARMExidxSentinelSection<ELF64LE>;
>>>>> >  template class elf::ARMExidxSentinelSection<ELF64BE>;
>>>>> > +
>>>>> > +template class elf::ThunkSection<ELF32LE>;
>>>>> > +template class elf::ThunkSection<ELF32BE>;
>>>>> > +template class elf::ThunkSection<ELF64LE>;
>>>>> > +template class elf::ThunkSection<ELF64BE>;
>>>>> >
>>>>> > Modified: lld/trunk/ELF/SyntheticSections.h
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/SyntheticSections.h (original)
>>>>> > +++ lld/trunk/ELF/SyntheticSections.h Fri Jan 27 07:10:16 2017
>>>>> > @@ -699,6 +699,26 @@ public:
>>>>> >    void writeTo(uint8_t *Buf) override;
>>>>> >  };
>>>>> >
>>>>> > +// A container for one or more linker generated thunks. Instances of
>>>>> > these
>>>>> > +// thunks including ARM interworking and Mips LA25 PI to non-PI thunks.
>>>>> > +template <class ELFT> class ThunkSection : public
>>>>> > SyntheticSection<ELFT> {
>>>>> > +public:
>>>>> > +  // ThunkSection in OS, with desired OutSecOff of Off
>>>>> > +  ThunkSection(OutputSectionBase *OS, uint64_t Off);
>>>>> > +
>>>>> > +  // Add a newly created Thunk to this container:
>>>>> > +  // Thunk is given offset from start of this InputSection
>>>>> > +  // Thunk defines a symbol in this InputSection that can be used as
>>>>> > target
>>>>> > +  // of a relocation
>>>>> > +  void addThunk(Thunk<ELFT> *T);
>>>>> > +  size_t getSize() const override { return Size; }
>>>>> > +  void writeTo(uint8_t *Buf) override;
>>>>> > +
>>>>> > +private:
>>>>> > +  std::vector<const Thunk<ELFT> *> Thunks;
>>>>> > +  size_t Size = 0;
>>>>> > +};
>>>>> > +
>>>>> >  template <class ELFT> InputSection<ELFT> *createCommonSection();
>>>>> >  template <class ELFT> InputSection<ELFT> *createInterpSection();
>>>>> >  template <class ELFT> MergeInputSection<ELFT> *createCommentSection();
>>>>> >
>>>>> > Modified: lld/trunk/ELF/Target.cpp
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/Target.cpp (original)
>>>>> > +++ lld/trunk/ELF/Target.cpp Fri Jan 27 07:10:16 2017
>>>>> > @@ -228,8 +228,8 @@ public:
>>>>> >                  int32_t Index, unsigned RelOff) const override;
>>>>> >    void addPltSymbols(InputSectionData *IS, uint64_t Off) const
>>>>> > override;
>>>>> >    void addPltHeaderSymbols(InputSectionData *ISD) const override;
>>>>> > -  RelExpr getThunkExpr(RelExpr Expr, uint32_t RelocType, const
>>>>> > InputFile *File,
>>>>> > -                       const SymbolBody &S) const override;
>>>>> > +  bool needsThunk(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;
>>>>> >  };
>>>>> >
>>>>> > @@ -246,8 +246,8 @@ 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;
>>>>> > +  bool needsThunk(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;
>>>>> >  };
>>>>> > @@ -298,10 +298,9 @@ uint64_t TargetInfo::getImplicitAddend(c
>>>>> >
>>>>> >  bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return
>>>>> > false; }
>>>>> >
>>>>> > -RelExpr TargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
>>>>> > -                                 const InputFile *File,
>>>>> > -                                 const SymbolBody &S) const {
>>>>> > -  return Expr;
>>>>> > +bool TargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType,
>>>>> > +                            const InputFile *File, const SymbolBody &S)
>>>>> > const {
>>>>> > +  return false;
>>>>> >  }
>>>>> >
>>>>> >  bool TargetInfo::isTlsInitialExecRel(uint32_t Type) const { return
>>>>> > false; }
>>>>> > @@ -1771,15 +1770,15 @@ void ARMTargetInfo::addPltSymbols(InputS
>>>>> >    addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS);
>>>>> >  }
>>>>> >
>>>>> > -RelExpr ARMTargetInfo::getThunkExpr(RelExpr Expr, uint32_t RelocType,
>>>>> > -                                    const InputFile *File,
>>>>> > -                                    const SymbolBody &S) const {
>>>>> > +bool ARMTargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType,
>>>>> > +                               const InputFile *File,
>>>>> > +                               const SymbolBody &S) const {
>>>>> >    // If S is an undefined weak symbol in an executable we don't need a
>>>>> > Thunk.
>>>>> >    // In a DSO calls to undefined symbols, including weak ones get PLT
>>>>> > entries
>>>>> >    // which may need a thunk.
>>>>> >    if (S.isUndefined() && !S.isLocal() && S.symbol()->isWeak() &&
>>>>> >        !Config->Shared)
>>>>> > -    return Expr;
>>>>> > +    return false;
>>>>> >    // 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.
>>>>> > @@ -1790,19 +1789,17 @@ RelExpr ARMTargetInfo::getThunkExpr(RelE
>>>>> >      // 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;
>>>>> > +      return true;
>>>>> >      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;
>>>>> > +    if (Expr == R_PLT_PC || ((S.getVA<ELF32LE>() & 1) == 0))
>>>>> > +      return true;
>>>>> >      break;
>>>>> >    }
>>>>> > -  return Expr;
>>>>> > +  return false;
>>>>> >  }
>>>>> >
>>>>> >  void ARMTargetInfo::relocateOne(uint8_t *Loc, uint32_t Type,
>>>>> > @@ -2215,26 +2212,26 @@ void MipsTargetInfo<ELFT>::writePlt(uint
>>>>> >  }
>>>>> >
>>>>> >  template <class ELFT>
>>>>> > -RelExpr MipsTargetInfo<ELFT>::getThunkExpr(RelExpr Expr, uint32_t Type,
>>>>> > -                                           const InputFile *File,
>>>>> > -                                           const SymbolBody &S) const {
>>>>> > +bool MipsTargetInfo<ELFT>::needsThunk(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 Expr;
>>>>> > +    return false;
>>>>> >    auto *F = dyn_cast_or_null<ELFFileBase<ELFT>>(File);
>>>>> >    if (!F)
>>>>> > -    return Expr;
>>>>> > +    return false;
>>>>> >    // If current file has PIC code, LA25 stub is not required.
>>>>> >    if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC)
>>>>> > -    return Expr;
>>>>> > +    return false;
>>>>> >    auto *D = dyn_cast<DefinedRegular<ELFT>>(&S);
>>>>> >    // LA25 is required if target file has PIC code
>>>>> >    // or target symbol is a PIC symbol.
>>>>> > -  return D && D->isMipsPIC() ? R_THUNK_ABS : Expr;
>>>>> > +  return D && D->isMipsPIC();
>>>>> >  }
>>>>> >
>>>>> >  template <class ELFT>
>>>>> >
>>>>> > Modified: lld/trunk/ELF/Target.h
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/Target.h (original)
>>>>> > +++ lld/trunk/ELF/Target.h Fri Jan 27 07:10:16 2017
>>>>> > @@ -41,8 +41,8 @@ public:
>>>>> >    virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
>>>>> >                          uint64_t PltEntryAddr, int32_t Index,
>>>>> >                          unsigned RelOff) const {}
>>>>> > -  virtual void addPltHeaderSymbols(InputSectionData* IS) const {}
>>>>> > -  virtual void addPltSymbols(InputSectionData* IS, uint64_t Off) const
>>>>> > {}
>>>>> > +  virtual void addPltHeaderSymbols(InputSectionData *IS) const {}
>>>>> > +  virtual void addPltSymbols(InputSectionData *IS, uint64_t Off) const
>>>>> > {}
>>>>> >    // Returns true if a relocation only uses the low bits of a value
>>>>> > such that
>>>>> >    // all those bits are in in the same page. For example, if the
>>>>> > relocation
>>>>> >    // only uses the low 12 bits in a system with 4k pages. If this is
>>>>> > true, the
>>>>> > @@ -51,14 +51,9 @@ public:
>>>>> >    virtual bool usesOnlyLowPageBits(uint32_t Type) 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;
>>>>> > +  // targeting S.
>>>>> > +  virtual bool needsThunk(RelExpr Expr, uint32_t RelocType,
>>>>> > +                          const InputFile *File, const SymbolBody &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();
>>>>> >
>>>>> > Modified: lld/trunk/ELF/Thunks.cpp
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.cpp?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/Thunks.cpp (original)
>>>>> > +++ lld/trunk/ELF/Thunks.cpp Fri Jan 27 07:10:16 2017
>>>>> > @@ -28,6 +28,7 @@
>>>>> >  #include "Memory.h"
>>>>> >  #include "OutputSections.h"
>>>>> >  #include "Symbols.h"
>>>>> > +#include "SyntheticSections.h"
>>>>> >  #include "Target.h"
>>>>> >  #include "llvm/Support/Casting.h"
>>>>> >  #include "llvm/Support/ELF.h"
>>>>> > @@ -52,53 +53,54 @@ namespace {
>>>>> >  template <class ELFT>
>>>>> >  class ARMToThumbV7ABSLongThunk final : public Thunk<ELFT> {
>>>>> >  public:
>>>>> > -  ARMToThumbV7ABSLongThunk(const SymbolBody &Dest,
>>>>> > -                           const InputSection<ELFT> &Owner)
>>>>> > -      : Thunk<ELFT>(Dest, Owner) {}
>>>>> > +  ARMToThumbV7ABSLongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest)
>>>>> > {}
>>>>> >
>>>>> >    uint32_t size() const override { return 12; }
>>>>> > -  void writeTo(uint8_t *Buf) const override;
>>>>> > +  void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
>>>>> > +  void addSymbols(ThunkSection<ELFT> &IS) override;
>>>>> >  };
>>>>> >
>>>>> >  template <class ELFT> class ARMToThumbV7PILongThunk final : public
>>>>> > Thunk<ELFT> {
>>>>> >  public:
>>>>> > -  ARMToThumbV7PILongThunk(const SymbolBody &Dest,
>>>>> > -                          const InputSection<ELFT> &Owner)
>>>>> > -      : Thunk<ELFT>(Dest, Owner) {}
>>>>> > +  ARMToThumbV7PILongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest)
>>>>> > {}
>>>>> >
>>>>> >    uint32_t size() const override { return 16; }
>>>>> > -  void writeTo(uint8_t *Buf) const override;
>>>>> > +  void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
>>>>> > +  void addSymbols(ThunkSection<ELFT> &IS) override;
>>>>> >  };
>>>>> >
>>>>> >  template <class ELFT>
>>>>> >  class ThumbToARMV7ABSLongThunk final : public Thunk<ELFT> {
>>>>> >  public:
>>>>> > -  ThumbToARMV7ABSLongThunk(const SymbolBody &Dest,
>>>>> > -                           const InputSection<ELFT> &Owner)
>>>>> > -      : Thunk<ELFT>(Dest, Owner) {}
>>>>> > +  ThumbToARMV7ABSLongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest)
>>>>> > {
>>>>> > +    this->alignment = 2;
>>>>> > +  }
>>>>> >
>>>>> >    uint32_t size() const override { return 10; }
>>>>> > -  void writeTo(uint8_t *Buf) const override;
>>>>> > +  void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
>>>>> > +  void addSymbols(ThunkSection<ELFT> &IS) override;
>>>>> >  };
>>>>> >
>>>>> >  template <class ELFT> class ThumbToARMV7PILongThunk final : public
>>>>> > Thunk<ELFT> {
>>>>> >  public:
>>>>> > -  ThumbToARMV7PILongThunk(const SymbolBody &Dest,
>>>>> > -                          const InputSection<ELFT> &Owner)
>>>>> > -      : Thunk<ELFT>(Dest, Owner) {}
>>>>> > +  ThumbToARMV7PILongThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {
>>>>> > +    this->alignment = 2;
>>>>> > +  }
>>>>> >
>>>>> >    uint32_t size() const override { return 12; }
>>>>> > -  void writeTo(uint8_t *Buf) const override;
>>>>> > +  void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
>>>>> > +  void addSymbols(ThunkSection<ELFT> &IS) override;
>>>>> >  };
>>>>> >
>>>>> >  // MIPS LA25 thunk
>>>>> >  template <class ELFT> class MipsThunk final : public Thunk<ELFT> {
>>>>> >  public:
>>>>> > -  MipsThunk(const SymbolBody &Dest, const InputSection<ELFT> &Owner)
>>>>> > -      : Thunk<ELFT>(Dest, Owner) {}
>>>>> > +  MipsThunk(const SymbolBody &Dest) : Thunk<ELFT>(Dest) {}
>>>>> >
>>>>> >    uint32_t size() const override { return 16; }
>>>>> > -  void writeTo(uint8_t *Buf) const override;
>>>>> > +  void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const override;
>>>>> > +  void addSymbols(ThunkSection<ELFT> &IS) override;
>>>>> > +  InputSection<ELFT> *getTargetInputSection() const override;
>>>>> >  };
>>>>> >
>>>>> >  } // end anonymous namespace
>>>>> > @@ -110,7 +112,8 @@ template <class ELFT> static uint64_t ge
>>>>> >  }
>>>>> >
>>>>> >  template <class ELFT>
>>>>> > -void ARMToThumbV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf) const {
>>>>> > +void ARMToThumbV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf,
>>>>> > +                                             ThunkSection<ELFT> &IS)
>>>>> > const {
>>>>> >    const uint8_t Data[] = {
>>>>> >        0x00, 0xc0, 0x00, 0xe3, // movw         ip,:lower16:S
>>>>> >        0x00, 0xc0, 0x40, 0xe3, // movt         ip,:upper16:S
>>>>> > @@ -123,7 +126,16 @@ void ARMToThumbV7ABSLongThunk<ELFT>::wri
>>>>> >  }
>>>>> >
>>>>> >  template <class ELFT>
>>>>> > -void ThumbToARMV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf) const {
>>>>> > +void ARMToThumbV7ABSLongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS)
>>>>> > {
>>>>> > +  this->ThunkSym = addSyntheticLocal(
>>>>> > +      Saver.save("__ARMToThumbv7ABSLongThunk_" +
>>>>> > this->Destination.getName()),
>>>>> > +      STT_FUNC, this->Offset, size(), &IS);
>>>>> > +  addSyntheticLocal("$a", STT_NOTYPE, this->Offset, 0, &IS);
>>>>> > +}
>>>>> > +
>>>>> > +template <class ELFT>
>>>>> > +void ThumbToARMV7ABSLongThunk<ELFT>::writeTo(uint8_t *Buf,
>>>>> > +                                             ThunkSection<ELFT> &IS)
>>>>> > const {
>>>>> >    const uint8_t Data[] = {
>>>>> >        0x40, 0xf2, 0x00, 0x0c, // movw         ip, :lower16:S
>>>>> >        0xc0, 0xf2, 0x00, 0x0c, // movt         ip, :upper16:S
>>>>> > @@ -136,7 +148,16 @@ void ThumbToARMV7ABSLongThunk<ELFT>::wri
>>>>> >  }
>>>>> >
>>>>> >  template <class ELFT>
>>>>> > -void ARMToThumbV7PILongThunk<ELFT>::writeTo(uint8_t *Buf) const {
>>>>> > +void ThumbToARMV7ABSLongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS)
>>>>> > {
>>>>> > +  this->ThunkSym = addSyntheticLocal(
>>>>> > +      Saver.save("__ThumbToARMv7ABSLongThunk_" +
>>>>> > this->Destination.getName()),
>>>>> > +      STT_FUNC, this->Offset, size(), &IS);
>>>>> > +  addSyntheticLocal("$t", STT_NOTYPE, this->Offset, 0, &IS);
>>>>> > +}
>>>>> > +
>>>>> > +template <class ELFT>
>>>>> > +void ARMToThumbV7PILongThunk<ELFT>::writeTo(uint8_t *Buf,
>>>>> > +                                            ThunkSection<ELFT> &IS)
>>>>> > const {
>>>>> >    const uint8_t Data[] = {
>>>>> >        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)
>>>>> > @@ -144,14 +165,23 @@ void ARMToThumbV7PILongThunk<ELFT>::writ
>>>>> >        0x1c, 0xff, 0x2f, 0xe1, //     bx r12
>>>>> >    };
>>>>> >    uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
>>>>> > -  uint64_t P = this->getVA();
>>>>> > +  uint64_t P = this->ThunkSym->template getVA<ELFT>();
>>>>> >    memcpy(Buf, Data, sizeof(Data));
>>>>> >    Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, S - P - 16);
>>>>> >    Target->relocateOne(Buf + 4, R_ARM_MOVT_PREL, S - P - 12);
>>>>> >  }
>>>>> >
>>>>> >  template <class ELFT>
>>>>> > -void ThumbToARMV7PILongThunk<ELFT>::writeTo(uint8_t *Buf) const {
>>>>> > +void ARMToThumbV7PILongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS)
>>>>> > {
>>>>> > +  this->ThunkSym = addSyntheticLocal(
>>>>> > +      Saver.save("__ARMToThumbV7PILongThunk_" +
>>>>> > this->Destination.getName()),
>>>>> > +      STT_FUNC, this->Offset, size(), &IS);
>>>>> > +  addSyntheticLocal("$a", STT_NOTYPE, this->Offset, 0, &IS);
>>>>> > +}
>>>>> > +
>>>>> > +template <class ELFT>
>>>>> > +void ThumbToARMV7PILongThunk<ELFT>::writeTo(uint8_t *Buf,
>>>>> > +                                            ThunkSection<ELFT> &IS)
>>>>> > const {
>>>>> >    const uint8_t Data[] = {
>>>>> >        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)
>>>>> > @@ -159,14 +189,23 @@ void ThumbToARMV7PILongThunk<ELFT>::writ
>>>>> >        0x60, 0x47,             //     bx   r12
>>>>> >    };
>>>>> >    uint64_t S = getARMThunkDestVA<ELFT>(this->Destination);
>>>>> > -  uint64_t P = this->getVA();
>>>>> > +  uint64_t P = this->ThunkSym->template getVA<ELFT>();
>>>>> >    memcpy(Buf, Data, sizeof(Data));
>>>>> >    Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, S - P - 12);
>>>>> >    Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, S - P - 8);
>>>>> >  }
>>>>> >
>>>>> > +template <class ELFT>
>>>>> > +void ThumbToARMV7PILongThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS)
>>>>> > {
>>>>> > +  this->ThunkSym = addSyntheticLocal(
>>>>> > +      Saver.save("__ThumbToARMV7PILongThunk_" +
>>>>> > this->Destination.getName()),
>>>>> > +      STT_FUNC, this->Offset, size(), &IS);
>>>>> > +  addSyntheticLocal("$t", STT_NOTYPE, this->Offset, 0, &IS);
>>>>> > +}
>>>>> > +
>>>>> >  // Write MIPS LA25 thunk code to call PIC function from the non-PIC
>>>>> > one.
>>>>> > -template <class ELFT> void MipsThunk<ELFT>::writeTo(uint8_t *Buf) const
>>>>> > {
>>>>> > +template <class ELFT>
>>>>> > +void MipsThunk<ELFT>::writeTo(uint8_t *Buf, ThunkSection<ELFT> &) const
>>>>> > {
>>>>> >    const endianness E = ELFT::TargetEndianness;
>>>>> >
>>>>> >    uint64_t S = this->Destination.template getVA<ELFT>();
>>>>> > @@ -178,20 +217,26 @@ template <class ELFT> void MipsThunk<ELF
>>>>> >    Target->relocateOne(Buf + 8, R_MIPS_LO16, S);
>>>>> >  }
>>>>> >
>>>>> > -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> void
>>>>> > MipsThunk<ELFT>::addSymbols(ThunkSection<ELFT> &IS) {
>>>>> > +  this->ThunkSym = addSyntheticLocal(
>>>>> > +      Saver.save("__LA25Thunk_" + this->Destination.getName()),
>>>>> > STT_FUNC,
>>>>> > +      this->Offset, size(), &IS);
>>>>> > +}
>>>>> >
>>>>> > -template <class ELFT> typename ELFT::uint Thunk<ELFT>::getVA() const {
>>>>> > -  return Owner.OutSec->Addr + Owner.OutSecOff + Offset;
>>>>> > +template <class ELFT>
>>>>> > +InputSection<ELFT> *MipsThunk<ELFT>::getTargetInputSection() const {
>>>>> > +  auto *DR = dyn_cast<DefinedRegular<ELFT>>(&this->Destination);
>>>>> > +  return dyn_cast<InputSection<ELFT>>(DR->Section);
>>>>> >  }
>>>>> >
>>>>> > +template <class ELFT>
>>>>> > +Thunk<ELFT>::Thunk(const SymbolBody &D) : Destination(D), Offset(0) {}
>>>>> > +
>>>>> >  template <class ELFT> Thunk<ELFT>::~Thunk() = default;
>>>>> >
>>>>> >  // Creates a thunk for Thumb-ARM interworking.
>>>>> >  template <class ELFT>
>>>>> > -static Thunk<ELFT> *createThunkArm(uint32_t Reloc, SymbolBody &S,
>>>>> > -                                   InputSection<ELFT> &IS) {
>>>>> > +static Thunk<ELFT> *addThunkArm(uint32_t Reloc, SymbolBody &S) {
>>>>> >    // 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.
>>>>> > @@ -200,71 +245,34 @@ static Thunk<ELFT> *createThunkArm(uint3
>>>>> >    case R_ARM_PLT32:
>>>>> >    case R_ARM_JUMP24:
>>>>> >      if (Config->Pic)
>>>>> > -      return new (BAlloc) ARMToThumbV7PILongThunk<ELFT>(S, IS);
>>>>> > -    return new (BAlloc) ARMToThumbV7ABSLongThunk<ELFT>(S, IS);
>>>>> > +      return make<ARMToThumbV7PILongThunk<ELFT>>(S);
>>>>> > +    return make<ARMToThumbV7ABSLongThunk<ELFT>>(S);
>>>>> >    case R_ARM_THM_JUMP19:
>>>>> >    case R_ARM_THM_JUMP24:
>>>>> >      if (Config->Pic)
>>>>> > -      return new (BAlloc) ThumbToARMV7PILongThunk<ELFT>(S, IS);
>>>>> > -    return new (BAlloc) ThumbToARMV7ABSLongThunk<ELFT>(S, IS);
>>>>> > +      return make<ThumbToARMV7PILongThunk<ELFT>>(S);
>>>>> > +    return make<ThumbToARMV7ABSLongThunk<ELFT>>(S);
>>>>> >    }
>>>>> >    fatal("unrecognized relocation type");
>>>>> >  }
>>>>> >
>>>>> > -template <class ELFT>
>>>>> > -static void addThunkARM(uint32_t Reloc, SymbolBody &S,
>>>>> > InputSection<ELFT> &IS) {
>>>>> > -  // Only one Thunk supported per symbol.
>>>>> > -  if (S.hasThunk<ELFT>())
>>>>> > -    return;
>>>>> > -
>>>>> > -  // 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
>>>>> > -  Thunk<ELFT> *T = createThunkArm(Reloc, S, IS);
>>>>> > -  IS.addThunk(T);
>>>>> > -  if (auto *Sym = dyn_cast<DefinedRegular<ELFT>>(&S))
>>>>> > -    Sym->ThunkData = T;
>>>>> > -  else if (auto *Sym = dyn_cast<SharedSymbol<ELFT>>(&S))
>>>>> > -    Sym->ThunkData = T;
>>>>> > -  else if (auto *Sym = dyn_cast<Undefined<ELFT>>(&S))
>>>>> > -    Sym->ThunkData = T;
>>>>> > -  else
>>>>> > -    fatal("symbol not DefinedRegular or Shared");
>>>>> > -}
>>>>> > -
>>>>> > -template <class ELFT>
>>>>> > -static void addThunkMips(uint32_t RelocType, SymbolBody &S,
>>>>> > -                         InputSection<ELFT> &IS) {
>>>>> > -  // Only one Thunk supported per symbol.
>>>>> > -  if (S.hasThunk<ELFT>())
>>>>> > -    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 (BAlloc) MipsThunk<ELFT>(S, *Sec);
>>>>> > -  Sec->addThunk(T);
>>>>> > -  R->ThunkData = T;
>>>>> > +template <class ELFT> static Thunk<ELFT> *addThunkMips(SymbolBody &S) {
>>>>> > +  return make<MipsThunk<ELFT>>(S);
>>>>> >  }
>>>>> >
>>>>> > -template <class ELFT>
>>>>> > -void addThunk(uint32_t RelocType, SymbolBody &S, InputSection<ELFT>
>>>>> > &IS) {
>>>>> > +template <class ELFT> Thunk<ELFT> *addThunk(uint32_t RelocType,
>>>>> > SymbolBody &S) {
>>>>> >    if (Config->EMachine == EM_ARM)
>>>>> > -    addThunkARM<ELFT>(RelocType, S, IS);
>>>>> > +    return addThunkArm<ELFT>(RelocType, S);
>>>>> >    else if (Config->EMachine == EM_MIPS)
>>>>> > -    addThunkMips<ELFT>(RelocType, S, IS);
>>>>> > -  else
>>>>> > -    llvm_unreachable("add Thunk only supported for ARM and Mips");
>>>>> > +    return addThunkMips<ELFT>(S);
>>>>> > +  llvm_unreachable("add Thunk only supported for ARM and Mips");
>>>>> > +  return nullptr;
>>>>> >  }
>>>>> >
>>>>> > -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 Thunk<ELF32LE> *addThunk<ELF32LE>(uint32_t, SymbolBody &);
>>>>> > +template Thunk<ELF32BE> *addThunk<ELF32BE>(uint32_t, SymbolBody &);
>>>>> > +template Thunk<ELF64LE> *addThunk<ELF64LE>(uint32_t, SymbolBody &);
>>>>> > +template Thunk<ELF64BE> *addThunk<ELF64BE>(uint32_t, SymbolBody &);
>>>>> >
>>>>> >  template class Thunk<ELF32LE>;
>>>>> >  template class Thunk<ELF32BE>;
>>>>> >
>>>>> > Modified: lld/trunk/ELF/Thunks.h
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Thunks.h?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/Thunks.h (original)
>>>>> > +++ lld/trunk/ELF/Thunks.h Fri Jan 27 07:10:16 2017
>>>>> > @@ -15,8 +15,8 @@
>>>>> >  namespace lld {
>>>>> >  namespace elf {
>>>>> >  class SymbolBody;
>>>>> > -template <class ELFT> class InputSection;
>>>>> > -
>>>>> > +template <class ELFT> class ThunkSection;
>>>>> > +class OutputSectionBase;
>>>>> >  // 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
>>>>> > @@ -24,31 +24,35 @@ template <class ELFT> class InputSection
>>>>> >  // 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.
>>>>> > +// Thunks can be created for DefinedRegular, Shared and Undefined
>>>>> > Symbols.
>>>>> > +// Thunks are assigned to synthetic ThunkSections
>>>>> >  template <class ELFT> class Thunk {
>>>>> > -  typedef typename ELFT::uint uintX_t;
>>>>> > -
>>>>> >  public:
>>>>> > -  Thunk(const SymbolBody &Destination, const InputSection<ELFT>
>>>>> > &Owner);
>>>>> > +  Thunk(const SymbolBody &Destination);
>>>>> >    virtual ~Thunk();
>>>>> >
>>>>> >    virtual uint32_t size() const { return 0; }
>>>>> > -  virtual void writeTo(uint8_t *Buf) const {}
>>>>> > -  uintX_t getVA() const;
>>>>> > +  virtual void writeTo(uint8_t *Buf, ThunkSection<ELFT> &IS) const {}
>>>>> > +
>>>>> > +  // All Thunks must define at least one symbol ThunkSym so that we can
>>>>> > +  // redirect relocations to it.
>>>>> > +  virtual void addSymbols(ThunkSection<ELFT> &IS) {}
>>>>> > +
>>>>> > +  // Some Thunks must be placed immediately before their Target as they
>>>>> > elide
>>>>> > +  // a branch and fall through to the first Symbol in the Target.
>>>>> > +  virtual InputSection<ELFT> *getTargetInputSection() const { return
>>>>> > nullptr; }
>>>>> >
>>>>> > -protected:
>>>>> > +  // The alignment requirement for this Thunk, defaults to the size of
>>>>> > the
>>>>> > +  // typical code section alignment.
>>>>> >    const SymbolBody &Destination;
>>>>> > -  const InputSection<ELFT> &Owner;
>>>>> > +  SymbolBody *ThunkSym;
>>>>> >    uint64_t Offset;
>>>>> > +  uint32_t alignment = 4;
>>>>> >  };
>>>>> >
>>>>> > -// 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);
>>>>> > +// For a Relocation to symbol S create a Thunk to be added to a
>>>>> > synthetic
>>>>> > +// ThunkSection. At present there are implementations for ARM and Mips
>>>>> > Thunks.
>>>>> > +template <class ELFT> Thunk<ELFT> *addThunk(uint32_t RelocType,
>>>>> > SymbolBody &S);
>>>>> >
>>>>> >  } // namespace elf
>>>>> >  } // namespace lld
>>>>> >
>>>>> > Modified: lld/trunk/ELF/Writer.cpp
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/ELF/Writer.cpp (original)
>>>>> > +++ lld/trunk/ELF/Writer.cpp Fri Jan 27 07:10:16 2017
>>>>> > @@ -1027,6 +1027,12 @@ template <class ELFT> void Writer<ELFT>:
>>>>> >    if (In<ELFT>::Iplt && !In<ELFT>::Iplt->empty())
>>>>> >      In<ELFT>::Iplt->addSymbols();
>>>>> >
>>>>> > +  // Some architectures use small displacements for jump instructions.
>>>>> > +  // It is linker's responsibility to create thunks containing long
>>>>> > +  // jump instructions if jump targets are too far. Create thunks.
>>>>> > +  if (Target->NeedsThunks)
>>>>> > +    createThunks<ELFT>(OutputSections);
>>>>> > +
>>>>> >    // Now that we have defined all possible symbols including linker-
>>>>> >    // synthesized ones. Visit all symbols to give the finishing touches.
>>>>> >    for (Symbol *S : Symtab<ELFT>::X->getSymbols()) {
>>>>> > @@ -1072,12 +1078,6 @@ template <class ELFT> void Writer<ELFT>:
>>>>> >      fixHeaders();
>>>>> >    }
>>>>> >
>>>>> > -  // Some architectures use small displacements for jump instructions.
>>>>> > -  // It is linker's responsibility to create thunks containing long
>>>>> > -  // jump instructions if jump targets are too far. Create thunks.
>>>>> > -  if (Target->NeedsThunks)
>>>>> > -    createThunks<ELFT>(OutputSections);
>>>>> > -
>>>>> >    // Fill other section headers. The dynamic table is finalized
>>>>> >    // at the end because some tags like RELSZ depend on result
>>>>> >    // of finalizing other sections.
>>>>> >
>>>>> > Modified: lld/trunk/test/ELF/arm-thumb-interwork-shared.s
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-thumb-interwork-shared.s?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/test/ELF/arm-thumb-interwork-shared.s (original)
>>>>> > +++ lld/trunk/test/ELF/arm-thumb-interwork-shared.s Fri Jan 27 07:10:16
>>>>> > 2017
>>>>> > @@ -16,12 +16,15 @@ sym1:
>>>>> >
>>>>> >  // CHECK: Disassembly of section .text:
>>>>> >  // CHECK-NEXT: sym1:
>>>>> > -// CHECK:          1000:       00 f0 02 b8     b.w     #4
>>>>> > -// CHECK-NEXT:     1004:       00 f0 06 b8     b.w     #12
>>>>> > +// CHECK-NEXT: 1000: 00 f0 02 b8 b.w #4
>>>>> > <__ThumbToARMV7PILongThunk_elsewhere+0x4>
>>>>> > +// CHECK-NEXT: 1004: 00 f0 06 b8 b.w #12
>>>>> > <__ThumbToARMV7PILongThunk_weakref+0x4>
>>>>> > +// CHECK: __ThumbToARMV7PILongThunk_elsewhere:
>>>>> >  // CHECK-NEXT:     1008:       40 f2 20 0c     movw    r12, #32
>>>>> >  // CHECK-NEXT:     100c:       c0 f2 00 0c     movt    r12, #0
>>>>> >  // CHECK-NEXT:     1010:       fc 44   add     r12, pc
>>>>> >  // CHECK-NEXT:     1012:       60 47   bx      r12
>>>>> > +
>>>>> > +// CHECK: __ThumbToARMV7PILongThunk_weakref:
>>>>> >  // CHECK-NEXT:     1014:       40 f2 24 0c     movw    r12, #36
>>>>> >  // CHECK-NEXT:     1018:       c0 f2 00 0c     movt    r12, #0
>>>>> >  // CHECK-NEXT:     101c:       fc 44   add     r12, pc
>>>>> >
>>>>> > Modified: 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=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/test/ELF/arm-thumb-interwork-thunk.s (original)
>>>>> > +++ lld/trunk/test/ELF/arm-thumb-interwork-thunk.s Fri Jan 27 07:10:16
>>>>> > 2017
>>>>> > @@ -78,62 +78,65 @@ arm_caller:
>>>>> >   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
>>>>> > +// CHECK-ARM-ABS-ARM: Disassembly of section .arm_caller:
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT: arm_caller:
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1300:       3e ff ff fa     blx
>>>>> > #-776 <thumb_callee1>
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1304:       3d ff ff fa     blx
>>>>> > #-780 <thumb_callee1>
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1308:       06 00 00 ea     b       #24
>>>>> > <__ARMToThumbv7ABSLongThunk_thumb_callee1>
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     130c:       05 00 00 ea     b       #20
>>>>> > <__ARMToThumbv7ABSLongThunk_thumb_callee1>
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1310:       07 00 00 ea     b       #28
>>>>> > <__ARMToThumbv7ABSLongThunk_thumb_callee2>
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1314:       09 00 00 ea     b       #36
>>>>> > <__ARMToThumbv7ABSLongThunk_thumb_callee3>
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1318:       78 ff ff ea     b
>>>>> > #-544 <arm_callee1>
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     131c:       b7 00 00 0a     beq     #732
>>>>> > <arm_callee2>
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1320:       b7 00 00 1a     bne     #732
>>>>> > <arm_callee3>
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1324:       1e ff 2f e1     bx      lr
>>>>> > +// CHECK-ARM-ABS-ARM: __ARMToThumbv7ABSLongThunk_thumb_callee1:
>>>>> >  // 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
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1328:       01 c0 01 e3     movw    r12,
>>>>> > #4097
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     132c:       00 c0 40 e3     movt    r12,
>>>>> > #0
>>>>> > +// CHECK-ARM-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
>>>>> > +// CHECK-ARM-ABS-ARM: __ARMToThumbv7ABSLongThunk_thumb_callee2:
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1334:       01 c5 01 e3     movw    r12,
>>>>> > #5377
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1338:       00 c0 40 e3     movt    r12,
>>>>> > #0
>>>>> > +// CHECK-ARM-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-ARM-ABS-ARM: __ARMToThumbv7ABSLongThunk_thumb_callee3:
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1340:       03 c5 01 e3     movw    r12,
>>>>> > #5379
>>>>> > +// CHECK-ARM-ABS-ARM-NEXT:     1344:       00 c0 40 e3     movt    r12,
>>>>> > #0
>>>>> > +// CHECK-ARM-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
>>>>> > +// 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>
>>>>> > +// CHECK-PI-ARM-NEXT:     1308:       06 00 00 ea     b       #24
>>>>> > <__ARMToThumbV7PILongThunk_thumb_callee1>
>>>>> > +// CHECK-PI-ARM-NEXT:     130c:       05 00 00 ea     b       #20
>>>>> > <__ARMToThumbV7PILongThunk_thumb_callee1>
>>>>> > +// CHECK-PI-ARM-NEXT:     1310:       08 00 00 ea     b       #32
>>>>> > <__ARMToThumbV7PILongThunk_thumb_callee2>
>>>>> > +// CHECK-PI-ARM-NEXT:     1314:       0b 00 00 ea     b       #44
>>>>> > <__ARMToThumbV7PILongThunk_thumb_callee3>
>>>>> > +// 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
>>>>> > +// CHECK-PI-ARM: __ARMToThumbV7PILongThunk_thumb_callee1:
>>>>> >  // 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
>>>>> > +// 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
>>>>> > +// CHECK-PI-ARM: __ARMToThumbV7PILongThunk_thumb_callee2:
>>>>> > +
>>>>> > +// 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
>>>>> > +// CHECK-PI-ARM: __ARMToThumbV7PILongThunk_thumb_callee3:
>>>>> >  // 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
>>>>> > +// 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
>>>>> >  // 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:
>>>>> > @@ -182,60 +185,58 @@ thumb_caller:
>>>>> >   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
>>>>> > +// CHECK-ABS-THUMB-NEXT:     1400:       ff f7 7e ee     blx     #-772
>>>>> > +// CHECK-ABS-THUMB-NEXT:     1404:       ff f7 7c ee     blx     #-776
>>>>> > +// CHECK-ABS-THUMB-NEXT:     1408:       00 f0 0a b8     b.w     #20
>>>>> > <__ThumbToARMv7ABSLongThunk_arm_callee1+0x4>
>>>>> > +// CHECK-ABS-THUMB-NEXT:     140c:       00 f0 0d b8     b.w     #26
>>>>> > <__ThumbToARMv7ABSLongThunk_arm_callee2+0x4>
>>>>> > +// CHECK-ABS-THUMB-NEXT:     1410:       00 f0 10 b8     b.w     #32
>>>>> > <__ThumbToARMv7ABSLongThunk_arm_callee3+0x4>
>>>>> > +// CHECK-ABS-THUMB-NEXT:     1414:       00 f0 04 80     beq.w   #8
>>>>> > <__ThumbToARMv7ABSLongThunk_arm_callee1+0x4>
>>>>> > +// CHECK-ABS-THUMB-NEXT:     1418:       00 f0 07 80     beq.w   #14
>>>>> > <__ThumbToARMv7ABSLongThunk_arm_callee2+0x4>
>>>>> > +// CHECK-ABS-THUMB-NEXT:     141c:       40 f0 0a 80     bne.w   #20
>>>>> > <__ThumbToARMv7ABSLongThunk_arm_callee3+0x4>
>>>>> > +// CHECK-ABS-THUMB: __ThumbToARMv7ABSLongThunk_arm_callee1:
>>>>> >  // 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
>>>>> > +// 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
>>>>> > +// CHECK-ABS-THUMB: __ThumbToARMv7ABSLongThunk_arm_callee2:
>>>>> >  // 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
>>>>> > +// 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-ABS-THUMB: __ThumbToARMv7ABSLongThunk_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
>>>>> > +// 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
>>>>> > <__ThumbToARMV7PILongThunk_arm_callee1+0x4>
>>>>> > +// CHECK-PI-THUMB-NEXT:     140c:       00 f0 0e b8     b.w     #28
>>>>> > <__ThumbToARMV7PILongThunk_arm_callee2+0x4>
>>>>> > +// CHECK-PI-THUMB-NEXT:     1410:       00 f0 12 b8     b.w     #36
>>>>> > <__ThumbToARMV7PILongThunk_arm_callee3+0x4>
>>>>> > +// CHECK-PI-THUMB-NEXT:     1414:       00 f0 04 80     beq.w   #8
>>>>> > <__ThumbToARMV7PILongThunk_arm_callee1+0x4>
>>>>> > +// CHECK-PI-THUMB-NEXT:     1418:       00 f0 08 80     beq.w   #16
>>>>> > <__ThumbToARMV7PILongThunk_arm_callee2+0x4>
>>>>> > +// CHECK-PI-THUMB-NEXT:     141c:       40 f0 0c 80     bne.w   #24
>>>>> > <__ThumbToARMV7PILongThunk_arm_callee3+0x4>
>>>>> > +// CHECK-PI-THUMB: __ThumbToARMV7PILongThunk_arm_callee1:
>>>>> >  // 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
>>>>> > +// 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
>>>>> > +// CHECK-PI-THUMB: __ThumbToARMV7PILongThunk_arm_callee2:
>>>>> >  // 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
>>>>> > +// 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
>>>>> > +// CHECK-PI-THUMB: __ThumbToARMV7PILongThunk_arm_callee3:
>>>>> >  // 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-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:
>>>>> >
>>>>> > Modified: lld/trunk/test/ELF/mips-npic-call-pic.s
>>>>> > URL:
>>>>> > http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/mips-npic-call-pic.s?rev=293283&r1=293282&r2=293283&view=diff
>>>>> >
>>>>> > ==============================================================================
>>>>> > --- lld/trunk/test/ELF/mips-npic-call-pic.s (original)
>>>>> > +++ lld/trunk/test/ELF/mips-npic-call-pic.s Fri Jan 27 07:10:16 2017
>>>>> > @@ -15,60 +15,65 @@
>>>>> >
>>>>> >  # CHECK:     Disassembly of section .text:
>>>>> >  # CHECK-NEXT: __start:
>>>>> > -# CHECK-NEXT:    20000:       0c 00 80 0e     jal     131128
>>>>> > <foo1b+0x4>
>>>>> > -#                                                            ^--
>>>>> > .pic.foo1a
>>>>> > +# CHECK-NEXT:    20000:       0c 00 80 0c     jal     131120
>>>>> > <__LA25Thunk_foo1a>
>>>>> >  # CHECK-NEXT:    20004:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    20008:       0c 00 80 19     jal     131172 <foo2+0x4>
>>>>> > -#                                                            ^--
>>>>> > .pic.foo2
>>>>> > +# CHECK-NEXT:    20008:       0c 00 80 16     jal     131160
>>>>> > <__LA25Thunk_foo2>
>>>>> >  # CHECK-NEXT:    2000c:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    20010:       0c 00 80 12     jal     131144
>>>>> > <foo1b+0x14>
>>>>> > -#                                                            ^--
>>>>> > .pic.foo1b
>>>>> > +# CHECK-NEXT:    20010:       0c 00 80 10     jal     131136
>>>>> > <__LA25Thunk_foo1b>
>>>>> >  # CHECK-NEXT:    20014:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    20018:       0c 00 80 19     jal     131172 <foo2+0x4>
>>>>> > -#                                                            ^--
>>>>> > .pic.foo2
>>>>> > +# CHECK-NEXT:    20018:       0c 00 80 16     jal     131160
>>>>> > <__LA25Thunk_foo2>
>>>>> >  # CHECK-NEXT:    2001c:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    20020:       0c 00 80 25     jal     131220
>>>>> > <fnpic+0x4>
>>>>> > -#                                                            ^--
>>>>> > .pic.fpic
>>>>> > +# CHECK-NEXT:    20020:       0c 00 80 1d     jal     131188
>>>>> > <__LA25Thunk_fpic>
>>>>> >  # CHECK-NEXT:    20024:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    20028:       0c 00 80 24     jal     131216 <fnpic>
>>>>> > +# CHECK-NEXT:    20028:       0c 00 80 28     jal     131232 <fnpic>
>>>>> >  # CHECK-NEXT:    2002c:       00 00 00 00     nop
>>>>> >  #
>>>>> > -# CHECK:      foo1a:
>>>>> > -# CHECK-NEXT:    20030:       00 00 00 00     nop
>>>>> > -#
>>>>> > -# CHECK:      foo1b:
>>>>> > -# CHECK-NEXT:    20034:       00 00 00 00     nop
>>>>> > -#
>>>>> > -# CHECK-NEXT:    20038:       3c 19 00 02     lui     $25, 2
>>>>> > -# CHECK-NEXT:    2003c:       08 00 80 0c     j       131120 <foo1a>
>>>>> > -# CHECK-NEXT:    20040:       27 39 00 30     addiu   $25, $25, 48
>>>>> > -# CHECK-NEXT:    20044:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    20048:       3c 19 00 02     lui     $25, 2
>>>>> > -# CHECK-NEXT:    2004c:       08 00 80 0d     j       131124 <foo1b>
>>>>> > -# CHECK-NEXT:    20050:       27 39 00 34     addiu   $25, $25, 52
>>>>> > +# CHECK: __LA25Thunk_foo1a:
>>>>> > +# CHECK-NEXT:    20030:       3c 19 00 02     lui     $25, 2
>>>>> > +# CHECK-NEXT:    20034:       08 00 80 14     j       131152 <foo1a>
>>>>> > +# CHECK-NEXT:    20038:       27 39 00 50     addiu   $25, $25, 80
>>>>> > +# CHECK-NEXT:    2003c:       00 00 00 00     nop
>>>>> > +
>>>>> > +# CHECK: __LA25Thunk_foo1b:
>>>>> > +# CHECK-NEXT:    20040:       3c 19 00 02     lui     $25, 2
>>>>> > +# CHECK-NEXT:    20044:       08 00 80 15     j       131156 <foo1b>
>>>>> > +# CHECK-NEXT:    20048:       27 39 00 54     addiu   $25, $25, 84
>>>>> > +# CHECK-NEXT:    2004c:       00 00 00 00     nop
>>>>> > +
>>>>> > +# CHECK: foo1a:
>>>>> > +# CHECK-NEXT:    20050:       00 00 00 00     nop
>>>>> > +
>>>>> > +# CHECK: foo1b:
>>>>> >  # CHECK-NEXT:    20054:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    20058:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    2005c:       00 00 00 00     nop
>>>>> > -#
>>>>> > -# CHECK:      foo2:
>>>>> > -# CHECK-NEXT:    20060:       00 00 00 00     nop
>>>>> > -#
>>>>> > -# CHECK-NEXT:    20064:       3c 19 00 02     lui     $25, 2
>>>>> > -# CHECK-NEXT:    20068:       08 00 80 18     j       131168 <foo2>
>>>>> > -# CHECK-NEXT:    2006c:       27 39 00 60     addiu   $25, $25, 96
>>>>> > +
>>>>> > +# CHECK: __LA25Thunk_foo2:
>>>>> > +# CHECK-NEXT:    20058:       3c 19 00 02     lui     $25, 2
>>>>> > +# CHECK-NEXT:    2005c:       08 00 80 1c     j       131184 <foo2>
>>>>> > +# CHECK-NEXT:    20060:       27 39 00 70     addiu   $25, $25, 112
>>>>> > +# CHECK-NEXT:    20064:       00 00 00 00     nop
>>>>> > +# CHECK-NEXT:    20068:       00 00 00 00     nop
>>>>> > +# CHECK-NEXT:    2006c:       00 00 00 00     nop
>>>>> > +
>>>>> > +# CHECK: foo2:
>>>>> >  # CHECK-NEXT:    20070:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    20074:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    20078:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    2007c:       00 00 00 00     nop
>>>>> > -#
>>>>> > -# CHECK:       fpic:
>>>>> > -# CHECK-NEXT:    20080:            00 00 00 00     nop
>>>>> > -#
>>>>> > -# CHECK:       fnpic:
>>>>> > +
>>>>> > +# CHECK: __LA25Thunk_fpic:
>>>>> > +# CHECK-NEXT:    20074:       3c 19 00 02     lui     $25, 2
>>>>> > +# CHECK-NEXT:    20078:       08 00 80 24     j       131216 <fpic>
>>>>> > +# CHECK-NEXT:    2007c:       27 39 00 90     addiu   $25, $25, 144
>>>>> > +# CHECK-NEXT:    20080:       00 00 00 00     nop
>>>>> > +# CHECK-NEXT:    20084:       00 00 00 00     nop
>>>>> > +# CHECK-NEXT:    20088:       00 00 00 00     nop
>>>>> > +# CHECK-NEXT:    2008c:       00 00 00 00     nop
>>>>> > +
>>>>> > +# CHECK: fpic:
>>>>> >  # CHECK-NEXT:    20090:       00 00 00 00     nop
>>>>> > -# CHECK-NEXT:    20094:       3c 19 00 02     lui     $25, 2
>>>>> > -# CHECK-NEXT:    20098:       08 00 80 20     j       131200 <fpic>
>>>>> > -# CHECK-NEXT:    2009c:       27 39 00 80     addiu   $25, $25, 128
>>>>> > +# CHECK-NEXT:    20094:       00 00 00 00     nop
>>>>> > +# CHECK-NEXT:    20098:       00 00 00 00     nop
>>>>> > +# CHECK-NEXT:    2009c:       00 00 00 00     nop
>>>>> > +
>>>>> > +# CHECK: fnpic:
>>>>> > +# CHECK-NEXT:    200a0:       00 00 00 00     nop
>>>>> >
>>>>> >  # Make sure the thunks are created properly no matter how
>>>>> >  # objects are laid out.
>>>>> > @@ -76,54 +81,58 @@
>>>>> >  # RUN: ld.lld %t-pic.o %t-npic.o %t-sto-pic.o -o %t.exe
>>>>> >  # RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=REVERSE %s
>>>>> >
>>>>> > -# REVERSE:      foo1a:
>>>>> > -# REVERSE-NEXT:    20000:       00 00 00 00     nop
>>>>> > -#
>>>>> > -# REVERSE:      foo1b:
>>>>> > -# REVERSE-NEXT:    20004:       00 00 00 00     nop
>>>>> > -# REVERSE-NEXT:    20008:       3c 19 00 02     lui     $25, 2
>>>>> > -# REVERSE-NEXT:    2000c:       08 00 80 00     j       131072 <foo1a>
>>>>> > -# REVERSE-NEXT:    20010:       27 39 00 00     addiu   $25, $25, 0
>>>>> > -# REVERSE-NEXT:    20014:       00 00 00 00     nop
>>>>> > -# REVERSE-NEXT:    20018:       3c 19 00 02     lui     $25, 2
>>>>> > -# REVERSE-NEXT:    2001c:       08 00 80 01     j       131076 <foo1b>
>>>>> > -# REVERSE-NEXT:    20020:       27 39 00 04     addiu   $25, $25, 4
>>>>> > +# REVERSE: Disassembly of section .text:
>>>>> > +# REVERSE-NEXT: __LA25Thunk_foo1a:
>>>>> > +# REVERSE-NEXT:    20000:       3c 19 00 02     lui     $25, 2
>>>>> > +# REVERSE-NEXT:    20004:       08 00 80 08     j       131104 <foo1a>
>>>>> > +# REVERSE-NEXT:    20008:       27 39 00 20     addiu   $25, $25, 32
>>>>> > +# REVERSE-NEXT:    2000c:       00 00 00 00     nop
>>>>> > +# REVERSE: __LA25Thunk_foo1b:
>>>>> > +# REVERSE-NEXT:    20010:       3c 19 00 02     lui     $25, 2
>>>>> > +# REVERSE-NEXT:    20014:       08 00 80 09     j       131108 <foo1b>
>>>>> > +# REVERSE-NEXT:    20018:       27 39 00 24     addiu   $25, $25, 36
>>>>> > +# REVERSE-NEXT:    2001c:       00 00 00 00     nop
>>>>> > +# REVERSE: foo1a:
>>>>> > +# REVERSE-NEXT:    20020:       00 00 00 00     nop
>>>>> > +# REVERSE: foo1b:
>>>>> >  # REVERSE-NEXT:    20024:       00 00 00 00     nop
>>>>> > -# REVERSE-NEXT:    20028:       00 00 00 00     nop
>>>>> > -# REVERSE-NEXT:    2002c:       00 00 00 00     nop
>>>>> > -#
>>>>> > -# REVERSE:      foo2:
>>>>> > -# REVERSE-NEXT:    20030:       00 00 00 00     nop
>>>>> > -# REVERSE-NEXT:    20034:       3c 19 00 02     lui     $25, 2
>>>>> > -# REVERSE-NEXT:    20038:       08 00 80 0c     j       131120 <foo2>
>>>>> > -# REVERSE-NEXT:    2003c:       27 39 00 30     addiu   $25, $25, 48
>>>>> > +# REVERSE: __LA25Thunk_foo2:
>>>>> > +# REVERSE-NEXT:    20028:       3c 19 00 02     lui     $25, 2
>>>>> > +# REVERSE-NEXT:    2002c:       08 00 80 10     j       131136 <foo2>
>>>>> > +# REVERSE-NEXT:    20030:       27 39 00 40     addiu   $25, $25, 64
>>>>> > +# REVERSE-NEXT:    20034:       00 00 00 00     nop
>>>>> > +# REVERSE-NEXT:    20038:       00 00 00 00     nop
>>>>> > +# REVERSE-NEXT:    2003c:       00 00 00 00     nop
>>>>> > +# REVERSE: foo2:
>>>>> >  # REVERSE-NEXT:    20040:       00 00 00 00     nop
>>>>> >  # REVERSE-NEXT:    20044:       00 00 00 00     nop
>>>>> >  # REVERSE-NEXT:    20048:       00 00 00 00     nop
>>>>> >  # REVERSE-NEXT:    2004c:       00 00 00 00     nop
>>>>> > -#
>>>>> > -# REVERSE:      __start:
>>>>> > -# REVERSE-NEXT:    20050:       0c 00 80 02     jal     131080
>>>>> > <foo1b+0x4>
>>>>> > +# REVERSE: __start:
>>>>> > +# REVERSE-NEXT:    20050:       0c 00 80 00     jal     131072
>>>>> > <__LA25Thunk_foo1a>
>>>>> >  # REVERSE-NEXT:    20054:       00 00 00 00     nop
>>>>> > -# REVERSE-NEXT:    20058:       0c 00 80 0d     jal     131124
>>>>> > <foo2+0x4>
>>>>> > +# REVERSE-NEXT:    20058:       0c 00 80 0a     jal     131112
>>>>> > <__LA25Thunk_foo2>
>>>>> >  # REVERSE-NEXT:    2005c:       00 00 00 00     nop
>>>>> > -# REVERSE-NEXT:    20060:       0c 00 80 06     jal     131096
>>>>> > <foo1b+0x14>
>>>>> > +# REVERSE-NEXT:    20060:       0c 00 80 04     jal     131088
>>>>> > <__LA25Thunk_foo1b>
>>>>> >  # REVERSE-NEXT:    20064:       00 00 00 00     nop
>>>>> > -# REVERSE-NEXT:    20068:       0c 00 80 0d     jal     131124
>>>>> > <foo2+0x4>
>>>>> > +# REVERSE-NEXT:    20068:       0c 00 80 0a     jal     131112
>>>>> > <__LA25Thunk_foo2>
>>>>> >  # REVERSE-NEXT:    2006c:       00 00 00 00     nop
>>>>> > -# REVERSE-NEXT:    20070:       0c 00 80 25     jal     131220
>>>>> > <fnpic+0x4>
>>>>> > +# REVERSE-NEXT:    20070:       0c 00 80 20     jal     131200
>>>>> > <__LA25Thunk_fpic>
>>>>> >  # REVERSE-NEXT:    20074:       00 00 00 00     nop
>>>>> > -# REVERSE-NEXT:    20078:       0c 00 80 24     jal     131216 <fnpic>
>>>>> > +# REVERSE-NEXT:    20078:       0c 00 80 28     jal     131232 <fnpic>
>>>>> >  # REVERSE-NEXT:    2007c:       00 00 00 00     nop
>>>>> > -#
>>>>> > -# REVERSE:       fpic:
>>>>> > -# REVERSE-NEXT:    20080:       00 00 00 00     nop
>>>>> > -#
>>>>> > -# REVERSE:       fnpic:
>>>>> > +# REVERSE: __LA25Thunk_fpic:
>>>>> > +# REVERSE-NEXT:    20080:       3c 19 00 02     lui     $25, 2
>>>>> > +# REVERSE-NEXT:    20084:       08 00 80 24     j       131216 <fpic>
>>>>> > +# REVERSE-NEXT:    20088:       27 39 00 90     addiu   $25, $25, 144
>>>>> > +# REVERSE-NEXT:    2008c:       00 00 00 00     nop
>>>>> > +# REVERSE: fpic:
>>>>> >  # REVERSE-NEXT:    20090:       00 00 00 00     nop
>>>>> > -# REVERSE-NEXT:    20094:       3c 19 00 02     lui     $25, 2
>>>>> > -# REVERSE-NEXT:    20098:       08 00 80 20     j       131200 <fpic>
>>>>> > -# REVERSE-NEXT:    2009c:       27 39 00 80     addiu   $25, $25, 128
>>>>> > +# REVERSE-NEXT:    20094:       00 00 00 00     nop
>>>>> > +# REVERSE-NEXT:    20098:       00 00 00 00     nop
>>>>> > +# REVERSE-NEXT:    2009c:       00 00 00 00     nop
>>>>> > +# REVERSE: fnpic:
>>>>> > +# REVERSE-NEXT:    200a0:       00 00 00 00     nop
>>>>> >
>>>>> >    .text
>>>>> >    .globl __start
>>>>> >
>>>>> >
>>>>> > _______________________________________________
>>>>> > 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
>>>>
>>>>


More information about the llvm-commits mailing list