Index: ELF/Arch/ARM.cpp
===================================================================
--- ELF/Arch/ARM.cpp
+++ ELF/Arch/ARM.cpp
@@ -39,7 +39,7 @@
   void addPltSymbols(InputSectionBase *IS, uint64_t Off) const override;
   void addPltHeaderSymbols(InputSectionBase *ISD) const override;
   bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
-                  const SymbolBody &S) const override;
+                  uint64_t BranchAddr, const SymbolBody &S) const override;
   bool inBranchRange(uint32_t RelocType, uint64_t Src,
                      uint64_t Dst) const override;
   void relocateOne(uint8_t *Loc, uint32_t Type, uint64_t Val) const override;
@@ -218,7 +218,7 @@
 }
 
 bool ARM::needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
-                     const SymbolBody &S) const {
+                     uint64_t BranchAddr, 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.
@@ -236,14 +236,22 @@
     // Otherwise we need to interwork if Symbol has bit 0 set (Thumb).
     if (Expr == R_PC && ((S.getVA() & 1) == 1))
       return true;
-    break;
+    LLVM_FALLTHROUGH
+  case R_ARM_CALL: {
+    uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA();
+    return !inBranchRange(RelocType, BranchAddr, Dst);
+  }
   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 || ((S.getVA() & 1) == 0))
       return true;
-    break;
+    LLVM_FALLTHROUGH
+  case R_ARM_THM_CALL: {
+    uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA();
+    return !inBranchRange(RelocType, BranchAddr, Dst);
+  }
   }
   return false;
 }
Index: ELF/Arch/Mips.cpp
===================================================================
--- ELF/Arch/Mips.cpp
+++ ELF/Arch/Mips.cpp
@@ -38,7 +38,7 @@
   void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,
                 int32_t Index, unsigned RelOff) const override;
   bool needsThunk(RelExpr Expr, uint32_t RelocType, const InputFile *File,
-                  const SymbolBody &S) const override;
+                  uint64_t BranchAddr, 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;
 };
@@ -319,7 +319,7 @@
 
 template <class ELFT>
 bool MIPS<ELFT>::needsThunk(RelExpr Expr, uint32_t Type, const InputFile *File,
-                            const SymbolBody &S) const {
+                            uint64_t BranchAddr, 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
Index: ELF/Relocations.h
===================================================================
--- ELF/Relocations.h
+++ ELF/Relocations.h
@@ -135,7 +135,11 @@
 
 private:
   void mergeThunks(ArrayRef<OutputSection *> OutputSections);
-  ThunkSection *getISDThunkSec(OutputSection *OS, InputSectionDescription *ISD);
+
+  ThunkSection *getISDThunkSec(OutputSection *OS, InputSection *IS,
+                               InputSectionDescription *ISD, uint32_t Type,
+                               uint64_t Src);
+
   ThunkSection *getISThunkSec(InputSection *IS);
 
   void createInitialThunkSections(ArrayRef<OutputSection *> OutputSections);
@@ -144,7 +148,8 @@
       ArrayRef<OutputSection *> OutputSections,
       std::function<void(OutputSection *, InputSectionDescription *)> Fn);
 
-  std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type);
+  std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type,
+                                    uint64_t Src);
 
   ThunkSection *addThunkSection(OutputSection *OS, InputSectionDescription *,
                                 uint64_t Off);
Index: ELF/Relocations.cpp
===================================================================
--- ELF/Relocations.cpp
+++ ELF/Relocations.cpp
@@ -999,12 +999,18 @@
           // std::merge requires a strict weak ordering.
           if (A->OutSecOff < B->OutSecOff)
             return true;
-          if (A->OutSecOff == B->OutSecOff)
+          if (A->OutSecOff == B->OutSecOff) {
+            auto *TA = dyn_cast<ThunkSection>(A);
+            auto *TB = dyn_cast<ThunkSection>(B);
             // Check if Thunk is immediately before any specific Target
             // InputSection for example Mips LA25 Thunks.
-            if (auto *TA = dyn_cast<ThunkSection>(A))
-              if (TA && TA->getTargetInputSection() == B)
-                return true;
+            if (TA && TA->getTargetInputSection() == B)
+              return true;
+            if (TA && !TB && !TA->getTargetInputSection())
+              // Place Thunk Sections without specific targets before
+              // non-Thunk Sections.
+              return true;
+          }
           return false;
         };
         std::merge(ISD->Sections.begin(), ISD->Sections.end(),
@@ -1015,17 +1021,32 @@
       });
 }
 
-ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *OS,
-                                           InputSectionDescription *ISD) {
-  // FIXME: When range extension thunks are supported we will need to check
-  // that the ThunkSection is in range of the caller.
-  if (!ISD->ThunkSections.empty())
-    return ISD->ThunkSections.front();
-
-  // FIXME: When range extension thunks are supported we must handle the case
-  // where no pre-created ThunkSections are in range by creating a new one in
-  // range; for now, it is unreachable.
-  llvm_unreachable("Must have created at least one ThunkSection per ISR");
+// Find or create a ThunkSection within the InputSectionDescription (ISD) that
+// is in range of Src. An ISR maps to a range of InputSections described by a
+// linker script section pattern such as { .text .text.* }.
+ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *OS, InputSection *IS,
+                                           InputSectionDescription *ISD,
+                                           uint32_t Type, uint64_t Src) {
+  for (ThunkSection *TS : ISD->ThunkSections) {
+    uint64_t TSBase = OS->Addr + TS->OutSecOff;
+    uint64_t TSLimit = TSBase + TS->getSize();
+    if (Target->inBranchRange(Type, Src, (Src > TSLimit) ? TSBase : TSLimit))
+      return TS;
+  }
+
+  // No suitable ThunkSection exists. This can happen when there is a branch
+  // with lower range than the ThunkSection spacing or when there are too
+  // many Thunks. Create a new ThunkSection as close to the InputSection as
+  // possible. Error if InputSection is so large we cannot place ThunkSection
+  // anywhere in Range.
+  uint64_t ThunkSecOff = IS->OutSecOff;
+  if (!Target->inBranchRange(Type, Src, OS->Addr + ThunkSecOff)) {
+    ThunkSecOff = IS->OutSecOff + IS->getSize();
+    if (!Target->inBranchRange(Type, Src, OS->Addr + ThunkSecOff))
+      fatal("InputSection too large for range extension thunk " +
+            IS->getObjMsg<ELF32LE>(Src - (OS->Addr + IS->OutSecOff)));
+  }
+  return addThunkSection(OS, ISD, ThunkSecOff);
 }
 
 // Add a Thunk that needs to be placed in a ThunkSection that immediately
@@ -1094,13 +1115,14 @@
   return TS;
 }
 
-std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
-                                                uint32_t Type) {
+std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body, uint32_t Type,
+                                                uint64_t Src) {
   auto Res = ThunkedSymbols.insert({&Body, std::vector<Thunk *>()});
   if (!Res.second) {
     // Check existing Thunks for Body to see if they can be reused
     for (Thunk *ET : Res.first->second)
-      if (ET->isCompatibleWith(Type))
+      if (ET->isCompatibleWith(Type) &&
+          Target->inBranchRange(Type, Src, ET->ThunkSym->getVA()))
         return std::make_pair(ET, false);
   }
   // No existing compatible Thunk in range, create a new one
@@ -1131,8 +1153,7 @@
 // finalized. If any Thunks are added to an InputSectionDescription the
 // offsets within the OutputSection of the InputSections will change.
 //
-// FIXME: All Thunks are assumed to be in range of the relocation. Range
-// extension Thunks are not yet supported.
+// FIXME: Initial support for RangeThunks; only one pass supported.
 bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
   bool AddressesChanged = false;
   if (Pass == 0 && Target->ThunkSectionSpacing)
@@ -1148,12 +1169,13 @@
         for (InputSection *IS : ISD->Sections)
           for (Relocation &Rel : IS->Relocations) {
             SymbolBody &Body = *Rel.Sym;
+            uint64_t Src = OS->Addr + IS->OutSecOff + Rel.Offset;
             if (Thunks.find(&Body) != Thunks.end() ||
-                !Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
+                !Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Src, Body))
               continue;
             Thunk *T;
             bool IsNew;
-            std::tie(T, IsNew) = getThunk(Body, Rel.Type);
+            std::tie(T, IsNew) = getThunk(Body, Rel.Type, Src);
             if (IsNew) {
               AddressesChanged = true;
               // Find or create a ThunkSection for the new Thunk
@@ -1161,7 +1183,7 @@
               if (auto *TIS = T->getTargetInputSection())
                 TS = getISThunkSec(TIS);
               else
-                TS = getISDThunkSec(OS, ISD);
+                TS = getISDThunkSec(OS, IS, ISD, Rel.Type, Src);
               TS->addThunk(T);
               Thunks[T->ThunkSym] = T;
             }
Index: ELF/Target.h
===================================================================
--- ELF/Target.h
+++ ELF/Target.h
@@ -50,7 +50,8 @@
   // Decide whether a Thunk is needed for the relocation from File
   // targeting S.
   virtual bool needsThunk(RelExpr Expr, uint32_t RelocType,
-                          const InputFile *File, const SymbolBody &S) const;
+                          const InputFile *File, uint64_t BranchAddr,
+                          const SymbolBody &S) const;
   // Return true if we can reach Dst from Src with Relocation RelocType
   virtual bool inBranchRange(uint32_t RelocType, uint64_t Src,
                              uint64_t Dst) const;
