Index: ELF/LinkerScript.h
===================================================================
--- ELF/LinkerScript.h
+++ ELF/LinkerScript.h
@@ -227,6 +227,8 @@
 
   MemoryRegion *findMemoryRegion(OutputSectionCommand *Cmd);
 
+  void resetAddressState();
+
   void switchTo(OutputSection *Sec);
   void flush();
   void output(InputSection *Sec);
@@ -257,6 +259,8 @@
 
   std::vector<OutputSection *> *OutputSections;
   void fabricateDefaultCommands(bool AllocateHeader);
+  std::vector<std::vector<InputSectionBase *> *>
+  inputSectionRanges(StringRef S);
   void addOrphanSections(OutputSectionFactory &Factory);
   void removeEmptyCommands();
   void adjustSectionsBeforeSorting();
Index: ELF/LinkerScript.cpp
===================================================================
--- ELF/LinkerScript.cpp
+++ ELF/LinkerScript.cpp
@@ -458,11 +458,53 @@
   Opt.Commands = std::move(Commands);
 }
 
+std::vector<std::vector<InputSectionBase *> *>
+LinkerScript::inputSectionRanges(StringRef S) {
+  std::vector<std::vector<InputSectionBase *> *> Ranges;
+  auto OutCmdPos = std::find_if(
+      Opt.Commands.begin(), Opt.Commands.end(), [=](BaseCommand *Cmd) {
+        if (auto *OSCmd = dyn_cast<OutputSectionCommand>(Cmd))
+          return (OSCmd->Name == S);
+        return false;
+      });
+  if (OutCmdPos == Opt.Commands.end())
+    return Ranges;
+  auto *OutCmd = cast<OutputSectionCommand>(*OutCmdPos);
+  for (auto *BaseCmd : OutCmd->Commands) {
+    if (auto *ISD = dyn_cast<InputSectionDescription>(BaseCmd))
+      Ranges.push_back(&ISD->Sections);
+  }
+  return Ranges;
+}
+
 // Add sections that didn't match any sections command.
 void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) {
+  std::map<OutputSection *, std::vector<InputSectionBase *>> Orphanage;
   for (InputSectionBase *S : InputSections)
-    if (S->Live && !S->OutSec)
+    if (S->Live && !S->OutSec) {
       Factory.addInputSec(S, getOutputSectionName(S->Name));
+      Orphanage[S->OutSec].push_back(S);
+    }
+
+  // For each OutputSection that already has an OutputSectionCmd, add an
+  // InputSectionDescription at the end for the OrphanSections. This matches
+  // GNU ld behavior for scripts such as .text : { *(.text) SYM = .; } the
+  // orphan sections such as .text.suffix are added after the symbol assignment
+  for (auto &KV : Orphanage) {
+    OutputSection *OS = KV.first;
+    auto Pos = std::find_if(Opt.Commands.begin(), Opt.Commands.end(),
+                            [&](BaseCommand *Base) {
+                              auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
+                              return Cmd && Cmd->Name == OS->Name;
+                            });
+    if (Pos == Opt.Commands.end())
+      // A new OutputSection, we handle this case in placeOrphanSections()
+      continue;
+    auto *OSCmd = cast<OutputSectionCommand>(*Pos);
+    auto *ISD = make<InputSectionDescription>("");
+    OSCmd->Commands.push_back(ISD);
+    ISD->Sections = std::move(KV.second);
+  }
 }
 
 static bool isTbss(OutputSection *Sec) {
@@ -613,6 +655,21 @@
   return nullptr;
 }
 
