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

Peter Smith via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 30 12:25:06 PST 2017


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