Index: ELF/Target.cpp
===================================================================
--- ELF/Target.cpp
+++ ELF/Target.cpp
@@ -124,7 +124,8 @@
 bool TargetInfo::usesOnlyLowPageBits(uint32_t Type) const { return false; }
 
 bool TargetInfo::needsThunk(RelExpr Expr, uint32_t RelocType,
-                            const InputFile *File, const SymbolBody &S) const {
+                            const InputFile *File, uint64_t BranchAddr,
+                            const SymbolBody &S) const {
   return false;
 }
 
Index: ELF/Thunks.cpp
===================================================================
--- ELF/Thunks.cpp
+++ ELF/Thunks.cpp
@@ -246,11 +246,13 @@
   case R_ARM_PC24:
   case R_ARM_PLT32:
   case R_ARM_JUMP24:
+  case R_ARM_CALL:
     if (Config->Pic)
       return make<ARMV7PILongThunk>(S);
     return make<ARMV7ABSLongThunk>(S);
   case R_ARM_THM_JUMP19:
   case R_ARM_THM_JUMP24:
+  case R_ARM_THM_CALL:
     if (Config->Pic)
       return make<ThumbV7PILongThunk>(S);
     return make<ThumbV7ABSLongThunk>(S);
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -1383,17 +1383,12 @@
   // It is linker's responsibility to create thunks containing long
   // jump instructions if jump targets are too far. Create thunks.
   if (Target->NeedsThunks) {
-    // FIXME: only ARM Interworking and Mips LA25 Thunks are implemented,
-    // these
-    // do not require address information. To support range extension Thunks
-    // we need to assign addresses so that we can tell if jump instructions
-    // are out of range. This will need to turn into a loop that converges
-    // when no more Thunks are added
     ThunkCreator TC;
     Script->assignAddresses();
     if (TC.createThunks(OutputSections)) {
       applySynthetic({InX::MipsGot},
                      [](SyntheticSection *SS) { SS->updateAllocSize(); });
+      Script->assignAddresses();
       if (TC.createThunks(OutputSections))
         fatal("All non-range thunks should be created in first call");
     }
Index: test/ELF/arm-branch-error.s
===================================================================
--- test/ELF/arm-branch-error.s
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
-// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar
-// RUN: not ld.lld  %t %tfar -o %t2 2>&1 | FileCheck %s
-// REQUIRES: arm
- .syntax unified
- .section .text, "ax",%progbits
- .globl _start
- .balign 0x10000
- .type _start,%function
-_start:
- // address of too_far symbols are just out of range of ARM branch with
- // 26-bit immediate field and an addend of -8
- bl  too_far1
- b   too_far2
- beq too_far3
-
-// CHECK: R_ARM_CALL out of range
-// CHECK-NEXT: R_ARM_JUMP24 out of range
-// CHECK-NEXT: R_ARM_JUMP24 out of range
Index: test/ELF/arm-branch-rangethunk.s
===================================================================
--- /dev/null
+++ test/ELF/arm-branch-rangethunk.s
@@ -0,0 +1,34 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar
+// RUN: ld.lld  %t %tfar -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
+// REQUIRES: arm
+ .syntax unified
+ .section .text, "ax",%progbits
+ .globl _start
+ .balign 0x10000
+ .type _start,%function
+_start:
+ // address of too_far symbols are just out of range of ARM branch with
+ // 26-bit immediate field and an addend of -8
+ bl  too_far1
+ b   too_far2
+ beq too_far3
+
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: _start:
+// CHECK-NEXT:    20000:       01 00 00 eb     bl      #4 <__ARMv7ABSLongThunk_too_far1>
+// CHECK-NEXT:    20004:       03 00 00 ea     b       #12 <__ARMv7ABSLongThunk_too_far2>
+// CHECK-NEXT:    20008:       05 00 00 0a     beq     #20 <__ARMv7ABSLongThunk_too_far3>
+// CHECK: __ARMv7ABSLongThunk_too_far1:
+// CHECK-NEXT:    2000c:       08 c0 00 e3     movw    r12, #8
+// CHECK-NEXT:    20010:       02 c2 40 e3     movt    r12, #514
+// CHECK-NEXT:    20014:       1c ff 2f e1     bx      r12
+// CHECK: __ARMv7ABSLongThunk_too_far2:
+// CHECK-NEXT:    20018:       0c c0 00 e3     movw    r12, #12
+// CHECK-NEXT:    2001c:       02 c2 40 e3     movt    r12, #514
+// CHECK-NEXT:    20020:       1c ff 2f e1     bx      r12
+// CHECK: __ARMv7ABSLongThunk_too_far3:
+// CHECK-NEXT:    20024:       10 c0 00 e3     movw    r12, #16
+// CHECK-NEXT:    20028:       02 c2 40 e3     movt    r12, #514
+// CHECK-NEXT:    2002c:       1c ff 2f e1     bx      r12
Index: test/ELF/arm-thumb-branch-error.s
===================================================================
--- test/ELF/arm-thumb-branch-error.s
+++ /dev/null
@@ -1,19 +0,0 @@
-// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
-// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar
-// RUN: not ld.lld  %t %tfar -o %t2 2>&1 | FileCheck %s
-// REQUIRES: arm
- .syntax unified
- .section .text, "ax",%progbits
- .globl _start
- .balign 0x10000
- .type _start,%function
-_start:
- // address of too_far symbols are just out of range of ARM branch with
- // 26-bit immediate field and an addend of -8
- bl  too_far1
- b   too_far2
- beq.w too_far3
-
-// CHECK: R_ARM_THM_CALL out of range
-// CHECK-NEXT: R_ARM_THM_JUMP24 out of range
-// CHECK-NEXT: R_ARM_THM_JUMP19 out of range
Index: test/ELF/arm-thumb-branch-rangethunk.s
===================================================================
--- /dev/null
+++ test/ELF/arm-thumb-branch-rangethunk.s
@@ -0,0 +1,36 @@
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar
+// RUN: ld.lld  %t %tfar -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2
+// REQUIRES: arm
+ .syntax unified
+ .thumb
+ .section .text, "ax",%progbits
+ .globl _start
+ .balign 0x10000
+ .type _start,%function
+_start:
+ // address of too_far symbols are just out of range of ARM branch with
+ // 26-bit immediate field and an addend of -8
+ bl  too_far1
+ b   too_far2
+ beq.w too_far3
+
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: _start:
+// CHECK-NEXT:    20000:       00 f0 04 f8     bl      #8
+// CHECK-NEXT:    20004:       00 f0 07 b8     b.w     #14 <__Thumbv7ABSLongThunk_too_far2>
+// CHECK-NEXT:    20008:       00 f0 0a 80     beq.w   #20 <__Thumbv7ABSLongThunk_too_far3>
+// CHECK: __Thumbv7ABSLongThunk_too_far1:
+// CHECK-NEXT:    2000c:       40 f2 05 0c     movw    r12, #5
+// CHECK-NEXT:    20010:       c0 f2 02 1c     movt    r12, #258
+// CHECK-NEXT:    20014:       60 47   bx      r12
+// CHECK: __Thumbv7ABSLongThunk_too_far2:
+// CHECK-NEXT:    20016:       40 f2 09 0c     movw    r12, #9
+// CHECK-NEXT:    2001a:       c0 f2 02 1c     movt    r12, #258
+// CHECK-NEXT:    2001e:       60 47   bx      r12
+// CHECK: __Thumbv7ABSLongThunk_too_far3:
+// CHECK-NEXT:    20020:       40 f2 0d 0c     movw    r12, #13
+// CHECK-NEXT:    20024:       c0 f2 12 0c     movt    r12, #18
+// CHECK-NEXT:    20028:       60 47   bx      r12
+// CHECK-NEXT:    2002a:       00 00   movs    r0, r0
Index: test/ELF/arm-thumb-mix-range-thunk-os.s
===================================================================
--- /dev/null
+++ test/ELF/arm-thumb-mix-range-thunk-os.s
@@ -0,0 +1,195 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: ld.lld %t -o %t2 2>&1
+// The output file is large, most of it zeroes. We dissassemble only the
+// parts we need to speed up the test and avoid a large output file
+// RUN: llvm-objdump -d %t2 -start-address=1048576 -stop-address=1048604 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
+// RUN: llvm-objdump -d %t2 -start-address=2097152 -stop-address=2097162 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
+// RUN: llvm-objdump -d %t2 -start-address=16777220 -stop-address=16777232 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s
+// RUN: llvm-objdump -d %t2 -start-address=16777232 -stop-address=16777242 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s
+// RUN: llvm-objdump -d %t2 -start-address=32505860 -stop-address=32505870 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK5 %s
+// RUN: llvm-objdump -d %t2 -start-address=35651584 -stop-address=35651590 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK6 %s
+// RUN: llvm-objdump -d %t2 -start-address=36700160 -stop-address=36700168 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s
+// RUN: llvm-objdump -d %t2 -start-address=48234500 -stop-address=48234512 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK8 %s
+// RUN: llvm-objdump -d %t2 -start-address=63963140 -stop-address=63963160 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK9 %s
+// RUN: llvm-objdump -d %t2 -start-address=68157440 -stop-address=68157452 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK10 %s
+// RUN: llvm-objdump -d %t2 -start-address=69206016 -stop-address=69206024 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK11 %s
+
+// Test the Range extension Thunks for ARM and Thumb when all the code is in a
+// single OutputSection. The ARM branches and branch and link instructions
+// have a range of 32Mb, the Thumb unconditional branch and
+// branch and link instructions have . We create a series of Functions a
+// megabyte apart. We expect range extension thunks to be created when a
+// branch is out of range. Thunks will be reused whenever they are in range
+ .syntax unified
+
+// Define a function aligned on a megabyte boundary
+ .macro ARMFUNCTION suff
+ .section .text.\suff\(), "ax", %progbits
+ .arm
+ .balign 0x100000
+ .globl afunc\suff\()
+ .type  afunc\suff\(), %function
+afunc\suff\():
+ bx lr
+ .endm
+
+// Define a function aligned on a megabyte boundary
+ .macro THUMBFUNCTION suff
+ .section .text.\suff\(), "ax", %progbits
+ .thumb
+ .balign 0x100000
+ .globl tfunc\suff\()
+ .type  tfunc\suff\(), %function
+tfunc\suff\():
+ bx lr
+ .endm
+
+ .section .text, "ax", %progbits
+ .thumb
+ .globl _start
+_start:
+
+ ARMFUNCTION 00
+// Expect ARM bl to be in range (can use blx to change state)
+ bl tfunc31
+// ARM b and beq are in range but need Thunk to change state to Thumb
+ b  tfunc31
+ beq tfunc31
+// afunc32 is out of range of ARM branch and branch and link
+ bl afunc32
+ b  afunc32
+ bne afunc32
+// CHECK1:  afunc00:
+// CHECK1-NEXT:   100000:       1e ff 2f e1     bx      lr
+// CHECK1-NEXT:   100004:       fd ff 7b fa     blx     #32505844
+// CHECK1-NEXT:   100008:       fd ff 3b ea     b       #15728628
+// CHECK1-NEXT:   10000c:       fc ff 3b 0a     beq     #15728624
+// CHECK1-NEXT:   100010:       fa ff 7f eb     bl      #33554408
+// CHECK1-NEXT:   100014:       f9 ff 7f ea     b       #33554404
+// CHECK1-NEXT:   100018:       f8 ff 7f 1a     bne     #33554400
+ THUMBFUNCTION 01
+// Expect Thumb bl to be in range (can use blx to change state)
+ bl afunc14
+// In range but need thunk to change state to Thumb
+ b.w afunc14
+// CHECK2: tfunc01:
+// CHECK2-NEXT:   200000:       70 47   bx      lr
+// CHECK2-NEXT:   200002:       ff f0 fe c7     blx     #13631484
+// CHECK2-NEXT:   200006:       00 f2 03 90     b.w     #14680070 <__Thumbv7ABSLongThunk_afunc14>
+
+ ARMFUNCTION 02
+ THUMBFUNCTION 03
+ ARMFUNCTION 04
+ THUMBFUNCTION 05
+ ARMFUNCTION 06
+ THUMBFUNCTION 07
+ ARMFUNCTION 08
+ THUMBFUNCTION 09
+ ARMFUNCTION 10
+ THUMBFUNCTION 11
+ ARMFUNCTION 12
+ THUMBFUNCTION 13
+ ARMFUNCTION 14
+// CHECK3:   __ARMv7ABSLongThunk_tfunc31:
+// CHECK3-NEXT:  1000004:       01 c0 00 e3     movw    r12, #1
+// CHECK3-NEXT:  1000008:       00 c2 40 e3     movt    r12, #512
+// CHECK3-NEXT:  100000c:       1c ff 2f e1     bx      r12
+// CHECK4: __Thumbv7ABSLongThunk_afunc14:
+// CHECK4-NEXT:  1000010:       40 f2 00 0c     movw    r12, #0
+// CHECK4-NEXT:  1000014:       c0 f2 f0 0c     movt    r12, #240
+// CHECK4-NEXT:  1000018:       60 47   bx      r12
+ THUMBFUNCTION 15
+ ARMFUNCTION 16
+ THUMBFUNCTION 17
+ ARMFUNCTION 18
+ THUMBFUNCTION 19
+ ARMFUNCTION 20
+ THUMBFUNCTION 21
+ ARMFUNCTION 22
+ THUMBFUNCTION 23
+ ARMFUNCTION 24
+ THUMBFUNCTION 25
+ ARMFUNCTION 26
+ THUMBFUNCTION 27
+ ARMFUNCTION 28
+ THUMBFUNCTION 29
+ ARMFUNCTION 30
+// Expect precreated Thunk Section here
+// CHECK5: __Thumbv7ABSLongThunk_afunc00:
+// CHECK5-NEXT:  1f00004:       40 f2 00 0c     movw    r12, #0
+// CHECK5-NEXT:  1f00008:       c0 f2 10 0c     movt    r12, #16
+// CHECK5-NEXT:  1f0000c:       60 47   bx      r12
+ THUMBFUNCTION 31
+ ARMFUNCTION 32
+ THUMBFUNCTION 33
+// Out of range, can only reach closest Thunk Section
+ bl afunc00
+// CHECK6:  tfunc33:
+// CHECK6-NEXT:  2200000:       70 47   bx      lr
+// CHECK6-NEXT:  2200002:       ff f4 ff ff     bl      #-3145730
+ ARMFUNCTION 34
+// Out of range, can reach earlier Thunk Section
+// CHECK7:  afunc34:
+// CHECK7-NEXT:  2300000:       1e ff 2f e1     bx      lr
+// CHECK7-NEXT:  2300004:       fe ff ef fa     blx     #-4194312 <__Thumbv7ABSLongThunk_afunc00
+ bl afunc00
+ THUMBFUNCTION 35
+ ARMFUNCTION 36
+ THUMBFUNCTION 37
+ ARMFUNCTION 38
+ THUMBFUNCTION 39
+ ARMFUNCTION 40
+ THUMBFUNCTION 41
+ ARMFUNCTION 42
+ THUMBFUNCTION 43
+ ARMFUNCTION 44
+ THUMBFUNCTION 45
+// Expect precreated Thunk Section here
+// CHECK8: __ARMv7ABSLongThunk_tfunc35:
+// CHECK8-NEXT:  2e00004:       01 c0 00 e3     movw    r12, #1
+// CHECK8-NEXT:  2e00008:       40 c2 40 e3     movt    r12, #576
+// CHECK8-NEXT:  2e0000c:       1c ff 2f e1     bx      r12
+ ARMFUNCTION 46
+ THUMBFUNCTION 47
+ ARMFUNCTION 48
+ THUMBFUNCTION 49
+ ARMFUNCTION 50
+ THUMBFUNCTION 51
+ ARMFUNCTION 52
+ THUMBFUNCTION 53
+ ARMFUNCTION 54
+ THUMBFUNCTION 55
+ ARMFUNCTION 56
+ THUMBFUNCTION 57
+ ARMFUNCTION 58
+ THUMBFUNCTION 59
+ ARMFUNCTION 60
+// Expect precreated Thunk Section here
+// CHECK9: __Thumbv7ABSLongThunk_afunc34:
+// CHECK9-NEXT:  3d00004:       40 f2 00 0c     movw    r12, #0
+// CHECK9-NEXT:  3d00008:       c0 f2 30 2c     movt    r12, #560
+// CHECK9-NEXT:  3d0000c:       60 47   bx      r12
+// CHECK9: __Thumbv7ABSLongThunk_tfunc35:
+// CHECK9-NEXT:  3d0000e:       40 f2 01 0c     movw    r12, #1
+// CHECK9-NEXT:  3d00012:       c0 f2 40 2c     movt    r12, #576
+// CHECK9-NEXT:  3d00016:       60 47   bx      r12
+ THUMBFUNCTION 61
+ ARMFUNCTION 62
+ THUMBFUNCTION 63
+ ARMFUNCTION 64
+// afunc34 is in range, as is tfunc35 but a branch needs a state change Thunk
+ bl afunc34
+ b  tfunc35
+// CHECK10: afunc64:
+// CHECK10-NEXT:  4100000:       1e ff 2f e1     bx      lr
+// CHECK10-NEXT:  4100004:      fd ff 87 eb     bl      #-31457292 <afunc34>
+// CHECK10-NEXT:  4100008:      fd ff b3 ea     b       #-19922956 <__ARMv7ABSLongThunk_tfunc35>
+ THUMBFUNCTION 65
+// afunc34 and tfunc35 are both out of range
+ bl afunc34
+ bl tfunc35
+// CHECK11: tfunc65:
+// CHECK11:  4200000:   70 47   bx      lr
+// CHECK11-NEXT:  4200002:      ff f6 ff f7     bl      #-5242882
+// CHECK11-NEXT:  4200006:      00 f7 02 f0     bl      #-5242876
Index: test/ELF/arm-thumb-plt-range-thunk-os.s
===================================================================
--- /dev/null
+++ test/ELF/arm-thumb-plt-range-thunk-os.s
@@ -0,0 +1,88 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: ld.lld %t --shared -o %t.so
+// The output file is large, most of it zeroes. We dissassemble only the
+// parts we need to speed up the test and avoid a large output file
+// RUN: llvm-objdump -d %t.so -start-address=8388608 -stop-address=8388624 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
+// RUN: llvm-objdump -d %t.so -start-address=16777216 -stop-address=16777256 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
+// RUN: llvm-objdump -d %t.so -start-address=25165824 -stop-address=25165828 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s
+// RUN: llvm-objdump -d %t.so -start-address=25165828 -stop-address=25165908 -triple=armv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s
+ .syntax unified
+ .thumb
+
+// Make sure that we generate a range extension thunk to a PLT entry
+ .section ".text.1", "ax", %progbits
+ .global sym1
+ .global elsewhere
+ .type elsewhere, %function
+ .global preemptible
+ .type preemptible, %function
+ .global far_preemptible
+ .type far_preemptible, %function
+sym1:
+ bl elsewhere
+ bl preemptible
+ bx lr
+preemptible:
+ bl far_preemptible
+ bx lr
+// CHECK1: Disassembly of section .text:
+// CHECK1-NEXT: sym1:
+// CHECK1-NEXT:   800000:       00 f0 00 d8     bl      #8388608
+// CHECK1-NEXT:   800004:       00 f0 04 d8     bl      #8388616
+// CHECK1-NEXT:   800008:       70 47   bx      lr
+// CHECK1: preemptible:
+// CHECK1-NEXT:   80000a:       00 f0 07 d8     bl      #8388622
+// CHECK1-NEXT:   80000e:       70 47   bx      lr
+
+ .section .text.2, "ax", %progbits
+ .balign 0x0800000
+ bx lr
+// CHECK2: __ThumbV7PILongThunk_elsewhere:
+// CHECK2-NEXT:  1000004:       40 f2 14 0c     movw    r12, #20
+// CHECK2-NEXT:  1000008:       c0 f2 80 0c     movt    r12, #128
+// CHECK2-NEXT:  100000c:       fc 44   add     r12, pc
+// CHECK2-NEXT:  100000e:       60 47   bx      r12
+// CHECK2: __ThumbV7PILongThunk_preemptible:
+// CHECK2-NEXT:  1000010:       40 f2 18 0c     movw    r12, #24
+// CHECK2-NEXT:  1000014:       c0 f2 80 0c     movt    r12, #128
+// CHECK2-NEXT:  1000018:       fc 44   add     r12, pc
+// CHECK2-NEXT:  100001a:       60 47   bx      r12
+// CHECK2: __ThumbV7PILongThunk_far_preemptible:
+// CHECK2-NEXT:  100001c:       40 f2 1c 0c     movw    r12, #28
+// CHECK2-NEXT:  1000020:       c0 f2 80 0c     movt    r12, #128
+// CHECK2-NEXT:  1000024:       fc 44   add     r12, pc
+// CHECK2-NEXT:  1000026:       60 47   bx      r12
+ .section .text.3, "ax", %progbits
+.balign 0x0800000
+far_preemptible:
+ bl elsewhere
+// CHECK3: far_preemptible:
+// CHECK3:  1800000:       00 f0 10 e8     blx     #32
+
+// CHECK4: Disassembly of section .plt:
+// CHECK4-NEXT: $a:
+// CHECK4-NEXT:  1800010:       04 e0 2d e5     str     lr, [sp, #-4]!
+// CHECK4-NEXT:  1800014:       04 e0 9f e5     ldr     lr, [pc, #4]
+// CHECK4-NEXT:  1800018:       0e e0 8f e0     add     lr, pc, lr
+// CHECK4-NEXT:  180001c:       08 f0 be e5     ldr     pc, [lr, #8]!
+// CHECK4: $d:
+// CHECK4-NEXT:  1800020:       e0 0f 00 00     .word   0x00000fe0
+// CHECK4: $a:
+// CHECK4-NEXT:  1800024:       04 c0 9f e5     ldr     r12, [pc, #4]
+// CHECK4-NEXT:  1800028:       0f c0 8c e0     add     r12, r12, pc
+// CHECK4-NEXT:  180002c:       00 f0 9c e5     ldr     pc, [r12]
+// CHECK4: $d:
+// CHECK4-NEXT:  1800030:       dc 0f 00 00     .word   0x00000fdc
+// CHECK4: $a:
+// CHECK4-NEXT:  1800034:       04 c0 9f e5     ldr     r12, [pc, #4]
+// CHECK4-NEXT:  1800038:       0f c0 8c e0     add     r12, r12, pc
+// CHECK4-NEXT:  180003c:       00 f0 9c e5     ldr     pc, [r12]
+// CHECK4: $d:
+// CHECK4-NEXT:  1800040:       d0 0f 00 00     .word   0x00000fd0
+// CHECK4: $a:
+// CHECK4-NEXT:  1800044:       04 c0 9f e5     ldr     r12, [pc, #4]
+// CHECK4-NEXT:  1800048:       0f c0 8c e0     add     r12, r12, pc
+// CHECK4-NEXT:  180004c:       00 f0 9c e5     ldr     pc, [r12]
+// CHECK4: $d:
+// CHECK4-NEXT:  1800050:       c4 0f 00 00     .word   0x00000fc4
Index: test/ELF/arm-thumb-range-thunk-os.s
===================================================================
--- /dev/null
+++ test/ELF/arm-thumb-range-thunk-os.s
@@ -0,0 +1,159 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: ld.lld %t -o %t2 2>&1
+// The output file is large, most of it zeroes. We dissassemble only the
+// parts we need to speed up the test and avoid a large output file
+// RUN: llvm-objdump -d %t2 -start-address=1048576 -stop-address=1048588 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
+// RUN: llvm-objdump -d %t2 -start-address=2097152 -stop-address=2097154 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
+// RUN: llvm-objdump -d %t2 -start-address=3145728 -stop-address=3145730 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK3 %s
+// RUN: llvm-objdump -d %t2 -start-address=4194304 -stop-address=4194310 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK4 %s
+// RUN: llvm-objdump -d %t2 -start-address=16777216 -stop-address=16777270 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK5 %s
+// RUN: llvm-objdump -d %t2 -start-address=17825792 -stop-address=17825808 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK6 %s
+// RUN: llvm-objdump -d %t2 -start-address=31457280 -stop-address=31457286 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK7 %s
+// RUN: llvm-objdump -d %t2 -start-address=32505860 -stop-address=32505880 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK8 %s
+// RUN: llvm-objdump -d %t2 -start-address=35651584 -stop-address=35651594 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK9 %s
+// RUN: llvm-objdump -d %t2 -start-address=36700160 -stop-address=36700170 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK10 %s
+
+// Test the Range extension Thunks for Thumb when all the code is in a single
+// OutputSection. The Thumb unconditional branch b.w and branch and link bl
+// instructions have a range of 16Mb. We create a series of Functions a
+// megabyte apart. We expect range extension thunks to be created when a
+// branch is out of range. Thunks will be reused whenever they are in range
+ .syntax unified
+
+// Define a function aligned on a megabyte boundary
+ .macro FUNCTION suff
+ .section .text.\suff\(), "ax", %progbits
+ .thumb
+ .balign 0x100000
+ .globl tfunc\suff\()
+ .type  tfunc\suff\(), %function
+tfunc\suff\():
+ bx lr
+ .endm
+
+ .section .text, "ax", %progbits
+ .thumb
+ .globl _start
+_start:
+// tfunc00 and tfunc15 are within 16Mb no Range Thunks expected
+ bl tfunc00
+ bl tfunc15
+// tfunc16 is > 16Mb away, expect a Range Thunk to be generated, to go into
+// the first of the pre-created ThunkSections.
+ bl tfunc16
+// CHECK1: Disassembly of section .text:
+// CHECK1-NEXT: _start:
+// CHECK1-NEXT:   100000:       ff f0 fe ff     bl      #1048572
+// CHECK1-NEXT:   100004:       ff f3 fc d7     bl      #16777208
+// CHECK1-NEXT:   100008:       ff f2 fc d7     bl      #15728632
+
+ FUNCTION 00
+// CHECK2:  tfunc00:
+// CHECK2-NEXT:   200000:       70 47   bx      lr
+        FUNCTION 01
+// CHECK3: tfunc01:
+// CHECK3-NEXT:   300000:       70 47   bx      lr
+ FUNCTION 02
+// tfunc28 is > 16Mb away, expect a Range Thunk to be generated, to go into
+// the first of the pre-created ThunkSections.
+        b.w tfunc28
+// CHECK4: tfunc02:
+// CHECK4-NEXT:   400000:       70 47   bx      lr
+// CHECK4-NEXT:   400002:       00 f0 04 90     b.w     #12582920 <__Thumbv7ABSLongThunk_tfunc28>
+ FUNCTION 03
+ FUNCTION 04
+ FUNCTION 05
+ FUNCTION 06
+ FUNCTION 07
+ FUNCTION 08
+ FUNCTION 09
+ FUNCTION 10
+ FUNCTION 11
+ FUNCTION 12
+ FUNCTION 13
+ FUNCTION 14
+// Expect precreated ThunkSection here
+// CHECK5: __Thumbv7ABSLongThunk_tfunc16:
+// CHECK5-NEXT:  1000004:       40 f2 01 0c     movw    r12, #1
+// CHECK5-NEXT:  1000008:       c0 f2 20 1c     movt    r12, #288
+// CHECK5-NEXT:  100000c:       60 47   bx      r12
+// CHECK5: __Thumbv7ABSLongThunk_tfunc28:
+// CHECK5-NEXT:  100000e:       40 f2 01 0c     movw    r12, #1
+// CHECK5-NEXT:  1000012:       c0 f2 e0 1c     movt    r12, #480
+// CHECK5-NEXT:  1000016:       60 47   bx      r12
+// CHECK5: __Thumbv7ABSLongThunk_tfunc32:
+// CHECK5-NEXT:  1000018:       40 f2 01 0c     movw    r12, #1
+// CHECK5-NEXT:  100001c:       c0 f2 20 2c     movt    r12, #544
+// CHECK5-NEXT:  1000020:       60 47   bx      r12
+// CHECK5: __Thumbv7ABSLongThunk_tfunc33:
+// CHECK5-NEXT:  1000022:       40 f2 01 0c     movw    r12, #1
+// CHECK5-NEXT:  1000026:       c0 f2 30 2c     movt    r12, #560
+// CHECK5-NEXT:  100002a:       60 47   bx      r12
+// CHECK5: __Thumbv7ABSLongThunk_tfunc02:
+// CHECK5-NEXT:  100002c:       40 f2 01 0c     movw    r12, #1
+// CHECK5-NEXT:  1000030:       c0 f2 40 0c     movt    r12, #64
+// CHECK5-NEXT:  1000034:       60 47   bx      r12
+ FUNCTION 15
+// tfunc00 and tfunc01 are < 16Mb away, expect no range extension thunks
+ bl tfunc00
+ bl tfunc01
+// tfunc32 and tfunc33 are > 16Mb away, expect range extension thunks in the
+// precreated thunk section
+ bl tfunc32
+ bl tfunc33
+// CHECK6:  tfunc15:
+// CHECK6-NEXT:  1100000:       70 47   bx      lr
+// CHECK6-NEXT:  1100002:       ff f4 fd d7     bl      #-15728646
+// CHECK6-NEXT:  1100006:       ff f5 fb d7     bl      #-14680074
+// CHECK6-NEXT:  110000a:       00 f7 05 f8     bl      #-1048566
+// CHECK6-NEXT:  110000e:       00 f7 08 f8     bl      #-1048560
+ FUNCTION 16
+ FUNCTION 17
+ FUNCTION 18
+ FUNCTION 19
+ FUNCTION 20
+ FUNCTION 21
+ FUNCTION 22
+ FUNCTION 23
+ FUNCTION 24
+ FUNCTION 25
+ FUNCTION 26
+ FUNCTION 27
+ FUNCTION 28
+// tfunc02 is > 16Mb away, expect range extension thunks in precreated thunk
+// section
+// CHECK7:  tfunc28:
+// CHECK7-NEXT:  1e00000:       70 47   bx      lr
+// CHECK7-NEXT:  1e00002:       00 f6 13 90     b.w     #-14680026 <__Thumbv7ABSLongThunk_tfunc02>
+
+ b.w tfunc02
+ FUNCTION 29
+// Expect another precreated thunk section here
+// CHECK8: __Thumbv7ABSLongThunk_tfunc15:
+// CHECK8-NEXT:  1f00004:       40 f2 01 0c     movw    r12, #1
+// CHECK8-NEXT:  1f00008:       c0 f2 10 1c     movt    r12, #272
+// CHECK8-NEXT:  1f0000c:       60 47   bx      r12
+// CHECK8: __Thumbv7ABSLongThunk_tfunc16:
+// CHECK8-NEXT:  1f0000e:       40 f2 01 0c     movw    r12, #1
+// CHECK8-NEXT:  1f00012:       c0 f2 20 1c     movt    r12, #288
+// CHECK8-NEXT:  1f00016:       60 47   bx      r12
+ FUNCTION 30
+ FUNCTION 31
+ FUNCTION 32
+ // tfunc15 and tfunc16 are > 16 Mb away expect Thunks in the nearest
+ // precreated thunk section.
+ bl tfunc15
+ bl tfunc16
+// CHECK9: tfunc32:
+// CHECK9:  2200000:    70 47   bx      lr
+// CHECK9-NEXT:  2200002:       ff f4 ff ff     bl      #-3145730
+// CHECK9-NEXT:  2200006:       00 f5 02 f8     bl      #-3145724
+
+ FUNCTION 33
+ bl tfunc15
+ bl tfunc16
+// CHECK10: tfunc33:
+// CHECK10:  2300000:   70 47   bx      lr
+// CHECK10-NEXT:  2300002:      ff f7 ff f7     bl      #-4194306
+// CHECK10-NEXT:  2300006:      00 f4 02 f8     bl      #-4194300
Index: test/ELF/arm-thunk-largesection.s
===================================================================
--- /dev/null
+++ test/ELF/arm-thunk-largesection.s
@@ -0,0 +1,42 @@
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: ld.lld %t -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=69632 -stop-address=69636 %t2 | FileCheck -check-prefix=CHECK1 %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=73732 -stop-address=73742 %t2 | FileCheck -check-prefix=CHECK2 %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=16850944 -stop-address=16850948 %t2 | FileCheck -check-prefix=CHECK3 %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=33628160 -stop-address=33628164 %t2 | FileCheck -check-prefix=CHECK4 %s
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=50405364 -stop-address=50405376 %t2 | FileCheck -check-prefix=CHECK5 %s
+// REQUIRES: arm
+ .syntax unified
+ .balign 0x1000
+ .thumb
+ .text
+ .globl _start
+ .type _start, %function
+_start:
+ bx lr
+ .space 0x1000
+// CHECK1: Disassembly of section .text:
+// CHECK1-NEXT: _start:
+// CHECK1-NEXT:    11000:       70 47   bx      lr
+// CHECK1-NEXT:    11002:       00 00   movs    r0, r0
+
+// CHECK2: __Thumbv7ABSLongThunk__start:
+// CHECK2-NEXT:    12004:       41 f2 01 0c     movw    r12, #4097
+// CHECK2-NEXT:    12008:       c0 f2 01 0c     movt    r12, #1
+// CHECK2-NEXT:    1200c:       60 47   bx      r12
+
+// Gigantic section where we need a ThunkSection either side of it
+ .section .text.large1, "ax", %progbits
+ .balign 4
+ .space (16 * 1024 * 1024) - 16
+ bl _start
+ .space (16 * 1024 * 1024) - 4
+ bl _start
+ .space (16 * 1024 * 1024) - 16
+// CHECK3: 1012000:     00 f4 00 d0     bl      #-16777216
+// CHECK4: 2012000:     ff f3 f8 d7     bl      #16777200
+
+// CHECK5: __Thumbv7ABSLongThunk__start:
+// CHECK5-NEXT:  3011ff4:       41 f2 01 0c     movw    r12, #4097
+// CHECK5-NEXT:  3011ff8:       c0 f2 01 0c     movt    r12, #1
+// CHECK5-NEXT:  3011ffc:       60 47   bx      r12
Index: test/ELF/arm-thunk-linkerscript-dotexpr.s
===================================================================
--- /dev/null
+++ test/ELF/arm-thunk-linkerscript-dotexpr.s
@@ -0,0 +1,76 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: echo "SECTIONS { \
+// RUN:       . = SIZEOF_HEADERS; \
+// RUN:       .text_low : { *(.text_low) *(.text_low2) . = . + 0x2000000 ; *(.text_high) *(.text_high2) } \
+// RUN:       } " > %t.script
+// RUN: ld.lld --script %t.script %t -o %t2 2>&1
+// RUN: llvm-objdump -d %t2 -start-address=148 -stop-address=188 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
+// RUN: llvm-objdump -d %t2 -start-address=33554620 -stop-address=33554654 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
+// Test that range extension thunks can handle location expressions within
+// a Section Description
+ .syntax unified
+ .section .text_low, "ax", %progbits
+ .thumb
+ .globl _start
+_start: bx lr
+ .globl low_target
+ .type low_target, %function
+low_target:
+ bl high_target
+ bl high_target2
+
+ .section .text_low2, "ax", %progbits
+ .thumb
+ .globl low_target2
+ .type low_target2, %function
+low_target2:
+ bl high_target
+ bl high_target2
+// CHECK1: Disassembly of section .text_low:
+// CHECK1-NEXT: _start:
+// CHECK1-NEXT:       94:       70 47   bx      lr
+// CHECK1: low_target:
+// CHECK1-NEXT:       96:       00 f0 03 f8     bl      #6
+// CHECK1-NEXT:       9a:       00 f0 06 f8     bl      #12
+// CHECK1: __Thumbv7ABSLongThunk_high_target:
+// CHECK1-NEXT:       a0:       40 f2 bd 0c     movw    r12, #189
+// CHECK1-NEXT:       a4:       c0 f2 00 2c     movt    r12, #512
+// CHECK1-NEXT:       a8:       60 47   bx      r12
+// CHECK1: __Thumbv7ABSLongThunk_high_target2:
+// CHECK1-NEXT:       aa:       40 f2 d9 0c     movw    r12, #217
+// CHECK1-NEXT:       ae:       c0 f2 00 2c     movt    r12, #512
+// CHECK1-NEXT:       b2:       60 47   bx      r12
+// CHECK1: low_target2:
+// CHECK1-NEXT:       b4:       ff f7 f4 ff     bl      #-24
+// CHECK1-NEXT:       b8:       ff f7 f7 ff     bl      #-18
+
+ .section .text_high, "ax", %progbits
+ .thumb
+ .globl high_target
+ .type high_target, %function
+high_target:
+ bl low_target
+ bl low_target2
+
+ .section .text_high2, "ax", %progbits
+ .thumb
+ .globl high_target2
+ .type high_target2, %function
+high_target2:
+ bl low_target
+ bl low_target2
+
+// CHECK2: high_target:
+// CHECK2-NEXT:  20000bc:       00 f0 02 f8     bl      #4
+// CHECK2-NEXT:  20000c0:       00 f0 05 f8     bl      #10
+// CHECK2: __Thumbv7ABSLongThunk_low_target:
+// CHECK2-NEXT:  20000c4:       40 f2 97 0c     movw    r12, #151
+// CHECK2-NEXT:  20000c8:       c0 f2 00 0c     movt    r12, #0
+// CHECK2-NEXT:  20000cc:       60 47   bx      r12
+// CHECK2: __Thumbv7ABSLongThunk_low_target2:
+// CHECK2-NEXT:  20000ce:       40 f2 b5 0c     movw    r12, #181
+// CHECK2-NEXT:  20000d2:       c0 f2 00 0c     movt    r12, #0
+// CHECK2-NEXT:  20000d6:       60 47   bx      r12
+// CHECK2: high_target2:
+// CHECK2-NEXT:  20000d8:       ff f7 f4 ff     bl      #-24
+// CHECK2-NEXT:  20000dc:       ff f7 f7 ff     bl      #-18
Index: test/ELF/arm-thunk-linkerscript-large.s
===================================================================
--- /dev/null
+++ test/ELF/arm-thunk-linkerscript-large.s
@@ -0,0 +1,176 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: echo "SECTIONS { \
+// RUN:       .text 0x100000 : { *(.text) } \
+// RUN:       .textl : { *(.text_l0*) *(.text_l1*) *(.text_l2*) *(.text_l3*) } \
+// RUN:       .texth : { *(.text_h0*) *(.text_h1*) *(.text_h2*) *(.text_h3*) } \
+// RUN:       }" > %t.script
+// RUN: ld.lld --script %t.script %t -o %t2 2>&1
+// The output file is large, most of it zeroes. We dissassemble only the
+// parts we need to speed up the test and avoid a large output file
+// RUN: llvm-objdump -d %t2 -start-address=1048576 -stop-address=1048594 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK1 %s
+// RUN: llvm-objdump -d %t2 -start-address=2097152 -stop-address=2097160 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK2 %s
+// RUN: llvm-objdump -d %t2 -start-address=11534340 -stop-address=11534350 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK3 %s
+// RUN: llvm-objdump -d %t2 -start-address=34603008 -stop-address=34603034 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK4 %s
+// RUN: llvm-objdump -d %t2 -start-address=35651584 -stop-address=35651598 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK5 %s
+// RUN: llvm-objdump -d %t2 -start-address=68157440 -stop-address=68157472 -triple=thumbv7a-linux-gnueabihf | FileCheck --check-prefix=CHECK6 %s
+
+// Test the range extensions in a linker script where there are several
+// OutputSections requiring range extension Thunks. We should be able to reuse
+// Thunks between OutputSections but our placement of new Thunks is done on a
+// per OutputSection basis
+ .syntax unified
+
+// Define a function that we can match with .text_l* aligned on a megabyte      // boundary
+ .macro FUNCTIONL suff
+ .section .text_l\suff\(), "ax", %progbits
+ .thumb
+ .balign 0x100000
+ .globl tfuncl\suff\()
+ .type  tfuncl\suff\(), %function
+tfuncl\suff\():
+ bx lr
+ .endm
+
+// Define a function that we can match with .text_h* aligned on a megabyte
+// boundary
+ .macro FUNCTIONH suff
+ .section .text_h\suff\(), "ax", %progbits
+ .thumb
+ .balign 0x100000
+ .globl tfunch\suff\()
+ .type  tfunch\suff\(), %function
+tfunch\suff\():
+ bx lr
+ .endm
+
+ .section .text, "ax", %progbits
+ .thumb
+ .globl _start
+_start:
+ bl tfuncl00
+ // Expect a range extension thunk in .text OutputSection
+ bl tfunch31
+// CHECK1: Disassembly of section .text:
+// CHECK1-NEXT: _start:
+// CHECK1-NEXT:   100000:       ff f0 fe ff     bl      #1048572
+// CHECK1-NEXT:   100004:       00 f0 00 f8     bl      #0
+// CHECK1: __Thumbv7ABSLongThunk_tfunch31:
+// CHECK1-NEXT:   100008:       40 f2 01 0c     movw    r12, #1
+// CHECK1-NEXT:   10000c:       c0 f2 10 4c     movt    r12, #1040
+// CHECK1-NEXT:   100010:       60 47   bx      r12
+ FUNCTIONL 00
+ // Create a range extension thunk in .textl
+ bl tfuncl24
+ // We can reuse existing thunk in .text
+ bl tfunch31
+// CHECK2: Disassembly of section .textl:
+// CHECK2-NEXT: tfuncl00:
+// CHECK2-NEXT:   200000:	70 47 	bx	lr
+// CHECK2-NEXT:   200002:	ff f0 ff df 	bl	#9437182
+// CHECK2-NEXT:   200006:	ff f6 ff ff 	bl	#-1048578
+ FUNCTIONL 01
+ FUNCTIONL 02
+ FUNCTIONL 03
+ FUNCTIONL 04
+ FUNCTIONL 05
+ FUNCTIONL 06
+ FUNCTIONL 07
+ FUNCTIONL 08
+ FUNCTIONL 09
+// CHECK3: __Thumbv7ABSLongThunk_tfuncl24:
+// CHECK3-NEXT:   b00004:	40 f2 01 0c 	movw	r12, #1
+// CHECK3-NEXT:   b00008:	c0 f2 a0 1c 	movt	r12, #416
+// CHECK3-NEXT:   b0000c:	60 47 	bx	r12
+ FUNCTIONL 10
+ FUNCTIONL 11
+ FUNCTIONL 12
+ FUNCTIONL 13
+ FUNCTIONL 14
+ FUNCTIONL 15
+ FUNCTIONL 16
+ FUNCTIONL 17
+ FUNCTIONL 18
+ FUNCTIONL 19
+ FUNCTIONL 20
+ FUNCTIONL 21
+ FUNCTIONL 22
+ FUNCTIONL 23
+ FUNCTIONL 24
+ FUNCTIONL 25
+ FUNCTIONL 26
+ FUNCTIONL 27
+ FUNCTIONL 28
+ FUNCTIONL 29
+ FUNCTIONL 30
+ FUNCTIONL 31
+ // Create range extension thunks in .textl
+ bl tfuncl00
+ bl tfuncl24
+ // Shouldn't need a thunk
+ bl tfunch00
+// CHECK4:  2100002:    00 f0 05 f8     bl      #10
+// CHECK4-NEXT:  2100006:       ff f4 fb f7     bl      #-7340042
+// CHECK4-NEXT:  210000a:       ff f0 f9 ff     bl      #1048562
+// CHECK4: __Thumbv7ABSLongThunk_tfuncl00:
+// CHECK4-NEXT:  2100010:       40 f2 01 0c     movw    r12, #1
+// CHECK4-NEXT:  2100014:       c0 f2 20 0c     movt    r12, #32
+// CHECK4-NEXT:  2100018:       60 47   bx      r12
+ FUNCTIONH 00
+ // Can reuse existing thunks in .textl
+ bl tfuncl00
+ bl tfuncl24
+ // Shouldn't need a thunk
+        bl tfuncl31
+// CHECK5:  Disassembly of section .texth:
+// CHECK5-NEXT: tfunch00:
+// CHECK5-NEXT:  2200000:       70 47   bx      lr
+// CHECK5-NEXT:  2200002:       00 f7 05 f8     bl      #-1048566
+// CHECK5-NEXT:  2200006:       ff f7 fb df     bl      #-8388618
+// CHECK5-NEXT:  220000a:       ff f6 f9 ff     bl      #-1048590
+ FUNCTIONH 01
+ FUNCTIONH 02
+ FUNCTIONH 03
+ FUNCTIONH 04
+ FUNCTIONH 05
+ FUNCTIONH 06
+ FUNCTIONH 07
+ FUNCTIONH 08
+ FUNCTIONH 09
+ FUNCTIONH 10
+ FUNCTIONH 11
+ FUNCTIONH 12
+ FUNCTIONH 13
+ FUNCTIONH 14
+ FUNCTIONH 15
+ FUNCTIONH 16
+ FUNCTIONH 17
+ FUNCTIONH 18
+ FUNCTIONH 19
+ FUNCTIONH 20
+ FUNCTIONH 21
+ FUNCTIONH 22
+ FUNCTIONH 23
+ FUNCTIONH 24
+ FUNCTIONH 25
+ FUNCTIONH 26
+ FUNCTIONH 27
+ FUNCTIONH 28
+ FUNCTIONH 29
+ FUNCTIONH 30
+ FUNCTIONH 31
+// expect Thunks in .texth
+ bl tfuncl00
+ bl tfunch00
+// CHECK6: tfunch31:
+// CHECK6-NEXT:  4100000:       70 47   bx      lr
+// CHECK6-NEXT:  4100002:       00 f0 03 f8     bl      #6
+// CHECK6-NEXT:  4100006:       00 f0 06 f8     bl      #12
+// CHECK6: __Thumbv7ABSLongThunk_tfuncl00:
+// CHECK6-NEXT:  410000c:       40 f2 01 0c     movw    r12, #1
+// CHECK6-NEXT:  4100010:       c0 f2 20 0c     movt    r12, #32
+// CHECK6-NEXT:  4100014:       60 47   bx      r12
+// CHECK6: __Thumbv7ABSLongThunk_tfunch00:
+// CHECK6-NEXT:  4100016:       40 f2 01 0c     movw    r12, #1
+// CHECK6-NEXT:  410001a:       c0 f2 20 2c     movt    r12, #544
+// CHECK6-NEXT:  410001e:       60 47   bx      r12
Index: test/ELF/arm-thunk-linkerscript-orphan.s
===================================================================
--- /dev/null
+++ test/ELF/arm-thunk-linkerscript-orphan.s
@@ -0,0 +1,63 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: echo "SECTIONS { \
+// RUN:       .text_low 0x100000 : { *(.text_low) } \
+// RUN:       .text_high 0x2000000 : { *(.text_high) } \
+// RUN:       .data : { *(.data) } \
+// RUN:       }" > %t.script
+// RUN: ld.lld --script %t.script %t -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s
+ .syntax unified
+ .section .text_low, "ax", %progbits
+ .thumb
+ .globl _start
+_start: bx lr
+ .globl low_target
+ .type low_target, %function
+low_target:
+ bl high_target
+ bl orphan_target
+// CHECK: Disassembly of section .text_low:
+// CHECK-NEXT: _start:
+// CHECK-NEXT:   100000:        70 47   bx      lr
+// CHECK: low_target:
+// CHECK-NEXT:   100002:        00 f0 03 f8     bl      #6
+// CHECK-NEXT:   100006:        00 f0 06 f8     bl      #12
+// CHECK: __Thumbv7ABSLongThunk_high_target:
+// CHECK-NEXT:   10000c:        40 f2 01 0c     movw    r12, #1
+// CHECK-NEXT:   100010:        c0 f2 00 2c     movt    r12, #512
+// CHECK-NEXT:   100014:        60 47   bx      r12
+// CHECK: __Thumbv7ABSLongThunk_orphan_target:
+// CHECK-NEXT:   100016:        40 f2 15 0c     movw    r12, #21
+// CHECK-NEXT:   10001a:        c0 f2 00 2c     movt    r12, #512
+// CHECK-NEXT:   10001e:        60 47   bx      r12
+  .section .text_high, "ax", %progbits
+ .thumb
+ .globl high_target
+ .type high_target, %function
+high_target:
+ bl low_target
+ bl orphan_target
+// CHECK: Disassembly of section .text_high:
+// CHECK-NEXT: high_target:
+// CHECK-NEXT:  2000000:        00 f0 02 f8     bl      #4
+// CHECK-NEXT:  2000004:        00 f0 06 f8     bl      #12
+// CHECK: __Thumbv7ABSLongThunk_low_target:
+// CHECK-NEXT:  2000008:        40 f2 03 0c     movw    r12, #3
+// CHECK-NEXT:  200000c:        c0 f2 10 0c     movt    r12, #16
+// CHECK-NEXT:  2000010:        60 47   bx      r12
+
+ .section orphan, "ax", %progbits
+ .thumb
+ .globl orphan_target
+ .type orphan_target, %function
+orphan_target:
+ bl low_target
+ bl high_target
+// CHECK: Disassembly of section orphan:
+// CHECK-NEXT: orphan_target:
+// CHECK-NEXT:  2000014:        ff f7 f8 ff     bl      #-16
+// CHECK-NEXT:  2000018:        ff f7 f2 ff     bl      #-28
+
+ .data
+ .word 10
Index: test/ELF/arm-thunk-linkerscript-sort.s
===================================================================
--- /dev/null
+++ test/ELF/arm-thunk-linkerscript-sort.s
@@ -0,0 +1,71 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: echo "SECTIONS { \
+// RUN:       .text 0x100000 : { *(SORT_BY_NAME(.text.*)) } \
+// RUN:       }" > %t.script
+// RUN: ld.lld --script %t.script %t -o %t2 2>&1
+// RUN: llvm-objdump -d %t2 -start-address=1048576 -stop-address=1048584 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s
+// RUN: llvm-objdump -d %t2 -start-address=16777220 -stop-address=16777230 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s
+
+ .syntax unified
+
+// Test that linkerscript sorting does not apply to Thunks, we expect that the
+// sort will reverse the order of sections presented here.
+
+// Define a function aligned on a megabyte boundary
+ .macro FUNCTION suff
+ .section .text.\suff\(), "ax", %progbits
+ .thumb
+ .balign 0x100000
+ .globl tfunc\suff\()
+ .type  tfunc\suff\(), %function
+tfunc\suff\():
+ bx lr
+ .endm
+
+ FUNCTION 31
+ FUNCTION 30
+ FUNCTION 29
+ FUNCTION 28
+ FUNCTION 27
+ FUNCTION 26
+ FUNCTION 25
+ FUNCTION 24
+ FUNCTION 23
+ FUNCTION 22
+ FUNCTION 21
+ FUNCTION 20
+ FUNCTION 19
+ FUNCTION 18
+ FUNCTION 17
+ FUNCTION 16
+ FUNCTION 15
+// CHECK2: __Thumbv7ABSLongThunk_tfunc31:
+// CHECK2-NEXT:  1000004:       40 f2 01 0c     movw    r12, #1
+// CHECK2-NEXT:  1000008:       c0 f2 00 2c     movt    r12, #512
+// CHECK2-NEXT:  100000c:       60 47   bx      r12
+ FUNCTION 14
+ FUNCTION 13
+ FUNCTION 12
+ FUNCTION 11
+ FUNCTION 10
+ FUNCTION 09
+ FUNCTION 08
+ FUNCTION 07
+ FUNCTION 06
+ FUNCTION 05
+ FUNCTION 04
+ FUNCTION 03
+ FUNCTION 02
+ FUNCTION 01
+ .section .text.00, "ax", %progbits
+ .thumb
+ .globl _start
+_start:
+// Expect no range extension needed for tfunc01 and an extension needed for
+// tfunc31
+ bl tfunc01
+ bl tfunc31
+// CHECK1: _start:
+// CHECK1-NEXT:   100000:       ff f0 fe ff     bl      #1048572
+// CHECK1-NEXT:   100004:       ff f2 fe d7     bl      #15728636
Index: test/ELF/arm-thunk-linkerscript.s
===================================================================
--- /dev/null
+++ test/ELF/arm-thunk-linkerscript.s
@@ -0,0 +1,78 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: echo "SECTIONS { \
+// RUN:       . = SIZEOF_HEADERS; \
+// RUN:       .text_low : { *(.text_low) *(.text_low2) } \
+// RUN:       .text_high 0x2000000 : { *(.text_high) *(.text_high2) } \
+// RUN:       } " > %t.script
+// RUN: ld.lld --script %t.script %t -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s
+
+// Simple test that we can support range extension thunks with linker scripts
+ .syntax unified
+ .section .text_low, "ax", %progbits
+ .thumb
+ .globl _start
+_start: bx lr
+ .globl low_target
+ .type low_target, %function
+low_target:
+ bl high_target
+ bl high_target2
+
+ .section .text_low2, "ax", %progbits
+ .thumb
+ .globl low_target2
+ .type low_target2, %function
+low_target2:
+ bl high_target
+ bl high_target2
+
+// CHECK: Disassembly of section .text_low:
+// CHECK-NEXT: _start:
+// CHECK-NEXT:       94:        70 47   bx      lr
+// CHECK: low_target:
+// CHECK-NEXT:       96:        00 f0 03 f8     bl      #6
+// CHECK-NEXT:       9a:        00 f0 06 f8     bl      #12
+// CHECK: __Thumbv7ABSLongThunk_high_target:
+// CHECK-NEXT:       a0:        40 f2 01 0c     movw    r12, #1
+// CHECK-NEXT:       a4:        c0 f2 00 2c     movt    r12, #512
+// CHECK-NEXT:       a8:        60 47   bx      r12
+// CHECK: __Thumbv7ABSLongThunk_high_target2:
+// CHECK-NEXT:       aa:        40 f2 1d 0c     movw    r12, #29
+// CHECK-NEXT:       ae:        c0 f2 00 2c     movt    r12, #512
+// CHECK-NEXT:       b2:        60 47   bx      r12
+// CHECK: low_target2:
+// CHECK-NEXT:       b4:        ff f7 f4 ff     bl      #-24
+// CHECK-NEXT:       b8:        ff f7 f7 ff     bl      #-18
+
+ .section .text_high, "ax", %progbits
+ .thumb
+ .globl high_target
+ .type high_target, %function
+high_target:
+ bl low_target
+ bl low_target2
+
+ .section .text_high2, "ax", %progbits
+ .thumb
+ .globl high_target2
+ .type high_target2, %function
+high_target2:
+ bl low_target
+ bl low_target2
+
+// CHECK: Disassembly of section .text_high:
+// CHECK-NEXT: high_target:
+// CHECK-NEXT:  2000000:        00 f0 02 f8     bl      #4
+// CHECK-NEXT:  2000004:        00 f0 05 f8     bl      #10
+// CHECK: __Thumbv7ABSLongThunk_low_target:
+// CHECK-NEXT:  2000008:        40 f2 97 0c     movw    r12, #151
+// CHECK-NEXT:  200000c:        c0 f2 00 0c     movt    r12, #0
+// CHECK-NEXT:  2000010:        60 47   bx      r12
+// CHECK: __Thumbv7ABSLongThunk_low_target2:
+// CHECK-NEXT:  2000012:        40 f2 b5 0c     movw    r12, #181
+// CHECK-NEXT:  2000016:        c0 f2 00 0c     movt    r12, #0
+// CHECK-NEXT:  200001a:        60 47   bx      r12
+// CHECK: high_target2:
+// CHECK-NEXT:  200001c:        ff f7 f4 ff     bl      #-24
+// CHECK-NEXT:  2000020:        ff f7 f7 ff     bl      #-18
Index: test/ELF/arm-thunk-toolargesection.s
===================================================================
--- /dev/null
+++ test/ELF/arm-thunk-toolargesection.s
@@ -0,0 +1,19 @@
+// RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t
+// RUN: not ld.lld %t -o %t2 2>&1 | FileCheck %s
+// REQUIRES: arm
+ .syntax unified
+ .balign 0x1000
+ .thumb
+ .text
+ .globl _start
+ .type _start, %function
+_start:
+ bx lr
+
+ .section .text.large1, "ax", %progbits
+ .balign 4
+.space (17 * 1024 * 1024)
+ bl _start
+.space (17 * 1024 * 1024)
+
+// CHECK: error: InputSection too large for range extension thunk {{.*}}.text.large1