+// Reset the members associated with address assigment to their initial values
+// this permits addressAssignment to be run again.
+void LinkerScript::resetAddressState() {
+  LMAOffset = 0;
+  CurOutSec = nullptr;
+  CurMemRegion = nullptr;
+  ThreadBssOffset = 0;
+  for (auto &MRI : Opt.MemoryRegions) {
+    MemoryRegion &MR = MRI.second;
+    MR.Offset = MR.Origin;
+  }
+  AlreadyOutputOS.clear();
+  AlreadyOutputIS.clear();
+}
+
 // This function assigns offsets to input sections and an output section
 // for a single sections command (e.g. ".text { *(.text); }").
 void LinkerScript::assignOffsets(OutputSectionCommand *Cmd) {
@@ -823,6 +880,16 @@
       auto *Cmd = make<OutputSectionCommand>(Name);
       Cmd->Sec = Sec;
       Opt.Commands.insert(CmdIter, Cmd);
+
+      // Create an InputSectionDescription for orphan input sections
+      if (!Sec->Sections.empty() && (Sec->Flags & SHF_ALLOC)) {
+        auto *ISD = make<InputSectionDescription>("");
+        Cmd->Commands.push_back(ISD);
+        for (InputSection *ISec : Sec->Sections) {
+          ISD->Sections.push_back(ISec);
+          ISec->Assigned = true;
+        }
+      }
       ++CmdIndex;
       continue;
     }
@@ -844,6 +911,7 @@
 void LinkerScript::assignAddresses(std::vector<PhdrEntry> &Phdrs) {
   // Assign addresses as instructed by linker script SECTIONS sub-commands.
   Dot = 0;
+  resetAddressState();
   ErrorOnMissingSection = true;
   switchTo(Aether);
 
Index: ELF/OutputSections.cpp
===================================================================
--- ELF/OutputSections.cpp
+++ ELF/OutputSections.cpp
@@ -69,7 +69,7 @@
                   /*Info*/ 0,
                   /*Link*/ 0) {}
 
