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