Merge OutputSectionCommand and OutputSection.

This is a bit of a hack, but it is *so* convenient.

Now that we create synthetic linker scripts when none is provided, we
always have to handle paired OutputSection and OutputsectionCommand and
keep a mapping from one to the other.

This patch simplifies things by merging them and creating what used to
be OutputSectionCommands really early.

llvm-svn: 309311
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index f3e580c..a9e3856 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -46,7 +46,6 @@
   void run();
 
 private:
-  void clearOutputSections();
   void createSyntheticSections();
   void copyLocalSymbols();
   void addSectionSymbols();
@@ -79,8 +78,7 @@
   void addStartEndSymbols();
   void addStartStopSymbols(OutputSection *Sec);
   uint64_t getEntryAddr();
-  OutputSection *findSectionInScript(StringRef Name);
-  OutputSectionCommand *findSectionCommand(StringRef Name);
+  OutputSection *findSection(StringRef Name);
 
   std::vector<PhdrEntry *> Phdrs;
 
@@ -150,15 +148,6 @@
   V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());
 }
 
-template <class ELFT> void Writer<ELFT>::clearOutputSections() {
-  // Clear the OutputSections to make sure it is not used anymore. Any
-  // code from this point on should be using the linker script
-  // commands.
-  for (OutputSection *Sec : OutputSections)
-    Sec->Sections.clear();
-  OutputSections.clear();
-}
-
 // The main function of the writer.
 template <class ELFT> void Writer<ELFT>::run() {
   // Create linker-synthesized sections such as .got or .plt.
@@ -188,7 +177,6 @@
     Script->processCommands(Factory);
     createSections();
   }
-  clearOutputSections();
 
   if (Config->Discard != DiscardPolicy::All)
     copyLocalSymbols();
@@ -210,9 +198,8 @@
   // If -compressed-debug-sections is specified, we need to compress
   // .debug_* sections. Do it right now because it changes the size of
   // output sections.
-  parallelForEach(
-      OutputSectionCommands.begin(), OutputSectionCommands.end(),
-      [](OutputSectionCommand *Cmd) { Cmd->maybeCompress<ELFT>(); });
+  parallelForEach(OutputSections.begin(), OutputSections.end(),
+                  [](OutputSection *Sec) { Sec->maybeCompress<ELFT>(); });
 
   Script->assignAddresses();
   Script->allocateHeaders(Phdrs);
@@ -230,8 +217,8 @@
   setPhdrs();
 
   if (Config->Relocatable) {
-    for (OutputSectionCommand *Cmd : OutputSectionCommands)
-      Cmd->Sec->Addr = 0;
+    for (OutputSection *Sec : OutputSections)
+      Sec->Addr = 0;
   } else {
     fixPredefinedSymbols();
   }
@@ -258,7 +245,7 @@
     return;
 
   // Handle -Map option.
-  writeMapFile<ELFT>(OutputSectionCommands);
+  writeMapFile<ELFT>();
   if (ErrorCount)
     return;
 