-static bool compareByFilePosition(InputSection *A, InputSection *B) {
+static bool compareByFilePosition(InputSectionBase *A, InputSectionBase *B) {
   // Synthetic doesn't have link order dependecy, stable_sort will keep it last
   if (A->kind() == InputSectionBase::Synthetic ||
       B->kind() == InputSectionBase::Synthetic)
@@ -85,9 +85,28 @@
 
 template <class ELFT> void OutputSection::finalize() {
   if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) {
-    std::sort(Sections.begin(), Sections.end(), compareByFilePosition);
-    assignOffsets();
-
+    if (Config->Relocatable) {
+      std::sort(Sections.begin(), Sections.end(), compareByFilePosition);
+      assignOffsets();
+    } else {
+      std::vector<std::vector<InputSectionBase *> *> InputRanges =
+          Script->inputSectionRanges(Name);
+      auto &FirstRange = *InputRanges.front();
+      if (InputRanges.size() > 1) {
+        // We must sort over a single InputSectionRange to produce a contiguous
+        // table, account for scripts with *(.ARM.exidx) instead of
+        // *(.ARM.exidx*)
+        // Move all the Sections into a the first range.
+        auto Iter = InputRanges.begin();
+        auto End = InputRanges.end();
+        for (++Iter; Iter != End; ++Iter) {
+          auto *Range = *Iter;
+          FirstRange.insert(FirstRange.begin(), Range->begin(), Range->end());
+          Range->clear();
+        }
+      }
+      std::sort(FirstRange.begin(), FirstRange.end(), compareByFilePosition);
+    }
     // We must preserve the link order dependency of sections with the
     // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We
     // need to translate the InputSection sh_link to the OutputSection sh_link,
Index: ELF/Relocations.h
===================================================================
--- ELF/Relocations.h
+++ ELF/Relocations.h
@@ -123,10 +123,11 @@
 public:
   // Return true if Thunks have been added to OutputSections
   bool createThunks(ArrayRef<OutputSection *> OutputSections);
-
+  using ISRange = std::vector<InputSectionBase *>;
 private:
-  void mergeThunks(OutputSection *OS, std::vector<ThunkSection *> &Thunks);
-  ThunkSection *getOSThunkSec(ThunkSection *&TS, OutputSection *OS);
+  void mergeThunks(ISRange* ISR, std::vector<ThunkSection *> &Thunks);
+  ThunkSection *getOSThunkSec(ThunkSection *&TS, OutputSection *OS,
+                              ISRange *ISR);
   ThunkSection *getISThunkSec(InputSection *IS, OutputSection *OS);
   std::pair<Thunk *, bool> getThunk(SymbolBody &Body, uint32_t Type);
 
@@ -136,8 +137,11 @@
   // Track InputSections that have a ThunkSection placed in front
   llvm::DenseMap<InputSection *, ThunkSection *> ThunkedSections;
 
-  // Track the ThunksSections that need to be inserted into an OutputSection
-  std::map<OutputSection *, std::vector<ThunkSection *>> ThunkSections;
+  // Track the ThunksSections that need to be inserted into an InputSectionRange
+  std::map<ISRange *, std::vector<ThunkSection *>> ThunkSections;
+
+  // Remember the Input Section Ranges for this LinkerScript
+  std::map<OutputSection *, std::vector<ISRange *>> ISRanges;
 };
 
 // Return a int64_t to make sure we get the sign extension out of the way as
Index: ELF/Relocations.cpp
===================================================================
--- ELF/Relocations.cpp
+++ ELF/Relocations.cpp
@@ -43,6 +43,7 @@
 
 #include "Relocations.h"
 #include "Config.h"
+#include "LinkerScript.h"
 #include "Memory.h"
 #include "OutputSections.h"
 #include "Strings.h"
@@ -974,7 +975,7 @@
 // offsets.
 // This may invalidate any output section offsets stored outside of InputSection
 template <class ELFT>
-void ThunkCreator<ELFT>::mergeThunks(OutputSection *OS,
+void ThunkCreator<ELFT>::mergeThunks(ISRange *ISR,
                                      std::vector<ThunkSection *> &Thunks) {
   // Order Thunks in ascending OutSecOff
   auto ThunkCmp = [](const ThunkSection *A, const ThunkSection *B) {
@@ -983,29 +984,37 @@
   std::stable_sort(Thunks.begin(), Thunks.end(), ThunkCmp);
 
   // Merge sorted vectors of Thunks and InputSections by OutSecOff
-  std::vector<InputSection *> Tmp;
-  Tmp.reserve(OS->Sections.size() + Thunks.size());
-  auto MergeCmp = [](const InputSection *A, const InputSection *B) {
+  std::vector<InputSectionBase *> Tmp;
+  Tmp.reserve(ISR->size() + Thunks.size());
+  auto MergeCmp = [](const InputSectionBase *A, const InputSectionBase *B) {
     // std::merge requires a strict weak ordering.
-    if (A->OutSecOff < B->OutSecOff)
+    auto *ISA = cast<InputSection>(A);
+    auto *ISB = cast<InputSection>(B);
+    if (ISA->OutSecOff < ISB->OutSecOff)
       return true;
-    if (A->OutSecOff == B->OutSecOff)
+    if (ISA->OutSecOff == ISB->OutSecOff)
       // 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)
+      if (auto *TA = dyn_cast<ThunkSection>(ISA))
+        if (TA && TA->getTargetInputSection() == ISB)
           return true;
     return false;
   };
-  std::merge(OS->Sections.begin(), OS->Sections.end(), Thunks.begin(),
-             Thunks.end(), std::back_inserter(Tmp), MergeCmp);
-  OS->Sections = std::move(Tmp);
-  OS->assignOffsets();
+  std::merge(ISR->begin(), ISR->end(), Thunks.begin(), Thunks.end(),
+             std::back_inserter(Tmp), MergeCmp);
+  *ISR = std::move(Tmp);
+
+  // Add Thunks to OutputSection::Sections, order is defined by the
+  // ISRange so we can just add to the end.
+  OutputSection *OS = cast<InputSection>(ISR->front())->OutSec;
+  for (auto *TS : Thunks)
+    OS->Sections.push_back(TS);
 }
 
 template <class ELFT>
 ThunkSection *ThunkCreator<ELFT>::getOSThunkSec(ThunkSection *&TS,
-                                                OutputSection *OS) {
+                                                OutputSection *OS,
+                                                ISRange *ISR) {
   if (TS == nullptr) {
     uint32_t Off = 0;
     for (auto *IS : OS->Sections) {
@@ -1014,7 +1023,7 @@
         break;
     }
     TS = make<ThunkSection>(OS, Off);
-    ThunkSections[OS].push_back(TS);
+    ThunkSections[ISR].push_back(TS);
   }
   return TS;
 }
@@ -1027,7 +1036,16 @@
     return TS;
   auto *TOS = cast<OutputSection>(IS->OutSec);
   TS = make<ThunkSection>(TOS, IS->OutSecOff);
-  ThunkSections[TOS].push_back(TS);
+
+  // Find InputSectionRange within TOS that IS is in
+  std::vector<ISRange *> &Ranges = ISRanges[TOS];
+  auto ISIter = std::find_if(Ranges.begin(), Ranges.end(), [=](ISRange *R) {
+    InputSection *first = cast<InputSection>(R->front());
+    InputSection *last = cast<InputSection>(R->back());
+    return IS->OutSecOff >= first->OutSecOff &&
+           IS->OutSecOff <= last->OutSecOff;
+  });
+  ThunkSections[*ISIter].push_back(TS);
   ThunkedSections[IS] = TS;
   return TS;
 }
@@ -1054,6 +1072,14 @@
 template <class ELFT>
 bool ThunkCreator<ELFT>::createThunks(
     ArrayRef<OutputSection *> OutputSections) {
+
+  // Each OutputSection containing instructions has one or more
+  // InputSectionRanges that we use to assign addresses to InputSections.
+  for (OutputSection *OS : OutputSections) {
+    if ((OS->Flags & SHF_ALLOC) && (OS->Flags & SHF_EXECINSTR))
+      ISRanges[OS] = Script->inputSectionRanges(OS->Name);
+  }
+
   // Create all the Thunks and insert them into synthetic ThunkSections. The
   // ThunkSections are later inserted back into the OutputSection.
 
@@ -1061,27 +1087,33 @@
   // ThunkSections back into the OutputSection as ThunkSections are not always
   // inserted into the same OutputSection as the caller.
   for (OutputSection *OS : OutputSections) {
-    ThunkSection *OSTS = nullptr;
-    for (InputSection *IS : OS->Sections) {
-      for (Relocation &Rel : IS->Relocations) {
-        SymbolBody &Body = *Rel.Sym;
-        if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
-          continue;
-        Thunk *T;
-        bool IsNew;
-        std::tie(T, IsNew) = getThunk(Body, Rel.Type);
-        if (IsNew) {
-          // Find or create a ThunkSection for the new Thunk
-          ThunkSection *TS;
-          if (auto *TIS = T->getTargetInputSection())
-            TS = getISThunkSec(TIS, OS);
-          else
-            TS = getOSThunkSec(OSTS, OS);
-          TS->addThunk(T);
+    if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR))
+      continue;
+    std::vector<ISRange *> &Ranges = ISRanges[OS];
+    for (ISRange *Range : Ranges) {
+      for (InputSectionBase *ISB : *Range) {
+        ThunkSection *ISRTS = nullptr;
+        auto *IS = cast<InputSection>(ISB);
+        for (Relocation &Rel : IS->Relocations) {
+          SymbolBody &Body = *Rel.Sym;
+          if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Body))
+            continue;
+          Thunk *T;
+          bool IsNew;
+          std::tie(T, IsNew) = getThunk(Body, Rel.Type);
+          if (IsNew) {
+            // Find or create a ThunkSection for the new Thunk
+            ThunkSection *TS;
+            if (auto *TIS = T->getTargetInputSection())
+              TS = getISThunkSec(TIS, OS);
+            else
+              TS = getOSThunkSec(ISRTS, OS, Range);
+            TS->addThunk(T);
+          }
+          // Redirect relocation to Thunk, we never go via the PLT to a Thunk
+          Rel.Sym = T->ThunkSym;
+          Rel.Expr = fromPlt(Rel.Expr);
         }
-        // Redirect relocation to Thunk, we never go via the PLT to a Thunk
-        Rel.Sym = T->ThunkSym;
-        Rel.Expr = fromPlt(Rel.Expr);
       }
     }
   }
Index: ELF/SyntheticSections.cpp
===================================================================
--- ELF/SyntheticSections.cpp
+++ ELF/SyntheticSections.cpp
@@ -2199,8 +2199,10 @@
 // | PREL31 upper bound of code that has exception tables | EXIDX_CANTUNWIND |
 void ARMExidxSentinelSection::writeTo(uint8_t *Buf) {
   // Get the InputSection before us, we are by definition last
-  auto RI = cast<OutputSection>(this->OutSec)->Sections.rbegin();
-  InputSection *LE = *(++RI);
+  std::vector<std::vector<InputSectionBase *> *> InputRanges =
+      Script->inputSectionRanges(this->OutSec->Name);
+  auto RI = InputRanges.front()->rbegin();
+  InputSection *LE = cast<InputSection>(*(++RI));
   InputSection *LC = cast<InputSection>(LE->getLinkOrderDep());
   uint64_t S = LC->OutSec->Addr + LC->getOffset(LC->getSize());
   uint64_t P = this->getVA();
Index: ELF/Writer.cpp
===================================================================
--- ELF/Writer.cpp
+++ ELF/Writer.cpp
@@ -249,10 +249,6 @@
   if (Config->Relocatable) {
     assignFileOffsets();
   } else {
-    if (!Script->Opt.HasSections) {
-      fixSectionAlignments();
-      Script->fabricateDefaultCommands(Config->MaxPageSize);
-    }
     Script->assignAddresses(Phdrs);
 
     // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
@@ -1195,21 +1191,28 @@
                   In<ELFT>::Dynamic},
                  [](SyntheticSection *SS) { SS->finalizeContents(); });
 
+  if (!Script->Opt.HasSections) {
+    fixSectionAlignments();
+    Script->fabricateDefaultCommands(Config->MaxPageSize);
+  }
+
   // Some architectures use small displacements for jump instructions.
   // It is linker's responsibility to create thunks containing long
   // jump instructions if jump targets are too far. Create thunks.
-  if (Target->NeedsThunks) {
+  if (Target->NeedsThunks && !Config->Relocatable) {
     // 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
+    Script->assignAddresses(Phdrs);
     ThunkCreator<ELFT> TC;
     if (TC.createThunks(OutputSections))
       applySynthetic({In<ELFT>::MipsGot},
                      [](SyntheticSection *SS) { SS->updateAllocSize(); });
   }
+
   // Fill other section headers. The dynamic table is finalized
   // at the end because some tags like RELSZ depend on result
   // of finalizing other sections.
@@ -1225,8 +1228,19 @@
   // ARM ABI requires .ARM.exidx to be terminated by some piece of data.
   // We have the terminater synthetic section class. Add that at the end.
   auto *OS = dyn_cast_or_null<OutputSection>(findSection(".ARM.exidx"));
-  if (OS && !OS->Sections.empty() && !Config->Relocatable)
-    OS->addSection(make<ARMExidxSentinelSection>());
+  if (!OS || OS->Sections.empty() || Config->Relocatable)
+    return;
+  auto *Sentinel = make<ARMExidxSentinelSection>();
+  OS->addSection(Sentinel);
+  // If the script has a section pattern matching .ARM.exidx we will need
+  // to add the Sentinel to the InputSectionDescription. In the non-script
+  // case fabricateDefaultCommands() will add it for us.
+  if (Script->Opt.HasSections) {
+    std::vector<std::vector<InputSectionBase *> *> InputRanges =
+        Script->inputSectionRanges(OS->Name);
+    if (!InputRanges.empty())
+      InputRanges.front()->push_back(Sentinel);
+  }
 }
 
 // The linker is expected to define SECNAME_start and SECNAME_end
Index: test/ELF/mips-npic-call-pic-script.s
===================================================================
--- /dev/null
+++ test/ELF/mips-npic-call-pic-script.s
@@ -0,0 +1,141 @@
+# REQUIRES: mips
+# Check LA25 stubs creation. This stub code is necessary when
+# non-PIC code calls PIC function.
+# RUN: echo "SECTIONS { .out 0x20000 : { *(.text.*) . = . + 0x100 ;  *(.text) }  }" > %t1.script
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN:   %p/Inputs/mips-fpic.s -o %t-fpic.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN:   %p/Inputs/mips-fnpic.s -o %t-fnpic.o
+# RUN: ld.lld -r %t-fpic.o %t-fnpic.o -o %t-sto-pic.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN:   %p/Inputs/mips-pic.s -o %t-pic.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-npic.o
+# RUN: ld.lld --script %t1.script %t-npic.o %t-pic.o %t-sto-pic.o -o %t.exe --Map=m.txt
+# RUN: llvm-objdump -d %t.exe | FileCheck %s
+
+# CHECK: Disassembly of section .out:
+# CHECK-NEXT: __LA25Thunk_foo1a:
+# CHECK-NEXT:    20000:       3c 19 00 02     lui     $25, 2
+# CHECK-NEXT:    20004:       08 00 80 08     j       131104 <foo1a>
+# CHECK-NEXT:    20008:       27 39 00 20     addiu   $25, $25, 32
+# CHECK-NEXT:    2000c:       00 00 00 00     nop
+# CHECK: __LA25Thunk_foo1b:
+# CHECK-NEXT:    20010:       3c 19 00 02     lui     $25, 2
+# CHECK-NEXT:    20014:       08 00 80 09     j       131108 <foo1b>
+# CHECK-NEXT:    20018:       27 39 00 24     addiu   $25, $25, 36
+# CHECK-NEXT:    2001c:       00 00 00 00     nop
+# CHECK: foo1a:
+# CHECK-NEXT:    20020:       00 00 00 00     nop
+# CHECK: foo1b:
+# CHECK-NEXT:    20024:       00 00 00 00     nop
+# CHECK: __LA25Thunk_foo2:
+# CHECK-NEXT:    20028:       3c 19 00 02     lui     $25, 2
+# CHECK-NEXT:    2002c:       08 00 80 10     j       131136 <foo2>
+# CHECK-NEXT:    20030:       27 39 00 40     addiu   $25, $25, 64
+# CHECK-NEXT:    20034:       00 00 00 00     nop
+# CHECK-NEXT:    20038:       00 00 00 00     nop
+# CHECK-NEXT:    2003c:       00 00 00 00     nop
+# CHECK: foo2:
+# CHECK-NEXT:    20040:       00 00 00 00     nop
+# CHECK-NEXT:    20044:       00 00 00 00     nop
+# CHECK-NEXT:    20048:       00 00 00 00     nop
+# CHECK-NEXT:    2004c:       00 00 00 00     nop
+# CHECK-NEXT:    20050:       00 00 00 00     nop
+# CHECK-NEXT:    20054:       00 00 00 00     nop
+# CHECK-NEXT:    20058:       00 00 00 00     nop
+# CHECK-NEXT:    2005c:       00 00 00 00     nop
+# CHECK-NEXT:    20060:       00 00 00 00     nop
+# CHECK-NEXT:    20064:       00 00 00 00     nop
+# CHECK-NEXT:    20068:       00 00 00 00     nop
+# CHECK-NEXT:    2006c:       00 00 00 00     nop
+# CHECK-NEXT:    20070:       00 00 00 00     nop
+# CHECK-NEXT:    20074:       00 00 00 00     nop
+# CHECK-NEXT:    20078:       00 00 00 00     nop
+# CHECK-NEXT:    2007c:       00 00 00 00     nop
+# CHECK-NEXT:    20080:       00 00 00 00     nop
+# CHECK-NEXT:    20084:       00 00 00 00     nop
+# CHECK-NEXT:    20088:       00 00 00 00     nop
+# CHECK-NEXT:    2008c:       00 00 00 00     nop
+# CHECK-NEXT:    20090:       00 00 00 00     nop
+# CHECK-NEXT:    20094:       00 00 00 00     nop
+# CHECK-NEXT:    20098:       00 00 00 00     nop
+# CHECK-NEXT:    2009c:       00 00 00 00     nop
+# CHECK-NEXT:    200a0:       00 00 00 00     nop
+# CHECK-NEXT:    200a4:       00 00 00 00     nop
+# CHECK-NEXT:    200a8:       00 00 00 00     nop
+# CHECK-NEXT:    200ac:       00 00 00 00     nop
+# CHECK-NEXT:    200b0:       00 00 00 00     nop
+# CHECK-NEXT:    200b4:       00 00 00 00     nop
+# CHECK-NEXT:    200b8:       00 00 00 00     nop
+# CHECK-NEXT:    200bc:       00 00 00 00     nop
+# CHECK-NEXT:    200c0:       00 00 00 00     nop
+# CHECK-NEXT:    200c4:       00 00 00 00     nop
+# CHECK-NEXT:    200c8:       00 00 00 00     nop
+# CHECK-NEXT:    200cc:       00 00 00 00     nop
+# CHECK-NEXT:    200d0:       00 00 00 00     nop
+# CHECK-NEXT:    200d4:       00 00 00 00     nop
+# CHECK-NEXT:    200d8:       00 00 00 00     nop
+# CHECK-NEXT:    200dc:       00 00 00 00     nop
+# CHECK-NEXT:    200e0:       00 00 00 00     nop
+# CHECK-NEXT:    200e4:       00 00 00 00     nop
+# CHECK-NEXT:    200e8:       00 00 00 00     nop
+# CHECK-NEXT:    200ec:       00 00 00 00     nop
+# CHECK-NEXT:    200f0:       00 00 00 00     nop
+# CHECK-NEXT:    200f4:       00 00 00 00     nop
+# CHECK-NEXT:    200f8:       00 00 00 00     nop
+# CHECK-NEXT:    200fc:       00 00 00 00     nop
+# CHECK-NEXT:    20100:       00 00 00 00     nop
+# CHECK-NEXT:    20104:       00 00 00 00     nop
+# CHECK-NEXT:    20108:       00 00 00 00     nop
+# CHECK-NEXT:    2010c:       00 00 00 00     nop
+# CHECK-NEXT:    20110:       00 00 00 00     nop
+# CHECK-NEXT:    20114:       00 00 00 00     nop
+# CHECK-NEXT:    20118:       00 00 00 00     nop
+# CHECK-NEXT:    2011c:       00 00 00 00     nop
+# CHECK-NEXT:    20120:       00 00 00 00     nop
+# CHECK-NEXT:    20124:       00 00 00 00     nop
+# CHECK-NEXT:    20128:       00 00 00 00     nop
+# CHECK-NEXT:    2012c:       00 00 00 00     nop
+# CHECK-NEXT:    20130:       00 00 00 00     nop
+# CHECK-NEXT:    20134:       00 00 00 00     nop
+# CHECK-NEXT:    20138:       00 00 00 00     nop
+# CHECK-NEXT:    2013c:       00 00 00 00     nop
+# CHECK-NEXT:    20140:       00 00 00 00     nop
+# CHECK-NEXT:    20144:       00 00 00 00     nop
+# CHECK-NEXT:    20148:       00 00 00 00     nop
+# CHECK-NEXT:    2014c:       00 00 00 00     nop
+# CHECK: __start:
+# CHECK-NEXT:    20150:       0c 00 80 00     jal     131072 <__LA25Thunk_foo1a>
+# CHECK-NEXT:    20154:       00 00 00 00     nop
+# CHECK-NEXT:    20158:       0c 00 80 0a     jal     131112 <__LA25Thunk_foo2>
+# CHECK-NEXT:    2015c:       00 00 00 00     nop
+# CHECK-NEXT:    20160:       0c 00 80 04     jal     131088 <__LA25Thunk_foo1b>
+# CHECK-NEXT:    20164:       00 00 00 00     nop
+# CHECK-NEXT:    20168:       0c 00 80 0a     jal     131112 <__LA25Thunk_foo2>
+# CHECK-NEXT:    2016c:       00 00 00 00     nop
+# CHECK-NEXT:    20170:       0c 00 80 60     jal     131456 <__LA25Thunk_fpic>
+# CHECK-NEXT:    20174:       00 00 00 00     nop
+# CHECK-NEXT:    20178:       0c 00 80 68     jal     131488 <fnpic>
+# CHECK-NEXT:    2017c:       00 00 00 00     nop
+# CHECK: __LA25Thunk_fpic:
+# CHECK-NEXT:    20180:       3c 19 00 02     lui     $25, 2
+# CHECK-NEXT:    20184:       08 00 80 64     j       131472 <fpic>
+# CHECK-NEXT:    20188:       27 39 01 90     addiu   $25, $25, 400
+# CHECK-NEXT:    2018c:       00 00 00 00     nop
+# CHECK: fpic:
+# CHECK-NEXT:    20190:       00 00 00 00     nop
+# CHECK-NEXT:    20194:       00 00 00 00     nop
+# CHECK-NEXT:    20198:       00 00 00 00     nop
+# CHECK-NEXT:    2019c:       00 00 00 00     nop
+# CHECK: fnpic:
+# CHECK-NEXT:    201a0:       00 00 00 00     nop
+
+  .text
+  .globl __start
+__start:
+  jal foo1a
+  jal foo2
+  jal foo1b
+  jal foo2
+  jal fpic
+  jal fnpic