@@ -496,15 +483,15 @@
   // Create one STT_SECTION symbol for each output section we might
   // have a relocation with.
   for (BaseCommand *Base : Script->Opt.Commands) {
-    auto *Cmd = dyn_cast<OutputSectionCommand>(Base);
-    if (!Cmd)
+    auto *Sec = dyn_cast<OutputSection>(Base);
+    if (!Sec)
       continue;
-    auto I = llvm::find_if(Cmd->Commands, [](BaseCommand *Base) {
+    auto I = llvm::find_if(Sec->Commands, [](BaseCommand *Base) {
       if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
         return !ISD->Sections.empty();
       return false;
     });
-    if (I == Cmd->Commands.end())
+    if (I == Sec->Commands.end())
       continue;
     InputSection *IS = cast<InputSectionDescription>(*I)->Sections[0];
     if (isa<SyntheticSection>(IS) || IS->Type == SHT_REL ||
@@ -735,8 +722,8 @@
 }
 
 static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) {
-  const OutputSection *A = cast<OutputSectionCommand>(ACmd)->Sec;
-  const OutputSection *B = cast<OutputSectionCommand>(BCmd)->Sec;
+  const OutputSection *A = cast<OutputSection>(ACmd);
+  const OutputSection *B = cast<OutputSection>(BCmd);
   if (A->SortRank != B->SortRank)
     return A->SortRank < B->SortRank;
   if (!(A->SortRank & RF_NOT_ADDR_SET))
@@ -867,13 +854,13 @@
 
 // Sort input sections by section name suffixes for
 // __attribute__((init_priority(N))).
-static void sortInitFini(OutputSectionCommand *Cmd) {
+static void sortInitFini(OutputSection *Cmd) {
   if (Cmd)
     Cmd->sortInitFini();
 }
 
 // Sort input sections by the special rule for .ctors and .dtors.
-static void sortCtorsDtors(OutputSectionCommand *Cmd) {
+static void sortCtorsDtors(OutputSection *Cmd) {
   if (Cmd)
     Cmd->sortCtorsDtors();
 }
@@ -905,8 +892,8 @@
 
   // Sort sections by priority.
   for (BaseCommand *Base : Script->Opt.Commands)
-    if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
-      Cmd->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); });
+    if (auto *Sec = dyn_cast<OutputSection>(Base))
+      Sec->sort([&](InputSectionBase *S) { return SectionOrder.lookup(S); });
 }
 
 template <class ELFT>
@@ -932,30 +919,34 @@
 }
 
 template <class ELFT> void Writer<ELFT>::createSections() {
+  std::vector<BaseCommand *> Old = Script->Opt.Commands;
+  Script->Opt.Commands.clear();
   for (InputSectionBase *IS : InputSections)
     if (IS)
       Factory.addInputSec(IS, getOutputSectionName(IS->Name));
+  Script->Opt.Commands.insert(Script->Opt.Commands.end(), Old.begin(),
+                              Old.end());
 
   Script->fabricateDefaultCommands();
   sortBySymbolsOrder<ELFT>();
-  sortInitFini(findSectionCommand(".init_array"));
-  sortInitFini(findSectionCommand(".fini_array"));
-  sortCtorsDtors(findSectionCommand(".ctors"));
-  sortCtorsDtors(findSectionCommand(".dtors"));
+  sortInitFini(findSection(".init_array"));
+  sortInitFini(findSection(".fini_array"));
+  sortCtorsDtors(findSection(".ctors"));
+  sortCtorsDtors(findSection(".dtors"));
 }
 
 // We want to find how similar two ranks are.
 // The more branches in getSectionRank that match, the more similar they are.
 // Since each branch corresponds to a bit flag, we can just use
 // countLeadingZeros.
-static int getRankProximity(OutputSection *A, OutputSection *B) {
+static int getRankProximityAux(OutputSection *A, OutputSection *B) {
   return countLeadingZeros(A->SortRank ^ B->SortRank);
 }
 
 static int getRankProximity(OutputSection *A, BaseCommand *B) {
-  if (auto *Cmd = dyn_cast<OutputSectionCommand>(B))
-    if (Cmd->Sec)
-      return getRankProximity(A, Cmd->Sec);
+  if (auto *Sec = dyn_cast<OutputSection>(B))
+    if (Sec->Live)
+      return getRankProximityAux(A, Sec);
   return -1;
 }
 
@@ -974,7 +965,7 @@
 //  rw_sec : { *(rw_sec) }
 // would mean that the RW PT_LOAD would become unaligned.
 static bool shouldSkip(BaseCommand *Cmd) {
-  if (isa<OutputSectionCommand>(Cmd))
+  if (isa<OutputSection>(Cmd))
     return false;
   if (auto *Assign = dyn_cast<SymbolAssignment>(Cmd))
     return Assign->Name != ".";
@@ -988,7 +979,7 @@
 static std::vector<BaseCommand *>::iterator
 findOrphanPos(std::vector<BaseCommand *>::iterator B,
               std::vector<BaseCommand *>::iterator E) {
-  OutputSection *Sec = cast<OutputSectionCommand>(*E)->Sec;
+  OutputSection *Sec = cast<OutputSection>(*E);
 
   // Find the first element that has as close a rank as possible.
   auto I = std::max_element(B, E, [=](BaseCommand *A, BaseCommand *B) {
@@ -1000,16 +991,16 @@
   // Consider all existing sections with the same proximity.
   int Proximity = getRankProximity(Sec, *I);
   for (; I != E; ++I) {
-    auto *Cmd = dyn_cast<OutputSectionCommand>(*I);
-    if (!Cmd || !Cmd->Sec)
+    auto *CurSec = dyn_cast<OutputSection>(*I);
+    if (!CurSec || !CurSec->Live)
       continue;
-    if (getRankProximity(Sec, Cmd->Sec) != Proximity ||
-        Sec->SortRank < Cmd->Sec->SortRank)
+    if (getRankProximity(Sec, CurSec) != Proximity ||
+        Sec->SortRank < CurSec->SortRank)
       break;
   }
   auto J = std::find_if(
       llvm::make_reverse_iterator(I), llvm::make_reverse_iterator(B),
-      [](BaseCommand *Cmd) { return isa<OutputSectionCommand>(Cmd); });
+      [](BaseCommand *Cmd) { return isa<OutputSection>(Cmd); });
   I = J.base();
   while (I != E && shouldSkip(*I))
     ++I;
@@ -1026,18 +1017,15 @@
     return;
 
   for (BaseCommand *Base : Script->Opt.Commands)
-    if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
-      if (OutputSection *Sec = Cmd->Sec)
-        Sec->SortRank = getSectionRank(Sec);
+    if (auto *Sec = dyn_cast<OutputSection>(Base))
+      Sec->SortRank = getSectionRank(Sec);
 
   if (!Script->Opt.HasSections) {
-    // We know that all the OutputSectionCommands are contiguous in
+    // We know that all the OutputSections are contiguous in
     // this case.
     auto E = Script->Opt.Commands.end();
     auto I = Script->Opt.Commands.begin();
-    auto IsSection = [](BaseCommand *Base) {
-      return isa<OutputSectionCommand>(Base);
-    };
+    auto IsSection = [](BaseCommand *Base) { return isa<OutputSection>(Base); };
     I = std::find_if(I, E, IsSection);
     E = std::find_if(llvm::make_reverse_iterator(E),
                      llvm::make_reverse_iterator(I), IsSection)
@@ -1088,8 +1076,8 @@
   auto I = Script->Opt.Commands.begin();
   auto E = Script->Opt.Commands.end();
   auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) {
-    if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
-      return Cmd->Sec && Cmd->Sec->SectionIndex == INT_MAX;
+    if (auto *Sec = dyn_cast<OutputSection>(Base))
+      return Sec->Live && Sec->SectionIndex == INT_MAX;
     return false;
   });
 
@@ -1109,13 +1097,13 @@
 
   while (NonScriptI != E) {
     auto Pos = findOrphanPos<ELFT>(I, NonScriptI);
-    OutputSection *Orphan = cast<OutputSectionCommand>(*NonScriptI)->Sec;
+    OutputSection *Orphan = cast<OutputSection>(*NonScriptI);
 
     // As an optimization, find all sections with the same sort rank
     // and insert them with one rotate.
     unsigned Rank = Orphan->SortRank;
     auto End = std::find_if(NonScriptI + 1, E, [=](BaseCommand *Cmd) {
-      return cast<OutputSectionCommand>(Cmd)->Sec->SortRank != Rank;
+      return cast<OutputSection>(Cmd)->SortRank != Rank;
     });
     std::rotate(Pos, NonScriptI, End);
     NonScriptI = End;
@@ -1149,9 +1137,8 @@
     if ((SS == InX::Got || SS == InX::MipsGot) && ElfSym::GlobalOffsetTable)
       continue;
 
-    OutputSectionCommand *Cmd = Script->getCmd(OS);
-    std::vector<BaseCommand *>::iterator Empty = Cmd->Commands.end();
-    for (auto I = Cmd->Commands.begin(), E = Cmd->Commands.end(); I != E; ++I) {
+    std::vector<BaseCommand *>::iterator Empty = OS->Commands.end();
+    for (auto I = OS->Commands.begin(), E = OS->Commands.end(); I != E; ++I) {
       BaseCommand *B = *I;
       if (auto *ISD = dyn_cast<InputSectionDescription>(B)) {
         auto P = std::find(ISD->Sections.begin(), ISD->Sections.end(), SS);
@@ -1161,17 +1148,17 @@
           Empty = I;
       }
     }
-    if (Empty != Cmd->Commands.end())
-      Cmd->Commands.erase(Empty);
+    if (Empty != OS->Commands.end())
+      OS->Commands.erase(Empty);
 
     // If there are no other sections in the output section, remove it from the
     // output.
-    if (Cmd->Commands.empty()) {
+    if (OS->Commands.empty()) {
       // Also remove script commands matching the output section.
       auto &Cmds = Script->Opt.Commands;
-      auto I = std::remove_if(Cmds.begin(), Cmds.end(), [&](BaseCommand *Cmd) {
-        if (auto *OSCmd = dyn_cast<OutputSectionCommand>(Cmd))
-          return OSCmd->Sec == OS;
+      auto I = std::remove_if(Cmds.begin(), Cmds.end(), [&](BaseCommand *Cmd2) {
+        if (auto *Sec = dyn_cast<OutputSection>(Cmd2))
+          return Sec == OS;
         return false;
       });
       Cmds.erase(I, Cmds.end());
@@ -1181,10 +1168,10 @@
 
 // Create output section objects and add them to OutputSections.
 template <class ELFT> void Writer<ELFT>::finalizeSections() {
-  Out::DebugInfo = findSectionInScript(".debug_info");
-  Out::PreinitArray = findSectionInScript(".preinit_array");
-  Out::InitArray = findSectionInScript(".init_array");
-  Out::FiniArray = findSectionInScript(".fini_array");
+  Out::DebugInfo = findSection(".debug_info");
+  Out::PreinitArray = findSection(".preinit_array");
+  Out::InitArray = findSection(".init_array");
+  Out::FiniArray = findSection(".fini_array");
 
   // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop
   // symbols for sections, so that the runtime can get the start and end
@@ -1192,9 +1179,8 @@
   if (!Config->Relocatable) {
     addStartEndSymbols();
     for (BaseCommand *Base : Script->Opt.Commands)
-      if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
-        if (Cmd->Sec)
-          addStartStopSymbols(Cmd->Sec);
+      if (auto *Sec = dyn_cast<OutputSection>(Base))
+        addStartStopSymbols(Sec);
   }
 
   // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type.
@@ -1250,16 +1236,16 @@
   sortSections();
 
   // Now that we have the final list, create a list of all the
-  // OutputSectionCommands for convenience.
+  // OutputSections for convenience.
   for (BaseCommand *Base : Script->Opt.Commands)
-    if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
-      OutputSectionCommands.push_back(Cmd);
+    if (auto *Sec = dyn_cast<OutputSection>(Base))
+      OutputSections.push_back(Sec);
 
   // Prefer command line supplied address over other constraints.
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    auto I = Config->SectionStartMap.find(Cmd->Name);
+  for (OutputSection *Sec : OutputSections) {
+    auto I = Config->SectionStartMap.find(Sec->Name);
     if (I != Config->SectionStartMap.end())
-      Cmd->AddrExpr = [=] { return I->second; };
+      Sec->AddrExpr = [=] { return I->second; };
   }
 
   // This is a bit of a hack. A value of 0 means undef, so we set it
@@ -1268,8 +1254,7 @@
   Out::ElfHeader->SectionIndex = 1;
 
   unsigned I = 1;
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    OutputSection *Sec = Cmd->Sec;
+  for (OutputSection *Sec : OutputSections) {
     Sec->SectionIndex = I++;
     Sec->ShName = InX::ShStrTab->addString(Sec->Name);
   }
@@ -1307,10 +1292,10 @@
     // when no more Thunks are added
     ThunkCreator TC;
     Script->assignAddresses();
-    if (TC.createThunks(OutputSectionCommands)) {
+    if (TC.createThunks(OutputSections)) {
       applySynthetic({InX::MipsGot},
                      [](SyntheticSection *SS) { SS->updateAllocSize(); });
-      if (TC.createThunks(OutputSectionCommands))
+      if (TC.createThunks(OutputSections))
         fatal("All non-range thunks should be created in first call");
     }
   }
@@ -1318,8 +1303,8 @@
   // Fill other section headers. The dynamic table is finalized
   // at the end because some tags like RELSZ depend on result
   // of finalizing other sections.
-  for (OutputSectionCommand *Cmd : OutputSectionCommands)
-    Cmd->finalize<ELFT>();
+  for (OutputSection *Sec : OutputSections)
+    Sec->finalize<ELFT>();
 
   // createThunks may have added local symbols to the static symbol table
   applySynthetic({InX::SymTab, InX::ShStrTab, InX::StrTab},
@@ -1329,18 +1314,12 @@
 template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
   // 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.
-  OutputSectionCommand *Cmd = findSectionCommand(".ARM.exidx");
-  if (!Cmd || !Cmd->Sec || Config->Relocatable)
+  OutputSection *Cmd = findSection(".ARM.exidx");
+  if (!Cmd || !Cmd->Live || Config->Relocatable)
     return;
 
   auto *Sentinel = make<ARMExidxSentinelSection>();
-  Cmd->Sec->addSection(Sentinel);
-  // Add the sentinel to the last of these too.
-  auto ISD = std::find_if(Cmd->Commands.rbegin(), Cmd->Commands.rend(),
-                          [](const BaseCommand *Base) {
-                            return isa<InputSectionDescription>(Base);
-                          });
-  cast<InputSectionDescription>(*ISD)->Sections.push_back(Sentinel);
+  Cmd->addSection(Sentinel);
 }
 
 // The linker is expected to define SECNAME_start and SECNAME_end
@@ -1364,7 +1343,7 @@
   Define("__init_array_start", "__init_array_end", Out::InitArray);
   Define("__fini_array_start", "__fini_array_end", Out::FiniArray);
 
-  if (OutputSection *Sec = findSectionInScript(".ARM.exidx"))
+  if (OutputSection *Sec = findSection(".ARM.exidx"))
     Define("__exidx_start", "__exidx_end", Sec);
 }
 
@@ -1382,19 +1361,11 @@
   addOptionalRegular<ELFT>(Saver.save("__stop_" + S), Sec, -1, STV_DEFAULT);
 }
 
-template <class ELFT>
-OutputSectionCommand *Writer<ELFT>::findSectionCommand(StringRef Name) {
+template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) {
   for (BaseCommand *Base : Script->Opt.Commands)
-    if (auto *Cmd = dyn_cast<OutputSectionCommand>(Base))
-      if (Cmd->Name == Name)
-        return Cmd;
-  return nullptr;
-}
-
-template <class ELFT>
-OutputSection *Writer<ELFT>::findSectionInScript(StringRef Name) {
-  if (OutputSectionCommand *Cmd = findSectionCommand(Name))
-    return Cmd->Sec;
+    if (auto *Sec = dyn_cast<OutputSection>(Base))
+      if (Sec->Name == Name)
+        return Sec;
   return nullptr;
 }
 
@@ -1435,8 +1406,8 @@
   AddHdr(PT_PHDR, PF_R)->add(Out::ProgramHeaders);
 
   // PT_INTERP must be the second entry if exists.
-  if (OutputSection *Sec = findSectionInScript(".interp"))
-    AddHdr(PT_INTERP, Sec->getPhdrFlags())->add(Sec);
+  if (OutputSection *Cmd = findSection(".interp"))
+    AddHdr(PT_INTERP, Cmd->getPhdrFlags())->add(Cmd);
 
   // Add the first PT_LOAD segment for regular output sections.
   uint64_t Flags = computeFlags(PF_R);
@@ -1446,8 +1417,7 @@
   Load->add(Out::ElfHeader);
   Load->add(Out::ProgramHeaders);
 
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    OutputSection *Sec = Cmd->Sec;
+  for (OutputSection *Sec : OutputSections) {
     if (!(Sec->Flags & SHF_ALLOC))
       break;
     if (!needsPtLoad(Sec))
@@ -1459,7 +1429,7 @@
     // different flags or is loaded at a discontiguous address using AT linker
     // script command.
     uint64_t NewFlags = computeFlags(Sec->getPhdrFlags());
-    if (Cmd->LMAExpr || Flags != NewFlags) {
+    if (Sec->LMAExpr || Flags != NewFlags) {
       Load = AddHdr(PT_LOAD, NewFlags);
       Flags = NewFlags;
     }
@@ -1469,11 +1439,9 @@
 
   // Add a TLS segment if any.
   PhdrEntry *TlsHdr = make<PhdrEntry>(PT_TLS, PF_R);
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    OutputSection *Sec = Cmd->Sec;
+  for (OutputSection *Sec : OutputSections)
     if (Sec->Flags & SHF_TLS)
       TlsHdr->add(Sec);
-  }
   if (TlsHdr->First)
     Ret.push_back(TlsHdr);
 
@@ -1485,11 +1453,9 @@
   // PT_GNU_RELRO includes all sections that should be marked as
   // read-only by dynamic linker after proccessing relocations.
   PhdrEntry *RelRo = make<PhdrEntry>(PT_GNU_RELRO, PF_R);
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    OutputSection *Sec = Cmd->Sec;
+  for (OutputSection *Sec : OutputSections)
     if (needsPtLoad(Sec) && isRelroSection(Sec))
       RelRo->add(Sec);
-  }
   if (RelRo->First)
     Ret.push_back(RelRo);
 
@@ -1501,8 +1467,8 @@
 
   // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes
   // the dynamic linker fill the segment with random data.
-  if (OutputSection *Sec = findSectionInScript(".openbsd.randomdata"))
-    AddHdr(PT_OPENBSD_RANDOMIZE, Sec->getPhdrFlags())->add(Sec);
+  if (OutputSection *Cmd = findSection(".openbsd.randomdata"))
+    AddHdr(PT_OPENBSD_RANDOMIZE, Cmd->getPhdrFlags())->add(Cmd);
 
   // PT_GNU_STACK is a special section to tell the loader to make the
   // pages for the stack non-executable. If you really want an executable
@@ -1524,10 +1490,9 @@
 
   // Create one PT_NOTE per a group of contiguous .note sections.
   PhdrEntry *Note = nullptr;
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    OutputSection *Sec = Cmd->Sec;
+  for (OutputSection *Sec : OutputSections) {
     if (Sec->Type == SHT_NOTE) {
-      if (!Note || Cmd->LMAExpr)
+      if (!Note || Sec->LMAExpr)
         Note = AddHdr(PT_NOTE, PF_R);
       Note->add(Sec);
     } else {
@@ -1541,15 +1506,15 @@
 void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry *> &Phdrs) {
   if (Config->EMachine != EM_ARM)
     return;
-  auto I = llvm::find_if(OutputSectionCommands, [](OutputSectionCommand *Cmd) {
-    return Cmd->Sec->Type == SHT_ARM_EXIDX;
+  auto I = llvm::find_if(OutputSections, [](OutputSection *Cmd) {
+    return Cmd->Type == SHT_ARM_EXIDX;
   });
-  if (I == OutputSectionCommands.end())
+  if (I == OutputSections.end())
     return;
 
   // PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME
   PhdrEntry *ARMExidx = make<PhdrEntry>(PT_ARM_EXIDX, PF_R);
-  ARMExidx->add((*I)->Sec);
+  ARMExidx->add(*I);
   Phdrs.push_back(ARMExidx);
 }
 
@@ -1557,8 +1522,7 @@
 // first section after PT_GNU_RELRO have to be page aligned so that the dynamic
 // linker can set the permissions.
 template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
-  auto PageAlign = [](OutputSection *Sec) {
-    OutputSectionCommand *Cmd = Script->getCmd(Sec);
+  auto PageAlign = [](OutputSection *Cmd) {
     if (Cmd && !Cmd->AddrExpr)
       Cmd->AddrExpr = [=] {
         return alignTo(Script->getDot(), Config->MaxPageSize);
@@ -1576,14 +1540,13 @@
       PageAlign(P->First);
     // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we
     // have to align it to a page.
-    auto End = OutputSectionCommands.end();
-    auto I =
-        std::find(OutputSectionCommands.begin(), End, Script->getCmd(P->Last));
+    auto End = OutputSections.end();
+    auto I = std::find(OutputSections.begin(), End, P->Last);
     if (I == End || (I + 1) == End)
       continue;
-    OutputSection *Sec = (*(I + 1))->Sec;
-    if (needsPtLoad(Sec))
-      PageAlign(Sec);
+    OutputSection *Cmd = (*(I + 1));
+    if (needsPtLoad(Cmd))
+      PageAlign(Cmd);
   }
 }
 
@@ -1591,41 +1554,39 @@
 // its new file offset. The file offset must be the same with its
 // virtual address (modulo the page size) so that the loader can load
 // executables without any address adjustment.
-static uint64_t getFileAlignment(uint64_t Off, OutputSection *Sec) {
-  OutputSection *First = Sec->FirstInPtLoad;
+static uint64_t getFileAlignment(uint64_t Off, OutputSection *Cmd) {
+  OutputSection *First = Cmd->FirstInPtLoad;
   // If the section is not in a PT_LOAD, we just have to align it.
   if (!First)
-    return alignTo(Off, Sec->Alignment);
+    return alignTo(Off, Cmd->Alignment);
 
   // The first section in a PT_LOAD has to have congruent offset and address
   // module the page size.
-  if (Sec == First)
-    return alignTo(Off, std::max<uint64_t>(Sec->Alignment, Config->MaxPageSize),
-                   Sec->Addr);
+  if (Cmd == First)
+    return alignTo(Off, std::max<uint64_t>(Cmd->Alignment, Config->MaxPageSize),
+                   Cmd->Addr);
 
   // If two sections share the same PT_LOAD the file offset is calculated
   // using this formula: Off2 = Off1 + (VA2 - VA1).
-  return First->Offset + Sec->Addr - First->Addr;
+  return First->Offset + Cmd->Addr - First->Addr;
 }
 
-static uint64_t setOffset(OutputSection *Sec, uint64_t Off) {
-  if (Sec->Type == SHT_NOBITS) {
-    Sec->Offset = Off;
+static uint64_t setOffset(OutputSection *Cmd, uint64_t Off) {
+  if (Cmd->Type == SHT_NOBITS) {
+    Cmd->Offset = Off;
     return Off;
   }
 
-  Off = getFileAlignment(Off, Sec);
-  Sec->Offset = Off;
-  return Off + Sec->Size;
+  Off = getFileAlignment(Off, Cmd);
+  Cmd->Offset = Off;
+  return Off + Cmd->Size;
 }
 
 template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
   uint64_t Off = 0;
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    OutputSection *Sec = Cmd->Sec;
+  for (OutputSection *Sec : OutputSections)
     if (Sec->Flags & SHF_ALLOC)
       Off = setOffset(Sec, Off);
-  }
   FileSize = alignTo(Off, Config->Wordsize);
 }
 
@@ -1635,12 +1596,11 @@
   Off = setOffset(Out::ElfHeader, Off);
   Off = setOffset(Out::ProgramHeaders, Off);
 
-  for (OutputSectionCommand *Cmd : OutputSectionCommands)
-    Off = setOffset(Cmd->Sec, Off);
+  for (OutputSection *Sec : OutputSections)
+    Off = setOffset(Sec, Off);
 
   SectionHeaderOff = alignTo(Off, Config->Wordsize);
-  FileSize =
-      SectionHeaderOff + (OutputSectionCommands.size() + 1) * sizeof(Elf_Shdr);
+  FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);
 }
 
 // Finalize the program headers. We call this function after we assign
@@ -1696,7 +1656,7 @@
     return Addr;
 
   // Case 4
-  if (OutputSection *Sec = findSectionInScript(".text")) {
+  if (OutputSection *Sec = findSection(".text")) {
     if (Config->WarnMissingEntry)
       warn("cannot find entry symbol " + Config->Entry + "; defaulting to 0x" +
            utohexstr(Sec->Addr));
@@ -1738,9 +1698,9 @@
       LastRO = P;
   }
 
-  auto Set = [](DefinedRegular *S, OutputSection *Sec, uint64_t Value) {
+  auto Set = [](DefinedRegular *S, OutputSection *Cmd, uint64_t Value) {
     if (S) {
-      S->Section = Sec;
+      S->Section = Cmd;
       S->Value = Value;
     }
   };
@@ -1759,15 +1719,15 @@
   }
 
   if (ElfSym::Bss)
-    ElfSym::Bss->Section = findSectionInScript(".bss");
+    ElfSym::Bss->Section = findSection(".bss");
 
   // Setup MIPS _gp_disp/__gnu_local_gp symbols which should
   // be equal to the _gp symbol's value.
   if (Config->EMachine == EM_MIPS && !ElfSym::MipsGp->Value) {
     // Find GP-relative section with the lowest address
     // and use this address to calculate default _gp value.
-    for (const OutputSectionCommand *Cmd : OutputSectionCommands) {
-      OutputSection *OS = Cmd->Sec;
+    for (const OutputSection *Cmd : OutputSections) {
+      const OutputSection *OS = Cmd;
       if (OS->Flags & SHF_MIPS_GPREL) {
         ElfSym::MipsGp->Value = OS->Addr + 0x7ff0;
         break;
@@ -1794,7 +1754,7 @@
   EHdr->e_ehsize = sizeof(Elf_Ehdr);
   EHdr->e_phnum = Phdrs.size();
   EHdr->e_shentsize = sizeof(Elf_Shdr);
-  EHdr->e_shnum = OutputSectionCommands.size() + 1;
+  EHdr->e_shnum = OutputSections.size() + 1;
   EHdr->e_shstrndx = InX::ShStrTab->getParent()->SectionIndex;
 
   if (Config->EMachine == EM_ARM)
@@ -1826,8 +1786,8 @@
 
   // Write the section header table. Note that the first table entry is null.
   auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);
-  for (OutputSectionCommand *Cmd : OutputSectionCommands)
-    Cmd->Sec->writeHeaderTo<ELFT>(++SHdrs);
+  for (OutputSection *Sec : OutputSections)
+    Sec->writeHeaderTo<ELFT>(++SHdrs);
 }
 
 // Open a result file.
@@ -1850,11 +1810,9 @@
 
 template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
   uint8_t *Buf = Buffer->getBufferStart();
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    OutputSection *Sec = Cmd->Sec;
+  for (OutputSection *Sec : OutputSections)
     if (Sec->Flags & SHF_ALLOC)
-      Cmd->writeTo<ELFT>(Buf + Sec->Offset);
-  }
+      Sec->writeTo<ELFT>(Buf + Sec->Offset);
 }
 
 // Write section contents to a mmap'ed file.
@@ -1863,8 +1821,8 @@
 
   // PPC64 needs to process relocations in the .opd section
   // before processing relocations in code-containing sections.
-  if (auto *OpdCmd = findSectionCommand(".opd")) {
-    Out::Opd = OpdCmd->Sec;
+  if (auto *OpdCmd = findSection(".opd")) {
+    Out::Opd = OpdCmd;
     Out::OpdBuf = Buf + Out::Opd->Offset;
     OpdCmd->template writeTo<ELFT>(Buf + Out::Opd->Offset);
   }
@@ -1877,25 +1835,19 @@
   // In -r or -emit-relocs mode, write the relocation sections first as in
   // ELf_Rel targets we might find out that we need to modify the relocated
   // section while doing it.
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    OutputSection *Sec = Cmd->Sec;
+  for (OutputSection *Sec : OutputSections)
     if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA)
-      Cmd->writeTo<ELFT>(Buf + Sec->Offset);
-  }
+      Sec->writeTo<ELFT>(Buf + Sec->Offset);
 
-  for (OutputSectionCommand *Cmd : OutputSectionCommands) {
-    OutputSection *Sec = Cmd->Sec;
+  for (OutputSection *Sec : OutputSections)
     if (Sec != Out::Opd && Sec != EhFrameHdr && Sec->Type != SHT_REL &&
         Sec->Type != SHT_RELA)
-      Cmd->writeTo<ELFT>(Buf + Sec->Offset);
-  }
+      Sec->writeTo<ELFT>(Buf + Sec->Offset);
 
   // The .eh_frame_hdr depends on .eh_frame section contents, therefore
   // it should be written after .eh_frame is written.
-  if (EhFrameHdr) {
-    OutputSectionCommand *Cmd = Script->getCmd(EhFrameHdr);
-    Cmd->writeTo<ELFT>(Buf + EhFrameHdr->Offset);
-  }
+  if (EhFrameHdr)
+    EhFrameHdr->writeTo<ELFT>(Buf + EhFrameHdr->Offset);
 }
 
 template <class ELFT> void Writer<ELFT>::writeBuildId() {